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 17 package com.android.inputmethod.latin.utils; 18 19 import android.util.Log; 20 21 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; 22 import com.android.inputmethod.latin.define.DebugFlags; 23 24 public 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 AutoCorrectionUtils()29 private AutoCorrectionUtils() { 30 // Purely static class: can't instantiate. 31 } 32 suggestionExceedsAutoCorrectionThreshold( final SuggestedWordInfo suggestion, final String consideredWord, final float autoCorrectionThreshold)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 shouldBlockAutoCorrectionBySafetyNet(final String typedWord, final String suggestion)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