Skip to content

Commit

Permalink
Merge pull request #3806 from /issues/4207
Browse files Browse the repository at this point in the history
Fixes maximum daily ads at 21 instead of 20 (follow up to #3849)
  • Loading branch information
tmancey authored Nov 4, 2019
2 parents a22a5c6 + 082203b commit 69dc5fc
Show file tree
Hide file tree
Showing 33 changed files with 2,185 additions and 237 deletions.
11 changes: 10 additions & 1 deletion test/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,16 @@ test("brave_unit_tests") {

if (brave_ads_enabled) {
sources += [
"//brave/components/brave_ads/browser/ads_service_impl_unittest.cc"
"//brave/components/brave_ads/browser/ads_service_impl_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/client_mock.h",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/client_mock.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/exclusion_rules/daily_cap_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/exclusion_rules/per_day_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/exclusion_rules/per_hour_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/exclusion_rules/total_max_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/permission_rules/minimum_wait_time_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/permission_rules/ads_per_day_frequency_cap_unittest.cc",
"//brave/vendor/bat-native-ads/src/bat/ads/internal/frequency_capping/permission_rules/ads_per_hour_frequency_cap_unittest.cc",
]
}

Expand Down
18 changes: 18 additions & 0 deletions vendor/bat-native-ads/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,24 @@ source_set("ads") {
"src/bat/ads/internal/filtered_category.h",
"src/bat/ads/internal/flagged_ad.cc",
"src/bat/ads/internal/flagged_ad.h",
"src/bat/ads/internal/frequency_capping/exclusion_rule.h",
"src/bat/ads/internal/frequency_capping/exclusion_rules/daily_cap_frequency_cap.cc",
"src/bat/ads/internal/frequency_capping/exclusion_rules/daily_cap_frequency_cap.h",
"src/bat/ads/internal/frequency_capping/exclusion_rules/per_day_frequency_cap.cc",
"src/bat/ads/internal/frequency_capping/exclusion_rules/per_day_frequency_cap.h",
"src/bat/ads/internal/frequency_capping/exclusion_rules/per_hour_frequency_cap.cc",
"src/bat/ads/internal/frequency_capping/exclusion_rules/per_hour_frequency_cap.h",
"src/bat/ads/internal/frequency_capping/exclusion_rules/total_max_frequency_cap.cc",
"src/bat/ads/internal/frequency_capping/exclusion_rules/total_max_frequency_cap.h",
"src/bat/ads/internal/frequency_capping/frequency_capping.cc",
"src/bat/ads/internal/frequency_capping/frequency_capping.h",
"src/bat/ads/internal/frequency_capping/permission_rule.h",
"src/bat/ads/internal/frequency_capping/permission_rules/minimum_wait_time_frequency_cap.cc",
"src/bat/ads/internal/frequency_capping/permission_rules/minimum_wait_time_frequency_cap.h",
"src/bat/ads/internal/frequency_capping/permission_rules/ads_per_day_frequency_cap.cc",
"src/bat/ads/internal/frequency_capping/permission_rules/ads_per_day_frequency_cap.h",
"src/bat/ads/internal/frequency_capping/permission_rules/ads_per_hour_frequency_cap.cc",
"src/bat/ads/internal/frequency_capping/permission_rules/ads_per_hour_frequency_cap.h",
"src/bat/ads/internal/json_helper.cc",
"src/bat/ads/internal/json_helper.h",
"src/bat/ads/internal/locale_helper.cc",
Expand Down
269 changes: 77 additions & 192 deletions vendor/bat-native-ads/src/bat/ads/internal/ads_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@
#include "bat/ads/internal/static_values.h"
#include "bat/ads/internal/time.h"
#include "bat/ads/internal/uri_helper.h"
#include "bat/ads/internal/frequency_capping/exclusion_rule.h"
#include "bat/ads/internal/frequency_capping/frequency_capping.h"
#include "bat/ads/internal/frequency_capping/exclusion_rules/per_hour_frequency_cap.h"
#include "bat/ads/internal/frequency_capping/exclusion_rules/per_day_frequency_cap.h"
#include "bat/ads/internal/frequency_capping/exclusion_rules/daily_cap_frequency_cap.h"
#include "bat/ads/internal/frequency_capping/exclusion_rules/total_max_frequency_cap.h"
#include "bat/ads/internal/frequency_capping/permission_rules/minimum_wait_time_frequency_cap.h"
#include "bat/ads/internal/frequency_capping/permission_rules/ads_per_day_frequency_cap.h"
#include "bat/ads/internal/frequency_capping/permission_rules/ads_per_hour_frequency_cap.h"

#include "rapidjson/document.h"
#include "rapidjson/error/en.h"
Expand Down Expand Up @@ -79,6 +88,7 @@ AdsImpl::AdsImpl(AdsClient* ads_client) :
client_(std::make_unique<Client>(this, ads_client)),
bundle_(std::make_unique<Bundle>(this, ads_client)),
ads_serve_(std::make_unique<AdsServe>(this, ads_client, bundle_.get())),
frequency_capping_(std::make_unique<FrequencyCapping>(client_.get())),
notifications_(std::make_unique<Notifications>(this, ads_client)),
user_model_(nullptr),
is_initialized_(false),
Expand Down Expand Up @@ -1069,38 +1079,48 @@ void AdsImpl::FailedToServeAd(
}
}

std::vector<AdInfo> AdsImpl::GetEligibleAds(
const std::vector<AdInfo>& ads) {
std::vector<AdInfo> eligible_ads = {};
std::vector<std::unique_ptr<ExclusionRule>>
AdsImpl::CreateExclusionRules() const {
std::vector<std::unique_ptr<ExclusionRule>> exclusion_rules;

auto unseen_ads = GetUnseenAdsAndRoundRobinIfNeeded(ads);
std::unique_ptr<ExclusionRule> daily_cap_frequency_cap =
std::make_unique<DailyCapFrequencyCap>(frequency_capping_.get());
exclusion_rules.push_back(std::move(daily_cap_frequency_cap));

for (const auto& ad : unseen_ads) {
if (!AdRespectsTotalMaxFrequencyCapping(ad)) {
BLOG(WARNING) << "creativeSetId " << ad.creative_set_id
<< " has exceeded the frequency capping for totalMax";
std::unique_ptr<ExclusionRule> per_day_frequency_cap =
std::make_unique<PerDayFrequencyCap>(frequency_capping_.get());
exclusion_rules.push_back(std::move(per_day_frequency_cap));

continue;
}
std::unique_ptr<ExclusionRule> per_hour_frequency_cap =
std::make_unique<PerHourFrequencyCap>(frequency_capping_.get());
exclusion_rules.push_back(std::move(per_hour_frequency_cap));

if (!AdRespectsPerHourFrequencyCapping(ad)) {
BLOG(WARNING) << "adUUID " << ad.uuid
<< " has exceeded the frequency capping for perHour";
std::unique_ptr<ExclusionRule> total_max_frequency_cap =
std::make_unique<TotalMaxFrequencyCap>(frequency_capping_.get());
exclusion_rules.push_back(std::move(total_max_frequency_cap));

continue;
}
return exclusion_rules;
}

if (!AdRespectsPerDayFrequencyCapping(ad)) {
BLOG(WARNING) << "creativeSetId " << ad.creative_set_id
<< " has exceeded the frequency capping for perDay";
std::vector<AdInfo> AdsImpl::GetEligibleAds(
const std::vector<AdInfo>& ads) {
std::vector<AdInfo> eligible_ads = {};

continue;
}
auto unseen_ads = GetUnseenAdsAndRoundRobinIfNeeded(ads);

std::vector<std::unique_ptr<ExclusionRule>> exclusion_rules =
CreateExclusionRules();

if (!AdRespectsDailyCapFrequencyCapping(ad)) {
BLOG(WARNING) << "campaignId " << ad.campaign_id
<< " has exceeded the frequency capping for dailyCap";
for (const auto& ad : unseen_ads) {
bool should_exclude = false;
for (std::unique_ptr<ExclusionRule>& exclusion_rule : exclusion_rules) {
if (exclusion_rule->ShouldExclude(ad)) {
BLOG(INFO) << exclusion_rule->GetLastMessage();
should_exclude = true;
}
}

if (should_exclude) {
continue;
}

Expand Down Expand Up @@ -1151,81 +1171,6 @@ std::vector<AdInfo> AdsImpl::GetUnseenAds(
return unseen_ads;
}

bool AdsImpl::AdRespectsTotalMaxFrequencyCapping(
const AdInfo& ad) {
auto creative_set = GetCreativeSetForId(ad.creative_set_id);
if (creative_set.size() >= ad.total_max) {
return false;
}

return true;
}

bool AdsImpl::AdRespectsPerHourFrequencyCapping(
const AdInfo& ad) {
auto ads_shown = GetAdsShownForId(ad.uuid);
auto hour_window = base::Time::kSecondsPerHour;

return HistoryRespectsRollingTimeConstraint(
ads_shown, hour_window, 1);
}

bool AdsImpl::AdRespectsPerDayFrequencyCapping(
const AdInfo& ad) {
auto creative_set = GetCreativeSetForId(ad.creative_set_id);
auto day_window = base::Time::kSecondsPerHour * base::Time::kHoursPerDay;

return HistoryRespectsRollingTimeConstraint(
creative_set, day_window, ad.per_day);
}

bool AdsImpl::AdRespectsDailyCapFrequencyCapping(
const AdInfo& ad) {
auto campaign = GetCampaignForId(ad.campaign_id);
auto day_window = base::Time::kSecondsPerHour * base::Time::kHoursPerDay;

return HistoryRespectsRollingTimeConstraint(
campaign, day_window, ad.daily_cap);
}

std::deque<uint64_t> AdsImpl::GetAdsShownForId(
const std::string& id) {
std::deque<uint64_t> ads_shown = {};

auto ads_shown_history = client_->GetAdsShownHistory();
for (const auto& ad_shown : ads_shown_history) {
if (ad_shown.ad_content.uuid == id) {
ads_shown.push_back(ad_shown.timestamp_in_seconds);
}
}

return ads_shown;
}

std::deque<uint64_t> AdsImpl::GetCreativeSetForId(
const std::string& id) {
std::deque<uint64_t> creative_set = {};

auto creative_set_history = client_->GetCreativeSetHistory();
if (creative_set_history.find(id) != creative_set_history.end()) {
creative_set = creative_set_history.at(id);
}

return creative_set;
}

std::deque<uint64_t> AdsImpl::GetCampaignForId(
const std::string& id) {
std::deque<uint64_t> campaign = {};

auto campaign_history = client_->GetCampaignHistory();
if (campaign_history.find(id) != campaign_history.end()) {
campaign = campaign_history.at(id);
}

return campaign;
}

bool AdsImpl::IsAdValid(
const AdInfo& ad_info) {
if (ad_info.advertiser.empty() ||
Expand Down Expand Up @@ -1256,6 +1201,15 @@ bool AdsImpl::ShowAd(
return false;
}

auto now_in_seconds = Time::NowInSeconds();

client_->AppendTimestampToCreativeSetHistoryForUuid(ad.creative_set_id,
now_in_seconds);
client_->AppendTimestampToCampaignHistoryForUuid(ad.campaign_id,
now_in_seconds);

client_->UpdateAdsUUIDSeen(ad.uuid, 1);

auto notification_info = std::make_unique<NotificationInfo>();
notification_info->id = base::GenerateGUID();
notification_info->advertiser = ad.advertiser;
Expand Down Expand Up @@ -1287,114 +1241,45 @@ bool AdsImpl::ShowAd(
}
#endif


client_->AppendCurrentTimeToCreativeSetHistory(ad.creative_set_id);
client_->AppendCurrentTimeToCampaignHistory(ad.campaign_id);

client_->UpdateAdsUUIDSeen(ad.uuid, 1);

return true;
}

bool AdsImpl::HistoryRespectsRollingTimeConstraint(
const std::deque<uint64_t> history,
const uint64_t seconds_window,
const uint64_t allowable_ad_count) const {
uint64_t recent_count = 0;
std::vector<std::unique_ptr<PermissionRule>>
AdsImpl::CreatePermissionRules() const {
std::vector<std::unique_ptr<PermissionRule>> permission_rules;

auto now_in_seconds = Time::NowInSeconds();
std::unique_ptr<PermissionRule> ads_per_hour_frequency_cap =
std::make_unique<AdsPerHourFrequencyCap>(this, ads_client_,
frequency_capping_.get());
permission_rules.push_back(std::move(ads_per_hour_frequency_cap));

for (const auto& timestamp_in_seconds : history) {
if (now_in_seconds - timestamp_in_seconds < seconds_window) {
recent_count++;
}
}
std::unique_ptr<PermissionRule> minimum_wait_time_frequency_cap =
std::make_unique<MinimumWaitTimeFrequencyCap>(this, ads_client_,
frequency_capping_.get());
permission_rules.push_back(std::move(minimum_wait_time_frequency_cap));

if (recent_count <= allowable_ad_count) {
return true;
}
std::unique_ptr<PermissionRule> ads_per_day_frequency_cap =
std::make_unique<AdsPerDayFrequencyCap>(ads_client_,
frequency_capping_.get());
permission_rules.push_back(std::move(ads_per_day_frequency_cap));

return false;
return permission_rules;
}

bool AdsImpl::HistoryRespectsRollingTimeConstraint(
const std::deque<AdHistoryDetail> history,
const uint64_t seconds_window,
const uint64_t allowable_ad_count) const {
uint64_t recent_count = 0;
bool AdsImpl::IsAllowedToServeAds() {
std::vector<std::unique_ptr<PermissionRule>> permission_rules =
CreatePermissionRules();

auto now_in_seconds = Time::NowInSeconds();
bool is_allowed = true;

for (const auto& detail : history) {
if (now_in_seconds - detail.timestamp_in_seconds < seconds_window) {
recent_count++;
for (std::unique_ptr<PermissionRule>& permission_rule : permission_rules) {
if (!permission_rule->IsAllowed()) {
BLOG(INFO) << permission_rule->GetLastMessage();
is_allowed = false;
}
}

if (recent_count <= allowable_ad_count) {
return true;
}

return false;
}

bool AdsImpl::IsAllowedToServeAds() {
auto does_history_respect_ads_per_day_limit =
DoesHistoryRespectAdsPerDayLimit();

bool does_history_respect_minimum_wait_time;
if (!IsMobile()) {
does_history_respect_minimum_wait_time =
DoesHistoryRespectMinimumWaitTimeToServeAds();
} else {
does_history_respect_minimum_wait_time = true;
}

BLOG(INFO) << "IsAllowedToServeAds:";
BLOG(INFO) << " does_history_respect_minimum_wait_time: "
<< does_history_respect_minimum_wait_time;
BLOG(INFO) << " does_history_respect_ads_per_day_limit: "
<< does_history_respect_ads_per_day_limit;

return does_history_respect_minimum_wait_time &&
does_history_respect_ads_per_day_limit;
}

bool AdsImpl::DoesHistoryRespectMinimumWaitTimeToServeAds() {
auto ads_shown_history = client_->GetAdsShownHistory();

auto hour_window = base::Time::kSecondsPerHour;
auto hour_allowed = ads_client_->GetAdsPerHour();
auto respects_hour_limit = HistoryRespectsRollingTimeConstraint(
ads_shown_history, hour_window, hour_allowed);

auto minimum_wait_time = hour_window / hour_allowed;
auto respects_minimum_wait_time = HistoryRespectsRollingTimeConstraint(
ads_shown_history, minimum_wait_time, 0);

BLOG(INFO) << "DoesHistoryRespectMinimumWaitTimeToServeAds:";
BLOG(INFO) << " respects_hour_limit: "
<< respects_hour_limit;
BLOG(INFO) << " respects_minimum_wait_time: "
<< respects_minimum_wait_time;

return respects_hour_limit && respects_minimum_wait_time;
}

bool AdsImpl::DoesHistoryRespectAdsPerDayLimit() {
auto ads_shown_history = client_->GetAdsShownHistory();

auto day_window = base::Time::kSecondsPerHour * base::Time::kHoursPerDay;
auto day_allowed = ads_client_->GetAdsPerDay();

auto respects_day_limit = HistoryRespectsRollingTimeConstraint(
ads_shown_history, day_window, day_allowed);

BLOG(INFO) << "DoesHistoryRespectAdsPerDayLimit:";
BLOG(INFO) << " respects_day_limit: "
<< respects_day_limit;

return respects_day_limit;
return is_allowed;
}

void AdsImpl::StartCollectingActivity(
Expand Down
Loading

0 comments on commit 69dc5fc

Please sign in to comment.