OLD | NEW |
---|---|
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/category_rankers/click_based_category_ranker.h " | 5 #include "components/ntp_snippets/category_rankers/click_based_category_ranker.h " |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
11 #include "components/ntp_snippets/category_rankers/constant_category_ranker.h" | 11 #include "components/ntp_snippets/category_rankers/constant_category_ranker.h" |
12 #include "components/ntp_snippets/features.h" | |
12 #include "components/ntp_snippets/pref_names.h" | 13 #include "components/ntp_snippets/pref_names.h" |
13 #include "components/prefs/pref_registry_simple.h" | 14 #include "components/prefs/pref_registry_simple.h" |
14 #include "components/prefs/pref_service.h" | 15 #include "components/prefs/pref_service.h" |
16 #include "components/variations/variations_associated_data.h" | |
15 | 17 |
16 namespace ntp_snippets { | 18 namespace ntp_snippets { |
17 | 19 |
18 namespace { | 20 namespace { |
19 | 21 |
20 // In order to increase stability and predictability of the order, an extra | 22 // In order to increase stability and predictability of the order, an extra |
21 // level of "confidence" is required before moving a category upwards. In other | 23 // level of "confidence" is required before moving a category upwards. In other |
22 // words, the category is moved not when it reaches the previous one, but rather | 24 // words, the category is moved not when it reaches the previous one, but rather |
23 // when it leads by some amount. We refer to this required extra "confidence" as | 25 // when it leads by some amount. We refer to this required extra "confidence" as |
24 // a passing margin. Each position has its own passing margin. The category is | 26 // a passing margin. Each position has its own passing margin. The category is |
(...skipping 24 matching lines...) Expand all Loading... | |
49 const base::TimeDelta kTimeBetweenDecays = base::TimeDelta::FromDays(1); | 51 const base::TimeDelta kTimeBetweenDecays = base::TimeDelta::FromDays(1); |
50 | 52 |
51 // Decay factor as a fraction. The current value approximates the seventh root | 53 // Decay factor as a fraction. The current value approximates the seventh root |
52 // of 0.5. This yields a 50% decay per seven decays. Seven weak decays are used | 54 // of 0.5. This yields a 50% decay per seven decays. Seven weak decays are used |
53 // instead of one 50% decay in order to decrease difference of click weight in | 55 // instead of one 50% decay in order to decrease difference of click weight in |
54 // time. | 56 // time. |
55 const int kDecayFactorNumerator = 91; | 57 const int kDecayFactorNumerator = 91; |
56 const int kDecayFactorDenominator = 100; // pow(0.91, 7) = 0.517 | 58 const int kDecayFactorDenominator = 100; // pow(0.91, 7) = 0.517 |
57 | 59 |
58 // Number of positions by which a dismissed category is downgraded. | 60 // Number of positions by which a dismissed category is downgraded. |
59 const int kDismissedCategoryPenalty = 1; | 61 const int kDefaultDismissedCategoryPenalty = 1; |
62 const char* kDismissedCategoryPenaltyParamName = | |
63 "click_based_category_ranker_dismissed_category_penalty"; | |
60 | 64 |
61 const char kCategoryIdKey[] = "category"; | 65 const char kCategoryIdKey[] = "category"; |
62 const char kClicksKey[] = "clicks"; | 66 const char kClicksKey[] = "clicks"; |
63 | 67 |
68 int GetDismissedCategoryPenaltyVariationValue() { | |
69 return variations::GetVariationParamByFeatureAsInt( | |
vitaliii
2017/01/05 09:28:18
Are you aware of any way to change the value in te
jkrcal
2017/01/05 10:34:36
Sure, see variations::testing::VariationParamsMana
vitaliii
2017/01/05 12:42:28
Done.
GetDismissedCategoryPenalty() allows to exp
jkrcal
2017/01/05 13:48:07
I think you get better tests if you always overrid
vitaliii
2017/01/16 16:00:16
Partially done.
I override to 2 only where this i
| |
70 kCategoryRanker, kDismissedCategoryPenaltyParamName, | |
71 kDefaultDismissedCategoryPenalty); | |
72 } | |
73 | |
64 } // namespace | 74 } // namespace |
65 | 75 |
66 ClickBasedCategoryRanker::ClickBasedCategoryRanker( | 76 ClickBasedCategoryRanker::ClickBasedCategoryRanker( |
67 PrefService* pref_service, | 77 PrefService* pref_service, |
68 std::unique_ptr<base::Clock> clock) | 78 std::unique_ptr<base::Clock> clock) |
69 : pref_service_(pref_service), clock_(std::move(clock)) { | 79 : pref_service_(pref_service), clock_(std::move(clock)) { |
70 if (!ReadOrderFromPrefs(&ordered_categories_)) { | 80 if (!ReadOrderFromPrefs(&ordered_categories_)) { |
71 // TODO(crbug.com/676273): Handle adding new hardcoded KnownCategories to | 81 // TODO(crbug.com/676273): Handle adding new hardcoded KnownCategories to |
72 // existing order from prefs. Currently such new category is completely | 82 // existing order from prefs. Currently such new category is completely |
73 // ignored and may be never shown. | 83 // ignored and may be never shown. |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 StoreOrderToPrefs(ordered_categories_); | 185 StoreOrderToPrefs(ordered_categories_); |
176 } | 186 } |
177 | 187 |
178 void ClickBasedCategoryRanker::OnCategoryDismissed(Category category) { | 188 void ClickBasedCategoryRanker::OnCategoryDismissed(Category category) { |
179 if (!ContainsCategory(category)) { | 189 if (!ContainsCategory(category)) { |
180 LOG(DFATAL) << "The category with ID " << category.id() | 190 LOG(DFATAL) << "The category with ID " << category.id() |
181 << " has not been added using AppendCategoryIfNecessary."; | 191 << " has not been added using AppendCategoryIfNecessary."; |
182 return; | 192 return; |
183 } | 193 } |
184 | 194 |
195 const int penalty = GetDismissedCategoryPenaltyVariationValue(); | |
196 if (penalty == 0) { | |
vitaliii
2017/01/05 09:28:18
Is this ok in your view? Or should I consider pena
jkrcal
2017/01/05 10:34:36
This is okay, let's keep it simple.
vitaliii
2017/01/05 12:42:28
Acknowledged.
| |
197 // The dismissed category penalty is turned off, the call is ignored. | |
198 return; | |
199 } | |
200 | |
185 std::vector<RankedCategory>::iterator current = FindCategory(category); | 201 std::vector<RankedCategory>::iterator current = FindCategory(category); |
186 for (int downgrade = 0; downgrade < kDismissedCategoryPenalty; ++downgrade) { | 202 for (int downgrade = 0; downgrade < penalty; ++downgrade) { |
187 std::vector<RankedCategory>::iterator next = current + 1; | 203 std::vector<RankedCategory>::iterator next = current + 1; |
188 if (next == ordered_categories_.end()) { | 204 if (next == ordered_categories_.end()) { |
189 break; | 205 break; |
190 } | 206 } |
191 std::swap(*current, *next); | 207 std::swap(*current, *next); |
192 current = next; | 208 current = next; |
193 } | 209 } |
194 | 210 |
195 int next_clicks = 0; | 211 int next_clicks = 0; |
196 std::vector<RankedCategory>::iterator next = current + 1; | 212 std::vector<RankedCategory>::iterator next = current + 1; |
(...skipping 22 matching lines...) Expand all Loading... | |
219 return kPassingMargin; | 235 return kPassingMargin; |
220 } | 236 } |
221 | 237 |
222 // static | 238 // static |
223 int ClickBasedCategoryRanker::GetNumTopCategoriesWithExtraMargin() { | 239 int ClickBasedCategoryRanker::GetNumTopCategoriesWithExtraMargin() { |
224 return kNumTopCategoriesWithExtraMargin; | 240 return kNumTopCategoriesWithExtraMargin; |
225 } | 241 } |
226 | 242 |
227 // static | 243 // static |
228 int ClickBasedCategoryRanker::GetDismissedCategoryPenalty() { | 244 int ClickBasedCategoryRanker::GetDismissedCategoryPenalty() { |
229 return kDismissedCategoryPenalty; | 245 return GetDismissedCategoryPenaltyVariationValue(); |
230 } | 246 } |
231 | 247 |
232 ClickBasedCategoryRanker::RankedCategory::RankedCategory(Category category, | 248 ClickBasedCategoryRanker::RankedCategory::RankedCategory(Category category, |
233 int clicks) | 249 int clicks) |
234 : category(category), clicks(clicks) {} | 250 : category(category), clicks(clicks) {} |
235 | 251 |
236 // Returns passing margin for a given position taking into account whether it is | 252 // Returns passing margin for a given position taking into account whether it is |
237 // a top category. | 253 // a top category. |
238 int ClickBasedCategoryRanker::GetPositionPassingMargin( | 254 int ClickBasedCategoryRanker::GetPositionPassingMargin( |
239 std::vector<RankedCategory>::const_iterator category_position) const { | 255 std::vector<RankedCategory>::const_iterator category_position) const { |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
376 num_pending_decays * kTimeBetweenDecays); | 392 num_pending_decays * kTimeBetweenDecays); |
377 | 393 |
378 if (executed_decays > 0) { | 394 if (executed_decays > 0) { |
379 StoreOrderToPrefs(ordered_categories_); | 395 StoreOrderToPrefs(ordered_categories_); |
380 return true; | 396 return true; |
381 } | 397 } |
382 return false; | 398 return false; |
383 } | 399 } |
384 | 400 |
385 } // namespace ntp_snippets | 401 } // namespace ntp_snippets |
OLD | NEW |