Home | History | Annotate | Download | only in internal
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef LATINIME_DIC_NODE_STATE_SCORING_H
     18 #define LATINIME_DIC_NODE_STATE_SCORING_H
     19 
     20 #include <stdint.h>
     21 
     22 #include "defines.h"
     23 #include "suggest/core/dictionary/digraph_utils.h"
     24 
     25 namespace latinime {
     26 
     27 class DicNodeStateScoring {
     28  public:
     29     AK_FORCE_INLINE DicNodeStateScoring()
     30             : mDoubleLetterLevel(NOT_A_DOUBLE_LETTER),
     31               mDigraphIndex(DigraphUtils::NOT_A_DIGRAPH_INDEX),
     32               mEditCorrectionCount(0), mProximityCorrectionCount(0),
     33               mNormalizedCompoundDistance(0.0f), mSpatialDistance(0.0f), mLanguageDistance(0.0f),
     34               mRawLength(0.0f), mExactMatch(true),
     35               mNormalizedCompoundDistanceAfterFirstWord(MAX_VALUE_FOR_WEIGHTING) {
     36     }
     37 
     38     virtual ~DicNodeStateScoring() {}
     39 
     40     void init() {
     41         mEditCorrectionCount = 0;
     42         mProximityCorrectionCount = 0;
     43         mNormalizedCompoundDistance = 0.0f;
     44         mSpatialDistance = 0.0f;
     45         mLanguageDistance = 0.0f;
     46         mRawLength = 0.0f;
     47         mDoubleLetterLevel = NOT_A_DOUBLE_LETTER;
     48         mDigraphIndex = DigraphUtils::NOT_A_DIGRAPH_INDEX;
     49         mNormalizedCompoundDistanceAfterFirstWord = MAX_VALUE_FOR_WEIGHTING;
     50         mExactMatch = true;
     51     }
     52 
     53     AK_FORCE_INLINE void init(const DicNodeStateScoring *const scoring) {
     54         mEditCorrectionCount = scoring->mEditCorrectionCount;
     55         mProximityCorrectionCount = scoring->mProximityCorrectionCount;
     56         mNormalizedCompoundDistance = scoring->mNormalizedCompoundDistance;
     57         mSpatialDistance = scoring->mSpatialDistance;
     58         mLanguageDistance = scoring->mLanguageDistance;
     59         mRawLength = scoring->mRawLength;
     60         mDoubleLetterLevel = scoring->mDoubleLetterLevel;
     61         mDigraphIndex = scoring->mDigraphIndex;
     62         mExactMatch = scoring->mExactMatch;
     63         mNormalizedCompoundDistanceAfterFirstWord =
     64                 scoring->mNormalizedCompoundDistanceAfterFirstWord;
     65     }
     66 
     67     void addCost(const float spatialCost, const float languageCost, const bool doNormalization,
     68             const int inputSize, const int totalInputIndex, const ErrorType errorType) {
     69         addDistance(spatialCost, languageCost, doNormalization, inputSize, totalInputIndex);
     70         switch (errorType) {
     71             case ET_EDIT_CORRECTION:
     72                 ++mEditCorrectionCount;
     73                 mExactMatch = false;
     74                 break;
     75             case ET_PROXIMITY_CORRECTION:
     76                 ++mProximityCorrectionCount;
     77                 mExactMatch = false;
     78                 break;
     79             case ET_COMPLETION:
     80                 mExactMatch = false;
     81                 break;
     82             case ET_NEW_WORD:
     83                 mExactMatch = false;
     84                 break;
     85             case ET_INTENTIONAL_OMISSION:
     86                 mExactMatch = false;
     87                 break;
     88             case ET_NOT_AN_ERROR:
     89                 break;
     90         }
     91     }
     92 
     93     // Saves the current normalized distance for space-aware gestures.
     94     // See getNormalizedCompoundDistanceAfterFirstWord for details.
     95     void saveNormalizedCompoundDistanceAfterFirstWordIfNoneYet() {
     96         // We get called here after each word. We only want to store the distance after
     97         // the first word, so if we already have a distance we skip saving -- hence "IfNoneYet"
     98         // in the method name.
     99         if (mNormalizedCompoundDistanceAfterFirstWord >= MAX_VALUE_FOR_WEIGHTING) {
    100             mNormalizedCompoundDistanceAfterFirstWord = getNormalizedCompoundDistance();
    101         }
    102     }
    103 
    104     void addRawLength(const float rawLength) {
    105         mRawLength += rawLength;
    106     }
    107 
    108     float getCompoundDistance() const {
    109         return getCompoundDistance(1.0f);
    110     }
    111 
    112     float getCompoundDistance(const float languageWeight) const {
    113         return mSpatialDistance + mLanguageDistance * languageWeight;
    114     }
    115 
    116     float getNormalizedCompoundDistance() const {
    117         return mNormalizedCompoundDistance;
    118     }
    119 
    120     // For space-aware gestures, we store the normalized distance at the char index
    121     // that ends the first word of the suggestion. We call this the distance after
    122     // first word.
    123     float getNormalizedCompoundDistanceAfterFirstWord() const {
    124         return mNormalizedCompoundDistanceAfterFirstWord;
    125     }
    126 
    127     float getSpatialDistance() const {
    128         return mSpatialDistance;
    129     }
    130 
    131     float getLanguageDistance() const {
    132         return mLanguageDistance;
    133     }
    134 
    135     int16_t getEditCorrectionCount() const {
    136         return mEditCorrectionCount;
    137     }
    138 
    139     int16_t getProximityCorrectionCount() const {
    140         return mProximityCorrectionCount;
    141     }
    142 
    143     float getRawLength() const {
    144         return mRawLength;
    145     }
    146 
    147     DoubleLetterLevel getDoubleLetterLevel() const {
    148         return mDoubleLetterLevel;
    149     }
    150 
    151     void setDoubleLetterLevel(DoubleLetterLevel doubleLetterLevel) {
    152         switch(doubleLetterLevel) {
    153             case NOT_A_DOUBLE_LETTER:
    154                 break;
    155             case A_DOUBLE_LETTER:
    156                 if (mDoubleLetterLevel != A_STRONG_DOUBLE_LETTER) {
    157                     mDoubleLetterLevel = doubleLetterLevel;
    158                 }
    159                 break;
    160             case A_STRONG_DOUBLE_LETTER:
    161                 mDoubleLetterLevel = doubleLetterLevel;
    162                 break;
    163         }
    164     }
    165 
    166     DigraphUtils::DigraphCodePointIndex getDigraphIndex() const {
    167         return mDigraphIndex;
    168     }
    169 
    170     void advanceDigraphIndex() {
    171         switch(mDigraphIndex) {
    172             case DigraphUtils::NOT_A_DIGRAPH_INDEX:
    173                 mDigraphIndex = DigraphUtils::FIRST_DIGRAPH_CODEPOINT;
    174                 break;
    175             case DigraphUtils::FIRST_DIGRAPH_CODEPOINT:
    176                 mDigraphIndex = DigraphUtils::SECOND_DIGRAPH_CODEPOINT;
    177                 break;
    178             case DigraphUtils::SECOND_DIGRAPH_CODEPOINT:
    179                 mDigraphIndex = DigraphUtils::NOT_A_DIGRAPH_INDEX;
    180                 break;
    181         }
    182     }
    183 
    184     bool isExactMatch() const {
    185         return mExactMatch;
    186     }
    187 
    188  private:
    189     // Caution!!!
    190     // Use a default copy constructor and an assign operator because shallow copies are ok
    191     // for this class
    192     DoubleLetterLevel mDoubleLetterLevel;
    193     DigraphUtils::DigraphCodePointIndex mDigraphIndex;
    194 
    195     int16_t mEditCorrectionCount;
    196     int16_t mProximityCorrectionCount;
    197 
    198     float mNormalizedCompoundDistance;
    199     float mSpatialDistance;
    200     float mLanguageDistance;
    201     float mRawLength;
    202     bool mExactMatch;
    203     float mNormalizedCompoundDistanceAfterFirstWord;
    204 
    205     AK_FORCE_INLINE void addDistance(float spatialDistance, float languageDistance,
    206             bool doNormalization, int inputSize, int totalInputIndex) {
    207         mSpatialDistance += spatialDistance;
    208         mLanguageDistance += languageDistance;
    209         if (!doNormalization) {
    210             mNormalizedCompoundDistance = mSpatialDistance + mLanguageDistance;
    211         } else {
    212             mNormalizedCompoundDistance = (mSpatialDistance + mLanguageDistance)
    213                     / static_cast<float>(max(1, totalInputIndex));
    214         }
    215     }
    216 };
    217 } // namespace latinime
    218 #endif // LATINIME_DIC_NODE_STATE_SCORING_H
    219