Search in sources :

Example 1 with SuggestionResults

use of com.android.inputmethod.latin.utils.SuggestionResults in project android_packages_inputmethods_LatinIME by CyanogenMod.

the class DictionaryFacilitatorImpl method getSuggestionResults.

// TODO: Revise the way to fusion suggestion results.
@Override
@Nonnull
public SuggestionResults getSuggestionResults(ComposedData composedData, NgramContext ngramContext, @Nonnull final Keyboard keyboard, SettingsValuesForSuggestion settingsValuesForSuggestion, int sessionId, int inputStyle) {
    long proximityInfoHandle = keyboard.getProximityInfo().getNativeProximityInfo();
    final SuggestionResults suggestionResults = new SuggestionResults(SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext(), false);
    final float[] weightOfLangModelVsSpatialModel = new float[] { Dictionary.NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL };
    for (final String dictType : ALL_DICTIONARY_TYPES) {
        final Dictionary dictionary = mDictionaryGroup.getDict(dictType);
        if (null == dictionary)
            continue;
        final float weightForLocale = composedData.mIsBatchMode ? mDictionaryGroup.mWeightForGesturingInLocale : mDictionaryGroup.mWeightForTypingInLocale;
        final ArrayList<SuggestedWordInfo> dictionarySuggestions = dictionary.getSuggestions(composedData, ngramContext, proximityInfoHandle, settingsValuesForSuggestion, sessionId, weightForLocale, weightOfLangModelVsSpatialModel);
        if (null == dictionarySuggestions)
            continue;
        suggestionResults.addAll(dictionarySuggestions);
        if (null != suggestionResults.mRawSuggestions) {
            suggestionResults.mRawSuggestions.addAll(dictionarySuggestions);
        }
    }
    return suggestionResults;
}
Also used : UserHistoryDictionary(com.android.inputmethod.latin.personalization.UserHistoryDictionary) SuggestionResults(com.android.inputmethod.latin.utils.SuggestionResults) SuggestedWordInfo(com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo) Nonnull(javax.annotation.Nonnull)

Example 2 with SuggestionResults

use of com.android.inputmethod.latin.utils.SuggestionResults in project android_packages_inputmethods_LatinIME by CyanogenMod.

the class Suggest method getSuggestedWordsForBatchInput.

// Retrieves suggestions for the batch input
// and calls the callback function with the suggestions.
private void getSuggestedWordsForBatchInput(final WordComposer wordComposer, final NgramContext ngramContext, final Keyboard keyboard, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int inputStyle, final int sequenceNumber, final OnGetSuggestedWordsCallback callback) {
    final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(wordComposer.getComposedDataSnapshot(), ngramContext, keyboard, settingsValuesForSuggestion, SESSION_ID_GESTURE, inputStyle);
    // For transforming words that don't come from a dictionary, because it's our best bet
    final Locale locale = mDictionaryFacilitator.getLocale();
    final ArrayList<SuggestedWordInfo> suggestionsContainer = new ArrayList<>(suggestionResults);
    final int suggestionsCount = suggestionsContainer.size();
    final boolean isFirstCharCapitalized = wordComposer.wasShiftedNoLock();
    final boolean isAllUpperCase = wordComposer.isAllUpperCase();
    if (isFirstCharCapitalized || isAllUpperCase) {
        for (int i = 0; i < suggestionsCount; ++i) {
            final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
            final Locale wordlocale = wordInfo.mSourceDict.mLocale;
            final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(wordInfo, null == wordlocale ? locale : wordlocale, isAllUpperCase, isFirstCharCapitalized, 0);
            suggestionsContainer.set(i, transformedWordInfo);
        }
    }
    if (SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION && suggestionsContainer.size() > 1 && TextUtils.equals(suggestionsContainer.get(0).mWord, wordComposer.getRejectedBatchModeSuggestion())) {
        final SuggestedWordInfo rejected = suggestionsContainer.remove(0);
        suggestionsContainer.add(1, rejected);
    }
    SuggestedWordInfo.removeDups(null, /* typedWord */
    suggestionsContainer);
    // TODO: Find a more robust way to detect distracters.
    for (int i = suggestionsContainer.size() - 1; i >= 0; --i) {
        if (suggestionsContainer.get(i).mScore < SUPPRESS_SUGGEST_THRESHOLD) {
            suggestionsContainer.remove(i);
        }
    }
    // In the batch input mode, the most relevant suggested word should act as a "typed word"
    // (typedWordValid=true), not as an "auto correct word" (willAutoCorrect=false).
    // Note that because this method is never used to get predictions, there is no need to
    // modify inputType such in getSuggestedWordsForNonBatchInput.
    final SuggestedWordInfo pseudoTypedWordInfo = suggestionsContainer.isEmpty() ? null : suggestionsContainer.get(0);
    callback.onGetSuggestedWords(new SuggestedWords(suggestionsContainer, suggestionResults.mRawSuggestions, pseudoTypedWordInfo, true, /* typedWordValid */
    false, /* willAutoCorrect */
    false, /* isObsoleteSuggestions */
    inputStyle, sequenceNumber));
}
Also used : Locale(java.util.Locale) SuggestionResults(com.android.inputmethod.latin.utils.SuggestionResults) SuggestedWordInfo(com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo) ArrayList(java.util.ArrayList)

