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