Index: components/translate/core/browser/language_model.cc |
diff --git a/components/translate/core/browser/language_model.cc b/components/translate/core/browser/language_model.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..60c435a80d8ed83c0f0a24463852737a08678de1 |
--- /dev/null |
+++ b/components/translate/core/browser/language_model.cc |
@@ -0,0 +1,127 @@ |
+// 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 "components/translate/core/browser/language_model.h" |
+ |
+#include <algorithm> |
+#include <map> |
+#include <set> |
+ |
+#include "components/prefs/pref_registry_simple.h" |
+#include "components/prefs/pref_service.h" |
+#include "components/prefs/scoped_user_pref_update.h" |
+ |
+namespace translate { |
+ |
+namespace { |
+ |
+const char kLanguageModelCounters[] = "language_model_counters"; |
+ |
+const int kMaxCountersSum = 1000; |
+const float kCutoffRatio = 0.005f; |
+const float kDiscountFactor = 0.75f; |
+ |
+// Gets the sum of the counter for all languages in the model. |
+int GetCountersSum(const base::DictionaryValue& dict) { |
+ int sum = 0; |
+ int counter_value = 0; |
+ for (base::DictionaryValue::Iterator itr(dict); !itr.IsAtEnd(); |
+ itr.Advance()) { |
+ if (itr.value().GetAsInteger(&counter_value)) |
+ sum += counter_value; |
+ } |
+ return sum; |
+} |
+ |
+// Removes languages with small counter values and discount remaining counters. |
+void DiscountAndCleanCounters(base::DictionaryValue* dict) { |
+ std::set<std::string> remove_keys; |
+ |
+ int counter_value = 0; |
+ for (base::DictionaryValue::Iterator itr(*dict); !itr.IsAtEnd(); |
+ itr.Advance()) { |
+ // Remove languages with invalid or small values. |
+ if (!itr.value().GetAsInteger(&counter_value) || |
+ counter_value < (kCutoffRatio * kMaxCountersSum)) { |
+ remove_keys.insert(itr.key()); |
+ continue; |
+ } |
+ |
+ // Discount the value. |
+ dict->SetInteger(itr.key(), counter_value * kDiscountFactor); |
+ } |
+ |
+ for (const std::string& lang_to_remove : remove_keys) |
+ dict->Remove(lang_to_remove, nullptr); |
+} |
+ |
+// Transforms the counters from prefs into a list of LanguageInfo structs. |
+std::vector<LanguageModel::LanguageInfo> GetAllLanguages( |
+ const base::DictionaryValue& dict) { |
+ |
+ std::vector<LanguageModel::LanguageInfo> top_languages; |
+ int counters_sum = GetCountersSum(dict); |
+ |
+ int counter_value = 0; |
+ for (base::DictionaryValue::Iterator itr(dict); !itr.IsAtEnd(); |
+ itr.Advance()) { |
+ if (!itr.value().GetAsInteger(&counter_value)) |
+ continue; |
+ top_languages.push_back( |
+ {itr.key(), static_cast<float>(counter_value) / counters_sum}); |
+ } |
+ return top_languages; |
+} |
+ |
+} // namespace |
+ |
+LanguageModel::LanguageModel(PrefService* pref_service) |
+ : pref_service_(pref_service) {} |
+ |
+LanguageModel::~LanguageModel() = default; |
+ |
+// static |
+void LanguageModel::RegisterProfilePrefs(PrefRegistrySimple* registry) { |
+ registry->RegisterDictionaryPref(kLanguageModelCounters); |
+} |
+ |
+std::vector<LanguageModel::LanguageInfo> LanguageModel::GetTopLanguages() |
+ const { |
+ std::vector<LanguageModel::LanguageInfo> top_languages = |
+ GetAllLanguages(*pref_service_->GetDictionary(kLanguageModelCounters)); |
+ |
+ std::sort(top_languages.begin(), top_languages.end(), |
+ [](LanguageModel::LanguageInfo a, LanguageModel::LanguageInfo b) { |
+ return a.frequency > b.frequency; |
+ }); |
+ |
+ return top_languages; |
+} |
+ |
+float LanguageModel::GetLanguageFrequency( |
+ const std::string& language_code) const { |
+ const base::DictionaryValue* dict = |
+ pref_service_->GetDictionary(kLanguageModelCounters); |
+ int counter_value = 0; |
+ // If the key |language_code| does not exist, |counter_value| stays 0. |
+ dict->GetInteger(language_code, &counter_value); |
+ |
+ int counters_sum = GetCountersSum(*dict); |
+ |
+ return static_cast<float>(counter_value) / counters_sum; |
+} |
+ |
+void LanguageModel::OnPageVisited(const std::string& language_code) { |
+ DictionaryPrefUpdate update(pref_service_, kLanguageModelCounters); |
+ base::DictionaryValue* dict = update.Get(); |
+ int counter_value = 0; |
+ // If the key |language_code| does not exist, |counter_value| stays 0. |
+ dict->GetInteger(language_code, &counter_value); |
+ dict->SetInteger(language_code, counter_value + 1); |
+ |
+ if (GetCountersSum(*dict) > kMaxCountersSum) |
+ DiscountAndCleanCounters(dict); |
+} |
+ |
+} // namespace translate |