From a8a64e530b419555975807d46a17b38d64531ad6 Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Thu, 6 Jul 2017 18:07:39 -0400 Subject: [PATCH] Add an informational betting_market_rules object, linked to betting market groups --- libraries/app/impacted.cpp | 1 + libraries/chain/betting_market_evaluator.cpp | 29 ++++++++++++++++ libraries/chain/db_init.cpp | 5 +++ libraries/chain/db_notify.cpp | 1 + .../chain/betting_market_evaluator.hpp | 10 ++++++ .../graphene/chain/betting_market_object.hpp | 21 ++++++++++++ .../chain/protocol/betting_market.hpp | 33 +++++++++++++++++++ .../graphene/chain/protocol/operations.hpp | 1 + .../include/graphene/chain/protocol/types.hpp | 5 +++ libraries/chain/protocol/betting_market.cpp | 5 +++ tests/betting/betting_tests.cpp | 3 +- tests/common/database_fixture.cpp | 13 +++++++- tests/common/database_fixture.hpp | 3 +- 13 files changed, 127 insertions(+), 3 deletions(-) diff --git a/libraries/app/impacted.cpp b/libraries/app/impacted.cpp index e2a22937..15bbcb09 100644 --- a/libraries/app/impacted.cpp +++ b/libraries/app/impacted.cpp @@ -206,6 +206,7 @@ struct get_impacted_account_visitor void operator()( const sport_create_operation& op ) {} void operator()( const event_group_create_operation& op ) {} void operator()( const event_create_operation& op ) {} + void operator()( const betting_market_rules_create_operation& op ) {} void operator()( const betting_market_group_create_operation& op ) {} void operator()( const betting_market_create_operation& op ) {} void operator()( const betting_market_resolve_operation& op ) {} diff --git a/libraries/chain/betting_market_evaluator.cpp b/libraries/chain/betting_market_evaluator.cpp index fe19f7b4..00904816 100644 --- a/libraries/chain/betting_market_evaluator.cpp +++ b/libraries/chain/betting_market_evaluator.cpp @@ -31,6 +31,22 @@ namespace graphene { namespace chain { +void_result betting_market_rules_create_evaluator::do_evaluate(const betting_market_rules_create_operation& op) +{ try { + FC_ASSERT(trx_state->_is_proposed_trx); + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + +object_id_type betting_market_rules_create_evaluator::do_apply(const betting_market_rules_create_operation& op) +{ try { + const betting_market_rules_object& new_betting_market_rules = + db().create( [&]( betting_market_rules_object& betting_market_rules_obj ) { + betting_market_rules_obj.name = op.name; + betting_market_rules_obj.description = op.description; + }); + return new_betting_market_rules.id; +} FC_CAPTURE_AND_RETHROW( (op) ) } + void_result betting_market_group_create_evaluator::do_evaluate(const betting_market_group_create_operation& op) { try { FC_ASSERT(trx_state->_is_proposed_trx); @@ -46,6 +62,18 @@ void_result betting_market_group_create_evaluator::do_evaluate(const betting_mar "event_id must refer to a event_id_type"); event_id = resolved_event_id; FC_ASSERT( db().find_object(event_id), "Invalid event specified" ); + + // the rules_id in the operation can be a relative id. If it is, + // resolve it and verify that it is truly rules + object_id_type resolved_rules_id = op.rules_id; + if (is_relative(op.rules_id)) + resolved_rules_id = get_relative_id(op.rules_id); + + FC_ASSERT(resolved_rules_id.space() == betting_market_rules_id_type::space_id && + resolved_rules_id.type() == betting_market_rules_id_type::type_id, + "rules_id must refer to a betting_market_rules_id_type"); + rules_id = resolved_rules_id; + FC_ASSERT( db().find_object(rules_id), "Invalid rules specified" ); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -54,6 +82,7 @@ object_id_type betting_market_group_create_evaluator::do_apply(const betting_mar const betting_market_group_object& new_betting_market_group = db().create( [&]( betting_market_group_object& betting_market_group_obj ) { betting_market_group_obj.event_id = event_id; + betting_market_group_obj.rules_id = rules_id; betting_market_group_obj.description = op.description; }); return new_betting_market_group.id; diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index a87d4f45..9165fca6 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -146,6 +146,9 @@ const uint8_t event_group_object::type_id; const uint8_t event_object::space_id; const uint8_t event_object::type_id; +const uint8_t betting_market_rules_object::space_id; +const uint8_t betting_market_rules_object::type_id; + const uint8_t betting_market_group_object::space_id; const uint8_t betting_market_group_object::type_id; @@ -209,6 +212,7 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); + register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); @@ -244,6 +248,7 @@ void database::initialize_indexes() add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); + add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index dd0354ca..d923a9fe 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -188,6 +188,7 @@ struct get_impacted_account_visitor void operator()(const sport_create_operation&){} void operator()(const event_group_create_operation&){} void operator()(const event_create_operation&){} + void operator()(const betting_market_rules_create_operation&){} void operator()(const betting_market_group_create_operation&){} void operator()(const betting_market_create_operation&){} void operator()(const bet_place_operation&){} diff --git a/libraries/chain/include/graphene/chain/betting_market_evaluator.hpp b/libraries/chain/include/graphene/chain/betting_market_evaluator.hpp index bae04611..979c3dbe 100644 --- a/libraries/chain/include/graphene/chain/betting_market_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/betting_market_evaluator.hpp @@ -29,6 +29,15 @@ namespace graphene { namespace chain { + class betting_market_rules_create_evaluator : public evaluator + { + public: + typedef betting_market_rules_create_operation operation_type; + + void_result do_evaluate( const betting_market_rules_create_operation& o ); + object_id_type do_apply( const betting_market_rules_create_operation& o ); + }; + class betting_market_group_create_evaluator : public evaluator { public: @@ -38,6 +47,7 @@ namespace graphene { namespace chain { object_id_type do_apply( const betting_market_group_create_operation& o ); private: event_id_type event_id; + betting_market_rules_id_type rules_id; }; class betting_market_create_evaluator : public evaluator diff --git a/libraries/chain/include/graphene/chain/betting_market_object.hpp b/libraries/chain/include/graphene/chain/betting_market_object.hpp index 77bbc680..f1e13661 100644 --- a/libraries/chain/include/graphene/chain/betting_market_object.hpp +++ b/libraries/chain/include/graphene/chain/betting_market_object.hpp @@ -37,6 +37,17 @@ class database; struct by_event_id; struct by_betting_market_group_id; +class betting_market_rules_object : public graphene::db::abstract_object< betting_market_rules_object > +{ + public: + static const uint8_t space_id = protocol_ids; + static const uint8_t type_id = betting_market_rules_object_type; + + internationalized_string_type name; + + internationalized_string_type description; +}; + class betting_market_group_object : public graphene::db::abstract_object< betting_market_group_object > { public: @@ -46,6 +57,8 @@ class betting_market_group_object : public graphene::db::abstract_object< bettin internationalized_string_type description; event_id_type event_id; + + betting_market_rules_id_type rules_id; }; class betting_market_object : public graphene::db::abstract_object< betting_market_object > @@ -104,6 +117,13 @@ class betting_market_position_object : public graphene::db::abstract_object< bet share_type reduce(); }; +typedef multi_index_container< + betting_market_rules_object, + indexed_by< + ordered_unique< tag, member< object, object_id_type, &object::id > > + > > betting_market_rules_object_multi_index_type; +typedef generic_index betting_market_rules_object_index; + typedef multi_index_container< betting_market_group_object, indexed_by< @@ -404,6 +424,7 @@ typedef multi_index_container< typedef generic_index betting_market_position_index; } } // graphene::chain +FC_REFLECT_DERIVED( graphene::chain::betting_market_rules_object, (graphene::db::object), (name)(description) ) FC_REFLECT_DERIVED( graphene::chain::betting_market_group_object, (graphene::db::object), (event_id)(description) ) FC_REFLECT_DERIVED( graphene::chain::betting_market_object, (graphene::db::object), (group_id)(description)(payout_condition)(asset_id) ) FC_REFLECT_DERIVED( graphene::chain::bet_object, (graphene::db::object), (bettor_id)(betting_market_id)(amount_to_bet)(backer_multiplier)(amount_reserved_for_fees)(back_or_lay) ) diff --git a/libraries/chain/include/graphene/chain/protocol/betting_market.hpp b/libraries/chain/include/graphene/chain/protocol/betting_market.hpp index e35c1bd1..bfd9b492 100644 --- a/libraries/chain/include/graphene/chain/protocol/betting_market.hpp +++ b/libraries/chain/include/graphene/chain/protocol/betting_market.hpp @@ -28,6 +28,29 @@ namespace graphene { namespace chain { +struct betting_market_rules_create_operation : public base_operation +{ + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; + asset fee; + + /** + * A short name for the rules, like "Premier League Rules 1.0", probably not + * displayed to the user + */ + internationalized_string_type name; + + /** + * The full text of the rules to be displayed to the user. As yet, there is + * no standard format (html, markdown, etc) + */ + internationalized_string_type description; + + extensions_type extensions; + + account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + void validate()const; +}; + struct betting_market_group_create_operation : public base_operation { struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -45,6 +68,12 @@ struct betting_market_group_create_operation : public base_operation */ object_id_type event_id; + /** + * This can be a betting_market_rules_id_type, or a + * relative object id that resolves to a betting_market_rules_id_type + */ + object_id_type rules_id; + extensions_type extensions; account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } @@ -246,6 +275,10 @@ struct bet_canceled_operation : public base_operation } } +FC_REFLECT( graphene::chain::betting_market_rules_create_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::betting_market_rules_create_operation, + (fee)(name)(description)(extensions) ) + FC_REFLECT( graphene::chain::betting_market_group_create_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::betting_market_group_create_operation, (fee)(description)(event_id)(extensions) ) diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index f2cc8edc..c6d7e35c 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -99,6 +99,7 @@ namespace graphene { namespace chain { sport_create_operation, event_group_create_operation, event_create_operation, + betting_market_rules_create_operation, betting_market_group_create_operation, betting_market_create_operation, bet_place_operation, diff --git a/libraries/chain/include/graphene/chain/protocol/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp index 39327356..c99487ce 100644 --- a/libraries/chain/include/graphene/chain/protocol/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -137,6 +137,7 @@ namespace graphene { namespace chain { sport_object_type, event_group_object_type, event_object_type, + betting_market_rules_object_type, betting_market_group_object_type, betting_market_object_type, bet_object_type, @@ -186,6 +187,7 @@ namespace graphene { namespace chain { class sport_object; class event_group_object; class event_object; + class betting_market_rules_object; class betting_market_group_object; class betting_market_object; class bet_object; @@ -207,6 +209,7 @@ namespace graphene { namespace chain { typedef object_id< protocol_ids, sport_object_type, sport_object> sport_id_type; typedef object_id< protocol_ids, event_group_object_type, event_group_object> event_group_id_type; typedef object_id< protocol_ids, event_object_type, event_object> event_id_type; + typedef object_id< protocol_ids, betting_market_rules_object_type, betting_market_rules_object> betting_market_rules_id_type; typedef object_id< protocol_ids, betting_market_group_object_type, betting_market_group_object> betting_market_group_id_type; typedef object_id< protocol_ids, betting_market_object_type, betting_market_object> betting_market_id_type; typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type; @@ -371,6 +374,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type, (sport_object_type) (event_group_object_type) (event_object_type) + (betting_market_rules_object_type) (betting_market_group_object_type) (betting_market_object_type) (bet_object_type) @@ -417,6 +421,7 @@ FC_REFLECT_TYPENAME( graphene::chain::balance_id_type ) FC_REFLECT_TYPENAME( graphene::chain::sport_id_type ) FC_REFLECT_TYPENAME( graphene::chain::event_group_id_type ) FC_REFLECT_TYPENAME( graphene::chain::event_id_type ) +FC_REFLECT_TYPENAME( graphene::chain::betting_market_rules_id_type ) FC_REFLECT_TYPENAME( graphene::chain::betting_market_group_id_type ) FC_REFLECT_TYPENAME( graphene::chain::betting_market_id_type ) FC_REFLECT_TYPENAME( graphene::chain::bet_id_type ) diff --git a/libraries/chain/protocol/betting_market.cpp b/libraries/chain/protocol/betting_market.cpp index b0578c53..fab9f724 100644 --- a/libraries/chain/protocol/betting_market.cpp +++ b/libraries/chain/protocol/betting_market.cpp @@ -25,6 +25,11 @@ namespace graphene { namespace chain { +void betting_market_rules_create_operation::validate() const +{ + FC_ASSERT( fee.amount >= 0 ); +} + void betting_market_group_create_operation::validate() const { FC_ASSERT( fee.amount >= 0 ); diff --git a/tests/betting/betting_tests.cpp b/tests/betting/betting_tests.cpp index 6ab92ba1..05bf8d67 100644 --- a/tests/betting/betting_tests.cpp +++ b/tests/betting/betting_tests.cpp @@ -49,7 +49,8 @@ BOOST_FIXTURE_TEST_SUITE( betting_tests, database_fixture ) const sport_object& ice_hockey = create_sport({{"en", "Ice Hockey"}, {"zh_Hans", "冰球"}, {"ja", "アイスホッケー"}}); \ const event_group_object& nhl = create_event_group({{"en", "NHL"}, {"zh_Hans", "國家冰球聯盟"}, {"ja", "ナショナルホッケーリーグ"}}, ice_hockey.id); \ const event_object& capitals_vs_blackhawks = create_event({{"en", "Washington Capitals/Chicago Blackhawks"}, {"zh_Hans", "華盛頓首都隊/芝加哥黑鷹"}, {"ja", "ワシントン・キャピタルズ/シカゴ・ブラックホークス"}}, {{"en", "2016-17"}}, nhl.id); \ - const betting_market_group_object& moneyline_betting_markets = create_betting_market_group({{"en", "Moneyline"}}, capitals_vs_blackhawks.id); \ + const betting_market_rules_object& betting_market_rules = create_betting_market_rules({{"en", "NHL Rules v1.0"}}, {{"en", "The winner will be the team with the most points at the end of the game. The team with fewer points will not be the winner."}}); \ + const betting_market_group_object& moneyline_betting_markets = create_betting_market_group({{"en", "Moneyline"}}, capitals_vs_blackhawks.id, betting_market_rules.id); \ const betting_market_object& capitals_win_market = create_betting_market(moneyline_betting_markets.id, {{"en", "Washington Capitals win"}}, asset_id_type()); \ const betting_market_object& blackhawks_win_market = create_betting_market(moneyline_betting_markets.id, {{"en", "Chicago Blackhawks win"}}, asset_id_type()); diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 486324c1..2416c882 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -1150,11 +1150,22 @@ const event_object& database_fixture::create_event(internationalized_string_type return *event_index.rbegin(); } FC_CAPTURE_AND_RETHROW( (event_group_id) ) } -const betting_market_group_object& database_fixture::create_betting_market_group(internationalized_string_type description, event_id_type event_id) +const betting_market_rules_object& database_fixture::create_betting_market_rules(internationalized_string_type name, internationalized_string_type description) +{ try { + betting_market_rules_create_operation betting_market_rules_create_op; + betting_market_rules_create_op.name = name; + betting_market_rules_create_op.description = description; + process_operation_by_witnesses(betting_market_rules_create_op); + const auto& betting_market_rules_index = db.get_index_type().indices().get(); + return *betting_market_rules_index.rbegin(); +} FC_CAPTURE_AND_RETHROW( (name) ) } + +const betting_market_group_object& database_fixture::create_betting_market_group(internationalized_string_type description, event_id_type event_id, betting_market_rules_id_type rules_id) { try { betting_market_group_create_operation betting_market_group_create_op; betting_market_group_create_op.description = description; betting_market_group_create_op.event_id = event_id; + betting_market_group_create_op.rules_id = rules_id; process_operation_by_witnesses(betting_market_group_create_op); const auto& betting_market_group_index = db.get_index_type().indices().get(); return *betting_market_group_index.rbegin(); diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index 50d7ea30..717ab685 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -285,7 +285,8 @@ struct database_fixture { const sport_object& create_sport(internationalized_string_type name); const event_group_object& create_event_group(internationalized_string_type name, sport_id_type sport_id); const event_object& create_event(internationalized_string_type name, internationalized_string_type season, event_group_id_type event_group_id); - const betting_market_group_object& create_betting_market_group(internationalized_string_type description, event_id_type event_id); + const betting_market_rules_object& create_betting_market_rules(internationalized_string_type name, internationalized_string_type description); + const betting_market_group_object& create_betting_market_group(internationalized_string_type description, event_id_type event_id, betting_market_rules_id_type rules_id); const betting_market_object& create_betting_market(betting_market_group_id_type group_id, internationalized_string_type payout_condition, asset_id_type asset_id); void place_bet(account_id_type bettor_id, betting_market_id_type betting_market_id, bet_type back_or_lay, asset amount_to_bet, bet_multiplier_type backer_multiplier, share_type amount_reserved_for_fees);