Start updating historical information.

Bug: 11073222

Change-Id: Ic74951f46af05d3edfe08fca37352c5d5c1047e0
diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp
index 48ddb2f..ad437b1 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp
@@ -55,7 +55,7 @@
         }
         const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
                 newTargetTerminalId);
-        const BigramEntry bigramEntryToWrite = getUpdatedBigramEntry(&newBigramEntry,
+        const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(&newBigramEntry,
                 newProbability, timestamp);
         // Write an entry.
         const int writingPos =  mBigramDictContent->getBigramListHeadPos(terminalId);
@@ -81,7 +81,7 @@
         }
         const BigramEntry updatedBigramEntry =
                 originalBigramEntry.updateTargetTerminalIdAndGetEntry(newTargetTerminalId);
-        const BigramEntry bigramEntryToWrite = getUpdatedBigramEntry(
+        const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
                 &updatedBigramEntry, newProbability, timestamp);
         return mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, entryPosToUpdate);
     }
@@ -94,7 +94,7 @@
     // Write new entry at a head position of the bigram list.
     int writingPos = mBigramDictContent->getBigramListHeadPos(terminalId);
     const BigramEntry newBigramEntry(true /* hasNext */, NOT_A_PROBABILITY, newTargetTerminalId);
-    const BigramEntry bigramEntryToWrite = getUpdatedBigramEntry(
+    const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
             &newBigramEntry, newProbability, timestamp);
     if (!mBigramDictContent->writeBigramEntryAndAdvancePosition(&bigramEntryToWrite, &writingPos)) {
         return false;
@@ -218,14 +218,17 @@
     return invalidEntryPos;
 }
 
-const BigramEntry Ver4BigramListPolicy::getUpdatedBigramEntry(
+const BigramEntry Ver4BigramListPolicy::createUpdatedBigramEntryFrom(
         const BigramEntry *const originalBigramEntry, const int newProbability,
         const int timestamp) const {
     if (mNeedsToDecayWhenUpdating) {
-        // TODO: Update historical information.
         const int probability = ForgettingCurveUtils::getUpdatedEncodedProbability(
                 originalBigramEntry->getProbability(), newProbability);
-        return originalBigramEntry->updateProbabilityAndGetEntry(probability);
+        const HistoricalInfo updatedHistoricalInfo =
+                ForgettingCurveUtils::createUpdatedHistoricalInfoFrom(
+                        originalBigramEntry->getHistoricalInfo(), newProbability, timestamp);
+        return originalBigramEntry->updateProbabilityAndGetEntry(probability)
+                .updateHistoricalInfoAndGetEntry(&updatedHistoricalInfo);
     } else {
         return originalBigramEntry->updateProbabilityAndGetEntry(newProbability);
     }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h
index e718645..9721441 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h
@@ -59,7 +59,7 @@
 
     int getEntryPosToUpdate(const int targetTerminalIdToFind, const int bigramListPos) const;
 
-    const BigramEntry getUpdatedBigramEntry(const BigramEntry *const originalBigramEntry,
+    const BigramEntry createUpdatedBigramEntryFrom(const BigramEntry *const originalBigramEntry,
             const int newProbability, const int timestamp) const;
 
     BigramDictContent *const mBigramDictContent;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
index 92bec30..95921c5 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
@@ -292,10 +292,13 @@
         const ProbabilityEntry *const originalProbabilityEntry, const int newProbability,
         const int timestamp) const {
     if (mNeedsToDecayWhenUpdating) {
-        // TODO: Update historical information.
         const int updatedProbability = ForgettingCurveUtils::getUpdatedEncodedProbability(
                 originalProbabilityEntry->getProbability(), newProbability);
-        return originalProbabilityEntry->createEntryWithUpdatedProbability(updatedProbability);
+        const HistoricalInfo updatedHistoricalInfo =
+                ForgettingCurveUtils::createUpdatedHistoricalInfoFrom(
+                        originalProbabilityEntry->getHistoricalInfo(), newProbability, timestamp);
+        return originalProbabilityEntry->createEntryWithUpdatedProbability(updatedProbability)
+                .createEntryWithUpdatedHistoricalInfo(&updatedHistoricalInfo);
     } else {
         return originalProbabilityEntry->createEntryWithUpdatedProbability(newProbability);
     }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp
index 3ce5680..c7fb47e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp
@@ -39,8 +39,39 @@
 const float ForgettingCurveUtils::MIN_PROBABILITY_TO_DECAY = 0.03f;
 const int ForgettingCurveUtils::DECAY_INTERVAL_SECONDS = 2 * 60 * 60;
 
+const int ForgettingCurveUtils::MAX_LEVEL = 3;
+const int ForgettingCurveUtils::MAX_COUNT = 3;
+const int ForgettingCurveUtils::MIN_VALID_LEVEL = 1;
+
 const ForgettingCurveUtils::ProbabilityTable ForgettingCurveUtils::sProbabilityTable;
 
+/* static */ const HistoricalInfo ForgettingCurveUtils::createUpdatedHistoricalInfoFrom(
+        const HistoricalInfo *const originalHistoricalInfo,
+        const int newProbability, const int timestamp) {
+    if (newProbability != NOT_A_PROBABILITY && originalHistoricalInfo->getLevel() == 0) {
+        return HistoricalInfo(timestamp, MIN_VALID_LEVEL /* level */, 0 /* count */);
+    } else if (originalHistoricalInfo->getTimeStamp() == NOT_A_TIMESTAMP) {
+        // Initial information.
+        return HistoricalInfo(timestamp, 0 /* level */, 0 /* count */);
+    } else {
+        const int updatedCount = originalHistoricalInfo->getCount() + 1;
+        if (updatedCount > MAX_COUNT) {
+            // The count exceeds the max value the level can be incremented.
+            if (originalHistoricalInfo->getLevel() >= MAX_LEVEL) {
+                // The level is already max.
+                return HistoricalInfo(timestamp, originalHistoricalInfo->getLevel(),
+                        originalHistoricalInfo->getCount());
+            } else {
+                // Level up.
+                return HistoricalInfo(timestamp, originalHistoricalInfo->getLevel() + 1,
+                        0 /* count */);
+            }
+        } else {
+            return HistoricalInfo(timestamp, originalHistoricalInfo->getLevel(), updatedCount);
+        }
+    }
+}
+
 /* static */ int ForgettingCurveUtils::getProbability(const int encodedUnigramProbability,
         const int encodedBigramProbability) {
     if (encodedUnigramProbability == NOT_A_PROBABILITY) {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h
index a858719..3e5bdf6 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include "defines.h"
+#include "suggest/policyimpl/dictionary/utils/historical_info.h"
 
 namespace latinime {
 
@@ -35,6 +36,10 @@
     static const int MAX_BIGRAM_COUNT;
     static const int MAX_BIGRAM_COUNT_AFTER_GC;
 
+    static const HistoricalInfo createUpdatedHistoricalInfoFrom(
+            const HistoricalInfo *const originalHistoricalInfo, const int newProbability,
+            const int timestamp);
+
     static int getProbability(const int encodedUnigramProbability,
             const int encodedBigramProbability);
 
@@ -76,6 +81,10 @@
     static const float MIN_PROBABILITY_TO_DECAY;
     static const int DECAY_INTERVAL_SECONDS;
 
+    static const int MAX_LEVEL;
+    static const int MAX_COUNT;
+    static const int MIN_VALID_LEVEL;
+
     static const ProbabilityTable sProbabilityTable;
 
     static int decodeProbability(const int encodedProbability);