Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes maximum daily ads at 21 instead of 20 (follow up to #3849) #3806

Merged
merged 1 commit into from
Nov 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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