mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-04-27 10:06:21 +00:00
tune glide typing suggestions
prefer multi-letter over single letter suggestions prefer suggestions that also occur in next word suggestions for this ngram context (and do some tiny tuning)
This commit is contained in:
parent
7397deac57
commit
cb70ee2656
3 changed files with 64 additions and 8 deletions
|
@ -477,9 +477,10 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
|
|||
if (params.mIconsSet.getIconDrawable(KeyboardIconsSet.getIconId(this)) != null) return this
|
||||
val id = context.resources.getIdentifier("label_$this", "string", context.packageName)
|
||||
if (id == 0) {
|
||||
Log.w(this::class.simpleName, "no resource for label $this")
|
||||
val message = "no resource for label $this in ${params.mId}"
|
||||
Log.w(this::class.simpleName, message)
|
||||
if (DebugFlags.DEBUG_ENABLED)
|
||||
Toast.makeText(context, "no resource for label $this", Toast.LENGTH_LONG).show()
|
||||
Toast.makeText(context, message, Toast.LENGTH_LONG).show()
|
||||
return this
|
||||
}
|
||||
val ril = object : RunInLocale<String>() { // todo (later): simpler way of doing this in a single line?
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.dslul.openboard.inputmethod.latin;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
||||
import org.dslul.openboard.inputmethod.keyboard.Keyboard;
|
||||
|
@ -16,6 +17,7 @@ import org.dslul.openboard.inputmethod.latin.common.ComposedData;
|
|||
import org.dslul.openboard.inputmethod.latin.common.Constants;
|
||||
import org.dslul.openboard.inputmethod.latin.common.InputPointers;
|
||||
import org.dslul.openboard.inputmethod.latin.common.StringUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.define.DebugFlags;
|
||||
import org.dslul.openboard.inputmethod.latin.settings.Settings;
|
||||
import org.dslul.openboard.inputmethod.latin.settings.SettingsValuesForSuggestion;
|
||||
import org.dslul.openboard.inputmethod.latin.suggestions.SuggestionStripView;
|
||||
|
@ -25,6 +27,7 @@ import org.dslul.openboard.inputmethod.latin.utils.SuggestionResults;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
|
@ -32,6 +35,7 @@ import static org.dslul.openboard.inputmethod.latin.define.DecoderSpecificConsta
|
|||
import static org.dslul.openboard.inputmethod.latin.define.DecoderSpecificConstants.SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import kotlin.collections.CollectionsKt;
|
||||
|
||||
|
@ -424,11 +428,11 @@ public final class Suggest {
|
|||
final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
|
||||
wordComposer.getComposedDataSnapshot(), ngramContext, keyboard,
|
||||
settingsValuesForSuggestion, SESSION_ID_GESTURE, inputStyle);
|
||||
replaceSingleLetterFirstSuggestion(suggestionResults);
|
||||
|
||||
// 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 ArrayList<SuggestedWordInfo> suggestionsContainer = new ArrayList<>(suggestionResults);
|
||||
final int suggestionsCount = suggestionsContainer.size();
|
||||
final boolean isFirstCharCapitalized = wordComposer.wasShiftedNoLock();
|
||||
final boolean isAllUpperCase = wordComposer.isAllUpperCase();
|
||||
|
@ -443,12 +447,15 @@ public final class Suggest {
|
|||
}
|
||||
}
|
||||
|
||||
final SuggestedWordInfo rejected;
|
||||
if (SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION
|
||||
&& suggestionsContainer.size() > 1
|
||||
&& TextUtils.equals(suggestionsContainer.get(0).mWord,
|
||||
wordComposer.getRejectedBatchModeSuggestion())) {
|
||||
final SuggestedWordInfo rejected = suggestionsContainer.remove(0);
|
||||
rejected = suggestionsContainer.remove(0);
|
||||
suggestionsContainer.add(1, rejected);
|
||||
} else {
|
||||
rejected = null;
|
||||
}
|
||||
SuggestedWordInfo.removeDupsAndTypedWord(null /* typedWord */, suggestionsContainer);
|
||||
|
||||
|
@ -464,8 +471,8 @@ public final class Suggest {
|
|||
// (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);
|
||||
final SuggestedWordInfo pseudoTypedWordInfo = preferNextWordSuggestion(suggestionsContainer.isEmpty() ? null : suggestionsContainer.get(0),
|
||||
suggestionsContainer, getNextWordSuggestions(ngramContext, keyboard, inputStyle, settingsValuesForSuggestion), rejected);
|
||||
|
||||
final ArrayList<SuggestedWordInfo> suggestionsList;
|
||||
if (SuggestionStripView.DEBUG_SUGGESTIONS && !suggestionsContainer.isEmpty()) {
|
||||
|
@ -483,6 +490,54 @@ public final class Suggest {
|
|||
inputStyle, sequenceNumber));
|
||||
}
|
||||
|
||||
/** reduces score of the first suggestion if next one is close and has more than a single letter */
|
||||
private void replaceSingleLetterFirstSuggestion(final SuggestionResults suggestionResults) {
|
||||
if (suggestionResults.size() < 2 || suggestionResults.first().mWord.length() != 1) return;
|
||||
// suppress single letter suggestions if next suggestion is close and has more than one letter
|
||||
final Iterator<SuggestedWordInfo> iterator = suggestionResults.iterator();
|
||||
final SuggestedWordInfo first = iterator.next();
|
||||
final SuggestedWordInfo second = iterator.next();
|
||||
if (second.mWord.length() > 1 && second.mScore > 0.94 * first.mScore) {
|
||||
suggestionResults.remove(first); // remove and re-add with lower score
|
||||
suggestionResults.add(new SuggestedWordInfo(first.mWord, first.mPrevWordsContext, (int) (first.mScore * 0.93),
|
||||
first.mKindAndFlags, first.mSourceDict, first.mIndexOfTouchPointOfSecondWord, first.mAutoCommitFirstWordConfidence));
|
||||
if (DebugFlags.DEBUG_ENABLED)
|
||||
Log.d(TAG, "reduced score of "+first.mWord+" from "+first.mScore +", new first: "+suggestionResults.first().mWord+" ("+suggestionResults.first().mScore+")");
|
||||
}
|
||||
}
|
||||
|
||||
// returns new pseudoTypedWordInfo, puts it in suggestionsContainer, modifies nextWordSuggestions
|
||||
@Nullable
|
||||
private SuggestedWordInfo preferNextWordSuggestion(@Nullable final SuggestedWordInfo pseudoTypedWordInfo,
|
||||
@NonNull final ArrayList<SuggestedWordInfo> suggestionsContainer,
|
||||
@NonNull final SuggestionResults nextWordSuggestions, @Nullable final SuggestedWordInfo rejected) {
|
||||
if (pseudoTypedWordInfo == null
|
||||
|| !Settings.getInstance().getCurrent().mUsePersonalizedDicts
|
||||
|| !pseudoTypedWordInfo.mSourceDict.mDictType.equals(Dictionary.TYPE_MAIN)
|
||||
|| suggestionsContainer.size() < 2
|
||||
)
|
||||
return pseudoTypedWordInfo;
|
||||
CollectionsKt.removeAll(nextWordSuggestions, (info) -> info.mScore < 170); // we only want reasonably often typed words, value may require tuning
|
||||
if (nextWordSuggestions.isEmpty())
|
||||
return pseudoTypedWordInfo;
|
||||
// for each suggestion, check whether the word was already typed in this ngram context (i.e. is nextWordSuggestion)
|
||||
for (final SuggestedWordInfo suggestion : suggestionsContainer) {
|
||||
if (suggestion.mScore < pseudoTypedWordInfo.mScore * 0.93) break; // we only want reasonably good suggestions, value may require tuning
|
||||
if (suggestion == rejected) continue; // ignore rejected suggestions
|
||||
for (final SuggestedWordInfo nextWordSuggestion : nextWordSuggestions) {
|
||||
if (!nextWordSuggestion.mWord.equals(suggestion.mWord))
|
||||
continue;
|
||||
// if we have a high scoring suggestion in next word suggestions, take it (because it's expected that user might want to type it again)
|
||||
suggestionsContainer.remove(suggestion);
|
||||
suggestionsContainer.add(0, suggestion);
|
||||
if (DebugFlags.DEBUG_ENABLED)
|
||||
Log.d(TAG, "replaced batch word "+pseudoTypedWordInfo+" with "+suggestion);
|
||||
return suggestion;
|
||||
}
|
||||
}
|
||||
return pseudoTypedWordInfo;
|
||||
}
|
||||
|
||||
private static ArrayList<SuggestedWordInfo> getSuggestionsInfoListWithDebugInfo(
|
||||
final String typedWord, final ArrayList<SuggestedWordInfo> suggestions) {
|
||||
final int suggestionsSize = suggestions.size();
|
||||
|
|
|
@ -73,7 +73,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
|||
}
|
||||
|
||||
public static boolean DEBUG_SUGGESTIONS;
|
||||
private static final float DEBUG_INFO_TEXT_SIZE_IN_DIP = 6.0f;
|
||||
private static final float DEBUG_INFO_TEXT_SIZE_IN_DIP = 6.5f;
|
||||
private static final String VOICE_KEY_TAG = "voice_key";
|
||||
private static final String CLIPBOARD_KEY_TAG = "clipboard_key";
|
||||
private static final String SETTINGS_KEY_TAG = "settings_key";
|
||||
|
|
Loading…
Add table
Reference in a new issue