13107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka/*
23107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka * Copyright (C) 2012 The Android Open Source Project
33107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka *
43107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka * Licensed under the Apache License, Version 2.0 (the "License");
53107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka * you may not use this file except in compliance with the License.
63107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka * You may obtain a copy of the License at
73107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka *
83107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka *      http://www.apache.org/licenses/LICENSE-2.0
93107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka *
103107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka * Unless required by applicable law or agreed to in writing, software
113107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka * distributed under the License is distributed on an "AS IS" BASIS,
123107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka * See the License for the specific language governing permissions and
143107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka * limitations under the License.
153107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka */
163107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
173107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka#ifndef LATINIME_DIC_TRAVERSE_SESSION_H
183107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka#define LATINIME_DIC_TRAVERSE_SESSION_H
193107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
203107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka#include <stdint.h>
213107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka#include <vector>
223107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
233107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka#include "defines.h"
243107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka#include "jni.h"
259559dd2e30de288a9ff7069bfc59f8500b949a88Tom Ouyang#include "multi_bigram_map.h"
263107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka#include "proximity_info_state.h"
27b68e73448104714e8f12f89a1e00fb10b5fd14c4Ken Wakasa#include "suggest/core/dicnode/dic_nodes_cache.h"
283107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
293107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataokanamespace latinime {
303107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
313107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataokaclass Dictionary;
323107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataokaclass ProximityInfo;
333107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
343107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataokaclass DicTraverseSession {
353107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka public:
363107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr)
373107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            : mPrevWordPos(NOT_VALID_WORD), mProximityInfo(0),
389559dd2e30de288a9ff7069bfc59f8500b949a88Tom Ouyang              mDictionary(0), mDicNodesCache(), mMultiBigramMap(),
39252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka              mInputSize(0), mPartiallyCommited(false), mMaxPointerCount(1),
40252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka              mMultiWordCostMultiplier(1.0f) {
413107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        // NOTE: mProximityInfoStates is an array of instances.
423107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        // No need to initialize it explicitly here.
433107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    }
443107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
453107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    // Non virtual inline destructor -- never inherit this class
463107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    AK_FORCE_INLINE ~DicTraverseSession() {}
473107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
483107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    void init(const Dictionary *dictionary, const int *prevWord, int prevWordLength);
493107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    // TODO: Remove and merge into init
503107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    void setupForGetSuggestions(const ProximityInfo *pInfo, const int *inputCodePoints,
513107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            const int inputSize, const int *const inputXs, const int *const inputYs,
523107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            const int *const times, const int *const pointerIds, const float maxSpatialDistance,
533107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            const int maxPointerCount);
543107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    void resetCache(const int nextActiveCacheSize, const int maxWords);
553107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
56252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka    // TODO: Remove
573107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    const uint8_t *getOffsetDict() const;
58ede2333640accecc066de328cb4f93e03e4bc5d7Tom Ouyang    int getDictFlags() const;
593107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
603107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    //--------------------
613107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    // getters and setters
623107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    //--------------------
633107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    const ProximityInfo *getProximityInfo() const { return mProximityInfo; }
643107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    int getPrevWordPos() const { return mPrevWordPos; }
653107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    // TODO: REMOVE
663107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    void setPrevWordPos(int pos) { mPrevWordPos = pos; }
673107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    // TODO: Use proper parameter when changed
683107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    int getDicRootPos() const { return 0; }
693107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    DicNodesCache *getDicTraverseCache() { return &mDicNodesCache; }
709559dd2e30de288a9ff7069bfc59f8500b949a88Tom Ouyang    MultiBigramMap *getMultiBigramMap() { return &mMultiBigramMap; }
713107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    const ProximityInfoState *getProximityInfoState(int id) const {
723107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        return &mProximityInfoStates[id];
733107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    }
743107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    int getInputSize() const { return mInputSize; }
753107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    void setPartiallyCommited() { mPartiallyCommited = true; }
763107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    bool isPartiallyCommited() const { return mPartiallyCommited; }
773107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
783107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    bool isOnlyOnePointerUsed(int *pointerId) const {
793107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        // Not in the dictionary word
803107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        int usedPointerCount = 0;
813107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        int usedPointerId = 0;
823107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        for (int i = 0; i < mMaxPointerCount; ++i) {
833107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            if (mProximityInfoStates[i].isUsed()) {
843107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka                ++usedPointerCount;
853107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka                usedPointerId = i;
863107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            }
873107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        }
883107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        if (usedPointerCount != 1) {
893107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            return false;
903107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        }
913107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        *pointerId = usedPointerId;
923107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        return true;
933107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    }
943107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
953107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    void getSearchKeys(const DicNode *node, std::vector<int> *const outputSearchKeyVector) const {
963107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        for (int i = 0; i < MAX_POINTER_COUNT_G; ++i) {
973107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            if (!mProximityInfoStates[i].isUsed()) {
983107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka                continue;
993107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            }
1003107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            const int pointerId = node->getInputIndex(i);
1013107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            const std::vector<int> *const searchKeyVector =
1023107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka                    mProximityInfoStates[i].getSearchKeyVector(pointerId);
1033107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            outputSearchKeyVector->insert(outputSearchKeyVector->end(), searchKeyVector->begin(),
1043107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka                    searchKeyVector->end());
1053107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        }
1063107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    }
1073107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
1083107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    ProximityType getProximityTypeG(const DicNode *const node, const int childCodePoint) const {
1093107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        ProximityType proximityType = UNRELATED_CHAR;
1103107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        for (int i = 0; i < MAX_POINTER_COUNT_G; ++i) {
1113107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            if (!mProximityInfoStates[i].isUsed()) {
1123107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka                continue;
1133107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            }
1143107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            const int pointerId = node->getInputIndex(i);
1153107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            proximityType = mProximityInfoStates[i].getProximityTypeG(pointerId, childCodePoint);
1163107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            ASSERT(proximityType == UNRELATED_CHAR || proximityType == MATCH_CHAR);
1173107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            // TODO: Make this more generic
1183107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            // Currently we assume there are only two types here -- UNRELATED_CHAR
1193107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            // and MATCH_CHAR
1203107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            if (proximityType != UNRELATED_CHAR) {
1213107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka                return proximityType;
1223107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            }
1233107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        }
1243107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        return proximityType;
1253107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    }
1263107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
1273107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    AK_FORCE_INLINE bool isCacheBorderForTyping(const int inputSize) const {
1283107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        return mDicNodesCache.isCacheBorderForTyping(inputSize);
1293107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    }
1303107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
1313107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    /**
1323107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka     * Returns whether or not it is possible to continue suggestion from the previous search.
1333107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka     */
1343107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    // TODO: Remove. No need to check once the session is fully implemented.
1353107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    bool isContinuousSuggestionPossible() const {
1363107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        if (!mDicNodesCache.hasCachedDicNodesForContinuousSuggestion()) {
1373107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            return false;
1383107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        }
139a94bb198cf13a3729bb992fc9c5bfce779e58469Satoshi Kataoka        ASSERT(mMaxPointerCount <= MAX_POINTER_COUNT_G);
1403107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        for (int i = 0; i < mMaxPointerCount; ++i) {
1413107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            const ProximityInfoState *const pInfoState = getProximityInfoState(i);
1423107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            // If a proximity info state is not continuous suggestion possible,
1433107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            // do not continue searching.
1443107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            if (pInfoState->isUsed() && !pInfoState->isContinuousSuggestionPossible()) {
1453107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka                return false;
1463107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            }
1473107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        }
1483107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka        return true;
1493107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    }
1503107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
151837f46dcb35a8f42a6bd5bc5fc6395d7386acb81Satoshi Kataoka    bool isTouchPositionCorrectionEnabled() const {
152837f46dcb35a8f42a6bd5bc5fc6395d7386acb81Satoshi Kataoka        return mProximityInfoStates[0].touchPositionCorrectionEnabled();
153837f46dcb35a8f42a6bd5bc5fc6395d7386acb81Satoshi Kataoka    }
154837f46dcb35a8f42a6bd5bc5fc6395d7386acb81Satoshi Kataoka
155252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka    float getMultiWordCostMultiplier() const {
156252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka        return mMultiWordCostMultiplier;
157252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka    }
158252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka
1593107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka private:
1603107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseSession);
1613107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    // threshold to start caching
1623107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    static const int CACHE_START_INPUT_LENGTH_THRESHOLD;
1633107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    void initializeProximityInfoStates(const int *const inputCodePoints, const int *const inputXs,
1643107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            const int *const inputYs, const int *const times, const int *const pointerIds,
1653107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka            const int inputSize, const float maxSpatialDistance, const int maxPointerCount);
1663107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
1673107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    int mPrevWordPos;
1683107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    const ProximityInfo *mProximityInfo;
1693107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    const Dictionary *mDictionary;
1703107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
1713107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    DicNodesCache mDicNodesCache;
1723107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    // Temporary cache for bigram frequencies
1739559dd2e30de288a9ff7069bfc59f8500b949a88Tom Ouyang    MultiBigramMap mMultiBigramMap;
1743107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    ProximityInfoState mProximityInfoStates[MAX_POINTER_COUNT_G];
1753107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka
1763107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    int mInputSize;
1773107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    bool mPartiallyCommited;
1783107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka    int mMaxPointerCount;
179252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka
180252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka    /////////////////////////////////
181252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka    // Configuration per dictionary
182252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka    float mMultiWordCostMultiplier;
183252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka
1843107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka};
1853107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka} // namespace latinime
1863107b467c91c471ce4e00c5d8de559f7b0da2cd6Satoshi Kataoka#endif // LATINIME_DIC_TRAVERSE_SESSION_H
187