diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index c1863e67..69bee98b 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -179,6 +179,7 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); + register_evaluator(); } void database::initialize_indexes() diff --git a/libraries/chain/include/graphene/chain/protocol/tournament.hpp b/libraries/chain/include/graphene/chain/protocol/tournament.hpp index bc26910a..9138af48 100644 --- a/libraries/chain/include/graphene/chain/protocol/tournament.hpp +++ b/libraries/chain/include/graphene/chain/protocol/tournament.hpp @@ -153,7 +153,7 @@ namespace graphene { namespace chain { asset fee; - /// The account that payed the buy-in for the tournament + /// The account that is paying the fee account_id_type payer_account_id; /// The account that would play in the tournament, would receive any winnings. diff --git a/libraries/chain/include/graphene/chain/tournament_evaluator.hpp b/libraries/chain/include/graphene/chain/tournament_evaluator.hpp index e276ab13..18a0140d 100644 --- a/libraries/chain/include/graphene/chain/tournament_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/tournament_evaluator.hpp @@ -33,9 +33,6 @@ namespace graphene { namespace chain { private: const tournament_object* _tournament_obj = nullptr; const tournament_details_object* _tournament_details_obj = nullptr; - //const account_object* _payer_account = nullptr; - //const account_object* _player_account = nullptr; - //const asset_object* _buy_in_back_asset_type = nullptr; public: typedef tournament_leave_operation operation_type; diff --git a/libraries/chain/include/graphene/chain/tournament_object.hpp b/libraries/chain/include/graphene/chain/tournament_object.hpp index 840509ce..814d019f 100644 --- a/libraries/chain/include/graphene/chain/tournament_object.hpp +++ b/libraries/chain/include/graphene/chain/tournament_object.hpp @@ -38,6 +38,9 @@ namespace graphene { namespace chain { /// List of payers who have contributed to the prize pool flat_map payers; + /// List of player payer pairs needed by torunament leave operation + flat_map players_payers; + /// List of all matches in this tournament. When the tournament starts, all matches /// are created. Matches in the first round will have players, matches in later /// rounds will not be populated. diff --git a/libraries/chain/match_object.cpp b/libraries/chain/match_object.cpp index 996ca04d..7819d21e 100644 --- a/libraries/chain/match_object.cpp +++ b/libraries/chain/match_object.cpp @@ -125,13 +125,12 @@ namespace graphene { namespace chain { } else { - // $$$ III. Rock Paper Scissors Game Need to review how Ties are dealt with. - short i = std::rand() % match.players.size(); // ! event.db.get_random_bits(match.players.size()) ; + // III. Rock Paper Scissors Game Need to review how Ties are dealt with. + short i = match.number_of_ties == match.games.size() ? 0 : event.db.get_random_bits(match.players.size()) ; match.match_winners.insert(match.players[i]); ++match.number_of_wins[i]; if (match.number_of_ties == match.games.size()) match.game_winners[match.game_winners.size()-1].insert(match.players[i]); - } match.end_time = event.db.head_block_time(); diff --git a/libraries/chain/protocol/tournament.cpp b/libraries/chain/protocol/tournament.cpp index cc5fa667..57e80bf3 100644 --- a/libraries/chain/protocol/tournament.cpp +++ b/libraries/chain/protocol/tournament.cpp @@ -59,7 +59,7 @@ share_type tournament_leave_operation::calculate_fee(const fee_parameters_type& void tournament_leave_operation::validate()const { - FC_ASSERT( fee.amount >= 0 ); + // todo FC_ASSERT( fee.amount >= 0 ); } diff --git a/libraries/chain/tournament_evaluator.cpp b/libraries/chain/tournament_evaluator.cpp index 75bb54ea..73271b30 100644 --- a/libraries/chain/tournament_evaluator.cpp +++ b/libraries/chain/tournament_evaluator.cpp @@ -186,23 +186,11 @@ namespace graphene { namespace chain { _tournament_details_obj = &_tournament_obj->tournament_details_id(d); FC_ASSERT(_tournament_details_obj->registered_players.find(op.player_account_id) != _tournament_details_obj->registered_players.end(), "Player is not registered for this tournament"); - FC_ASSERT(_tournament_details_obj->payers.find(op.payer_account_id) != _tournament_details_obj->payers.end(), - "Payer is not registered for this tournament"); -#if 0 - _payer_account = &op.payer_account_id(d); - _buy_in_back_asset_type = &(_tournament_obj->options.buy_in.asset_id(d)); - GRAPHENE_ASSERT(!_buy_in_back_asset_type->is_transfer_restricted(), - transfer_restricted_transfer_asset, - "Asset {asset} has transfer_restricted flag enabled", - ("asset", _buy_in_back_asset_type->id)); + //FC_ASSERT(_tournament_details_obj->payers.find(op.payer_account_id) != _tournament_details_obj->payers.end(), + // "Payer is not registered for this tournament"); - GRAPHENE_ASSERT(is_authorized_asset(d, *_payer_account, *_buy_in_back_asset_type), - transfer_from_account_not_whitelisted, - "payer account ${payer} is not whitelisted for asset ${asset}", - ("payer", op.payer_account_id) - ("asset", _buy_in_back_asset_type->id)); -#endif - FC_ASSERT(_tournament_obj->get_state() == tournament_state::accepting_registrations); + FC_ASSERT(_tournament_obj->get_state() == tournament_state::accepting_registrations || + _tournament_obj->get_state() == tournament_state::awaiting_start); FC_ASSERT(d.head_block_time() <= _tournament_obj->options.registration_deadline, "Registration deadline has already passed"); return void_result(); diff --git a/libraries/chain/tournament_object.cpp b/libraries/chain/tournament_object.cpp index 4b4c6d07..4adb5bb7 100644 --- a/libraries/chain/tournament_object.cpp +++ b/libraries/chain/tournament_object.cpp @@ -391,6 +391,7 @@ namespace graphene { namespace chain { event.db.modify(tournament_details_obj, [&](tournament_details_object& tournament_details_obj){ tournament_details_obj.payers[event.payer_id] += tournament_obj->options.buy_in.amount; tournament_details_obj.registered_players.insert(event.player_id); + tournament_details_obj.players_payers[event.player_id] = event.payer_id; }); ++tournament_obj->registered_players; tournament_obj->prize_pool += tournament_obj->options.buy_in.amount; @@ -399,19 +400,21 @@ namespace graphene { namespace chain { void unregister_player(const player_unregistered& event) { fc_ilog(fc::logger::get("tournament"), - "In register_player action, player_id is ${player_id}, payer_id is ${payer_id}", - ("player_id", event.player_id)("payer_id", event.payer_id)); + "In unregister_player action, player_id is ${player_id}", + ("player_id", event.player_id)); event.db.adjust_balance(event.payer_id, tournament_obj->options.buy_in); const tournament_details_object& tournament_details_obj = tournament_obj->tournament_details_id(event.db); event.db.modify(tournament_details_obj, [&](tournament_details_object& tournament_details_obj){ - tournament_details_obj.payers[event.payer_id] -= tournament_obj->options.buy_in.amount; - if (tournament_details_obj.payers[event.payer_id] <= 0) - tournament_details_obj.payers.erase(event.payer_id); + account_id_type payer_id = tournament_details_obj.players_payers[event.player_id]; + tournament_details_obj.payers[payer_id] -= tournament_obj->options.buy_in.amount; + if (tournament_details_obj.payers[payer_id] <= 0) + tournament_details_obj.payers.erase(payer_id); tournament_details_obj.registered_players.erase(event.player_id); + tournament_details_obj.players_payers.erase(event.player_id); }); - ++tournament_obj->registered_players; - tournament_obj->prize_pool += tournament_obj->options.buy_in.amount; + --tournament_obj->registered_players; + tournament_obj->prize_pool -= tournament_obj->options.buy_in.amount; } // Transition table for tournament diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 14ee95ef..bd09660f 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1501,13 +1501,13 @@ class wallet_api signed_transaction tournament_join( string payer_account, string player_account, tournament_id_type tournament_id, string buy_in_amount, string buy_in_asset_symbol, bool broadcast = false ); /** Leave an existing tournament - * @param payer_account the account that payed buy-in and the fee to join the tournament + * @param payer_account the account that is paying the fee * @param player_account the account that would be playing in the tournament * @param tournament_id the tournament the user wishes to leave * @param broadcast true if you wish to broadcast the transaction * @return the signed version of the transaction */ - signed_transaction tournament_leave( string payer_account, string player_account, tournament_id_type tournament_id, bool broadcast = false); + signed_transaction tournament_leave(string payer_account, string player_account, tournament_id_type tournament_id, bool broadcast = false); /** Get a list of upcoming tournaments * @param limit the number of tournaments to return diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 8d282da5..40638e54 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -4859,8 +4859,8 @@ signed_transaction wallet_api::tournament_leave( string payer_account, bool broadcast) { FC_ASSERT( !is_locked() ); - account_object payer_account_obj = get_account(payer_account); account_object player_account_obj = get_account(player_account); + account_object payer_account_obj = get_account(payer_account); //graphene::chain::tournament_object tournament_obj = my->get_object(tournament_id); signed_transaction tx; diff --git a/tests/tournament/tournament_tests.cpp b/tests/tournament/tournament_tests.cpp index 1da5e3c4..8889f205 100644 --- a/tests/tournament/tournament_tests.cpp +++ b/tests/tournament/tournament_tests.cpp @@ -234,7 +234,34 @@ public: players.insert(player_id); players_keys[player_id] = sig_priv_key; - } + } + + void leave_tournament(const tournament_id_type & tournament_id, + const account_id_type& player_id, + const account_id_type& payer_id, + const fc::ecc::private_key& sig_priv_key + ) + { + graphene::chain::database& db = df.db; + const chain_parameters& params = db.get_global_properties().parameters; + signed_transaction tx; + tournament_leave_operation op; + + op.payer_account_id = payer_id; + op.player_account_id = player_id; + op.tournament_id = tournament_id; + tx.operations = {op}; + for( auto& op : tx.operations ) + db.current_fee_schedule().set_fee(op); + tx.validate(); + tx.set_expiration(db.head_block_time() + fc::seconds( params.block_interval * (params.maintenance_skip_slots + 1) * 3)); + df.sign(tx, sig_priv_key); + PUSH_TX(db, tx); + + //players.erase(player_id); + } + + // stolen from cli_wallet void rps_throw(const game_id_type& game_id, @@ -434,13 +461,14 @@ BOOST_FIXTURE_TEST_CASE( simple, database_fixture ) #define TEST2_NR_OF_PLAYERS_NUMBER 4 #endif BOOST_TEST_MESSAGE("Hello simple tournament test"); - ACTORS((nathan)(alice)(bob)(carol)(dave)(ed)(frank)(george)(harry)(ike)); + ACTORS((nathan)(alice)(bob)(carol)(dave)(ed)(frank)(george)(harry)(ike)(romek)); tournaments_helper tournament_helper(*this); fc::ecc::private_key nathan_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan"))); BOOST_TEST_MESSAGE( "Giving folks some money" ); transfer(committee_account, nathan_id, asset(1000000000)); + transfer(committee_account, romek_id, asset(2000000)); transfer(committee_account, alice_id, asset(2000000)); transfer(committee_account, bob_id, asset(3000000)); transfer(committee_account, carol_id, asset(4000000)); @@ -486,8 +514,13 @@ BOOST_FIXTURE_TEST_CASE( simple, database_fixture ) 3, 1, 3, 3600, 3, 3, true); BOOST_REQUIRE(tournament_id == tournament_id_type(1)); tournament_helper.join_tournament(tournament_id, alice_id, alice_id, fc::ecc::private_key::regenerate(fc::sha256::hash(string("alice"))), buy_in); + // romek joins but will leave + //tournament_helper.leave_tournament(tournament_id, romek_id, romek_id, fc::ecc::private_key::regenerate(fc::sha256::hash(string("romek")))); + tournament_helper.join_tournament(tournament_id, romek_id, romek_id, fc::ecc::private_key::regenerate(fc::sha256::hash(string("romek"))), buy_in); tournament_helper.join_tournament(tournament_id, bob_id, bob_id, fc::ecc::private_key::regenerate(fc::sha256::hash(string("bob"))), buy_in); tournament_helper.join_tournament(tournament_id, carol_id, carol_id, fc::ecc::private_key::regenerate(fc::sha256::hash(string("carol"))), buy_in); + // romek leaves + tournament_helper.leave_tournament(tournament_id, romek_id, romek_id, fc::ecc::private_key::regenerate(fc::sha256::hash(string("romek")))); tournament_helper.join_tournament(tournament_id, dave_id, dave_id, fc::ecc::private_key::regenerate(fc::sha256::hash(string("dave"))), buy_in); #if TEST2_NR_OF_PLAYERS_NUMBER > 4 tournament_helper.join_tournament(tournament_id, ed_id, ed_id, fc::ecc::private_key::regenerate(fc::sha256::hash(string("ed"))), buy_in); @@ -535,12 +568,7 @@ BOOST_FIXTURE_TEST_CASE( simple, database_fixture ) #endif }; -#if 0 - // trying to randomize automatic moves ? - auto n = std::rand() % 100; - for(int i = 0; i < n ; ++i) - db.get_random_bits(3); -#endif + abc("@ tournament awaiting start"); BOOST_TEST_MESSAGE( "Generating blocks, waiting for tournaments' completion"); generate_block(); @@ -599,6 +627,7 @@ BOOST_FIXTURE_TEST_CASE( simple, database_fixture ) } #endif +#if 1 // Test of handling ties, creating two tournamenst, joinig players, // All generated moves are identical. BOOST_FIXTURE_TEST_CASE( ties, database_fixture ) @@ -711,6 +740,7 @@ BOOST_FIXTURE_TEST_CASE( ties, database_fixture ) throw; } } +#endif // Test of canceled tournament // Checking buyin refund. @@ -1074,8 +1104,8 @@ BOOST_FIXTURE_TEST_CASE( massive, database_fixture ) { try { - #define MIN_TOURNAMENTS_NUMBER 1 - #define MAX_TOURNAMENTS_NUMBER 10 + #define MIN_TOURNAMENTS_NUMBER 7 + #define MAX_TOURNAMENTS_NUMBER 13 #define MIN_PLAYERS_NUMBER 2 #define MAX_PLAYERS_NUMBER 64 @@ -1093,7 +1123,7 @@ BOOST_FIXTURE_TEST_CASE( massive, database_fixture ) // creating a pool of actors std::vector> actors; - for(unsigned i = 0; i < 2 * MAX_PLAYERS_NUMBER; ++i) + for(unsigned i = 0; i < 3 * MAX_PLAYERS_NUMBER; ++i) { std::string name = "account" + std::to_string(i); auto priv_key = generate_private_key(name); @@ -1114,14 +1144,34 @@ BOOST_FIXTURE_TEST_CASE( massive, database_fixture ) asset buy_in = asset(1000 * number_of_players + 100 * i); tournament_id_type tournament_id; tournament_id = tournament_helper.create_tournament (nathan_id, nathan_priv_key, buy_in, number_of_players, 30, 30, number_of_wins); + const tournament_object& tournament = tournament_id(db); - for (unsigned j = 0; j < actors.size() && number_of_players > 0; ++j) + for (unsigned j = 0; j < actors.size()-1 && number_of_players > 0; ++j) { if (number_of_players < actors.size() - j && std::rand() % 2 == 0) continue; auto a = actors[j]; - --number_of_players; tournament_helper.join_tournament(tournament_id, std::get<1>(a), std::get<1>(a), std::get<2>(a), buy_in); + if (j == i) + { + BOOST_TEST_MESSAGE("Player " + std::get<0>(a) + " is leaving tournament " + std::to_string(i) + + ", when tournament state is " + std::to_string((int)tournament.get_state())); + tournament_helper.leave_tournament(tournament_id, std::get<1>(a), std::get<1>(a), std::get<2>(a)); + continue; + } + --number_of_players; + if (!number_of_players) + { + BOOST_TEST_MESSAGE("Player " + std::get<0>(a) + " is leaving tournament " + std::to_string(i) + + ", when tournament state is " + std::to_string((int)tournament.get_state())); + tournament_helper.leave_tournament(tournament_id, std::get<1>(a), std::get<1>(a), std::get<2>(a)); + ++j; + a = actors[j]; + BOOST_TEST_MESSAGE("Player " + std::get<0>(a) + " is joinig tournament " + std::to_string(i) + + ", when tournament state is " + std::to_string((int)tournament.get_state())); + tournament_helper.join_tournament(tournament_id, std::get<1>(a), std::get<1>(a), std::get<2>(a), buy_in); + } } + BOOST_TEST_MESSAGE("Tournament " + std::to_string(i) + " is in state " + std::to_string((int)tournament.get_state())); } uint16_t tournaments_to_complete = number_of_tournaments;