Example 3 with SuggestionResults

use of com.android.inputmethod.latin.utils.SuggestionResults in project android_packages_inputmethods_LatinIME by CyanogenMod.

the class Suggest method getSuggestedWordsForNonBatchInput.

// Retrieves suggestions for non-batch input (typing, recorrection, predictions...)
// and calls the callback function with the suggestions.
private void getSuggestedWordsForNonBatchInput(final WordComposer wordComposer, final NgramContext ngramContext, final Keyboard keyboard, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int inputStyleIfNotPrediction, final boolean isCorrectionEnabled, final int sequenceNumber, final OnGetSuggestedWordsCallback callback) {
    final String typedWordString = wordComposer.getTypedWord();
    final int trailingSingleQuotesCount = StringUtils.getTrailingSingleQuotesCount(typedWordString);
    final String consideredWord = trailingSingleQuotesCount > 0 ? typedWordString.substring(0, typedWordString.length() - trailingSingleQuotesCount) : typedWordString;
    final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(wordComposer.getComposedDataSnapshot(), ngramContext, keyboard, settingsValuesForSuggestion, SESSION_ID_TYPING, inputStyleIfNotPrediction);
    final Locale locale = mDictionaryFacilitator.getLocale();
    final ArrayList<SuggestedWordInfo> suggestionsContainer = getTransformedSuggestedWordInfoList(wordComposer, suggestionResults, trailingSingleQuotesCount, locale);
    boolean foundInDictionary = false;
    Dictionary sourceDictionaryOfRemovedWord = null;
    for (final SuggestedWordInfo info : suggestionsContainer) {
        // quality we can find.
        if (!foundInDictionary && typedWordString.equals(info.mWord)) {
            // Use this source if the old match had lower quality than this match
            sourceDictionaryOfRemovedWord = info.mSourceDict;
            foundInDictionary = true;
            break;
        }
    }
    final int firstOcurrenceOfTypedWordInSuggestions = SuggestedWordInfo.removeDups(typedWordString, suggestionsContainer);
    final SuggestedWordInfo whitelistedWordInfo = getWhitelistedWordInfoOrNull(suggestionsContainer);
    final String whitelistedWord = whitelistedWordInfo == null ? null : whitelistedWordInfo.mWord;
    final boolean resultsArePredictions = !wordComposer.isComposingWord();
    // We allow auto-correction if whitelisting is not required or the word is whitelisted,
    // or if the word had more than one char and was not suggested.
    final boolean allowsToBeAutoCorrected = (SHOULD_AUTO_CORRECT_USING_NON_WHITE_LISTED_SUGGESTION || whitelistedWord != null) || (consideredWord.length() > 1 && (sourceDictionaryOfRemovedWord == null));
    final boolean hasAutoCorrection;
    // the setting "Auto-correction" is "off": we still suggest, but we don't auto-correct.
    if (!isCorrectionEnabled || // If the word does not allow to be auto-corrected, then we don't auto-correct.
    !allowsToBeAutoCorrected || // If we are doing prediction, then we never auto-correct of course
    resultsArePredictions || // for auto-correction
    suggestionResults.isEmpty() || // was type with a lot of care
    wordComposer.hasDigits() || // certainly intentional (and careful input)
    wordComposer.isMostlyCaps() || // We never auto-correct when suggestions are resumed because it would be unexpected
    wordComposer.isResumed() || // TODO: now that we have personalization, we may want to re-evaluate this decision
    !mDictionaryFacilitator.hasAtLeastOneInitializedMainDictionary() || // TODO: we may want to have shortcut-only entries auto-correct in the future.
    suggestionResults.first().isKindOf(SuggestedWordInfo.KIND_SHORTCUT)) {
        hasAutoCorrection = false;
    } else {
        final SuggestedWordInfo firstSuggestion = suggestionResults.first();
        if (suggestionResults.mFirstSuggestionExceedsConfidenceThreshold && firstOcurrenceOfTypedWordInSuggestions != 0) {
            hasAutoCorrection = true;
        } else if (!AutoCorrectionUtils.suggestionExceedsThreshold(firstSuggestion, consideredWord, mAutoCorrectionThreshold)) {
            // Score is too low for autocorrect
            hasAutoCorrection = false;
        } else {
            // We have a high score, so we need to check if this suggestion is in the correct
            // form to allow auto-correcting to it in this language. For details of how this
            // is determined, see #isAllowedByAutoCorrectionWithSpaceFilter.
            // TODO: this should not have its own logic here but be handled by the dictionary.
            hasAutoCorrection = isAllowedByAutoCorrectionWithSpaceFilter(firstSuggestion);
        }
    }
    final SuggestedWordInfo typedWordInfo = new SuggestedWordInfo(typedWordString, "", /* prevWordsContext */
    SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_TYPED, null == sourceDictionaryOfRemovedWord ? Dictionary.DICTIONARY_USER_TYPED : sourceDictionaryOfRemovedWord, SuggestedWordInfo.NOT_AN_INDEX, /* indexOfTouchPointOfSecondWord */
    SuggestedWordInfo.NOT_A_CONFIDENCE);
    if (!TextUtils.isEmpty(typedWordString)) {
        suggestionsContainer.add(0, typedWordInfo);
    }
    final ArrayList<SuggestedWordInfo> suggestionsList;
    if (DBG && !suggestionsContainer.isEmpty()) {
        suggestionsList = getSuggestionsInfoListWithDebugInfo(typedWordString, suggestionsContainer);
    } else {
        suggestionsList = suggestionsContainer;
    }
    final int inputStyle;
    if (resultsArePredictions) {
        inputStyle = suggestionResults.mIsBeginningOfSentence ? SuggestedWords.INPUT_STYLE_BEGINNING_OF_SENTENCE_PREDICTION : SuggestedWords.INPUT_STYLE_PREDICTION;
    } else {
        inputStyle = inputStyleIfNotPrediction;
    }
    final boolean isTypedWordValid = firstOcurrenceOfTypedWordInSuggestions > -1 || (!resultsArePredictions && !allowsToBeAutoCorrected);
    callback.onGetSuggestedWords(new SuggestedWords(suggestionsList, suggestionResults.mRawSuggestions, typedWordInfo, isTypedWordValid, hasAutoCorrection, /* willAutoCorrect */
    false, /* isObsoleteSuggestions */
    inputStyle, sequenceNumber));
}
Also used : Locale(java.util.Locale) SuggestionResults(com.android.inputmethod.latin.utils.SuggestionResults) SuggestedWordInfo(com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo)

