Moved most of the logic for joining tournament into tournament_object
This commit is contained in:
parent
84a43f9a3c
commit
da43a8712d
6 changed files with 75 additions and 49 deletions
|
|
@ -75,6 +75,7 @@ add_library( graphene_chain
|
||||||
market_evaluator.cpp
|
market_evaluator.cpp
|
||||||
vesting_balance_evaluator.cpp
|
vesting_balance_evaluator.cpp
|
||||||
tournament_evaluator.cpp
|
tournament_evaluator.cpp
|
||||||
|
tournament_object.cpp
|
||||||
withdraw_permission_evaluator.cpp
|
withdraw_permission_evaluator.cpp
|
||||||
worker_evaluator.cpp
|
worker_evaluator.cpp
|
||||||
confidential_evaluator.cpp
|
confidential_evaluator.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
|
// this index is sorted on state and deadline, so the tournaments awaiting registrations with the earliest
|
||||||
// deadlines will be at the beginning
|
// deadlines will be at the beginning
|
||||||
while (registration_deadline_index.empty() &&
|
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())
|
registration_deadline_index.begin()->options.registration_deadline <= head_block_time())
|
||||||
{
|
{
|
||||||
const tournament_object& tournament_obj = *registration_deadline_index.begin();
|
const tournament_object& tournament_obj = *registration_deadline_index.begin();
|
||||||
|
|
@ -484,20 +484,8 @@ void database::update_tournaments()
|
||||||
"Canceling tournament ${id} because its deadline expired",
|
"Canceling tournament ${id} because its deadline expired",
|
||||||
("id", tournament_obj.id));
|
("id", tournament_obj.id));
|
||||||
// cancel this tournament
|
// 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) {
|
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
|
// 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));
|
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())
|
*start_iter->start_time <= head_block_time())
|
||||||
{
|
{
|
||||||
modify(*start_iter, [&](tournament_object& t) {
|
modify(*start_iter, [&](tournament_object& t) {
|
||||||
t.state = tournament_state::in_progress;
|
t.on_start_time_arrived();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -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
|
/// The winner of a round in the tournament is the first to reach this number of wins
|
||||||
uint32_t 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
|
/// Parameters that are specific to the type_of_game in this tournament
|
||||||
game_specific_options game_options;
|
game_specific_options game_options;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,8 @@ namespace graphene { namespace chain {
|
||||||
worker_object_type,
|
worker_object_type,
|
||||||
balance_object_type,
|
balance_object_type,
|
||||||
tournament_object_type,
|
tournament_object_type,
|
||||||
|
match_object_type,
|
||||||
|
game_object_type,
|
||||||
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
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 balance_object;
|
||||||
class blinded_balance_object;
|
class blinded_balance_object;
|
||||||
class tournament_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, account_object_type, account_object> account_id_type;
|
||||||
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_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, 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, 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, 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
|
// implementation types
|
||||||
class global_property_object;
|
class global_property_object;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ namespace graphene { namespace chain {
|
||||||
accepting_registrations,
|
accepting_registrations,
|
||||||
awaiting_start,
|
awaiting_start,
|
||||||
in_progress,
|
in_progress,
|
||||||
registration_period_expired
|
registration_period_expired,
|
||||||
|
concluded
|
||||||
};
|
};
|
||||||
|
|
||||||
class tournament_object : public graphene::db::abstract_object<tournament_object>
|
class tournament_object : public graphene::db::abstract_object<tournament_object>
|
||||||
|
|
@ -36,6 +37,11 @@ namespace graphene { namespace chain {
|
||||||
public:
|
public:
|
||||||
static const uint8_t space_id = protocol_ids;
|
static const uint8_t space_id = protocol_ids;
|
||||||
static const uint8_t type_id = tournament_object_type;
|
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
|
/// the account that created this tournament
|
||||||
account_id_type creator;
|
account_id_type creator;
|
||||||
|
|
@ -59,15 +65,51 @@ namespace graphene { namespace chain {
|
||||||
uint32_t registered_players = 0;
|
uint32_t registered_players = 0;
|
||||||
|
|
||||||
/// The current high-level status of the tournament (whether it is currently running or has been canceled, etc)
|
/// 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
|
/// Detailed information on this tournament
|
||||||
tournament_details_id_type tournament_details_id;
|
tournament_details_id_type tournament_details_id;
|
||||||
|
|
||||||
|
tournament_state get_state() const;
|
||||||
|
|
||||||
time_point_sec get_registration_deadline() const { return options.registration_deadline; }
|
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<impl> my;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class match_object : public graphene::db::abstract_object<match_object>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const uint8_t space_id = protocol_ids;
|
||||||
|
static const uint8_t type_id = match_object_type;
|
||||||
|
|
||||||
|
///
|
||||||
|
flat_set<account_id_type> players;
|
||||||
|
|
||||||
|
vector<flat_set<account_id_type> > game_winners;
|
||||||
|
};
|
||||||
|
|
||||||
|
class game_object : public graphene::db::abstract_object<game_object>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const uint8_t space_id = protocol_ids;
|
||||||
|
static const uint8_t type_id = game_object_type;
|
||||||
|
|
||||||
|
flat_set<account_id_type> players;
|
||||||
|
|
||||||
|
flat_set<account_id_type> winners;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct by_registration_deadline {};
|
struct by_registration_deadline {};
|
||||||
struct by_start_time {};
|
struct by_start_time {};
|
||||||
typedef multi_index_container<
|
typedef multi_index_container<
|
||||||
|
|
@ -76,11 +118,11 @@ namespace graphene { namespace chain {
|
||||||
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
||||||
ordered_non_unique< tag<by_registration_deadline>,
|
ordered_non_unique< tag<by_registration_deadline>,
|
||||||
composite_key<tournament_object,
|
composite_key<tournament_object,
|
||||||
member<tournament_object, tournament_state, &tournament_object::state>,
|
const_mem_fun<tournament_object, tournament_state, &tournament_object::get_state>,
|
||||||
const_mem_fun<tournament_object, time_point_sec, &tournament_object::get_registration_deadline> > >,
|
const_mem_fun<tournament_object, time_point_sec, &tournament_object::get_registration_deadline> > >,
|
||||||
ordered_non_unique< tag<by_start_time>,
|
ordered_non_unique< tag<by_start_time>,
|
||||||
composite_key<tournament_object,
|
composite_key<tournament_object,
|
||||||
member<tournament_object, tournament_state, &tournament_object::state>,
|
const_mem_fun<tournament_object, tournament_state, &tournament_object::get_state>,
|
||||||
member<tournament_object, optional<time_point_sec>, &tournament_object::start_time> > >
|
member<tournament_object, optional<time_point_sec>, &tournament_object::start_time> > >
|
||||||
>
|
>
|
||||||
> tournament_object_multi_index_type;
|
> tournament_object_multi_index_type;
|
||||||
|
|
@ -97,10 +139,11 @@ FC_REFLECT_DERIVED(graphene::chain::tournament_object, (graphene::db::object),
|
||||||
(start_time)
|
(start_time)
|
||||||
(end_time)
|
(end_time)
|
||||||
(prize_pool)
|
(prize_pool)
|
||||||
(state)
|
|
||||||
(tournament_details_id))
|
(tournament_details_id))
|
||||||
FC_REFLECT_ENUM(graphene::chain::tournament_state,
|
FC_REFLECT_ENUM(graphene::chain::tournament_state,
|
||||||
(accepting_registrations)
|
(accepting_registrations)
|
||||||
(awaiting_start)
|
(awaiting_start)
|
||||||
(in_progress)
|
(in_progress)
|
||||||
(registration_period_expired))
|
(registration_period_expired)
|
||||||
|
(concluded))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,12 +72,15 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
object_id_type tournament_create_evaluator::do_apply( const tournament_create_operation& op )
|
object_id_type tournament_create_evaluator::do_apply( const tournament_create_operation& op )
|
||||||
{ try {
|
{ try {
|
||||||
|
const tournament_details_object& tournament_details =
|
||||||
|
db().create<tournament_details_object>( [&]( tournament_details_object& a ) {
|
||||||
|
});
|
||||||
|
|
||||||
const tournament_object& new_tournament =
|
const tournament_object& new_tournament =
|
||||||
db().create<tournament_object>( [&]( tournament_object& t ) {
|
db().create<tournament_object>( [&]( tournament_object& t ) {
|
||||||
t.options = op.options;
|
t.options = op.options;
|
||||||
t.creator = op.creator;
|
t.creator = op.creator;
|
||||||
t.state = tournament_state::accepting_registrations;
|
t.tournament_details_id = tournament_details.id;
|
||||||
// t.dynamic_tournament_data_id = dyn_tournament.id;
|
|
||||||
});
|
});
|
||||||
return new_tournament.id;
|
return new_tournament.id;
|
||||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
@ -91,7 +94,7 @@ namespace graphene { namespace chain {
|
||||||
//const account_object& player_account = op.player_account_id(d);
|
//const account_object& player_account = op.player_account_id(d);
|
||||||
_buy_in_asset_type = &op.buy_in.asset_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,
|
FC_ASSERT(_tournament_details_obj->registered_players.size() < _tournament_obj->options.number_of_players,
|
||||||
"Tournament is already full");
|
"Tournament is already full");
|
||||||
FC_ASSERT(d.head_block_time() <= _tournament_obj->options.registration_deadline,
|
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 )
|
void_result tournament_join_evaluator::do_apply( const tournament_join_operation& op )
|
||||||
{ try {
|
{ 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){
|
db().modify(*_tournament_obj, [&](tournament_object& tournament_obj){
|
||||||
++tournament_obj.registered_players;
|
tournament_obj.on_player_registered(db(), op.payer_account_id, op.player_account_id);
|
||||||
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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return void_result();
|
return void_result();
|
||||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue