From da43a8712da52c0a89a1877116f18274f3cc711e Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Thu, 8 Sep 2016 18:34:43 -0400 Subject: [PATCH] Moved most of the logic for joining tournament into tournament_object --- libraries/chain/CMakeLists.txt | 1 + libraries/chain/db_update.cpp | 20 ++----- .../graphene/chain/protocol/tournament.hpp | 7 +++ .../include/graphene/chain/protocol/types.hpp | 6 ++ .../graphene/chain/tournament_object.hpp | 55 +++++++++++++++++-- libraries/chain/tournament_evaluator.cpp | 35 +++--------- 6 files changed, 75 insertions(+), 49 deletions(-) diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 375c8d2f..a8ae794d 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -75,6 +75,7 @@ add_library( graphene_chain market_evaluator.cpp vesting_balance_evaluator.cpp tournament_evaluator.cpp + tournament_object.cpp withdraw_permission_evaluator.cpp worker_evaluator.cpp confidential_evaluator.cpp diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index fb96c537..5ac6d3b1 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -476,7 +476,7 @@ void database::update_tournaments() // this index is sorted on state and deadline, so the tournaments awaiting registrations with the earliest // deadlines will be at the beginning while (registration_deadline_index.empty() && - registration_deadline_index.begin()->state == tournament_state::accepting_registrations && + registration_deadline_index.begin()->get_state() == tournament_state::accepting_registrations && registration_deadline_index.begin()->options.registration_deadline <= head_block_time()) { const tournament_object& tournament_obj = *registration_deadline_index.begin(); @@ -484,20 +484,8 @@ void database::update_tournaments() "Canceling tournament ${id} because its deadline expired", ("id", tournament_obj.id)); // cancel this tournament - // repay everyone who paid into the prize pool - const tournament_details_object& details = tournament_obj.tournament_details_id(*this); - for (const auto& payer_pair : details.payers) - { - // TODO: create a virtual operation to record the refund - // we'll think of this as just releasing an asset that the user had locked up - // for a period of time, not as a transfer back to the user; it doesn't matter - // if they are currently authorized to transfer this asset, they never really - // transferred it in the first place - adjust_balance(payer_pair.first, asset(payer_pair.second, tournament_obj.options.buy_in.asset_id)); - } - modify(tournament_obj, [&](tournament_object& t) { - t.state = tournament_state::registration_period_expired; + t.on_registration_deadline_passed(*this); }); } @@ -507,11 +495,11 @@ void database::update_tournaments() { // find the first tournament waiting to start; if its start time has arrived, start it auto start_iter = start_time_index.lower_bound(boost::make_tuple(tournament_state::awaiting_start)); - if (start_iter->state == tournament_state::awaiting_start && + if (start_iter->get_state() == tournament_state::awaiting_start && *start_iter->start_time <= head_block_time()) { modify(*start_iter, [&](tournament_object& t) { - t.state = tournament_state::in_progress; + t.on_start_time_arrived(); }); } else diff --git a/libraries/chain/include/graphene/chain/protocol/tournament.hpp b/libraries/chain/include/graphene/chain/protocol/tournament.hpp index fbc4099f..36636142 100644 --- a/libraries/chain/include/graphene/chain/protocol/tournament.hpp +++ b/libraries/chain/include/graphene/chain/protocol/tournament.hpp @@ -86,6 +86,13 @@ namespace graphene { namespace chain { /// The winner of a round in the tournament is the first to reach this number of wins uint32_t number_of_wins; + /// Metadata about this tournament. This can be empty or it can contain any keys the creator desires. + /// The GUI will standardize on displaying a few keys, likely: + /// "name" + /// "description" + /// "url" + fc::variant_object meta; + /// Parameters that are specific to the type_of_game in this tournament game_specific_options game_options; diff --git a/libraries/chain/include/graphene/chain/protocol/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp index 6c36fda4..8a7c9e56 100644 --- a/libraries/chain/include/graphene/chain/protocol/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -135,6 +135,8 @@ namespace graphene { namespace chain { worker_object_type, balance_object_type, tournament_object_type, + match_object_type, + game_object_type, OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types }; @@ -178,6 +180,8 @@ namespace graphene { namespace chain { class balance_object; class blinded_balance_object; class tournament_object; + class match_object; + class game_object; typedef object_id< protocol_ids, account_object_type, account_object> account_id_type; typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type; @@ -194,6 +198,8 @@ namespace graphene { namespace chain { typedef object_id< protocol_ids, worker_object_type, worker_object> worker_id_type; typedef object_id< protocol_ids, balance_object_type, balance_object> balance_id_type; typedef object_id< protocol_ids, tournament_object_type, tournament_object> tournament_id_type; + typedef object_id< protocol_ids, match_object_type, match_object> match_id_type; + typedef object_id< protocol_ids, game_object_type, game_object> game_id_type; // implementation types class global_property_object; diff --git a/libraries/chain/include/graphene/chain/tournament_object.hpp b/libraries/chain/include/graphene/chain/tournament_object.hpp index 9f132161..90ce2850 100644 --- a/libraries/chain/include/graphene/chain/tournament_object.hpp +++ b/libraries/chain/include/graphene/chain/tournament_object.hpp @@ -28,7 +28,8 @@ namespace graphene { namespace chain { accepting_registrations, awaiting_start, in_progress, - registration_period_expired + registration_period_expired, + concluded }; class tournament_object : public graphene::db::abstract_object @@ -36,6 +37,11 @@ namespace graphene { namespace chain { public: static const uint8_t space_id = protocol_ids; static const uint8_t type_id = tournament_object_type; + + tournament_object(); + tournament_object(const tournament_object& rhs); + ~tournament_object(); + tournament_object& operator=(const tournament_object& rhs); /// the account that created this tournament account_id_type creator; @@ -59,15 +65,51 @@ namespace graphene { namespace chain { uint32_t registered_players = 0; /// The current high-level status of the tournament (whether it is currently running or has been canceled, etc) - tournament_state state; + //tournament_state state; /// Detailed information on this tournament tournament_details_id_type tournament_details_id; + tournament_state get_state() const; + time_point_sec get_registration_deadline() const { return options.registration_deadline; } + /// called by database maintenance code when registration for this contest has expired + void on_registration_deadline_passed(database& db); + void on_player_registered(database& db, account_id_type payer_id, account_id_type player_id); + void on_start_time_arrived(); + void on_final_game_completed(); + + private: + class impl; + std::unique_ptr my; }; + class match_object : public graphene::db::abstract_object + { + public: + static const uint8_t space_id = protocol_ids; + static const uint8_t type_id = match_object_type; + + /// + flat_set players; + + vector > game_winners; + }; + + class game_object : public graphene::db::abstract_object + { + public: + static const uint8_t space_id = protocol_ids; + static const uint8_t type_id = game_object_type; + + flat_set players; + + flat_set winners; + }; + + + struct by_registration_deadline {}; struct by_start_time {}; typedef multi_index_container< @@ -76,11 +118,11 @@ namespace graphene { namespace chain { ordered_unique< tag, member< object, object_id_type, &object::id > >, ordered_non_unique< tag, composite_key, + const_mem_fun, const_mem_fun > >, ordered_non_unique< tag, composite_key, + const_mem_fun, member, &tournament_object::start_time> > > > > tournament_object_multi_index_type; @@ -97,10 +139,11 @@ FC_REFLECT_DERIVED(graphene::chain::tournament_object, (graphene::db::object), (start_time) (end_time) (prize_pool) - (state) (tournament_details_id)) FC_REFLECT_ENUM(graphene::chain::tournament_state, (accepting_registrations) (awaiting_start) (in_progress) - (registration_period_expired)) + (registration_period_expired) + (concluded)) + diff --git a/libraries/chain/tournament_evaluator.cpp b/libraries/chain/tournament_evaluator.cpp index 00e70050..69f5e36d 100644 --- a/libraries/chain/tournament_evaluator.cpp +++ b/libraries/chain/tournament_evaluator.cpp @@ -72,12 +72,15 @@ namespace graphene { namespace chain { object_id_type tournament_create_evaluator::do_apply( const tournament_create_operation& op ) { try { + const tournament_details_object& tournament_details = + db().create( [&]( tournament_details_object& a ) { + }); + const tournament_object& new_tournament = db().create( [&]( tournament_object& t ) { t.options = op.options; t.creator = op.creator; - t.state = tournament_state::accepting_registrations; - // t.dynamic_tournament_data_id = dyn_tournament.id; + t.tournament_details_id = tournament_details.id; }); return new_tournament.id; } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -91,7 +94,7 @@ namespace graphene { namespace chain { //const account_object& player_account = op.player_account_id(d); _buy_in_asset_type = &op.buy_in.asset_id(d); - FC_ASSERT(_tournament_obj->state == tournament_state::accepting_registrations); + // TODO FC_ASSERT(_tournament_obj->state == tournament_state::accepting_registrations); FC_ASSERT(_tournament_details_obj->registered_players.size() < _tournament_obj->options.number_of_players, "Tournament is already full"); FC_ASSERT(d.head_block_time() <= _tournament_obj->options.registration_deadline, @@ -127,31 +130,9 @@ namespace graphene { namespace chain { void_result tournament_join_evaluator::do_apply( const tournament_join_operation& op ) { try { - bool registration_complete = _tournament_details_obj->registered_players.size() + 1 == _tournament_obj->options.number_of_players; - if (registration_complete) - fc_ilog(fc::logger::get("tournament"), - "Tournament ${id} now has enough players registered to begin", - ("id", _tournament_obj->id)); - - db().adjust_balance(op.payer_account_id, -op.buy_in); - db().modify(*_tournament_details_obj, [&](tournament_details_object& tournament_details_obj){ - tournament_details_obj.payers[op.payer_account_id] += op.buy_in.amount; - tournament_details_obj.registered_players.insert(op.player_account_id); - }); db().modify(*_tournament_obj, [&](tournament_object& tournament_obj){ - ++tournament_obj.registered_players; - tournament_obj.prize_pool += op.buy_in.amount; - if (registration_complete) - { - if (tournament_obj.options.start_time) - tournament_obj.start_time = tournament_obj.options.start_time; - else - tournament_obj.start_time = db().head_block_time() + fc::seconds(*tournament_obj.options.start_delay); - // even if the start time is now, mark it as awaiting; we will promote it to in_progress - // in update_tournaments() called at the end of the block - tournament_obj.state = tournament_state::awaiting_start; - } - }); + tournament_obj.on_player_registered(db(), op.payer_account_id, op.player_account_id); + }); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) }