1a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka/*
2a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka * Copyright (C) 2012 The Android Open Source Project
3a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka *
4a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka * Licensed under the Apache License, Version 2.0 (the "License");
5a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka * you may not use this file except in compliance with the License.
6a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka * You may obtain a copy of the License at
7a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka *
8a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka *      http://www.apache.org/licenses/LICENSE-2.0
9a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka *
10a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka * Unless required by applicable law or agreed to in writing, software
11a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka * distributed under the License is distributed on an "AS IS" BASIS,
12a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka * See the License for the specific language governing permissions and
14a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka * limitations under the License.
15a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka */
16a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
17a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka#ifndef LATINIME_TYPING_WEIGHTING_H
18a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka#define LATINIME_TYPING_WEIGHTING_H
19a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
20a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka#include "defines.h"
21b68e73448104714e8f12f89a1e00fb10b5fd14c4Ken Wakasa#include "suggest/core/dicnode/dic_node_utils.h"
222fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "suggest/core/dictionary/error_type_utils.h"
2329432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa#include "suggest/core/layout/touch_position_correction_utils.h"
24b68e73448104714e8f12f89a1e00fb10b5fd14c4Ken Wakasa#include "suggest/core/policy/weighting.h"
25b68e73448104714e8f12f89a1e00fb10b5fd14c4Ken Wakasa#include "suggest/core/session/dic_traverse_session.h"
26b68e73448104714e8f12f89a1e00fb10b5fd14c4Ken Wakasa#include "suggest/policyimpl/typing/scoring_params.h"
27addea83bad5751308fef508d79c6989b8872f050Ken Wakasa#include "utils/char_utils.h"
28a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
29a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataokanamespace latinime {
30a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
31a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataokaclass DicNode;
32a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataokastruct DicNode_InputStateG;
339559dd2e30de288a9ff7069bfc59f8500b949a88Tom Ouyangclass MultiBigramMap;
34a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
35a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataokaclass TypingWeighting : public Weighting {
36a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka public:
37a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    static const TypingWeighting *getInstance() { return &sInstance; }
38a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
39a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka protected:
40866a6ced571a24f0f1b927aeccad7a1969da23b7Ken Wakasa    float getTerminalSpatialCost(const DicTraverseSession *const traverseSession,
41866a6ced571a24f0f1b927aeccad7a1969da23b7Ken Wakasa            const DicNode *const dicNode) const {
42a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        float cost = 0.0f;
43a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        if (dicNode->hasMultipleWords()) {
44a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka            cost += ScoringParams::HAS_MULTI_WORD_TERMINAL_COST;
45a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        }
46a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        if (dicNode->getProximityCorrectionCount() > 0) {
47a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka            cost += ScoringParams::HAS_PROXIMITY_TERMINAL_COST;
48a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        }
49a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        if (dicNode->getEditCorrectionCount() > 0) {
50a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka            cost += ScoringParams::HAS_EDIT_CORRECTION_TERMINAL_COST;
51a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        }
52a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        return cost;
53a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
54a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
55a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    float getOmissionCost(const DicNode *const parentDicNode, const DicNode *const dicNode) const {
5660a169f0c34bf0da89c420d99bfff5c2556f3fbfKeisuke Kuroynagi        const bool isZeroCostOmission = parentDicNode->isZeroCostOmission();
5714dd663fe51079e74c8527d1452d5aa68fecc4e8Keisuke Kuroyanagi        const bool isIntentionalOmission = parentDicNode->canBeIntentionalOmission();
5860a169f0c34bf0da89c420d99bfff5c2556f3fbfKeisuke Kuroynagi        const bool sameCodePoint = dicNode->isSameNodeCodePoint(parentDicNode);
59a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        // If the traversal omitted the first letter then the dicNode should now be on the second.
6009858cbde49c086dd1d4d3050b57f0ea1774158bKeisuke Kuroynagi        const bool isFirstLetterOmission = dicNode->getNodeCodePointCount() == 2;
6160a169f0c34bf0da89c420d99bfff5c2556f3fbfKeisuke Kuroynagi        float cost = 0.0f;
6260a169f0c34bf0da89c420d99bfff5c2556f3fbfKeisuke Kuroynagi        if (isZeroCostOmission) {
6360a169f0c34bf0da89c420d99bfff5c2556f3fbfKeisuke Kuroynagi            cost = 0.0f;
6414dd663fe51079e74c8527d1452d5aa68fecc4e8Keisuke Kuroyanagi        } else if (isIntentionalOmission) {
6514dd663fe51079e74c8527d1452d5aa68fecc4e8Keisuke Kuroyanagi            cost = ScoringParams::INTENTIONAL_OMISSION_COST;
6660a169f0c34bf0da89c420d99bfff5c2556f3fbfKeisuke Kuroynagi        } else if (isFirstLetterOmission) {
67a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka            cost = ScoringParams::OMISSION_COST_FIRST_CHAR;
68a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        } else {
69a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka            cost = sameCodePoint ? ScoringParams::OMISSION_COST_SAME_CHAR
70a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka                    : ScoringParams::OMISSION_COST;
71a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        }
72a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        return cost;
73a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
74a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
75866a6ced571a24f0f1b927aeccad7a1969da23b7Ken Wakasa    float getMatchedCost(const DicTraverseSession *const traverseSession,
76866a6ced571a24f0f1b927aeccad7a1969da23b7Ken Wakasa            const DicNode *const dicNode, DicNode_InputStateG *inputStateG) const {
77a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const int pointIndex = dicNode->getInputIndex(0);
78837f46dcb35a8f42a6bd5bc5fc6395d7386acb81Satoshi Kataoka        const float normalizedSquaredLength = traverseSession->getProximityInfoState(0)
79e639d7346c59b21fffc6b6e1e05022bb6b84fb74Keisuke Kuroyanagi                ->getPointToKeyLength(pointIndex,
80e639d7346c59b21fffc6b6e1e05022bb6b84fb74Keisuke Kuroyanagi                        CharUtils::toBaseLowerCase(dicNode->getNodeCodePoint()));
8129432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa        const float normalizedDistance = TouchPositionCorrectionUtils::getSweetSpotFactor(
82837f46dcb35a8f42a6bd5bc5fc6395d7386acb81Satoshi Kataoka                traverseSession->isTouchPositionCorrectionEnabled(), normalizedSquaredLength);
83837f46dcb35a8f42a6bd5bc5fc6395d7386acb81Satoshi Kataoka        const float weightedDistance = ScoringParams::DISTANCE_WEIGHT_LENGTH * normalizedDistance;
84837f46dcb35a8f42a6bd5bc5fc6395d7386acb81Satoshi Kataoka
85a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const bool isFirstChar = pointIndex == 0;
86a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const bool isProximity = isProximityDicNode(traverseSession, dicNode);
87cb4a7c1d87106c5ac8c13e752b1ceaf585448538Keisuke Kuroynagi        float cost = isProximity ? (isFirstChar ? ScoringParams::FIRST_CHAR_PROXIMITY_COST
88a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka                : ScoringParams::PROXIMITY_COST) : 0.0f;
89cb4a7c1d87106c5ac8c13e752b1ceaf585448538Keisuke Kuroynagi        if (isProximity && dicNode->getProximityCorrectionCount() == 0) {
90cb4a7c1d87106c5ac8c13e752b1ceaf585448538Keisuke Kuroynagi            cost += ScoringParams::FIRST_PROXIMITY_COST;
91cb4a7c1d87106c5ac8c13e752b1ceaf585448538Keisuke Kuroynagi        }
9209858cbde49c086dd1d4d3050b57f0ea1774158bKeisuke Kuroynagi        if (dicNode->getNodeCodePointCount() == 2) {
93a107dcaeb6302981974bab8284f6b7943673cf11Keisuke Kuroynagi            // At the second character of the current word, we check if the first char is uppercase
94a107dcaeb6302981974bab8284f6b7943673cf11Keisuke Kuroynagi            // and the word is a second or later word of a multiple word suggestion. We demote it
95a107dcaeb6302981974bab8284f6b7943673cf11Keisuke Kuroynagi            // if so.
96a107dcaeb6302981974bab8284f6b7943673cf11Keisuke Kuroynagi            const bool isSecondOrLaterWordFirstCharUppercase =
97a107dcaeb6302981974bab8284f6b7943673cf11Keisuke Kuroynagi                    dicNode->hasMultipleWords() && dicNode->isFirstCharUppercase();
98a107dcaeb6302981974bab8284f6b7943673cf11Keisuke Kuroynagi            if (isSecondOrLaterWordFirstCharUppercase) {
99a107dcaeb6302981974bab8284f6b7943673cf11Keisuke Kuroynagi                cost += ScoringParams::COST_SECOND_OR_LATER_WORD_FIRST_CHAR_UPPERCASE;
100a107dcaeb6302981974bab8284f6b7943673cf11Keisuke Kuroynagi            }
101a107dcaeb6302981974bab8284f6b7943673cf11Keisuke Kuroynagi        }
102a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        return weightedDistance + cost;
103a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
104a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
105866a6ced571a24f0f1b927aeccad7a1969da23b7Ken Wakasa    bool isProximityDicNode(const DicTraverseSession *const traverseSession,
106866a6ced571a24f0f1b927aeccad7a1969da23b7Ken Wakasa            const DicNode *const dicNode) const {
107a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const int pointIndex = dicNode->getInputIndex(0);
108464d3ba43257da34ab165da8ba0af11e928aae5cKen Wakasa        const int primaryCodePoint = CharUtils::toBaseLowerCase(
109a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka                traverseSession->getProximityInfoState(0)->getPrimaryCodePointAt(pointIndex));
110464d3ba43257da34ab165da8ba0af11e928aae5cKen Wakasa        const int dicNodeChar = CharUtils::toBaseLowerCase(dicNode->getNodeCodePoint());
111a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        return primaryCodePoint != dicNodeChar;
112a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
113a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
114866a6ced571a24f0f1b927aeccad7a1969da23b7Ken Wakasa    float getTranspositionCost(const DicTraverseSession *const traverseSession,
115866a6ced571a24f0f1b927aeccad7a1969da23b7Ken Wakasa            const DicNode *const parentDicNode, const DicNode *const dicNode) const {
116a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const int16_t parentPointIndex = parentDicNode->getInputIndex(0);
117a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const int prevCodePoint = parentDicNode->getNodeCodePoint();
118a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const float distance1 = traverseSession->getProximityInfoState(0)->getPointToKeyLength(
119e639d7346c59b21fffc6b6e1e05022bb6b84fb74Keisuke Kuroyanagi                parentPointIndex + 1, CharUtils::toBaseLowerCase(prevCodePoint));
120a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const int codePoint = dicNode->getNodeCodePoint();
121a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const float distance2 = traverseSession->getProximityInfoState(0)->getPointToKeyLength(
122e639d7346c59b21fffc6b6e1e05022bb6b84fb74Keisuke Kuroyanagi                parentPointIndex, CharUtils::toBaseLowerCase(codePoint));
123a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const float distance = distance1 + distance2;
124a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const float weightedLengthDistance =
125a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka                distance * ScoringParams::DISTANCE_WEIGHT_LENGTH;
126a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        return ScoringParams::TRANSPOSITION_COST + weightedLengthDistance;
127a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
128a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
129866a6ced571a24f0f1b927aeccad7a1969da23b7Ken Wakasa    float getInsertionCost(const DicTraverseSession *const traverseSession,
130a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka            const DicNode *const parentDicNode, const DicNode *const dicNode) const {
13124706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi        const int16_t insertedPointIndex = parentDicNode->getInputIndex(0);
13224706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi        const int prevCodePoint = traverseSession->getProximityInfoState(0)->getPrimaryCodePointAt(
13324706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi                insertedPointIndex);
134a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const int currentCodePoint = dicNode->getNodeCodePoint();
135a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const bool sameCodePoint = prevCodePoint == currentCodePoint;
13624706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi        const bool existsAdjacentProximityChars = traverseSession->getProximityInfoState(0)
13724706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi                ->existsAdjacentProximityChars(insertedPointIndex);
138a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const float dist = traverseSession->getProximityInfoState(0)->getPointToKeyLength(
139e639d7346c59b21fffc6b6e1e05022bb6b84fb74Keisuke Kuroyanagi                insertedPointIndex + 1, CharUtils::toBaseLowerCase(dicNode->getNodeCodePoint()));
140a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const float weightedDistance = dist * ScoringParams::DISTANCE_WEIGHT_LENGTH;
14109858cbde49c086dd1d4d3050b57f0ea1774158bKeisuke Kuroynagi        const bool singleChar = dicNode->getNodeCodePointCount() == 1;
14224706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi        float cost = (singleChar ? ScoringParams::INSERTION_COST_FIRST_CHAR : 0.0f);
14324706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi        if (sameCodePoint) {
14424706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi            cost += ScoringParams::INSERTION_COST_SAME_CHAR;
14524706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi        } else if (existsAdjacentProximityChars) {
14624706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi            cost += ScoringParams::INSERTION_COST_PROXIMITY_CHAR;
14724706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi        } else {
14824706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi            cost += ScoringParams::INSERTION_COST;
14924706f8f5c61785006af50cc19fdd96559faa9faKeisuke Kuroynagi        }
150a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        return cost + weightedDistance;
151a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
152a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
1538a809f3433c3b96a3a9002a5bdc166f8c689eeb0Keisuke Kuroyanagi    float getSpaceOmissionCost(const DicTraverseSession *const traverseSession,
1546bfeeb86947eb2131408ae8bd55a7f90486feb1dKeisuke Kuroynagi            const DicNode *const dicNode, DicNode_InputStateG *inputStateG) const {
1558a809f3433c3b96a3a9002a5bdc166f8c689eeb0Keisuke Kuroyanagi        const float cost = ScoringParams::SPACE_OMISSION_COST;
1568a809f3433c3b96a3a9002a5bdc166f8c689eeb0Keisuke Kuroyanagi        return cost * traverseSession->getMultiWordCostMultiplier();
157a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
158a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
1596bfeeb86947eb2131408ae8bd55a7f90486feb1dKeisuke Kuroynagi    float getNewWordBigramLanguageCost(const DicTraverseSession *const traverseSession,
160866a6ced571a24f0f1b927aeccad7a1969da23b7Ken Wakasa            const DicNode *const dicNode,
1619559dd2e30de288a9ff7069bfc59f8500b949a88Tom Ouyang            MultiBigramMap *const multiBigramMap) const {
162d81654cd61bd10f7cb56bfa4c89b34e9cfb18598Keisuke Kuroyanagi        return DicNodeUtils::getBigramNodeImprobability(
163d81654cd61bd10f7cb56bfa4c89b34e9cfb18598Keisuke Kuroyanagi                traverseSession->getDictionaryStructurePolicy(),
1649559dd2e30de288a9ff7069bfc59f8500b949a88Tom Ouyang                dicNode, multiBigramMap) * ScoringParams::DISTANCE_WEIGHT_LANGUAGE;
165a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
166a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
167a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    float getCompletionCost(const DicTraverseSession *const traverseSession,
168a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka            const DicNode *const dicNode) const {
169a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        // The auto completion starts when the input index is same as the input size
170a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        const bool firstCompletion = dicNode->getInputIndex(0)
171a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka                == traverseSession->getInputSize();
172a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        // TODO: Change the cost for the first completion for the gesture?
17377de3a4b65d9baa9cc9469c2600bcce8de32ba82Keisuke Kuroyanagi        const float cost = firstCompletion ? ScoringParams::COST_FIRST_COMPLETION
17477de3a4b65d9baa9cc9469c2600bcce8de32ba82Keisuke Kuroyanagi                : ScoringParams::COST_COMPLETION;
175a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        return cost;
176a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
177a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
178a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    float getTerminalLanguageCost(const DicTraverseSession *const traverseSession,
179a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka            const DicNode *const dicNode, const float dicNodeLanguageImprobability) const {
18034047d8905fbd2cbe4c99618aab105556ebee9edKeisuke Kuroynagi        return dicNodeLanguageImprobability * ScoringParams::DISTANCE_WEIGHT_LANGUAGE;
181a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
182a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
18375322cecb9fe02a0914b65c859cfbc2f4e1f70d9Satoshi Kataoka    float getTerminalInsertionCost(const DicTraverseSession *const traverseSession,
18475322cecb9fe02a0914b65c859cfbc2f4e1f70d9Satoshi Kataoka            const DicNode *const dicNode) const {
18575322cecb9fe02a0914b65c859cfbc2f4e1f70d9Satoshi Kataoka        const int inputIndex = dicNode->getInputIndex(0);
18675322cecb9fe02a0914b65c859cfbc2f4e1f70d9Satoshi Kataoka        const int inputSize = traverseSession->getInputSize();
18775322cecb9fe02a0914b65c859cfbc2f4e1f70d9Satoshi Kataoka        ASSERT(inputIndex < inputSize);
18875322cecb9fe02a0914b65c859cfbc2f4e1f70d9Satoshi Kataoka        // TODO: Implement more efficient logic
18975322cecb9fe02a0914b65c859cfbc2f4e1f70d9Satoshi Kataoka        return  ScoringParams::TERMINAL_INSERTION_COST * (inputSize - inputIndex);
19075322cecb9fe02a0914b65c859cfbc2f4e1f70d9Satoshi Kataoka    }
19175322cecb9fe02a0914b65c859cfbc2f4e1f70d9Satoshi Kataoka
192a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    AK_FORCE_INLINE bool needsToNormalizeCompoundDistance() const {
193a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        return false;
194a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
195a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
196a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    AK_FORCE_INLINE float getAdditionalProximityCost() const {
197a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        return ScoringParams::ADDITIONAL_PROXIMITY_COST;
198a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
199a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
200a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    AK_FORCE_INLINE float getSubstitutionCost() const {
201a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka        return ScoringParams::SUBSTITUTION_COST;
202a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
203a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
204866a6ced571a24f0f1b927aeccad7a1969da23b7Ken Wakasa    AK_FORCE_INLINE float getSpaceSubstitutionCost(const DicTraverseSession *const traverseSession,
205252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka            const DicNode *const dicNode) const {
2068a809f3433c3b96a3a9002a5bdc166f8c689eeb0Keisuke Kuroyanagi        const int inputIndex = dicNode->getInputIndex(0);
2078a809f3433c3b96a3a9002a5bdc166f8c689eeb0Keisuke Kuroyanagi        const float distanceToSpaceKey = traverseSession->getProximityInfoState(0)
2088a809f3433c3b96a3a9002a5bdc166f8c689eeb0Keisuke Kuroyanagi                ->getPointToKeyLength(inputIndex, KEYCODE_SPACE);
2098a809f3433c3b96a3a9002a5bdc166f8c689eeb0Keisuke Kuroyanagi        const float cost = ScoringParams::SPACE_SUBSTITUTION_COST * distanceToSpaceKey;
210252412d7eb4573f91588b06b0fe49ef9f0ac38acSatoshi Kataoka        return cost * traverseSession->getMultiWordCostMultiplier();
211a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    }
212a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
2132fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    ErrorTypeUtils::ErrorType getErrorType(const CorrectionType correctionType,
21460a169f0c34bf0da89c420d99bfff5c2556f3fbfKeisuke Kuroynagi            const DicTraverseSession *const traverseSession,
21560a169f0c34bf0da89c420d99bfff5c2556f3fbfKeisuke Kuroynagi            const DicNode *const parentDicNode, const DicNode *const dicNode) const;
21660a169f0c34bf0da89c420d99bfff5c2556f3fbfKeisuke Kuroynagi
217a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka private:
218a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    DISALLOW_COPY_AND_ASSIGN(TypingWeighting);
219a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    static const TypingWeighting sInstance;
220a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka
221a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    TypingWeighting() {}
222a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka    ~TypingWeighting() {}
223a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka};
224a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka} // namespace latinime
225a6a416519603d2e65416dd8f9507913b7e4fd0a0Satoshi Kataoka#endif // LATINIME_TYPING_WEIGHTING_H
226