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;
|
||||
|
||||
// Tournaments
|
||||
vector<tournament_object> get_upcoming_tournaments(fc::optional<account_id_type> account_filter, uint32_t limit)const;
|
||||
vector<tournament_object> get_active_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_id_type> get_registered_tournaments(account_id_type account_filter, uint32_t limit) const;
|
||||
|
||||
|
||||
//private:
|
||||
|
|
@ -1769,26 +1769,20 @@ vector<blinded_balance_object> database_api_impl::get_blinded_balances( const fl
|
|||
// Tournament methods //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
vector<tournament_object> database_api::get_upcoming_tournaments(fc::optional<account_id_type> account_filter, uint32_t limit)const
|
||||
vector<tournament_object> database_api::get_tournaments_in_state(tournament_state state, 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;
|
||||
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))
|
||||
{
|
||||
if (tournament_obj.options.whitelist.empty() ||
|
||||
!account_filter ||
|
||||
tournament_obj.options.whitelist.find(*account_filter) != tournament_obj.options.whitelist.end())
|
||||
{
|
||||
result.emplace_back(tournament_obj);
|
||||
subscribe_to_item( tournament_obj.id );
|
||||
}
|
||||
result.emplace_back(tournament_obj);
|
||||
subscribe_to_item( tournament_obj.id );
|
||||
|
||||
if (result.size() >= limit)
|
||||
break;
|
||||
|
|
@ -1796,39 +1790,21 @@ vector<tournament_object> database_api_impl::get_upcoming_tournaments(fc::option
|
|||
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& start_time_index = _db.get_index_type<tournament_index>().indices().get<by_start_time>();
|
||||
const auto& tournament_details_idx = _db.get_index_type<tournament_details_index>();
|
||||
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));
|
||||
const auto end = start_time_index.upper_bound(boost::make_tuple(tournament_state::in_progress));
|
||||
for (const tournament_object& tournament_obj : boost::make_iterator_range(begin, end))
|
||||
{
|
||||
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;
|
||||
vector<tournament_id_type> tournament_ids = players_idx.get_registered_tournaments_for_account(account_filter);
|
||||
if (tournament_ids.size() >= limit)
|
||||
tournament_ids.resize(limit);
|
||||
return tournament_ids;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -553,17 +553,14 @@ class database_api
|
|||
// Tournaments //
|
||||
/////////////////
|
||||
/**
|
||||
* @param account_filter if provided, this will only return tournaments the given account is
|
||||
* allowed to join (public tournaments or tournaments the account is whitelisted for)
|
||||
* @return the list of tournaments that are still accepting new registrations
|
||||
* @return the list of tournaments in the given state
|
||||
*/
|
||||
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
|
||||
* time to arrive
|
||||
* @return the list of tournaments that a given account is registered to play in
|
||||
*/
|
||||
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:
|
||||
std::shared_ptr< database_api_impl > my;
|
||||
|
|
@ -667,6 +664,6 @@ FC_API(graphene::app::database_api,
|
|||
(get_blinded_balances)
|
||||
|
||||
// Tournaments
|
||||
(get_upcoming_tournaments)
|
||||
(get_active_tournaments)
|
||||
(get_tournaments_in_state)
|
||||
(get_registered_tournaments)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -208,7 +208,8 @@ void database::initialize_indexes()
|
|||
add_index< primary_index<blinded_balance_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<game_index> >();
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ namespace graphene { namespace chain {
|
|||
static const uint8_t space_id = protocol_ids;
|
||||
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
|
||||
flat_set<account_id_type> registered_players;
|
||||
|
||||
|
|
@ -197,9 +200,35 @@ namespace graphene { namespace chain {
|
|||
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),
|
||||
(tournament_id)
|
||||
(registered_players)
|
||||
(payers)
|
||||
(matches))
|
||||
|
|
|
|||
|
|
@ -84,6 +84,12 @@ namespace graphene { namespace chain {
|
|||
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"),
|
||||
"Created tournament ${id} with details id ${details_id}",
|
||||
("id", new_tournament.id)("details_id", tournament_details.id));
|
||||
|
|
@ -107,7 +113,7 @@ namespace graphene { namespace chain {
|
|||
"Registration deadline has already passed");
|
||||
|
||||
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");
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
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 );
|
||||
|
||||
/** 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
|
||||
*/
|
||||
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
|
||||
* @param tournament_id the ID of the tournament
|
||||
|
|
|
|||
|
|
@ -951,12 +951,12 @@ public:
|
|||
game_cache.clear();
|
||||
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;
|
||||
for (const tournament_object& tournament : tournaments)
|
||||
std::vector<tournament_id_type> tournament_ids = _remote_db->get_registered_tournaments(my_account.id, 100);
|
||||
for (const tournament_id_type& tournament_id : tournament_ids)
|
||||
{
|
||||
try
|
||||
{
|
||||
tournament_object tournament = get_object<tournament_object>(tournament_id);
|
||||
auto insert_result = tournament_cache.insert(tournament);
|
||||
if (insert_result.second)
|
||||
{
|
||||
|
|
@ -967,10 +967,10 @@ public:
|
|||
}
|
||||
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));
|
||||
else
|
||||
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 );
|
||||
}
|
||||
|
||||
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;
|
||||
if (player_account)
|
||||
player_account_id = get_account(*player_account).id;
|
||||
return my->_remote_db->get_upcoming_tournaments(player_account_id, limit);
|
||||
return my->_remote_db->get_tournaments_in_state(tournament_state::accepting_registrations, limit);
|
||||
}
|
||||
|
||||
tournament_object wallet_api::get_tournament(tournament_id_type id)
|
||||
|
|
|
|||
Loading…
Reference in a new issue