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_PROXIMITY_INFO_STATE_H
18#define LATINIME_PROXIMITY_INFO_STATE_H
19
20#include <cstring> // for memset()
21#include <unordered_map>
22#include <vector>
23
24#include "defines.h"
25#include "suggest/core/layout/proximity_info_params.h"
26#include "suggest/core/layout/proximity_info_state_utils.h"
27
28namespace latinime {
29
30class ProximityInfo;
31
32class ProximityInfoState {
33 public:
34    /////////////////////////////////////////
35    // Defined in proximity_info_state.cpp //
36    /////////////////////////////////////////
37    void initInputParams(const int pointerId, const float maxPointToKeyLength,
38            const ProximityInfo *proximityInfo, const int *const inputCodes,
39            const int inputSize, const int *xCoordinates, const int *yCoordinates,
40            const int *const times, const int *const pointerIds, const bool isGeometric,
41            const std::vector<int> *locale);
42
43    /////////////////////////////////////////
44    // Defined here                        //
45    /////////////////////////////////////////
46    AK_FORCE_INLINE ProximityInfoState()
47            : mProximityInfo(nullptr), mMaxPointToKeyLength(0.0f), mAverageSpeed(0.0f),
48              mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0),
49              mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0),
50              mIsContinuousSuggestionPossible(false), mHasBeenUpdatedByGeometricInput(false),
51              mSampledInputXs(), mSampledInputYs(), mSampledTimes(), mSampledInputIndice(),
52              mSampledLengthCache(), mBeelineSpeedPercentiles(),
53              mSampledNormalizedSquaredLengthCache(), mSpeedRates(), mDirections(),
54              mCharProbabilities(), mSampledSearchKeySets(), mSampledSearchKeyVectors(),
55              mTouchPositionCorrectionEnabled(false), mSampledInputSize(0),
56              mMostProbableStringProbability(0.0f) {
57        memset(mInputProximities, 0, sizeof(mInputProximities));
58        memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord));
59        memset(mMostProbableString, 0, sizeof(mMostProbableString));
60    }
61
62    // Non virtual inline destructor -- never inherit this class
63    AK_FORCE_INLINE ~ProximityInfoState() {}
64
65    inline int getPrimaryCodePointAt(const int index) const {
66        return getProximityCodePointsAt(index)[0];
67    }
68
69    int getPrimaryOriginalCodePointAt(const int index) const;
70
71    inline bool sameAsTyped(const int *word, int length) const {
72        if (length != mSampledInputSize) {
73            return false;
74        }
75        const int *inputProximities = mInputProximities;
76        while (length--) {
77            if (*inputProximities != *word) {
78                return false;
79            }
80            inputProximities += MAX_PROXIMITY_CHARS_SIZE;
81            word++;
82        }
83        return true;
84    }
85
86    AK_FORCE_INLINE bool existsCodePointInProximityAt(const int index, const int c) const {
87        const int *codePoints = getProximityCodePointsAt(index);
88        int i = 0;
89        while (codePoints[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE) {
90            if (codePoints[i++] == c) {
91                return true;
92            }
93        }
94        return false;
95    }
96
97    AK_FORCE_INLINE bool existsAdjacentProximityChars(const int index) const {
98        if (index < 0 || index >= mSampledInputSize) return false;
99        const int currentCodePoint = getPrimaryCodePointAt(index);
100        const int leftIndex = index - 1;
101        if (leftIndex >= 0 && existsCodePointInProximityAt(leftIndex, currentCodePoint)) {
102            return true;
103        }
104        const int rightIndex = index + 1;
105        if (rightIndex < mSampledInputSize
106                && existsCodePointInProximityAt(rightIndex, currentCodePoint)) {
107            return true;
108        }
109        return false;
110    }
111
112    inline bool touchPositionCorrectionEnabled() const {
113        return mTouchPositionCorrectionEnabled;
114    }
115
116    bool isUsed() const {
117        return mSampledInputSize > 0;
118    }
119
120    int size() const {
121        return mSampledInputSize;
122    }
123
124    int getInputX(const int index) const {
125        return mSampledInputXs[index];
126    }
127
128    int getInputY(const int index) const {
129        return mSampledInputYs[index];
130    }
131
132    int getInputIndexOfSampledPoint(const int sampledIndex) const {
133        return mSampledInputIndice[sampledIndex];
134    }
135
136    bool hasSpaceProximity(const int index) const;
137
138    int getLengthCache(const int index) const {
139        return mSampledLengthCache[index];
140    }
141
142    bool isContinuousSuggestionPossible() const {
143        return mIsContinuousSuggestionPossible;
144    }
145
146    // TODO: Rename s/Length/NormalizedSquaredLength/
147    float getPointToKeyByIdLength(const int inputIndex, const int keyId) const;
148    // TODO: Rename s/Length/NormalizedSquaredLength/
149    float getPointToKeyLength(const int inputIndex, const int codePoint) const;
150
151    ProximityType getProximityType(const int index, const int codePoint,
152            const bool checkProximityChars, int *proximityIndex = 0) const;
153
154    ProximityType getProximityTypeG(const int index, const int codePoint) const;
155
156    float getSpeedRate(const int index) const {
157        return mSpeedRates[index];
158    }
159
160    AK_FORCE_INLINE int getBeelineSpeedPercentile(const int id) const {
161        return mBeelineSpeedPercentiles[id];
162    }
163
164    AK_FORCE_INLINE DoubleLetterLevel getDoubleLetterLevel(const int id) const {
165        const int beelineSpeedRate = getBeelineSpeedPercentile(id);
166        if (beelineSpeedRate == 0) {
167            return A_STRONG_DOUBLE_LETTER;
168        } else if (beelineSpeedRate
169                < ProximityInfoParams::MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE) {
170            return A_DOUBLE_LETTER;
171        } else {
172            return NOT_A_DOUBLE_LETTER;
173        }
174    }
175
176    float getDirection(const int index) const {
177        return mDirections[index];
178    }
179    // get xy direction
180    float getDirection(const int x, const int y) const;
181
182    float getMostProbableString(int *const codePointBuf) const;
183
184    float getProbability(const int index, const int charCode) const;
185
186    bool isKeyInSerchKeysAfterIndex(const int index, const int keyId) const;
187
188 private:
189    DISALLOW_COPY_AND_ASSIGN(ProximityInfoState);
190
191    inline const int *getProximityCodePointsAt(const int index) const {
192        return ProximityInfoStateUtils::getProximityCodePointsAt(mInputProximities, index);
193    }
194
195    // const
196    const ProximityInfo *mProximityInfo;
197    float mMaxPointToKeyLength;
198    float mAverageSpeed;
199    bool mHasTouchPositionCorrectionData;
200    int mMostCommonKeyWidthSquare;
201    int mKeyCount;
202    int mCellHeight;
203    int mCellWidth;
204    int mGridHeight;
205    int mGridWidth;
206    bool mIsContinuousSuggestionPossible;
207    bool mHasBeenUpdatedByGeometricInput;
208
209    std::vector<int> mSampledInputXs;
210    std::vector<int> mSampledInputYs;
211    std::vector<int> mSampledTimes;
212    std::vector<int> mSampledInputIndice;
213    std::vector<int> mSampledLengthCache;
214    std::vector<int> mBeelineSpeedPercentiles;
215    std::vector<float> mSampledNormalizedSquaredLengthCache;
216    std::vector<float> mSpeedRates;
217    std::vector<float> mDirections;
218    // probabilities of skipping or mapping to a key for each point.
219    std::vector<std::unordered_map<int, float>> mCharProbabilities;
220    // The vector for the key code set which holds nearby keys of some trailing sampled input points
221    // for each sampled input point. These nearby keys contain the next characters which can be in
222    // the dictionary. Specifically, currently we are looking for keys nearby trailing sampled
223    // inputs including the current input point.
224    std::vector<ProximityInfoStateUtils::NearKeycodesSet> mSampledSearchKeySets;
225    std::vector<std::vector<int>> mSampledSearchKeyVectors;
226    bool mTouchPositionCorrectionEnabled;
227    int mInputProximities[MAX_PROXIMITY_CHARS_SIZE * MAX_WORD_LENGTH];
228    int mSampledInputSize;
229    int mPrimaryInputWord[MAX_WORD_LENGTH];
230    float mMostProbableStringProbability;
231    int mMostProbableString[MAX_WORD_LENGTH];
232};
233} // namespace latinime
234#endif // LATINIME_PROXIMITY_INFO_STATE_H
235