Rework the API calls for tournaments, add an index for getting tournaments
registered by a given account
This commit is contained in:
parent
72d48cf3d2
commit
30874697cc
8 changed files with 137 additions and 65 deletions
|
|
@ -139,8 +139,8 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
||||||
vector<blinded_balance_object> get_blinded_balances( const flat_set<commitment_type>& commitments )const;
|
vector<blinded_balance_object> get_blinded_balances( const flat_set<commitment_type>& commitments )const;
|
||||||
|
|
||||||
// Tournaments
|
// Tournaments
|
||||||
vector<tournament_object> get_upcoming_tournaments(fc::optional<account_id_type> account_filter, uint32_t limit)const;
|
vector<tournament_object> get_tournaments_in_state(tournament_state state, uint32_t limit) const;
|
||||||
vector<tournament_object> get_active_tournaments(fc::optional<account_id_type> account_filter, uint32_t limit)const;
|
vector<tournament_id_type> get_registered_tournaments(account_id_type account_filter, uint32_t limit) const;
|
||||||
|
|
||||||
|
|
||||||
//private:
|
//private:
|
||||||
|
|
@ -1769,26 +1769,20 @@ vector<blinded_balance_object> database_api_impl::get_blinded_balances( const fl
|
||||||
// Tournament methods //
|
// Tournament methods //
|
||||||
// //
|
// //
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
vector<tournament_object> database_api::get_tournaments_in_state(tournament_state state, uint32_t limit) const
|
||||||
vector<tournament_object> database_api::get_upcoming_tournaments(fc::optional<account_id_type> account_filter, uint32_t limit)const
|
|
||||||
{
|
{
|
||||||
return my->get_upcoming_tournaments(account_filter, limit);
|
return my->get_tournaments_in_state(state, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<tournament_object> database_api_impl::get_upcoming_tournaments(fc::optional<account_id_type> account_filter, uint32_t limit)const
|
vector<tournament_object> database_api_impl::get_tournaments_in_state(tournament_state state, uint32_t limit) const
|
||||||
{
|
{
|
||||||
vector<tournament_object> result;
|
vector<tournament_object> result;
|
||||||
const auto& registration_deadline_index = _db.get_index_type<tournament_index>().indices().get<by_registration_deadline>();
|
const auto& registration_deadline_index = _db.get_index_type<tournament_index>().indices().get<by_registration_deadline>();
|
||||||
const auto range = registration_deadline_index.equal_range(boost::make_tuple(tournament_state::accepting_registrations));
|
const auto range = registration_deadline_index.equal_range(boost::make_tuple(state));
|
||||||
for (const tournament_object& tournament_obj : boost::make_iterator_range(range.first, range.second))
|
for (const tournament_object& tournament_obj : boost::make_iterator_range(range.first, range.second))
|
||||||
{
|
{
|
||||||
if (tournament_obj.options.whitelist.empty() ||
|
result.emplace_back(tournament_obj);
|
||||||
!account_filter ||
|
subscribe_to_item( tournament_obj.id );
|
||||||
tournament_obj.options.whitelist.find(*account_filter) != tournament_obj.options.whitelist.end())
|
|
||||||
{
|
|
||||||
result.emplace_back(tournament_obj);
|
|
||||||
subscribe_to_item( tournament_obj.id );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.size() >= limit)
|
if (result.size() >= limit)
|
||||||
break;
|
break;
|
||||||
|
|
@ -1796,39 +1790,21 @@ vector<tournament_object> database_api_impl::get_upcoming_tournaments(fc::option
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<tournament_object> database_api::get_active_tournaments(fc::optional<account_id_type> account_filter, uint32_t limit)const
|
vector<tournament_id_type> database_api::get_registered_tournaments(account_id_type account_filter, uint32_t limit) const
|
||||||
{
|
{
|
||||||
return my->get_active_tournaments(account_filter, limit);
|
return my->get_registered_tournaments(account_filter, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<tournament_object> database_api_impl::get_active_tournaments(fc::optional<account_id_type> account_filter, uint32_t limit)const
|
vector<tournament_id_type> database_api_impl::get_registered_tournaments(account_id_type account_filter, uint32_t limit) const
|
||||||
{
|
{
|
||||||
vector<tournament_object> result;
|
const auto& tournament_details_idx = _db.get_index_type<tournament_details_index>();
|
||||||
const auto& start_time_index = _db.get_index_type<tournament_index>().indices().get<by_start_time>();
|
const auto& tournament_details_primary_idx = dynamic_cast<const primary_index<tournament_details_index>&>(tournament_details_idx);
|
||||||
|
const auto& players_idx = tournament_details_primary_idx.get_secondary_index<graphene::chain::tournament_players_index>();
|
||||||
|
|
||||||
const auto begin = start_time_index.lower_bound(boost::make_tuple(tournament_state::awaiting_start));
|
vector<tournament_id_type> tournament_ids = players_idx.get_registered_tournaments_for_account(account_filter);
|
||||||
const auto end = start_time_index.upper_bound(boost::make_tuple(tournament_state::in_progress));
|
if (tournament_ids.size() >= limit)
|
||||||
for (const tournament_object& tournament_obj : boost::make_iterator_range(begin, end))
|
tournament_ids.resize(limit);
|
||||||
{
|
return tournament_ids;
|
||||||
if (account_filter)
|
|
||||||
{
|
|
||||||
const tournament_details_object& tournament_details_obj = tournament_obj.tournament_details_id(_db);
|
|
||||||
if (tournament_details_obj.registered_players.find(*account_filter) != tournament_details_obj.registered_players.end())
|
|
||||||
{
|
|
||||||
result.emplace_back(tournament_obj);
|
|
||||||
subscribe_to_item( tournament_obj.id );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.emplace_back(tournament_obj);
|
|
||||||
subscribe_to_item( tournament_obj.id );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.size() >= limit)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -553,17 +553,14 @@ class database_api
|
||||||
// Tournaments //
|
// Tournaments //
|
||||||
/////////////////
|
/////////////////
|
||||||
/**
|
/**
|
||||||
* @param account_filter if provided, this will only return tournaments the given account is
|
* @return the list of tournaments in the given state
|
||||||
* allowed to join (public tournaments or tournaments the account is whitelisted for)
|
|
||||||
* @return the list of tournaments that are still accepting new registrations
|
|
||||||
*/
|
*/
|
||||||
vector<tournament_object> get_upcoming_tournaments(fc::optional<account_id_type> account_filter, uint32_t limit)const;
|
vector<tournament_object> get_tournaments_in_state(tournament_state state, uint32_t limit) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the list of tournaments that are either in-progress or fully-registered and just waiting on their start
|
* @return the list of tournaments that a given account is registered to play in
|
||||||
* time to arrive
|
|
||||||
*/
|
*/
|
||||||
vector<tournament_object> get_active_tournaments(fc::optional<account_id_type> account_filter, uint32_t limit)const;
|
vector<tournament_id_type> get_registered_tournaments(account_id_type account_filter, uint32_t limit) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr< database_api_impl > my;
|
std::shared_ptr< database_api_impl > my;
|
||||||
|
|
@ -667,6 +664,6 @@ FC_API(graphene::app::database_api,
|
||||||
(get_blinded_balances)
|
(get_blinded_balances)
|
||||||
|
|
||||||
// Tournaments
|
// Tournaments
|
||||||
(get_upcoming_tournaments)
|
(get_tournaments_in_state)
|
||||||
(get_active_tournaments)
|
(get_registered_tournaments)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,8 @@ void database::initialize_indexes()
|
||||||
add_index< primary_index<blinded_balance_index> >();
|
add_index< primary_index<blinded_balance_index> >();
|
||||||
|
|
||||||
add_index< primary_index<tournament_index> >();
|
add_index< primary_index<tournament_index> >();
|
||||||
add_index< primary_index<tournament_details_index> >();
|
auto tournament_details_idx = add_index< primary_index<tournament_details_index> >();
|
||||||
|
tournament_details_idx->add_secondary_index<tournament_players_index>();
|
||||||
add_index< primary_index<match_index> >();
|
add_index< primary_index<match_index> >();
|
||||||
add_index< primary_index<game_index> >();
|
add_index< primary_index<game_index> >();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,9 @@ namespace graphene { namespace chain {
|
||||||
static const uint8_t space_id = protocol_ids;
|
static const uint8_t space_id = protocol_ids;
|
||||||
static const uint8_t type_id = tournament_details_object_type;
|
static const uint8_t type_id = tournament_details_object_type;
|
||||||
|
|
||||||
|
/// the tournament object for which this is the details
|
||||||
|
tournament_id_type tournament_id;
|
||||||
|
|
||||||
/// List of players registered for this tournament
|
/// List of players registered for this tournament
|
||||||
flat_set<account_id_type> registered_players;
|
flat_set<account_id_type> registered_players;
|
||||||
|
|
||||||
|
|
@ -197,9 +200,35 @@ namespace graphene { namespace chain {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This secondary index will allow a reverse lookup of all tournaments
|
||||||
|
* a particular account has registered for. This will be attached
|
||||||
|
* to the tournament details index because the registrations are contained
|
||||||
|
* in the tournament details object, but it will index the tournament ids
|
||||||
|
* since that is most useful to the GUI.
|
||||||
|
*/
|
||||||
|
class tournament_players_index : public secondary_index
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void object_inserted( const object& obj ) override;
|
||||||
|
virtual void object_removed( const object& obj ) override;
|
||||||
|
virtual void about_to_modify( const object& before ) override;
|
||||||
|
virtual void object_modified( const object& after ) override;
|
||||||
|
|
||||||
|
/** given an account, map it to the set of tournaments in which that account is registered as a player */
|
||||||
|
map< account_id_type, flat_set<tournament_id_type> > account_to_joined_tournaments;
|
||||||
|
|
||||||
|
vector<tournament_id_type> get_registered_tournaments_for_account( const account_id_type& a )const;
|
||||||
|
protected:
|
||||||
|
|
||||||
|
flat_set<account_id_type> before_account_ids;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
||||||
FC_REFLECT_DERIVED(graphene::chain::tournament_details_object, (graphene::db::object),
|
FC_REFLECT_DERIVED(graphene::chain::tournament_details_object, (graphene::db::object),
|
||||||
|
(tournament_id)
|
||||||
(registered_players)
|
(registered_players)
|
||||||
(payers)
|
(payers)
|
||||||
(matches))
|
(matches))
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,12 @@ namespace graphene { namespace chain {
|
||||||
t.tournament_details_id = tournament_details.id;
|
t.tournament_details_id = tournament_details.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: look up how to do this in the initial create
|
||||||
|
db().modify(tournament_details, [&]( tournament_details_object& a ) {
|
||||||
|
a.tournament_id = new_tournament.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
fc_ilog(fc::logger::get("tournament"),
|
fc_ilog(fc::logger::get("tournament"),
|
||||||
"Created tournament ${id} with details id ${details_id}",
|
"Created tournament ${id} with details id ${details_id}",
|
||||||
("id", new_tournament.id)("details_id", tournament_details.id));
|
("id", new_tournament.id)("details_id", tournament_details.id));
|
||||||
|
|
@ -107,7 +113,7 @@ namespace graphene { namespace chain {
|
||||||
"Registration deadline has already passed");
|
"Registration deadline has already passed");
|
||||||
|
|
||||||
FC_ASSERT(_tournament_obj->options.whitelist.empty() ||
|
FC_ASSERT(_tournament_obj->options.whitelist.empty() ||
|
||||||
_tournament_obj->options.whitelist.find(op.player_account_id) == _tournament_obj->options.whitelist.end(),
|
_tournament_obj->options.whitelist.find(op.player_account_id) != _tournament_obj->options.whitelist.end(),
|
||||||
"Player is not on the whitelist for this tournament");
|
"Player is not on the whitelist for this tournament");
|
||||||
|
|
||||||
FC_ASSERT(_tournament_details_obj->registered_players.find(op.player_account_id) == _tournament_details_obj->registered_players.end(),
|
FC_ASSERT(_tournament_details_obj->registered_players.find(op.player_account_id) == _tournament_details_obj->registered_players.end(),
|
||||||
|
|
|
||||||
|
|
@ -479,6 +479,73 @@ namespace graphene { namespace chain {
|
||||||
return fc::sha256::hash(full_throw_packed.data(), full_throw_packed.size());
|
return fc::sha256::hash(full_throw_packed.data(), full_throw_packed.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vector<tournament_id_type> tournament_players_index::get_registered_tournaments_for_account( const account_id_type& a )const
|
||||||
|
{
|
||||||
|
auto iter = account_to_joined_tournaments.find(a);
|
||||||
|
if (iter != account_to_joined_tournaments.end())
|
||||||
|
return vector<tournament_id_type>(iter->second.begin(), iter->second.end());
|
||||||
|
return vector<tournament_id_type>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tournament_players_index::object_inserted(const object& obj)
|
||||||
|
{
|
||||||
|
assert( dynamic_cast<const tournament_details_object*>(&obj) ); // for debug only
|
||||||
|
const tournament_details_object& details = static_cast<const tournament_details_object&>(obj);
|
||||||
|
|
||||||
|
for (const account_id_type& account_id : details.registered_players)
|
||||||
|
account_to_joined_tournaments[account_id].insert(details.tournament_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tournament_players_index::object_removed(const object& obj)
|
||||||
|
{
|
||||||
|
assert( dynamic_cast<const tournament_details_object*>(&obj) ); // for debug only
|
||||||
|
const tournament_details_object& details = static_cast<const tournament_details_object&>(obj);
|
||||||
|
|
||||||
|
for (const account_id_type& account_id : details.registered_players)
|
||||||
|
{
|
||||||
|
auto iter = account_to_joined_tournaments.find(account_id);
|
||||||
|
if (iter != account_to_joined_tournaments.end())
|
||||||
|
iter->second.erase(details.tournament_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tournament_players_index::about_to_modify(const object& before)
|
||||||
|
{
|
||||||
|
assert( dynamic_cast<const tournament_details_object*>(&before) ); // for debug only
|
||||||
|
const tournament_details_object& details = static_cast<const tournament_details_object&>(before);
|
||||||
|
before_account_ids = details.registered_players;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tournament_players_index::object_modified(const object& after)
|
||||||
|
{
|
||||||
|
assert( dynamic_cast<const tournament_details_object*>(&after) ); // for debug only
|
||||||
|
const tournament_details_object& details = static_cast<const tournament_details_object&>(after);
|
||||||
|
|
||||||
|
{
|
||||||
|
vector<account_id_type> newly_registered_players(details.registered_players.size());
|
||||||
|
auto end_iter = std::set_difference(details.registered_players.begin(), details.registered_players.end(),
|
||||||
|
before_account_ids.begin(), before_account_ids.end(),
|
||||||
|
newly_registered_players.begin());
|
||||||
|
newly_registered_players.resize(end_iter - newly_registered_players.begin());
|
||||||
|
for (const account_id_type& account_id : newly_registered_players)
|
||||||
|
account_to_joined_tournaments[account_id].insert(details.tournament_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
vector<account_id_type> newly_unregistered_players(before_account_ids.size());
|
||||||
|
auto end_iter = std::set_difference(before_account_ids.begin(), before_account_ids.end(),
|
||||||
|
details.registered_players.begin(), details.registered_players.end(),
|
||||||
|
newly_unregistered_players.begin());
|
||||||
|
newly_unregistered_players.resize(end_iter - newly_unregistered_players.begin());
|
||||||
|
for (const account_id_type& account_id : newly_unregistered_players)
|
||||||
|
{
|
||||||
|
auto iter = account_to_joined_tournaments.find(account_id);
|
||||||
|
if (iter != account_to_joined_tournaments.end())
|
||||||
|
iter->second.erase(details.tournament_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
|
|
|
||||||
|
|
@ -1422,10 +1422,9 @@ 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 );
|
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 );
|
||||||
|
|
||||||
/** Get a list of upcoming tournaments
|
/** Get a list of upcoming tournaments
|
||||||
* @param player_accounts if non-empty, only return tournaments for which at least one of the named players is eligible. If empty, return all tournaments
|
|
||||||
* @param limit the number of tournaments to return
|
* @param limit the number of tournaments to return
|
||||||
*/
|
*/
|
||||||
vector<tournament_object> get_upcoming_tournaments(optional<string> player_accounts, uint32_t limit);
|
vector<tournament_object> get_upcoming_tournaments(uint32_t limit);
|
||||||
|
|
||||||
/** Get specific information about a tournament
|
/** Get specific information about a tournament
|
||||||
* @param tournament_id the ID of the tournament
|
* @param tournament_id the ID of the tournament
|
||||||
|
|
|
||||||
|
|
@ -951,12 +951,12 @@ public:
|
||||||
game_cache.clear();
|
game_cache.clear();
|
||||||
for (const account_object& my_account : _wallet.my_accounts)
|
for (const account_object& my_account : _wallet.my_accounts)
|
||||||
{
|
{
|
||||||
std::vector<tournament_object> tournaments = _remote_db->get_active_tournaments(my_account.id, 100);
|
std::vector<tournament_id_type> tournament_ids = _remote_db->get_registered_tournaments(my_account.id, 100);
|
||||||
std::vector<tournament_id_type> tournament_ids;
|
for (const tournament_id_type& tournament_id : tournament_ids)
|
||||||
for (const tournament_object& tournament : tournaments)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
tournament_object tournament = get_object<tournament_object>(tournament_id);
|
||||||
auto insert_result = tournament_cache.insert(tournament);
|
auto insert_result = tournament_cache.insert(tournament);
|
||||||
if (insert_result.second)
|
if (insert_result.second)
|
||||||
{
|
{
|
||||||
|
|
@ -967,10 +967,10 @@ public:
|
||||||
}
|
}
|
||||||
catch (const fc::exception& e)
|
catch (const fc::exception& e)
|
||||||
{
|
{
|
||||||
edump((e)(tournament));
|
edump((e)(tournament_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tournaments.empty())
|
if (!tournament_ids.empty())
|
||||||
ilog("Account ${my_account} is registered for tournaments: ${tournaments}", ("my_account", my_account.name)("tournaments", tournament_ids));
|
ilog("Account ${my_account} is registered for tournaments: ${tournaments}", ("my_account", my_account.name)("tournaments", tournament_ids));
|
||||||
else
|
else
|
||||||
ilog("Account ${my_account} is not registered for any tournaments", ("my_account", my_account.name));
|
ilog("Account ${my_account} is not registered for any tournaments", ("my_account", my_account.name));
|
||||||
|
|
@ -4552,12 +4552,9 @@ signed_transaction wallet_api::tournament_join( string payer_account,
|
||||||
return my->sign_transaction( tx, broadcast );
|
return my->sign_transaction( tx, broadcast );
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<tournament_object> wallet_api::get_upcoming_tournaments(fc::optional<string> player_account, uint32_t limit)
|
vector<tournament_object> wallet_api::get_upcoming_tournaments(uint32_t limit)
|
||||||
{
|
{
|
||||||
fc::optional<account_id_type> player_account_id;
|
return my->_remote_db->get_tournaments_in_state(tournament_state::accepting_registrations, limit);
|
||||||
if (player_account)
|
|
||||||
player_account_id = get_account(*player_account).id;
|
|
||||||
return my->_remote_db->get_upcoming_tournaments(player_account_id, limit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tournament_object wallet_api::get_tournament(tournament_id_type id)
|
tournament_object wallet_api::get_tournament(tournament_id_type id)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue