1/*
2 * Copyright (C) 2011 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
17package com.android.inputmethod.latin.utils;
18
19import android.util.Log;
20
21import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
22import com.android.inputmethod.latin.define.DebugFlags;
23
24public final class AutoCorrectionUtils {
25    private static final boolean DBG = DebugFlags.DEBUG_ENABLED;
26    private static final String TAG = AutoCorrectionUtils.class.getSimpleName();
27    private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4;
28
29    private AutoCorrectionUtils() {
30        // Purely static class: can't instantiate.
31    }
32
33    public static boolean suggestionExceedsAutoCorrectionThreshold(
34            final SuggestedWordInfo suggestion, final String consideredWord,
35            final float autoCorrectionThreshold) {
36        if (null != suggestion) {
37            // Shortlist a whitelisted word
38            if (suggestion.isKindOf(SuggestedWordInfo.KIND_WHITELIST)) {
39                return true;
40            }
41            final int autoCorrectionSuggestionScore = suggestion.mScore;
42            // TODO: when the normalized score of the first suggestion is nearly equals to
43            //       the normalized score of the second suggestion, behave less aggressive.
44            final float normalizedScore = BinaryDictionaryUtils.calcNormalizedScore(
45                    consideredWord, suggestion.mWord, autoCorrectionSuggestionScore);
46            if (DBG) {
47                Log.d(TAG, "Normalized " + consideredWord + "," + suggestion + ","
48                        + autoCorrectionSuggestionScore + ", " + normalizedScore
49                        + "(" + autoCorrectionThreshold + ")");
50            }
51            if (normalizedScore >= autoCorrectionThreshold) {
52                if (DBG) {
53                    Log.d(TAG, "Auto corrected by S-threshold.");
54                }
55                return !shouldBlockAutoCorrectionBySafetyNet(consideredWord, suggestion.mWord);
56            }
57        }
58        return false;
59    }
60
61    // TODO: Resolve the inconsistencies between the native auto correction algorithms and
62    // this safety net
63    public static boolean shouldBlockAutoCorrectionBySafetyNet(final String typedWord,
64            final String suggestion) {
65        // Safety net for auto correction.
66        // Actually if we hit this safety net, it's a bug.
67        // If user selected aggressive auto correction mode, there is no need to use the safety
68        // net.
69        // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH,
70        // we should not use net because relatively edit distance can be big.
71        final int typedWordLength = typedWord.length();
72        if (typedWordLength < MINIMUM_SAFETY_NET_CHAR_LENGTH) {
73            return false;
74        }
75        final int maxEditDistanceOfNativeDictionary = (typedWordLength / 2) + 1;
76        final int distance = BinaryDictionaryUtils.editDistance(typedWord, suggestion);
77        if (DBG) {
78            Log.d(TAG, "Autocorrected edit distance = " + distance
79                    + ", " + maxEditDistanceOfNativeDictionary);
80        }
81        if (distance > maxEditDistanceOfNativeDictionary) {
82            if (DBG) {
83                Log.e(TAG, "Safety net: before = " + typedWord + ", after = " + suggestion);
84                Log.e(TAG, "(Error) The edit distance of this correction exceeds limit. "
85                        + "Turning off auto-correction.");
86            }
87            return true;
88        } else {
89            return false;
90        }
91    }
92}
93