blob: 5f998d602207139b04cfd93c838100768fabaaf7 [file] [log] [blame]
// 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 <memory>
#include <string>
#include <vector>
#include "base/optional.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "components/ntp_snippets/category.h"
#include "components/ntp_snippets/category_rankers/category_ranker.h"
class PrefRegistrySimple;
class PrefService;
namespace ntp_snippets {
// An implementation of a CategoryRanker based on a number of clicks per
// category. Initial order is hardcoded, but sections with more clicks are moved
// to the top. The new remote categories must be registered using
// AppendCategoryIfNecessary. All other categories must be hardcoded in the
// initial order. The order and category usage data are persisted in prefs and
// reloaded on startup.
// TODO( Remove unused categories from prefs.
class ClickBasedCategoryRanker : public CategoryRanker {
explicit ClickBasedCategoryRanker(PrefService* pref_service,
base::Clock* clock);
~ClickBasedCategoryRanker() override;
// CategoryRanker implementation.
bool Compare(Category left, Category right) const override;
void ClearHistory(base::Time begin, base::Time end) override;
void AppendCategoryIfNecessary(Category category) override;
void InsertCategoryBeforeIfNecessary(Category category_to_insert,
Category anchor) override;
void InsertCategoryAfterIfNecessary(Category category_to_insert,
Category anchor) override;
std::vector<CategoryRanker::DebugDataItem> GetDebugData() override;
void OnSuggestionOpened(Category category) override;
void OnCategoryDismissed(Category category) override;
// Returns time when last decay occured. For testing only.
base::Time GetLastDecayTime() const;
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
// Returns passing margin, i.e. a number of extra clicks required to move a
// category upwards. For testing only.
static int GetPassingMargin();
// Returns number of top categories with extra margin (i.e. with increased
// passing margin). For testing only.
static int GetNumTopCategoriesWithExtraMargin();
// Returns number of positions by which a dismissed category is downgraded.
// For testing only.
static int GetDismissedCategoryPenalty();
struct RankedCategory {
Category category;
int clicks;
base::Time last_dismissed;
RankedCategory(Category category,
int clicks,
const base::Time& last_dismissed);
base::Optional<Category> DeterminePromotedCategory();
int GetPositionPassingMargin(
std::vector<RankedCategory>::const_iterator category_position) const;
void RestoreDefaultOrder();
void AppendKnownCategory(KnownCategories known_category);
bool ReadOrderFromPrefs(std::vector<RankedCategory>* result_categories) const;
void StoreOrderToPrefs(const std::vector<RankedCategory>& ordered_categories);
std::vector<RankedCategory>::iterator FindCategory(Category category);
bool ContainsCategory(Category category) const;
void InsertCategoryRelativeToIfNecessary(Category category_to_insert,
Category anchor,
bool after);
base::Time ReadLastDecayTimeFromPrefs() const;
void StoreLastDecayTimeToPrefs(base::Time last_decay_time);
bool IsEnoughClicksToDecay() const;
bool DecayClicksIfNeeded();
std::vector<RankedCategory> ordered_categories_;
PrefService* pref_service_;
base::Clock* clock_;
base::Optional<Category> promoted_category_;
} // namespace ntp_snippets