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