Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1891)

Unified Diff: chrome/browser/engagement/site_engagement_score.cc

Issue 1975723002: Reduce the site engagement service public interface. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Push messaging now uses engagement Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/engagement/site_engagement_score.cc
diff --git a/chrome/browser/engagement/site_engagement_score.cc b/chrome/browser/engagement/site_engagement_score.cc
new file mode 100644
index 0000000000000000000000000000000000000000..140cd01b1135e78e3b8eb5d14a60d6bff2f2cdfe
--- /dev/null
+++ b/chrome/browser/engagement/site_engagement_score.cc
@@ -0,0 +1,305 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/engagement/site_engagement_score.h"
+
+#include <cmath>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/time/clock.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "chrome/browser/engagement/site_engagement_metrics.h"
+#include "components/variations/variations_associated_data.h"
+
+namespace {
+
+// Delta within which to consider scores equal.
+const double kScoreDelta = 0.001;
+
+// Delta within which to consider internal time values equal. Internal time
+// values are in microseconds, so this delta comes out at one second.
+const double kTimeDelta = 1000000;
+
+// Number of days after the last launch of an origin from an installed shortcut
+// for which WEB_APP_INSTALLED_POINTS will be added to the engagement score.
+const int kMaxDaysSinceShortcutLaunch = 10;
+
+// Keys used in the variations params. Order matches
+// SiteEngagementScore::Variation enum.
+const char* kVariationNames[] = {
+ "max_points_per_day",
+ "decay_period_in_days",
+ "decay_points",
+ "navigation_points",
+ "user_input_points",
+ "visible_media_playing_points",
+ "hidden_media_playing_points",
+ "web_app_installed_points",
+ "first_daily_engagement_points",
+ "medium_engagement_boundary",
+ "high_engagement_boundary",
+};
+
+bool DoublesConsideredDifferent(double value1, double value2, double delta) {
+ double abs_difference = fabs(value1 - value2);
+ return abs_difference > delta;
+}
+
+} // namespace
+
+const double SiteEngagementScore::kMaxPoints = 100;
+double SiteEngagementScore::param_values[] = {
+ 5, // MAX_POINTS_PER_DAY
+ 7, // DECAY_PERIOD_IN_DAYS
+ 5, // DECAY_POINTS
+ 0.5, // NAVIGATION_POINTS
+ 0.2, // USER_INPUT_POINTS
+ 0.02, // VISIBLE_MEDIA_POINTS
+ 0.01, // HIDDEN_MEDIA_POINTS
+ 5, // WEB_APP_INSTALLED_POINTS
+ 0.5, // FIRST_DAILY_ENGAGEMENT
+ 8, // BOOTSTRAP_POINTS
+ 5, // MEDIUM_ENGAGEMENT_BOUNDARY
+ 50, // HIGH_ENGAGEMENT_BOUNDARY
+};
+
+const char* SiteEngagementScore::kRawScoreKey = "rawScore";
+const char* SiteEngagementScore::kPointsAddedTodayKey = "pointsAddedToday";
+const char* SiteEngagementScore::kLastEngagementTimeKey = "lastEngagementTime";
+const char* SiteEngagementScore::kLastShortcutLaunchTimeKey =
+ "lastShortcutLaunchTime";
+
+double SiteEngagementScore::GetMaxPointsPerDay() {
+ return param_values[MAX_POINTS_PER_DAY];
+}
+
+double SiteEngagementScore::GetDecayPeriodInDays() {
+ return param_values[DECAY_PERIOD_IN_DAYS];
+}
+
+double SiteEngagementScore::GetDecayPoints() {
+ return param_values[DECAY_POINTS];
+}
+
+double SiteEngagementScore::GetNavigationPoints() {
+ return param_values[NAVIGATION_POINTS];
+}
+
+double SiteEngagementScore::GetUserInputPoints() {
+ return param_values[USER_INPUT_POINTS];
+}
+
+double SiteEngagementScore::GetVisibleMediaPoints() {
+ return param_values[VISIBLE_MEDIA_POINTS];
+}
+
+double SiteEngagementScore::GetHiddenMediaPoints() {
+ return param_values[HIDDEN_MEDIA_POINTS];
+}
+
+double SiteEngagementScore::GetWebAppInstalledPoints() {
+ return param_values[WEB_APP_INSTALLED_POINTS];
+}
+
+double SiteEngagementScore::GetFirstDailyEngagementPoints() {
+ return param_values[FIRST_DAILY_ENGAGEMENT];
+}
+
+double SiteEngagementScore::GetBootstrapPoints() {
+ return param_values[BOOTSTRAP_POINTS];
+}
+
+double SiteEngagementScore::GetMediumEngagementBoundary() {
+ return param_values[MEDIUM_ENGAGEMENT_BOUNDARY];
+}
+
+double SiteEngagementScore::GetHighEngagementBoundary() {
+ return param_values[HIGH_ENGAGEMENT_BOUNDARY];
+}
+
+// static
+void SiteEngagementScore::UpdateFromVariations(const char* param_name) {
+ double param_vals[MAX_VARIATION];
+
+ for (int i = 0; i < MAX_VARIATION; ++i) {
+ std::string param_string =
+ variations::GetVariationParamValue(param_name, kVariationNames[i]);
+
+ // Bail out if we didn't get a param string for the key, or if we couldn't
+ // convert the param string to a double, or if we get a negative value.
+ if (param_string.empty() ||
+ !base::StringToDouble(param_string, &param_vals[i]) ||
+ param_vals[i] < 0) {
+ return;
+ }
+ }
+
+ // Once we're sure everything is valid, assign the variation to the param
+ // values array.
+ for (int i = 0; i < MAX_VARIATION; ++i)
+ SiteEngagementScore::param_values[i] = param_vals[i];
+}
+
+SiteEngagementScore::SiteEngagementScore(base::Clock* clock,
+ const base::DictionaryValue& score_dict)
+ : SiteEngagementScore(clock) {
+ score_dict.GetDouble(kRawScoreKey, &raw_score_);
+ score_dict.GetDouble(kPointsAddedTodayKey, &points_added_today_);
+
+ double internal_time;
+ if (score_dict.GetDouble(kLastEngagementTimeKey, &internal_time))
+ last_engagement_time_ = base::Time::FromInternalValue(internal_time);
+ if (score_dict.GetDouble(kLastShortcutLaunchTimeKey, &internal_time))
+ last_shortcut_launch_time_ = base::Time::FromInternalValue(internal_time);
+}
+
+SiteEngagementScore::~SiteEngagementScore() {}
+
+void SiteEngagementScore::AddPoints(double points) {
+ DCHECK_NE(0, points);
+ double decayed_score = DecayedScore();
+
+ // Record the original and decayed scores after a decay event.
+ if (decayed_score < raw_score_) {
+ SiteEngagementMetrics::RecordScoreDecayedFrom(raw_score_);
+ SiteEngagementMetrics::RecordScoreDecayedTo(decayed_score);
+ }
+
+ // As the score is about to be updated, commit any decay that has happened
+ // since the last update.
+ raw_score_ = decayed_score;
+
+ base::Time now = clock_->Now();
+ if (!last_engagement_time_.is_null() &&
+ now.LocalMidnight() != last_engagement_time_.LocalMidnight()) {
+ points_added_today_ = 0;
+ }
+
+ if (points_added_today_ == 0) {
+ // Award bonus engagement for the first engagement of the day for a site.
+ points += GetFirstDailyEngagementPoints();
+ SiteEngagementMetrics::RecordEngagement(
+ SiteEngagementMetrics::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT);
+ }
+
+ double to_add = std::min(kMaxPoints - raw_score_,
+ GetMaxPointsPerDay() - points_added_today_);
+ to_add = std::min(to_add, points);
+
+ points_added_today_ += to_add;
+ raw_score_ += to_add;
+
+ last_engagement_time_ = now;
+}
+
+double SiteEngagementScore::GetScore() const {
+ return std::min(DecayedScore() + BonusScore(), kMaxPoints);
+}
+
+bool SiteEngagementScore::MaxPointsPerDayAdded() const {
+ if (!last_engagement_time_.is_null() &&
+ clock_->Now().LocalMidnight() != last_engagement_time_.LocalMidnight()) {
+ return false;
+ }
+
+ return points_added_today_ == GetMaxPointsPerDay();
+}
+
+void SiteEngagementScore::Reset(double points, const base::Time* updated_time) {
+ raw_score_ = points;
+ points_added_today_ = 0;
+
+ // This must be set in order to prevent the score from decaying when read.
+ if (updated_time) {
+ last_engagement_time_ = *updated_time;
+ if (!last_shortcut_launch_time_.is_null())
+ last_shortcut_launch_time_ = *updated_time;
+ } else {
+ last_engagement_time_ = clock_->Now();
+ }
+}
+
+bool SiteEngagementScore::UpdateScoreDict(base::DictionaryValue* score_dict) {
+ double raw_score_orig = 0;
+ double points_added_today_orig = 0;
+ double last_engagement_time_internal_orig = 0;
+ double last_shortcut_launch_time_internal_orig = 0;
+
+ score_dict->GetDouble(kRawScoreKey, &raw_score_orig);
+ score_dict->GetDouble(kPointsAddedTodayKey, &points_added_today_orig);
+ score_dict->GetDouble(kLastEngagementTimeKey,
+ &last_engagement_time_internal_orig);
+ score_dict->GetDouble(kLastShortcutLaunchTimeKey,
+ &last_shortcut_launch_time_internal_orig);
+ bool changed =
+ DoublesConsideredDifferent(raw_score_orig, raw_score_, kScoreDelta) ||
+ DoublesConsideredDifferent(points_added_today_orig, points_added_today_,
+ kScoreDelta) ||
+ DoublesConsideredDifferent(last_engagement_time_internal_orig,
+ last_engagement_time_.ToInternalValue(),
+ kTimeDelta) ||
+ DoublesConsideredDifferent(last_shortcut_launch_time_internal_orig,
+ last_shortcut_launch_time_.ToInternalValue(),
+ kTimeDelta);
+
+ if (!changed)
+ return false;
+
+ score_dict->SetDouble(kRawScoreKey, raw_score_);
+ score_dict->SetDouble(kPointsAddedTodayKey, points_added_today_);
+ score_dict->SetDouble(kLastEngagementTimeKey,
+ last_engagement_time_.ToInternalValue());
+ score_dict->SetDouble(kLastShortcutLaunchTimeKey,
+ last_shortcut_launch_time_.ToInternalValue());
+
+ return true;
+}
+
+SiteEngagementScore::SiteEngagementScore(base::Clock* clock)
+ : clock_(clock),
+ raw_score_(0),
+ points_added_today_(0),
+ last_engagement_time_(),
+ last_shortcut_launch_time_() {}
+
+double SiteEngagementScore::DecayedScore() const {
+ // Note that users can change their clock, so from this system's perspective
+ // time can go backwards. If that does happen and the system detects that the
+ // current day is earlier than the last engagement, no decay (or growth) is
+ // applied.
+ int days_since_engagement = (clock_->Now() - last_engagement_time_).InDays();
+ if (days_since_engagement < 0)
+ return raw_score_;
+
+ int periods = days_since_engagement / GetDecayPeriodInDays();
+ return std::max(0.0, raw_score_ - periods * GetDecayPoints());
+}
+
+double SiteEngagementScore::BonusScore() const {
+ int days_since_shortcut_launch =
+ (clock_->Now() - last_shortcut_launch_time_).InDays();
+ if (days_since_shortcut_launch <= kMaxDaysSinceShortcutLaunch)
+ return GetWebAppInstalledPoints();
+
+ return 0;
+}
+
+void SiteEngagementScore::SetParamValuesForTesting() {
+ param_values[MAX_POINTS_PER_DAY] = 5;
+ param_values[DECAY_PERIOD_IN_DAYS] = 7;
+ param_values[DECAY_POINTS] = 5;
+ param_values[NAVIGATION_POINTS] = 0.5;
+ param_values[USER_INPUT_POINTS] = 0.05;
+ param_values[VISIBLE_MEDIA_POINTS] = 0.02;
+ param_values[HIDDEN_MEDIA_POINTS] = 0.01;
+ param_values[WEB_APP_INSTALLED_POINTS] = 5;
+ param_values[BOOTSTRAP_POINTS] = 8;
+ param_values[MEDIUM_ENGAGEMENT_BOUNDARY] = 5;
+ param_values[HIGH_ENGAGEMENT_BOUNDARY] = 50;
+
+ // This is set to zero to avoid interference with tests and is set when
+ // testing this functionality.
+ param_values[FIRST_DAILY_ENGAGEMENT] = 0;
+}
« no previous file with comments | « chrome/browser/engagement/site_engagement_score.h ('k') | chrome/browser/engagement/site_engagement_score_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698