forked from venediktov/vanilla-rtb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathad_selector.hpp
146 lines (127 loc) · 5.31 KB
/
ad_selector.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
* File: bidder_selector.hpp
* Author: [email protected]
*
* Created on 16 февраля 2017 г., 21:15
*/
#ifndef BIDDER_SELECTOR_HPP
#define BIDDER_SELECTOR_HPP
#include "rtb/core/openrtb.hpp"
#include "rtb/core/banker.hpp"
#include "examples/campaign/campaign_cache.hpp"
#include "bidder_caches.hpp"
#include <memory>
#include <algorithm>
namespace vanilla {
template<typename Config = BidderConfig>
class AdSelector {
public:
using SpecBidderCaches = BidderCaches<Config>;
using AdPtr = std::shared_ptr<Ad>;
using AdSelectionAlg = std::function<AdPtr(const std::vector<Ad>&)>;
using self_type = AdSelector<Config>;
AdSelector(BidderCaches<Config> &bidder_caches):
bidder_caches{bidder_caches}
{
retrieved_cached_ads.reserve(500);
}
self_type& alg(const AdSelectionAlg &selection_alg_) {
selection_alg = selection_alg_;
return *this;
}
template<typename T>
AdPtr select(const openrtb::BidRequest<T> &req, const openrtb::Impression<T> &imp) {
AdPtr result;
Geo geo;
if(!getGeo(req, geo) ) {
LOG(debug) << "No geo";
return result;
}
if(!getGeoCampaigns(geo.geo_id)) {
LOG(debug) << "No campaigns for geo " << geo.geo_id;
return result;
}
else {
LOG(debug) << "Selected campaigns " << geo_campaigns.size();
}
if(!getCampaignAds(geo_campaigns, imp)) {
LOG(debug) << "No ads for geo " << geo.geo_id;
return result;
}
else {
LOG(debug) << "selected ads " << retrieved_cached_ads.size();
}
if(selection_alg) {
return selection_alg(retrieved_cached_ads);
}
return max_bid(retrieved_cached_ads);
}
bool getGeoCampaigns(uint32_t geo_id) {
geo_campaigns.clear();
if (!bidder_caches.geo_campaign_entity.retrieve(geo_campaigns, geo_id)) {
LOG(debug) << "GeoAd retrieve failed " << geo_id;
return false;
}
return true;
}
template <typename T>
bool getGeo(const openrtb::BidRequest<T> &req, Geo &geo) {
if (!req.user) {
LOG(debug) << "No user";
return true;
}
if (!req.user.get().geo) {
LOG(debug) << "No user geo";
return true;
}
auto &city_view = req.user.get().geo.get().city ;
auto &country_view = req.user.get().geo.get().country;
const std::string city = boost::algorithm::to_lower_copy(std::string(city_view.data(), city_view.size()));
const std::string country = boost::algorithm::to_lower_copy(std::string(country_view.data(), country_view.size()));
if (!bidder_caches.geo_data_entity.retrieve(geo, city, country)) {
LOG(debug) << "retrieve failed " << city << " " << country;
return false;
}
return true;
}
template <typename T>
bool getCampaignAds(const std::vector<GeoCampaign> &campaigns, const openrtb::Impression<T> &imp) {
retrieved_cached_ads.clear();
for (auto &campaign : campaigns) {
auto offset = retrieved_cached_ads.size();
if (!bidder_caches.ad_data_entity.retrieve(retrieved_cached_ads, campaign.campaign_id, imp.banner.get().w, imp.banner.get().h)) {
continue;
}
auto budget_bid = authorize(campaign.campaign_id);
std::transform(std::begin(retrieved_cached_ads) + offset,
std::end(retrieved_cached_ads),
std::begin(retrieved_cached_ads) + offset, [budget_bid](Ad & ad){
ad.auth_bid_micros = std::min(budget_bid, ad.max_bid_micros);
return ad;
});
}
return retrieved_cached_ads.size() > 0;
}
AdPtr max_bid(const std::vector<Ad>& ads) {
if(ads.size() == 0) {
return AdPtr();
}
const std::vector<Ad>::const_iterator result = std::max_element(ads.cbegin(), ads.cend(), [](const Ad &first, const Ad &second) -> bool {
return first.auth_bid_micros && second.auth_bid_micros ?
first.auth_bid_micros <second.auth_bid_micros : first.max_bid_micros < second.max_bid_micros;
});
return std::make_shared<Ad>(*result);
}
template<typename CampaignId>
auto authorize(CampaignId && campaign_id) {
return banker.authorize(bidder_caches.budget_cache, campaign_id);
}
private:
SpecBidderCaches &bidder_caches;
std::vector<GeoCampaign> geo_campaigns;
std::vector<Ad> retrieved_cached_ads;
AdSelectionAlg selection_alg;
vanilla::core::Banker<vanilla::BudgetManager> banker;
};
}
#endif /* BIDDER_SELECTOR_HPP */