Scorum
advertising_auction.cpp
Go to the documentation of this file.
2 
4 
5 #include <boost/range/algorithm/reverse.hpp>
6 #include <boost/range/algorithm/transform.hpp>
7 
11 
12 #include <scorum/utils/take_n_range.hpp>
13 #include <scorum/utils/collect_range_adaptor.hpp>
14 
15 namespace scorum {
16 namespace chain {
17 
19  advertising_property_service_i& adv_props_svc,
22  : _dprops_svc(dprops_svc)
23  , _adv_props_svc(adv_props_svc)
24  , _post_budget_svc(post_budget_svc)
25  , _banner_budget_svc(banner_budget_svc)
26 {
27 }
28 
30 {
31  const auto& post_coeffs = _adv_props_svc.get().auction_post_coefficients;
32  const auto& banner_coeffs = _adv_props_svc.get().auction_banner_coefficients;
33 
34  run_round(_post_budget_svc, std::vector<percent_type>{ post_coeffs.begin(), post_coeffs.end() });
35  run_round(_banner_budget_svc, std::vector<percent_type>{ banner_coeffs.begin(), banner_coeffs.end() });
36 }
37 
38 template <budget_type budget_type_v>
40  const std::vector<percent_type>& coeffs)
41 {
42  namespace br = boost::range;
43 
44  auto budgets = budget_svc.get_top_budgets(_dprops_svc.head_block_time());
45  std::vector<asset> per_block_list;
46  br::transform(budgets, std::back_inserter(per_block_list), [](auto b) { return b.get().per_block; });
47 
48  auto valuable_per_block_vec = boost::make_iterator_range(per_block_list)
49  | utils::adaptors::take_n(coeffs.size() + 1) //
50  | utils::adaptors::collect<std::vector>();
51 
52  auto auction_bets = calculate_bets(valuable_per_block_vec, coeffs);
53 
54  for (size_t i = 0; i < budgets.size(); ++i)
55  {
56  const auto& budget = budgets[i].get();
57 
58  auto per_block = budget_svc.allocate_cash(budget);
59 
60  auto adv_cash = asset(0, per_block.symbol());
61  if (i < auction_bets.size())
62  adv_cash = auction_bets[i];
63 
64  auto ret_cash = per_block - adv_cash;
65  FC_ASSERT(ret_cash.amount >= 0, "Owner's cash-back amount cannot be less than zero");
66 
67  budget_svc.update_pending_payouts(budget, ret_cash, adv_cash);
68  }
69 }
70 
71 std::vector<asset> advertising_auction::calculate_bets(const std::vector<asset>& per_blocks,
72  const std::vector<percent_type>& coeffs)
73 {
74  FC_ASSERT(coeffs.size() > 0, "invalid coefficient's list");
75  FC_ASSERT(per_blocks.size() <= coeffs.size() + 1, "invalid list of per-block values");
76  FC_ASSERT(std::is_sorted(coeffs.rbegin(), coeffs.rend()), "per-block list isn't sorted");
77  FC_ASSERT(std::is_sorted(per_blocks.rbegin(), per_blocks.rend()), "Auction coefficients aren't sorted");
78  FC_ASSERT(*coeffs.rbegin() > 0, "Auction coefficients should be positive");
79  FC_ASSERT(*coeffs.begin() <= 100, "Auction coefficients should be less than 100");
80  FC_ASSERT(per_blocks.empty() || per_blocks.rbegin()->amount > 0, "per-block amount should be positive");
81 
82  if (per_blocks.empty())
83  return {};
84 
85  int64_t bets_size = std::min(per_blocks.size(), coeffs.size());
86  std::vector<asset> bets;
87 
88  auto smallest_bet = bets_size < (int64_t)per_blocks.size() //
89  ? per_blocks[bets_size]
90  : per_blocks[bets_size - 1];
91  bets.push_back(smallest_bet);
92 
93  for (int64_t ridx = bets_size - 2; ridx >= 0l; --ridx)
94  {
95  auto factor = utils::make_fraction((coeffs[ridx] - coeffs[ridx + 1]), coeffs.front());
96  auto bet = bets.back() + per_blocks[ridx + 1] * factor;
97  bets.push_back(std::min(bet, per_blocks[ridx]));
98  }
99 
100  boost::reverse(bets);
101 
102  return bets;
103 }
104 }
105 }
advertising_auction(dynamic_global_property_service_i &dprops_svc, advertising_property_service_i &adv_props_svc, adv_budget_service_i< budget_type::post > &post_budget_svc, adv_budget_service_i< budget_type::banner > &banner_budget_svc)
static std::vector< asset > calculate_bets(const std::vector< asset > &per_blocks, const std::vector< percent_type > &coeffs)
Definition: asset.cpp:15
virtual budgets_type get_top_budgets(const fc::time_point_sec &until, uint16_t limit) const =0
virtual void update_pending_payouts(const adv_budget_object< budget_type_v > &budget, const asset &owner_incoming, const asset &budget_outgoing)=0
virtual asset allocate_cash(const adv_budget_object< budget_type_v > &budget)=0
virtual const object_type & get() const =0
virtual fc::time_point_sec head_block_time() const =0