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