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

Side by Side Diff: components/ntp_snippets/user_classifier.cc

Issue 2358983003: Making UserClassifier configurable by variation parameters (Closed)
Patch Set: Created 4 years, 2 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/ntp_snippets/user_classifier.h" 5 #include "components/ntp_snippets/user_classifier.h"
6 6
7 #include <float.h> 7 #include <float.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <string> 10 #include <string>
11 11
12 #include "base/metrics/histogram_macros.h" 12 #include "base/metrics/histogram_macros.h"
13 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
14 #include "components/ntp_snippets/features.h"
14 #include "components/ntp_snippets/pref_names.h" 15 #include "components/ntp_snippets/pref_names.h"
15 #include "components/prefs/pref_registry_simple.h" 16 #include "components/prefs/pref_registry_simple.h"
16 #include "components/prefs/pref_service.h" 17 #include "components/prefs/pref_service.h"
18 #include "components/variations/variations_associated_data.h"
17 19
18 namespace ntp_snippets { 20 namespace ntp_snippets {
19 21
20 namespace { 22 namespace {
21 23
22 // TODO(jkrcal): Make all of this configurable via variations_service.
23
24 // The discount factor for computing the discounted-average metrics. Must be 24 // The discount factor for computing the discounted-average metrics. Must be
25 // strictly larger than 0 and strictly smaller than 1! 25 // strictly larger than 0 and strictly smaller than 1!
26 const double kDiscountFactorPerDay = 0.25; 26 const double kDiscountFactorPerDay = 0.25;
27 const char kDiscountFactorPerDayParam[] =
28 "user_classifier_discount_factor_per_day";
27 29
28 // Never consider any larger interval than this (so that extreme situations such 30 // Never consider any larger interval than this (so that extreme situations such
29 // as losing your phone or going for a long offline vacation do not skew the 31 // as losing your phone or going for a long offline vacation do not skew the
30 // average too much). 32 // average too much).
31 const double kMaxHours = 7 * 24; 33 const double kMaxHours = 7 * 24;
34 const char kMaxHoursParam[] =
35 "user_classifier_max_hours";
Marc Treib 2016/09/22 12:29:05 fits on the previous line
jkrcal 2016/09/22 13:26:15 Done.
32 36
33 // Ignore events within |kMinHours| hours since the last event (|kMinHours| is 37 // Ignore events within |kMinHours| hours since the last event (|kMinHours| is
34 // the length of the browsing session where subsequent events of the same type 38 // the length of the browsing session where subsequent events of the same type
35 // do not count again). 39 // do not count again).
36 const double kMinHours = 0.5; 40 const double kMinHours = 0.5;
41 const char kMinHoursParam[] =
42 "user_classifier_min_hours";
Marc Treib 2016/09/22 12:29:05 here too
jkrcal 2016/09/22 13:26:15 Done.
37 43
38 // Classification constants. 44 // Classification constants.
39 const double kFrequentUserScrollsAtLeastOncePerHours = 24; 45 const double kActiveConsumerScrollsAtLeastOncePerHours = 24;
40 const double kOccasionalUserOpensNTPAtMostOncePerHours = 72; 46 const char kActiveConsumerScrollsAtLeastOncePerHoursParam[] =
47 "user_classifier_active_consumer_scrolls_at_least_once_per_hours";
41 48
49 const double kActiveConsumerOpensNTPAtLeastOncePerHours = 24;
50 const char kActiveConsumerOpensNTPAtLeastOncePerHoursParam[] =
51 "user_classifier_active_consumer_opens_ntp_at_least_once_per_hours";
52
53 const double kRareUserOpensNTPAtMostOncePerHours = 72;
54 const char kRareUserOpensNTPAtMostOncePerHoursParam[] =
55 "user_classifier_rare_user_opens_ntp_at_most_once_per_hours";
56
57 // Histograms for logging the estimated average hours to next event.
42 const char kHistogramAverageHoursToOpenNTP[] = 58 const char kHistogramAverageHoursToOpenNTP[] =
43 "NewTabPage.UserClassifier.AverageHoursToOpenNTP"; 59 "NewTabPage.UserClassifier.AverageHoursToOpenNTP";
44 const char kHistogramAverageHoursToShowSuggestions[] = 60 const char kHistogramAverageHoursToShowSuggestions[] =
45 "NewTabPage.UserClassifier.AverageHoursToShowSuggestions"; 61 "NewTabPage.UserClassifier.AverageHoursToShowSuggestions";
46 const char kHistogramAverageHoursToUseSuggestions[] = 62 const char kHistogramAverageHoursToUseSuggestions[] =
47 "NewTabPage.UserClassifier.AverageHoursToUseSuggestions"; 63 "NewTabPage.UserClassifier.AverageHoursToUseSuggestions";
48 64
49 // The enum used for iteration. 65 // The enum used for iteration.
50 const UserClassifier::Metric kMetrics[] = { 66 const UserClassifier::Metric kMetrics[] = {
51 UserClassifier::Metric::NTP_OPENED, 67 UserClassifier::Metric::NTP_OPENED,
52 UserClassifier::Metric::SUGGESTIONS_SHOWN, 68 UserClassifier::Metric::SUGGESTIONS_SHOWN,
53 UserClassifier::Metric::SUGGESTIONS_USED}; 69 UserClassifier::Metric::SUGGESTIONS_USED};
54 70
55 // The summary of the prefs. 71 // The summary of the prefs.
56 const char* kMetricKeys[] = { 72 const char* kMetricKeys[] = {
57 prefs::kUserClassifierAverageNTPOpenedPerHour, 73 prefs::kUserClassifierAverageNTPOpenedPerHour,
58 prefs::kUserClassifierAverageSuggestionsShownPerHour, 74 prefs::kUserClassifierAverageSuggestionsShownPerHour,
59 prefs::kUserClassifierAverageSuggestionsUsedPerHour}; 75 prefs::kUserClassifierAverageSuggestionsUsedPerHour};
60 const char* kLastTimeKeys[] = {prefs::kUserClassifierLastTimeToOpenNTP, 76 const char* kLastTimeKeys[] = {prefs::kUserClassifierLastTimeToOpenNTP,
61 prefs::kUserClassifierLastTimeToShowSuggestions, 77 prefs::kUserClassifierLastTimeToShowSuggestions,
62 prefs::kUserClassifierLastTimeToUseSuggestions}; 78 prefs::kUserClassifierLastTimeToUseSuggestions};
63 79
64 // Default lengths of the intervals for new users for the metrics. 80 // Default lengths of the intervals for new users for the metrics.
65 const double kDefaults[] = {24, 36, 48}; 81 const double kDefaults[] = {24, 36, 48};
82 const char* kDefaultParams[] = {
Marc Treib 2016/09/22 12:29:05 I think these could use a bit more descriptive nam
jkrcal 2016/09/22 13:26:14 Done.
83 "user_classifier_default_interval_ntp_opened",
84 "user_classifier_default_interval_suggestions_shown",
85 "user_classifier_default_interval_suggestions_used"};
66 86
67 static_assert(arraysize(kMetrics) == 87 static_assert(arraysize(kMetrics) ==
68 static_cast<int>(UserClassifier::Metric::COUNT) && 88 static_cast<int>(UserClassifier::Metric::COUNT) &&
69 arraysize(kMetricKeys) == 89 arraysize(kMetricKeys) ==
70 static_cast<int>(UserClassifier::Metric::COUNT) && 90 static_cast<int>(UserClassifier::Metric::COUNT) &&
71 arraysize(kLastTimeKeys) == 91 arraysize(kLastTimeKeys) ==
72 static_cast<int>(UserClassifier::Metric::COUNT) && 92 static_cast<int>(UserClassifier::Metric::COUNT) &&
73 arraysize(kDefaults) == 93 arraysize(kDefaults) ==
74 static_cast<int>(UserClassifier::Metric::COUNT), 94 static_cast<int>(UserClassifier::Metric::COUNT),
Marc Treib 2016/09/22 12:29:05 Add kDefaultParams?
jkrcal 2016/09/22 13:26:15 Done.
75 "Fill in info for all metrics."); 95 "Fill in info for all metrics.");
76 96
97 double GetParamValue(const char* param_name, double default_value) {
98 std::string param_value_str = variations::GetVariationParamValueByFeature(
99 kArticleSuggestionsFeature, param_name);
100 double param_value = 0;
101 if (!base::StringToDouble(param_value_str, &param_value)) {
102 LOG_IF(WARNING, !param_value_str.empty())
103 << "Invalid variation parameter for " << param_name;
104 return default_value;
105 }
106 return param_value;
107 }
108
77 // Computes the discount rate. 109 // Computes the discount rate.
78 double GetDiscountRatePerHour() { 110 double GetDiscountRatePerHour() {
111 double discount_factor_per_day =
112 GetParamValue(kDiscountFactorPerDayParam, kDiscountFactorPerDay);
79 // Compute discount_rate_per_hour such that 113 // Compute discount_rate_per_hour such that
80 // kDiscountFactorPerDay = 1 - e^{-discount_rate_per_hour * 24}. 114 // discount_factor_per_day = 1 - e^{-discount_rate_per_hour * 24}.
81 return std::log(1.0 / (1.0 - kDiscountFactorPerDay)) / 24.0; 115 return std::log(1.0 / (1.0 - discount_factor_per_day)) / 24.0;
116 }
117
118 double GetDefaultEstimate(UserClassifier::Metric metric) {
Marc Treib 2016/09/22 12:29:05 GetDefaultEstimateHoursBetweenEvents or GetInitial
jkrcal 2016/09/22 13:26:15 Done. GetInitialHoursBetweenEvents to match the co
119 return GetParamValue(kDefaultParams[static_cast<int>(metric)],
120 kDefaults[static_cast<int>(metric)]);
121 }
122
123 double GetMinHours() {
124 return GetParamValue(kMinHoursParam, kMinHours);
125 }
126
127 double GetMaxHours() {
128 return GetParamValue(kMaxHoursParam, kMaxHours);
82 } 129 }
83 130
84 // Returns the new value of the metric using its |old_value|, assuming 131 // Returns the new value of the metric using its |old_value|, assuming
85 // |hours_since_last_time| hours have passed since it was last discounted. 132 // |hours_since_last_time| hours have passed since it was last discounted.
86 double DiscountMetric(double old_value, 133 double DiscountMetric(double old_value,
87 double hours_since_last_time, 134 double hours_since_last_time,
88 double discount_rate_per_hour) { 135 double discount_rate_per_hour) {
89 // Compute the new discounted average according to the formula 136 // Compute the new discounted average according to the formula
90 // avg_events := e^{-discount_rate_per_hour * hours_since} * avg_events 137 // avg_events := e^{-discount_rate_per_hour * hours_since} * avg_events
91 return std::exp(-discount_rate_per_hour * hours_since_last_time) * old_value; 138 return std::exp(-discount_rate_per_hour * hours_since_last_time) * old_value;
92 } 139 }
93 140
94 // Compute the number of hours between two events for the given metric value 141 // Compute the number of hours between two events for the given metric value
95 // assuming the events were equally distributed. 142 // assuming the events were equally distributed.
96 double GetEstimateHoursBetweenEvents(double metric_value, 143 double GetEstimateHoursBetweenEvents(double metric_value,
97 double discount_rate_per_hour) { 144 double discount_rate_per_hour,
145 double min_hours,
146 double max_hours) {
98 // The computation below is well-defined only for |metric_value| > 1 (log of 147 // The computation below is well-defined only for |metric_value| > 1 (log of
99 // negative value or division by zero). When |metric_value| -> 1, the estimate 148 // negative value or division by zero). When |metric_value| -> 1, the estimate
100 // below -> infinity, so kMaxHours is a natural result, here. 149 // below -> infinity, so max_hours is a natural result, here.
101 if (metric_value <= 1) 150 if (metric_value <= 1)
102 return kMaxHours; 151 return max_hours;
103 152
104 // This is the estimate with the assumption that last event happened right 153 // This is the estimate with the assumption that last event happened right
105 // now and the system is in the steady-state. Solve estimate_hours in the 154 // now and the system is in the steady-state. Solve estimate_hours in the
106 // steady-state equation: 155 // steady-state equation:
107 // metric_value = 1 + e^{-discount_rate * estimate_hours} * metric_value, 156 // metric_value = 1 + e^{-discount_rate * estimate_hours} * metric_value,
108 // i.e. 157 // i.e.
109 // -discount_rate * estimate_hours = log((metric_value - 1) / metric_value), 158 // -discount_rate * estimate_hours = log((metric_value - 1) / metric_value),
110 // discount_rate * estimate_hours = log(metric_value / (metric_value - 1)), 159 // discount_rate * estimate_hours = log(metric_value / (metric_value - 1)),
111 // estimate_hours = log(metric_value / (metric_value - 1)) / discount_rate. 160 // estimate_hours = log(metric_value / (metric_value - 1)) / discount_rate.
112 double estimate_hours = 161 double estimate_hours =
113 std::log(metric_value / (metric_value - 1)) / discount_rate_per_hour; 162 std::log(metric_value / (metric_value - 1)) / discount_rate_per_hour;
114 return std::max(kMinHours, std::min(kMaxHours, estimate_hours)); 163 return std::max(min_hours, std::min(max_hours, estimate_hours));
115 } 164 }
116 165
117 // The inverse of GetEstimateHoursBetweenEvents(). 166 // The inverse of GetEstimateHoursBetweenEvents().
118 double GetMetricValueForEstimateHoursBetweenEvents( 167 double GetMetricValueForEstimateHoursBetweenEvents(
119 double estimate_hours, 168 double estimate_hours,
120 double discount_rate_per_hour) { 169 double discount_rate_per_hour,
121 // Keep the input value within [kMinHours, kMaxHours]. 170 double min_hours,
122 estimate_hours = std::max(kMinHours, std::min(kMaxHours, estimate_hours)); 171 double max_hours) {
123 172 // Keep the input value within [min_hours, max_hours].
173 estimate_hours = std::max(min_hours, std::min(max_hours, estimate_hours));
124 // Return |metric_value| such that GetEstimateHoursBetweenEvents for 174 // Return |metric_value| such that GetEstimateHoursBetweenEvents for
125 // |metric_value| returns |estimate_hours|. Thus, solve |metric_value| in 175 // |metric_value| returns |estimate_hours|. Thus, solve |metric_value| in
126 // metric_value = 1 + e^{-discount_rate * estimate_hours} * metric_value, 176 // metric_value = 1 + e^{-discount_rate * estimate_hours} * metric_value,
127 // i.e. 177 // i.e.
128 // metric_value * (1 - e^{-discount_rate * estimate_hours}) = 1, 178 // metric_value * (1 - e^{-discount_rate * estimate_hours}) = 1,
129 // metric_value = 1 / (1 - e^{-discount_rate * estimate_hours}). 179 // metric_value = 1 / (1 - e^{-discount_rate * estimate_hours}).
130 return 1.0 / (1.0 - std::exp(-discount_rate_per_hour * estimate_hours)); 180 return 1.0 / (1.0 - std::exp(-discount_rate_per_hour * estimate_hours));
131 } 181 }
132 182
133 } // namespace 183 } // namespace
134 184
135 UserClassifier::UserClassifier(PrefService* pref_service) 185 UserClassifier::UserClassifier(PrefService* pref_service)
136 : pref_service_(pref_service), 186 : pref_service_(pref_service),
137 discount_rate_per_hour_(GetDiscountRatePerHour()) { 187 discount_rate_per_hour_(GetDiscountRatePerHour()),
188 min_hours_(GetMinHours()),
189 max_hours_(GetMaxHours()),
190 active_consumer_scrolls_at_least_once_per_hours_(
191 GetParamValue(kActiveConsumerScrollsAtLeastOncePerHoursParam,
192 kActiveConsumerScrollsAtLeastOncePerHours)),
193 active_consumer_opens_ntp_at_least_once_per_hours_(
194 GetParamValue(kActiveConsumerOpensNTPAtLeastOncePerHoursParam,
195 kActiveConsumerOpensNTPAtLeastOncePerHours)),
196 rare_user_opens_ntp_at_most_once_per_hours_(
197 GetParamValue(kRareUserOpensNTPAtMostOncePerHoursParam,
198 kRareUserOpensNTPAtMostOncePerHours)) {
138 // The pref_service_ can be null in tests. 199 // The pref_service_ can be null in tests.
139 if (!pref_service_) 200 if (!pref_service_)
140 return; 201 return;
141 202
203 // TODO(jkrcal): Store the current discount rate per hour into prefs. If it
204 // differs from the previous value, rescale the metric values so that the
205 // expectation does not change abruptly!
206
142 // Initialize the prefs storing the last time: the counter has just started! 207 // Initialize the prefs storing the last time: the counter has just started!
143 for (const Metric metric : kMetrics) { 208 for (const Metric metric : kMetrics) {
144 if (!HasLastTime(metric)) 209 if (!HasLastTime(metric))
145 SetLastTimeToNow(metric); 210 SetLastTimeToNow(metric);
146 } 211 }
147 } 212 }
148 213
149 UserClassifier::~UserClassifier() {} 214 UserClassifier::~UserClassifier() {}
150 215
151 // static 216 // static
152 void UserClassifier::RegisterProfilePrefs(PrefRegistrySimple* registry) { 217 void UserClassifier::RegisterProfilePrefs(PrefRegistrySimple* registry) {
218 double discount_rate = GetDiscountRatePerHour();
219 double min_hours = GetMinHours();
220 double max_hours = GetMaxHours();
221
153 for (Metric metric : kMetrics) { 222 for (Metric metric : kMetrics) {
154 double default_metric_value = GetMetricValueForEstimateHoursBetweenEvents( 223 double default_metric_value = GetMetricValueForEstimateHoursBetweenEvents(
155 kDefaults[static_cast<int>(metric)], GetDiscountRatePerHour()); 224 GetDefaultEstimate(metric), discount_rate, min_hours, max_hours);
156 registry->RegisterDoublePref(kMetricKeys[static_cast<int>(metric)], 225 registry->RegisterDoublePref(kMetricKeys[static_cast<int>(metric)],
157 default_metric_value); 226 default_metric_value);
158 registry->RegisterInt64Pref(kLastTimeKeys[static_cast<int>(metric)], 0); 227 registry->RegisterInt64Pref(kLastTimeKeys[static_cast<int>(metric)], 0);
159 } 228 }
160 } 229 }
161 230
162 void UserClassifier::OnEvent(Metric metric) { 231 void UserClassifier::OnEvent(Metric metric) {
163 DCHECK_NE(metric, Metric::COUNT); 232 DCHECK_NE(metric, Metric::COUNT);
164 double metric_value = UpdateMetricOnEvent(metric); 233 double metric_value = UpdateMetricOnEvent(metric);
165 234
166 double avg = 235 double avg = GetEstimateHoursBetweenEvents(
167 GetEstimateHoursBetweenEvents(metric_value, discount_rate_per_hour_); 236 metric_value, discount_rate_per_hour_, min_hours_, max_hours_);
168 switch (metric) { 237 switch (metric) {
169 case Metric::NTP_OPENED: 238 case Metric::NTP_OPENED:
170 UMA_HISTOGRAM_CUSTOM_COUNTS(kHistogramAverageHoursToOpenNTP, avg, 1, 239 UMA_HISTOGRAM_CUSTOM_COUNTS(kHistogramAverageHoursToOpenNTP, avg, 1,
171 kMaxHours, 50); 240 kMaxHours, 50);
Marc Treib 2016/09/22 12:29:05 Hm, so the histograms still use kMaxHours rather t
jkrcal 2016/09/22 13:26:14 Oh, I missed this, thanks! Comments added.
172 break; 241 break;
173 case Metric::SUGGESTIONS_SHOWN: 242 case Metric::SUGGESTIONS_SHOWN:
174 UMA_HISTOGRAM_CUSTOM_COUNTS(kHistogramAverageHoursToShowSuggestions, avg, 243 UMA_HISTOGRAM_CUSTOM_COUNTS(kHistogramAverageHoursToShowSuggestions, avg,
175 1, kMaxHours, 50); 244 1, kMaxHours, 50);
176 break; 245 break;
177 case Metric::SUGGESTIONS_USED: 246 case Metric::SUGGESTIONS_USED:
178 UMA_HISTOGRAM_CUSTOM_COUNTS(kHistogramAverageHoursToUseSuggestions, avg, 247 UMA_HISTOGRAM_CUSTOM_COUNTS(kHistogramAverageHoursToUseSuggestions, avg,
179 1, kMaxHours, 50); 248 1, kMaxHours, 50);
180 break; 249 break;
181 case Metric::COUNT: 250 case Metric::COUNT:
182 NOTREACHED(); 251 NOTREACHED();
183 break; 252 break;
184 } 253 }
185 } 254 }
186 255
187 double UserClassifier::GetEstimatedAvgTime(Metric metric) const { 256 double UserClassifier::GetEstimatedAvgTime(Metric metric) const {
188 DCHECK_NE(metric, Metric::COUNT); 257 DCHECK_NE(metric, Metric::COUNT);
189 double metric_value = GetUpToDateMetricValue(metric); 258 double metric_value = GetUpToDateMetricValue(metric);
190 return GetEstimateHoursBetweenEvents(metric_value, discount_rate_per_hour_); 259 return GetEstimateHoursBetweenEvents(metric_value, discount_rate_per_hour_,
260 min_hours_, max_hours_);
191 } 261 }
192 262
193 UserClassifier::UserClass UserClassifier::GetUserClass() const { 263 UserClassifier::UserClass UserClassifier::GetUserClass() const {
194 if (GetEstimatedAvgTime(Metric::NTP_OPENED) >= 264 double avg_time_to_ntp = GetEstimatedAvgTime(Metric::NTP_OPENED);
195 kOccasionalUserOpensNTPAtMostOncePerHours) { 265
266 if (avg_time_to_ntp >= rare_user_opens_ntp_at_most_once_per_hours_) {
196 return UserClass::RARE_NTP_USER; 267 return UserClass::RARE_NTP_USER;
197 } 268 }
198 269
199 if (GetEstimatedAvgTime(Metric::SUGGESTIONS_SHOWN) <= 270 double avg_time_to_scroll = GetEstimatedAvgTime(Metric::SUGGESTIONS_SHOWN);
200 kFrequentUserScrollsAtLeastOncePerHours) { 271
272 if (avg_time_to_ntp <= active_consumer_opens_ntp_at_least_once_per_hours_ &&
273 avg_time_to_scroll <= active_consumer_scrolls_at_least_once_per_hours_) {
201 return UserClass::ACTIVE_SUGGESTIONS_CONSUMER; 274 return UserClass::ACTIVE_SUGGESTIONS_CONSUMER;
202 } 275 }
203 276
204 return UserClass::ACTIVE_NTP_USER; 277 return UserClass::ACTIVE_NTP_USER;
205 } 278 }
206 279
207 std::string UserClassifier::GetUserClassDescriptionForDebugging() const { 280 std::string UserClassifier::GetUserClassDescriptionForDebugging() const {
208 switch (GetUserClass()) { 281 switch (GetUserClass()) {
209 case UserClass::RARE_NTP_USER: 282 case UserClass::RARE_NTP_USER:
210 return "Rare user of the NTP"; 283 return "Rare user of the NTP";
(...skipping 16 matching lines...) Expand all
227 SetLastTimeToNow(metric); 300 SetLastTimeToNow(metric);
228 } 301 }
229 } 302 }
230 303
231 double UserClassifier::UpdateMetricOnEvent(Metric metric) { 304 double UserClassifier::UpdateMetricOnEvent(Metric metric) {
232 // The pref_service_ can be null in tests. 305 // The pref_service_ can be null in tests.
233 if (!pref_service_) 306 if (!pref_service_)
234 return 0; 307 return 0;
235 308
236 double hours_since_last_time = 309 double hours_since_last_time =
237 std::min(kMaxHours, GetHoursSinceLastTime(metric)); 310 std::min(max_hours_, GetHoursSinceLastTime(metric));
238 // Ignore events within the same "browsing session". 311 // Ignore events within the same "browsing session".
239 if (hours_since_last_time < kMinHours) 312 if (hours_since_last_time < min_hours_)
240 return GetUpToDateMetricValue(metric); 313 return GetUpToDateMetricValue(metric);
241 314
242 SetLastTimeToNow(metric); 315 SetLastTimeToNow(metric);
243 316
244 double metric_value = GetMetricValue(metric); 317 double metric_value = GetMetricValue(metric);
245 // Add 1 to the discounted metric as the event has happened right now. 318 // Add 1 to the discounted metric as the event has happened right now.
246 double new_metric_value = 319 double new_metric_value =
247 1 + DiscountMetric(metric_value, hours_since_last_time, 320 1 + DiscountMetric(metric_value, hours_since_last_time,
248 discount_rate_per_hour_); 321 discount_rate_per_hour_);
249 SetMetricValue(metric, new_metric_value); 322 SetMetricValue(metric, new_metric_value);
250 return new_metric_value; 323 return new_metric_value;
251 } 324 }
252 325
253 double UserClassifier::GetUpToDateMetricValue(Metric metric) const { 326 double UserClassifier::GetUpToDateMetricValue(Metric metric) const {
254 // The pref_service_ can be null in tests. 327 // The pref_service_ can be null in tests.
255 if (!pref_service_) 328 if (!pref_service_)
256 return 0; 329 return 0;
257 330
258 double hours_since_last_time = 331 double hours_since_last_time =
259 std::min(kMaxHours, GetHoursSinceLastTime(metric)); 332 std::min(max_hours_, GetHoursSinceLastTime(metric));
260 333
261 double metric_value = GetMetricValue(metric); 334 double metric_value = GetMetricValue(metric);
262 return DiscountMetric(metric_value, hours_since_last_time, 335 return DiscountMetric(metric_value, hours_since_last_time,
263 discount_rate_per_hour_); 336 discount_rate_per_hour_);
264 } 337 }
265 338
266 double UserClassifier::GetHoursSinceLastTime(Metric metric) const { 339 double UserClassifier::GetHoursSinceLastTime(Metric metric) const {
267 if (!HasLastTime(metric)) 340 if (!HasLastTime(metric))
268 return 0; 341 return 0;
269 342
(...skipping 18 matching lines...) Expand all
288 361
289 void UserClassifier::SetMetricValue(Metric metric, double metric_value) { 362 void UserClassifier::SetMetricValue(Metric metric, double metric_value) {
290 pref_service_->SetDouble(kMetricKeys[static_cast<int>(metric)], metric_value); 363 pref_service_->SetDouble(kMetricKeys[static_cast<int>(metric)], metric_value);
291 } 364 }
292 365
293 void UserClassifier::ClearMetricValue(Metric metric) { 366 void UserClassifier::ClearMetricValue(Metric metric) {
294 pref_service_->ClearPref(kMetricKeys[static_cast<int>(metric)]); 367 pref_service_->ClearPref(kMetricKeys[static_cast<int>(metric)]);
295 } 368 }
296 369
297 } // namespace ntp_snippets 370 } // namespace ntp_snippets
OLDNEW
« components/ntp_snippets/user_classifier.h ('K') | « components/ntp_snippets/user_classifier.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698