Scorum
invariants_validation.cpp
Go to the documentation of this file.
1 #include <boost/fusion/include/map.hpp>
2 #include <boost/fusion/include/at_key.hpp>
3 #include <boost/range/algorithm/set_algorithm.hpp>
4 #include <boost/range/algorithm/transform.hpp>
8 
9 namespace scorum {
10 namespace protocol {
11 
12 namespace bf = boost::fusion;
13 
14 // clang-format off
15 const bf::map<bf::pair<soccer_game, std::set<market_kind>>, bf::pair<hockey_game, std::set<market_kind>>> game_markets(
16  bf::make_pair<soccer_game>(std::set<market_kind>{
24  }),
25  bf::make_pair<hockey_game>(std::set<market_kind>{ //This type for tests purpose only. Now we have markets table for soccer only
28  }));
29 // clang-format on
30 
31 void validate_game(const game_type& game, const fc::flat_set<market_type>& markets)
32 {
33  const auto& expected_markets
34  = game.visit([&](const auto& g) { return bf::at_key<std::decay_t<decltype(g)>>(game_markets); });
35 
36  std::set<market_kind> actual_markets;
37  boost::transform(markets, std::inserter(actual_markets, actual_markets.begin()), [](const market_type& m) {
38  return m.visit([&](const auto& market_impl) { return market_impl.kind_v; });
39  });
40 
41  std::vector<market_kind> diff;
42  boost::set_difference(actual_markets, expected_markets, std::back_inserter(diff));
43 
44  FC_ASSERT(diff.empty(), "Markets [${m}] cannot be used with specified game", ("m", diff));
45 }
46 
47 void validate_markets(const fc::flat_set<market_type>& markets)
48 {
49  for (const auto& m : markets)
50  {
51  validate_market(m);
52  }
53 }
54 
55 void validate_wincases(const fc::flat_set<wincase_type>& wincases)
56 {
57  for (const auto& wincase : wincases)
58  {
59  validate_wincase(wincase);
60  }
61 }
62 
63 void validate_wincase(const wincase_type& wincase)
64 {
65  auto check_threshold = [](auto threshold) { return threshold % (SCORUM_BETTING_THRESHOLD_FACTOR / 2) == 0; };
66  auto check_positive_threshold = [&](auto threshold) { return check_threshold(threshold) && threshold > 0; };
67 
68  auto is_valid
69  = wincase.weak_visit([&](const total::over& w) { return check_positive_threshold(w.threshold); },
70  [&](const total::under& w) { return check_positive_threshold(w.threshold); },
71  [&](const handicap::over& w) { return check_threshold(w.threshold); },
72  [&](const handicap::under& w) { return check_threshold(w.threshold); },
73  [&](const total_goals_home::over& w) { return check_positive_threshold(w.threshold); },
74  [&](const total_goals_home::under& w) { return check_positive_threshold(w.threshold); },
75  [&](const total_goals_away::over& w) { return check_positive_threshold(w.threshold); },
76  [&](const total_goals_away::under& w) { return check_positive_threshold(w.threshold); });
77 
78  FC_ASSERT(is_valid.value_or(true), "Wincase '${w}' is invalid", ("w", wincase));
79 }
80 
81 void validate_if_wincase_in_game(const game_type& game, const wincase_type& wincase)
82 {
83  const auto& expected_markets
84  = game.visit([&](const auto& g) { return bf::at_key<std::decay_t<decltype(g)>>(game_markets); });
85 
86  auto kind = wincase.visit([](const auto& w) { return std::decay_t<decltype(w)>::kind_v; });
87 
88  FC_ASSERT(expected_markets.find(kind) != expected_markets.end(), "Invalid wincase '${w}'", ("w", wincase));
89 }
90 
91 void validate_bet_ids(const fc::flat_set<int64_t>& bet_ids)
92 {
93  FC_ASSERT(!bet_ids.empty());
94  for (const auto& id : bet_ids)
95  {
96  FC_ASSERT(id >= 0, "Invalid bet Id");
97  }
98 }
99 
101 {
102  auto wincase_pair = create_wincases(market);
103 
104  validate_wincase(wincase_pair.first);
105  validate_wincase(wincase_pair.second);
106 }
107 }
108 }
@ market
Rate limiting for all other actions.
void validate_market(const market_type &market)
void validate_wincases(const fc::flat_set< wincase_type > &wincases)
void validate_game(const game_type &game, const fc::flat_set< market_type > &markets)
const bf::map< bf::pair< soccer_game, std::set< market_kind > >, bf::pair< hockey_game, std::set< market_kind > > > game_markets(bf::make_pair< soccer_game >(std::set< market_kind >{ market_kind::result, market_kind::round, market_kind::handicap, market_kind::correct_score, market_kind::goal, market_kind::total, market_kind::total_goals }), bf::make_pair< hockey_game >(std::set< market_kind >{ market_kind::result, market_kind::goal }))
fc::static_variant< result_home::yes, result_home::no, result_draw::yes, result_draw::no, result_away::yes, result_away::no, round_home::yes, round_home::no, handicap::over, handicap::under, correct_score_home::yes, correct_score_home::no, correct_score_draw::yes, correct_score_draw::no, correct_score_away::yes, correct_score_away::no, correct_score::yes, correct_score::no, goal_home::yes, goal_home::no, goal_both::yes, goal_both::no, goal_away::yes, goal_away::no, total::over, total::under, total_goals_home::over, total_goals_home::under, total_goals_away::over, total_goals_away::under > wincase_type
Definition: market.hpp:128
void validate_bet_ids(const fc::flat_set< int64_t > &bet_ids)
void validate_if_wincase_in_game(const game_type &game, const wincase_type &wincase)
fc::static_variant< soccer_game, hockey_game > game_type
Definition: game.hpp:14
std::pair< wincase_type, wincase_type > create_wincases(const market_type &market)
Definition: market.cpp:51
fc::static_variant< result_home, result_draw, result_away, round_home, handicap, correct_score_home, correct_score_draw, correct_score_away, correct_score, goal_home, goal_both, goal_away, total, total_goals_home, total_goals_away > market_type
Definition: market.hpp:97
void validate_markets(const fc::flat_set< market_type > &markets)
void validate_wincase(const wincase_type &wincase)
Definition: asset.cpp:15
int16_t threshold
Market threshold x 1000 (i.e. -500 in 'handicap' market means -0.5)
Definition: wincase.hpp:11