5 #include <boost/range/algorithm/reverse.hpp>
6 #include <boost/range/algorithm/transform.hpp>
12 #include <scorum/utils/take_n_range.hpp>
13 #include <scorum/utils/collect_range_adaptor.hpp>
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)
31 const auto& post_coeffs = _adv_props_svc.
get().auction_post_coefficients;
32 const auto& banner_coeffs = _adv_props_svc.
get().auction_banner_coefficients;
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() });
38 template <budget_type budget_type_v>
40 const std::vector<percent_type>& coeffs)
42 namespace br = boost::range;
45 std::vector<asset> per_block_list;
46 br::transform(budgets, std::back_inserter(per_block_list), [](
auto b) {
return b.get().per_block; });
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>();
52 auto auction_bets =
calculate_bets(valuable_per_block_vec, coeffs);
54 for (
size_t i = 0; i < budgets.size(); ++i)
56 const auto& budget = budgets[i].get();
60 auto adv_cash = asset(0, per_block.symbol());
61 if (i < auction_bets.size())
62 adv_cash = auction_bets[i];
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");
72 const std::vector<percent_type>& coeffs)
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");
82 if (per_blocks.empty())
85 int64_t bets_size = std::min(per_blocks.size(), coeffs.size());
86 std::vector<asset> bets;
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);
93 for (int64_t ridx = bets_size - 2; ridx >= 0l; --ridx)
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]));
100 boost::reverse(bets);
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)
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