Example 4 with SuggestionResults

use of com.android.inputmethod.latin.utils.SuggestionResults in project android_packages_inputmethods_LatinIME by CyanogenMod.

the class AndroidWordLevelSpellCheckerSession method onGetSuggestionsInternal.

protected SuggestionsInfo onGetSuggestionsInternal(final TextInfo textInfo, final NgramContext ngramContext, final int suggestionsLimit) {
    try {
        final String text = textInfo.getText().replaceAll(AndroidSpellCheckerService.APOSTROPHE, AndroidSpellCheckerService.SINGLE_QUOTE).replaceAll("^" + quotesRegexp, "").replaceAll(quotesRegexp + "$", "");
        if (!mService.hasMainDictionaryForLocale(mLocale)) {
            return AndroidSpellCheckerService.getNotInDictEmptySuggestions(false);
        }
        // Handle special patterns like email, URI, telephone number.
        final int checkability = getCheckabilityInScript(text, mScript);
        if (CHECKABILITY_CHECKABLE != checkability) {
            if (CHECKABILITY_CONTAINS_PERIOD == checkability) {
                final String[] splitText = text.split(Constants.REGEXP_PERIOD);
                boolean allWordsAreValid = true;
                for (final String word : splitText) {
                    if (!mService.isValidWord(mLocale, word)) {
                        allWordsAreValid = false;
                        break;
                    }
                }
                if (allWordsAreValid) {
                    return new SuggestionsInfo(SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO | SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS, new String[] { TextUtils.join(Constants.STRING_SPACE, splitText) });
                }
            }
            return mService.isValidWord(mLocale, text) ? AndroidSpellCheckerService.getInDictEmptySuggestions() : AndroidSpellCheckerService.getNotInDictEmptySuggestions(CHECKABILITY_CONTAINS_PERIOD == checkability);
        }
        // Handle normal words.
        final int capitalizeType = StringUtils.getCapitalizationType(text);
        if (isInDictForAnyCapitalization(text, capitalizeType)) {
            if (DebugFlags.DEBUG_ENABLED) {
                Log.i(TAG, "onGetSuggestionsInternal() : [" + text + "] is a valid word");
            }
            return AndroidSpellCheckerService.getInDictEmptySuggestions();
        }
        if (DebugFlags.DEBUG_ENABLED) {
            Log.i(TAG, "onGetSuggestionsInternal() : [" + text + "] is NOT a valid word");
        }
        final Keyboard keyboard = mService.getKeyboardForLocale(mLocale);
        if (null == keyboard) {
            Log.w(TAG, "onGetSuggestionsInternal() : No keyboard for locale: " + mLocale);
            // If there is no keyboard for this locale, don't do any spell-checking.
            return AndroidSpellCheckerService.getNotInDictEmptySuggestions(false);
        }
        final WordComposer composer = new WordComposer();
        final int[] codePoints = StringUtils.toCodePointArray(text);
        final int[] coordinates;
        coordinates = keyboard.getCoordinates(codePoints);
        composer.setComposingWord(codePoints, coordinates);
        // TODO: Don't gather suggestions if the limit is <= 0 unless necessary
        final SuggestionResults suggestionResults = mService.getSuggestionResults(mLocale, composer.getComposedDataSnapshot(), ngramContext, keyboard);
        final Result result = getResult(capitalizeType, mLocale, suggestionsLimit, mService.getRecommendedThreshold(), text, suggestionResults);
        if (DebugFlags.DEBUG_ENABLED) {
            if (result.mSuggestions != null && result.mSuggestions.length > 0) {
                final StringBuilder builder = new StringBuilder();
                for (String suggestion : result.mSuggestions) {
                    builder.append(" [");
                    builder.append(suggestion);
                    builder.append("]");
                }
                Log.i(TAG, "onGetSuggestionsInternal() : Suggestions =" + builder);
            }
        }
        // Handle word not in dictionary.
        // This is called only once per unique word, so entering multiple
        // instances of the same word does not result in more than one call
        // to this method.
        // Also, upon changing the orientation of the device, this is called
        // again for every unique invalid word in the text box.
        StatsUtils.onInvalidWordIdentification(text);
        final int flags = SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO | (result.mHasRecommendedSuggestions ? SuggestionsInfoCompatUtils.getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS() : 0);
        final SuggestionsInfo retval = new SuggestionsInfo(flags, result.mSuggestions);
        mSuggestionsCache.putSuggestionsToCache(text, result.mSuggestions, flags);
        return retval;
    } catch (RuntimeException e) {
        // Don't kill the keyboard if there is a bug in the spell checker
        Log.e(TAG, "Exception while spellchecking", e);
        return AndroidSpellCheckerService.getNotInDictEmptySuggestions(false);
    }
}
Also used : WordComposer(com.android.inputmethod.latin.WordComposer) SuggestionResults(com.android.inputmethod.latin.utils.SuggestionResults) Keyboard(com.android.inputmethod.keyboard.Keyboard) SuggestionsInfo(android.view.textservice.SuggestionsInfo)

Aggregations

SuggestionResults (com.android.inputmethod.latin.utils.SuggestionResults)4 SuggestedWordInfo (com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo)3 Locale (java.util.Locale)2 SuggestionsInfo (android.view.textservice.SuggestionsInfo)1 Keyboard (com.android.inputmethod.keyboard.Keyboard)1 WordComposer (com.android.inputmethod.latin.WordComposer)1 UserHistoryDictionary (com.android.inputmethod.latin.personalization.UserHistoryDictionary)1 ArrayList (java.util.ArrayList)1 Nonnull (javax.annotation.Nonnull)1