Home | History | Annotate | Download | only in typing
      1 /*
      2  * Copyright (C) 2013 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_TYPING_TRAVERSAL_H
     18 #define LATINIME_TYPING_TRAVERSAL_H
     19 
     20 #include <stdint.h>
     21 
     22 #include "defines.h"
     23 #include "suggest/core/dicnode/dic_node.h"
     24 #include "suggest/core/dicnode/dic_node_vector.h"
     25 #include "suggest/core/layout/proximity_info_state.h"
     26 #include "suggest/core/layout/proximity_info_utils.h"
     27 #include "suggest/core/policy/traversal.h"
     28 #include "suggest/core/session/dic_traverse_session.h"
     29 #include "suggest/policyimpl/typing/scoring_params.h"
     30 #include "utils/char_utils.h"
     31 
     32 namespace latinime {
     33 class TypingTraversal : public Traversal {
     34  public:
     35     static const TypingTraversal *getInstance() { return &sInstance; }
     36 
     37     AK_FORCE_INLINE int getMaxPointerCount() const {
     38         return MAX_POINTER_COUNT;
     39     }
     40 
     41     AK_FORCE_INLINE bool allowsErrorCorrections(const DicNode *const dicNode) const {
     42         return dicNode->getNormalizedSpatialDistance()
     43                 < ScoringParams::NORMALIZED_SPATIAL_DISTANCE_THRESHOLD_FOR_EDIT;
     44     }
     45 
     46     AK_FORCE_INLINE bool isOmission(const DicTraverseSession *const traverseSession,
     47             const DicNode *const dicNode, const DicNode *const childDicNode,
     48             const bool allowsErrorCorrections) const {
     49         if (!CORRECT_OMISSION) {
     50             return false;
     51         }
     52         // Note: Always consider intentional omissions (like apostrophes) since they are common.
     53         const bool canConsiderOmission =
     54                 allowsErrorCorrections || childDicNode->canBeIntentionalOmission();
     55         if (!canConsiderOmission) {
     56             return false;
     57         }
     58         const int inputSize = traverseSession->getInputSize();
     59         // TODO: Don't refer to isCompletion?
     60         if (dicNode->isCompletion(inputSize)) {
     61             return false;
     62         }
     63         if (dicNode->canBeIntentionalOmission()) {
     64             return true;
     65         }
     66         const int point0Index = dicNode->getInputIndex(0);
     67         const int currentBaseLowerCodePoint =
     68                 CharUtils::toBaseLowerCase(childDicNode->getNodeCodePoint());
     69         const int typedBaseLowerCodePoint =
     70                 CharUtils::toBaseLowerCase(traverseSession->getProximityInfoState(0)
     71                         ->getPrimaryCodePointAt(point0Index));
     72         return (currentBaseLowerCodePoint != typedBaseLowerCodePoint);
     73     }
     74 
     75     AK_FORCE_INLINE bool isSpaceSubstitutionTerminal(
     76             const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
     77         if (!CORRECT_NEW_WORD_SPACE_SUBSTITUTION) {
     78             return false;
     79         }
     80         if (!canDoLookAheadCorrection(traverseSession, dicNode)) {
     81             return false;
     82         }
     83         const int point0Index = dicNode->getInputIndex(0);
     84         return dicNode->isTerminalWordNode()
     85                 && traverseSession->getProximityInfoState(0)->
     86                         hasSpaceProximity(point0Index);
     87     }
     88 
     89     AK_FORCE_INLINE bool isSpaceOmissionTerminal(
     90             const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
     91         if (!CORRECT_NEW_WORD_SPACE_OMISSION) {
     92             return false;
     93         }
     94         const int inputSize = traverseSession->getInputSize();
     95         // TODO: Don't refer to isCompletion?
     96         if (dicNode->isCompletion(inputSize)) {
     97             return false;
     98         }
     99         if (!dicNode->isTerminalWordNode()) {
    100             return false;
    101         }
    102         const int16_t pointIndex = dicNode->getInputIndex(0);
    103         return pointIndex <= inputSize && !dicNode->isTotalInputSizeExceedingLimit()
    104                 && !dicNode->shouldBeFilteredBySafetyNetForBigram();
    105     }
    106 
    107     AK_FORCE_INLINE bool shouldDepthLevelCache(
    108             const DicTraverseSession *const traverseSession) const {
    109         const int inputSize = traverseSession->getInputSize();
    110         return traverseSession->isCacheBorderForTyping(inputSize);
    111     }
    112 
    113     AK_FORCE_INLINE bool shouldNodeLevelCache(
    114             const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
    115         return false;
    116     }
    117 
    118     AK_FORCE_INLINE bool canDoLookAheadCorrection(
    119             const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
    120         const int inputSize = traverseSession->getInputSize();
    121         return dicNode->canDoLookAheadCorrection(inputSize);
    122     }
    123 
    124     AK_FORCE_INLINE ProximityType getProximityType(
    125             const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
    126             const DicNode *const childDicNode) const {
    127         return traverseSession->getProximityInfoState(0)->getProximityType(
    128                 dicNode->getInputIndex(0), childDicNode->getNodeCodePoint(),
    129                 true /* checkProximityChars */);
    130     }
    131 
    132     AK_FORCE_INLINE bool needsToTraverseAllUserInput() const {
    133         return true;
    134     }
    135 
    136     AK_FORCE_INLINE float getMaxSpatialDistance() const {
    137         return ScoringParams::MAX_SPATIAL_DISTANCE;
    138     }
    139 
    140     AK_FORCE_INLINE bool autoCorrectsToMultiWordSuggestionIfTop() const {
    141         return true;
    142     }
    143 
    144     AK_FORCE_INLINE int getDefaultExpandDicNodeSize() const {
    145         return DicNodeVector::DEFAULT_NODES_SIZE_FOR_OPTIMIZATION;
    146     }
    147 
    148     AK_FORCE_INLINE bool sameAsTyped(
    149             const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
    150         return traverseSession->getProximityInfoState(0)->sameAsTyped(
    151                 dicNode->getOutputWordBuf(), dicNode->getNodeCodePointCount());
    152     }
    153 
    154     AK_FORCE_INLINE int getMaxCacheSize(const int inputSize) const {
    155         return (inputSize <= 1) ? ScoringParams::MAX_CACHE_DIC_NODE_SIZE_FOR_SINGLE_POINT
    156                 : ScoringParams::MAX_CACHE_DIC_NODE_SIZE;
    157     }
    158 
    159     AK_FORCE_INLINE bool isPossibleOmissionChildNode(
    160             const DicTraverseSession *const traverseSession, const DicNode *const parentDicNode,
    161             const DicNode *const dicNode) const {
    162         const ProximityType proximityType =
    163                 getProximityType(traverseSession, parentDicNode, dicNode);
    164         if (!ProximityInfoUtils::isMatchOrProximityChar(proximityType)) {
    165             return false;
    166         }
    167         return true;
    168     }
    169 
    170     AK_FORCE_INLINE bool isGoodToTraverseNextWord(const DicNode *const dicNode) const {
    171         const int probability = dicNode->getProbability();
    172         if (probability < ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY) {
    173             return false;
    174         }
    175         const int c = dicNode->getOutputWordBuf()[0];
    176         const bool shortCappedWord = dicNode->getNodeCodePointCount()
    177                 < ScoringParams::THRESHOLD_SHORT_WORD_LENGTH && CharUtils::isAsciiUpper(c);
    178         return !shortCappedWord
    179                 || probability >= ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED;
    180     }
    181 
    182  private:
    183     DISALLOW_COPY_AND_ASSIGN(TypingTraversal);
    184     static const bool CORRECT_OMISSION;
    185     static const bool CORRECT_NEW_WORD_SPACE_SUBSTITUTION;
    186     static const bool CORRECT_NEW_WORD_SPACE_OMISSION;
    187     static const TypingTraversal sInstance;
    188 
    189     TypingTraversal() {}
    190     ~TypingTraversal() {}
    191 };
    192 } // namespace latinime
    193 #endif // LATINIME_TYPING_TRAVERSAL_H
    194