Scorum
betting_api_impl.hpp
Go to the documentation of this file.
2 
3 #include <chainbase/database_guard.hpp>
5 
7 
10 
11 #include <boost/range/algorithm/sort.hpp>
12 #include <boost/range/algorithm/unique.hpp>
13 #include <boost/range/algorithm_ext/push_back.hpp>
14 #include <boost/range/algorithm/set_algorithm.hpp>
15 #include <boost/range/adaptor/transformed.hpp>
16 #include <boost/range/adaptor/filtered.hpp>
17 
18 #include <scorum/utils/take_n_range.hpp>
19 #include <scorum/utils/range/join_range.hpp>
20 #include <scorum/utils/range/flatten_range.hpp>
21 #include <scorum/utils/collect_range_adaptor.hpp>
22 #include <scorum/utils/set_intersection.hpp>
23 
24 namespace scorum {
25 namespace app {
26 
27 using namespace scorum::chain;
28 using namespace scorum::protocol;
29 
31 {
32 public:
35  dba::db_accessor<matched_bet_object>& matched_bet_dba,
36  dba::db_accessor<pending_bet_object>& pending_bet_dba,
37  uint32_t lookup_limit = LOOKUP_LIMIT)
38  : _betting_prop_dba(betting_prop_dba)
39  , _game_dba(game_dba)
40  , _matched_bet_dba(matched_bet_dba)
41  , _pending_bet_dba(pending_bet_dba)
42  , _lookup_limit(lookup_limit)
43  {
44  }
45  std::vector<matched_bet_api_object> get_game_returns(const uuid_type& game_uuid) const
46  {
47  using namespace scorum::chain::dba;
48 
49  FC_ASSERT(_game_dba.is_exists_by<by_uuid>(game_uuid), "Game with uuid '${1}' doesn't exist", ("1", game_uuid));
50  const auto& game = _game_dba.get_by<by_uuid>(game_uuid);
51  auto bets_rng = _matched_bet_dba.get_range_by<by_game_uuid_market>(game_uuid);
52 
53  std::vector<matched_bet_api_object> winners;
54 
55  for (const matched_bet_object& bet : bets_rng)
56  {
57  auto fst_won = game.results.find(bet.bet1_data.wincase) != game.results.end();
58  auto snd_won = game.results.find(bet.bet2_data.wincase) != game.results.end();
59 
60  if (!fst_won && !snd_won)
61  {
62  winners.push_back(matched_bet_api_object(bet));
63  }
64  }
65 
66  return winners;
67  }
68 
69  std::vector<winner_api_object> get_game_winners(const uuid_type& game_uuid) const
70  {
71  using namespace scorum::chain::dba;
72 
73  FC_ASSERT(_game_dba.is_exists_by<by_uuid>(game_uuid), "Game with uuid '${1}' doesn't exist", ("1", game_uuid));
74  const auto& game = _game_dba.get_by<by_uuid>(game_uuid);
75  auto bets_rng = _matched_bet_dba.get_range_by<by_game_uuid_market>(game_uuid);
76 
77  std::vector<winner_api_object> winners;
78 
79  for (const matched_bet_object& bet : bets_rng)
80  {
81  auto fst_won = game.results.find(bet.bet1_data.wincase) != game.results.end();
82  auto snd_won = game.results.find(bet.bet2_data.wincase) != game.results.end();
83 
84  if (fst_won)
85  {
86  winners.push_back(winner_api_object(bet.market, bet.bet1_data, bet.bet2_data));
87  }
88  else if (snd_won)
89  {
90  winners.push_back(winner_api_object(bet.market, bet.bet2_data, bet.bet1_data));
91  }
92  }
93 
94  return winners;
95  }
96 
97  std::vector<game_api_object> get_games_by_status(const fc::flat_set<game_status>& filter) const
98  {
99  auto games = _game_dba.get_all_by<by_id>();
100  auto rng = games //
101  | boost::adaptors::filtered([&](const auto& obj) { return filter.find(obj.status) != filter.end(); })
102  | boost::adaptors::transformed([](const auto& obj) { return game_api_object(obj); });
103 
104  return { rng.begin(), rng.end() };
105  }
106 
107  std::vector<game_api_object> get_games_by_uuids(const std::vector<uuid_type>& uuids) const
108  {
109  using namespace boost::adaptors;
110  using namespace utils::adaptors;
111 
112  auto result = uuids //
113  | filtered([&](auto uid) { return _game_dba.is_exists_by<by_uuid>(uid); })
114  | transformed([&](auto uid) { return game_api_object(_game_dba.get_by<by_uuid>(uid)); })
115  | collect<std::vector>(uuids.size());
116 
117  return result;
118  }
119 
120  std::vector<game_api_object> lookup_games_by_id(game_id_type from, uint32_t limit) const
121  {
122  using namespace boost::adaptors;
123  using namespace utils::adaptors;
124 
125  auto lookup_limit = std::min(limit, _lookup_limit);
126  auto games = _game_dba.get_range_by<by_id>(from <= dba::_x, dba::unbounded);
127 
128  auto result = games //
129  | take_n(lookup_limit) //
130  | transformed([&](const auto& obj) { return game_api_object(obj); }) //
131  | collect<std::vector>(lookup_limit);
132 
133  return result;
134  }
135 
136  std::vector<matched_bet_api_object> lookup_matched_bets(matched_bet_id_type from, uint32_t limit) const
137  {
138  return get_bets<matched_bet_api_object>(_matched_bet_dba, from, limit);
139  }
140 
141  std::vector<pending_bet_api_object> lookup_pending_bets(pending_bet_id_type from, uint32_t limit) const
142  {
143  return get_bets<pending_bet_api_object>(_pending_bet_dba, from, limit);
144  }
145 
146  std::vector<matched_bet_api_object> get_matched_bets(const std::vector<uuid_type>& uuids) const
147  {
148  using namespace boost::adaptors;
149  using namespace utils::adaptors;
150 
151  auto with_bet1_matched = uuids
152  | transformed([&](auto uid) { return _matched_bet_dba.get_range_by<by_bet1_uuid>(uid); }) //
153  | flatten;
154 
155  auto with_bet2_matched = uuids
156  | transformed([&](auto uid) { return _matched_bet_dba.get_range_by<by_bet2_uuid>(uid); }) //
157  | flatten;
158 
159  auto matched_bets_vec = with_bet1_matched //
160  | joined(with_bet2_matched) //
161  | transformed([](const auto& bet) { return matched_bet_api_object(bet); }) //
162  | collect<std::vector>();
163 
164  boost::range::sort(matched_bets_vec, [](const auto& l, const auto& r) { return l.id < r.id; });
165  auto rng = boost::range::unique(matched_bets_vec, [](const auto& l, const auto& r) { return l.id == r.id; });
166 
167  matched_bets_vec.erase(rng.end(), matched_bets_vec.end());
168 
169  return matched_bets_vec;
170  }
171 
172  std::vector<pending_bet_api_object> get_pending_bets(const std::vector<uuid_type>& uuids) const
173  {
174  using namespace boost::adaptors;
175  using namespace utils::adaptors;
176 
177  auto result = uuids //
178  | filtered([&](auto uid) { return _pending_bet_dba.is_exists_by<by_uuid>(uid); })
179  | transformed([&](auto uid) { return pending_bet_api_object(_pending_bet_dba.get_by<by_uuid>(uid)); })
180  | collect<std::vector>(uuids.size());
181 
182  return result;
183  }
184 
185  template <typename TApiObject, typename TObject, typename TId>
186  std::vector<TApiObject> get_bets(dba::db_accessor<TObject>& accessor, TId from, uint32_t limit) const
187  {
188  using namespace dba;
189  using namespace boost::adaptors;
190  using namespace utils::adaptors;
191 
192  FC_ASSERT(limit <= _lookup_limit, "Limit should be le than LOOKUP_LIMIT",
193  ("limit", limit)("LOOKUP_LIMIT", _lookup_limit));
194 
195  auto bets = accessor.template get_range_by<by_id>(from <= _x, unbounded);
196  auto result = bets //
197  | take_n(limit) //
198  | transformed([](const auto& obj) { return TApiObject(obj); }) //
199  | collect<std::vector>();
200 
201  return result;
202  }
203 
205  {
206  return _betting_prop_dba.get();
207  }
208 
209  std::vector<matched_bet_api_object> get_game_matched_bets(const uuid_type& uuid) const
210  {
211  auto bets_rng = _matched_bet_dba.get_range_by<by_game_uuid_market>(uuid);
212 
213  std::vector<matched_bet_api_object> result;
214 
215  for (auto& bet : bets_rng)
216  {
217  result.push_back(bet);
218  }
219 
220  return result;
221  }
222 
223  std::vector<pending_bet_api_object> get_game_pending_bets(const uuid_type& uuid) const
224  {
225  auto bets_rng = _pending_bet_dba.get_range_by<by_game_uuid_market>(uuid);
226 
227  std::vector<pending_bet_api_object> result;
228 
229  for (auto& bet : bets_rng)
230  {
231  result.push_back(bet);
232  }
233 
234  return result;
235  }
236 
237 private:
240  dba::db_accessor<matched_bet_object>& _matched_bet_dba;
241  dba::db_accessor<pending_bet_object>& _pending_bet_dba;
242 
243  const uint32_t _lookup_limit;
244 };
245 
246 } // namespace app
247 } // namespace scorum
std::vector< pending_bet_api_object > get_pending_bets(const std::vector< uuid_type > &uuids) const
std::vector< matched_bet_api_object > get_game_returns(const uuid_type &game_uuid) const
std::vector< matched_bet_api_object > get_game_matched_bets(const uuid_type &uuid) const
std::vector< game_api_object > lookup_games_by_id(game_id_type from, uint32_t limit) const
std::vector< TApiObject > get_bets(dba::db_accessor< TObject > &accessor, TId from, uint32_t limit) const
betting_property_api_object get_betting_properties() const
std::vector< matched_bet_api_object > lookup_matched_bets(matched_bet_id_type from, uint32_t limit) const
std::vector< winner_api_object > get_game_winners(const uuid_type &game_uuid) const
std::vector< pending_bet_api_object > lookup_pending_bets(pending_bet_id_type from, uint32_t limit) const
std::vector< matched_bet_api_object > get_matched_bets(const std::vector< uuid_type > &uuids) const
std::vector< pending_bet_api_object > get_game_pending_bets(const uuid_type &uuid) const
impl(dba::db_accessor< betting_property_object > &betting_prop_dba, dba::db_accessor< game_object > &game_dba, dba::db_accessor< matched_bet_object > &matched_bet_dba, dba::db_accessor< pending_bet_object > &pending_bet_dba, uint32_t lookup_limit=LOOKUP_LIMIT)
std::vector< game_api_object > get_games_by_uuids(const std::vector< uuid_type > &uuids) const
std::vector< game_api_object > get_games_by_status(const fc::flat_set< game_status > &filter) const
#define LOOKUP_LIMIT
Definition: config_api.hpp:71
api_obj< chain::pending_bet_object > pending_bet_api_object
api_obj< chain::matched_bet_object > matched_bet_api_object
const param_placeholder _x
const unbounded_placeholder unbounded
Definition: asset.cpp:15
boost::uuids::uuid uuid_type
Definition: types.hpp:53