mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-17 23:42:55 +00:00
add unit tests for input logic (wip very much)
This commit is contained in:
parent
f1fde08a55
commit
70f419efe5
7 changed files with 590 additions and 270 deletions
|
@ -24,7 +24,8 @@ private class CrashReportExceptionHandler(val appContext: Context) : Thread.Unca
|
|||
|
||||
fun install(): Boolean {
|
||||
val ueh = Thread.getDefaultUncaughtExceptionHandler()
|
||||
check(ueh !is CrashReportExceptionHandler) { "May not install several CrashReportExceptionHandlers!" }
|
||||
if (ueh is CrashReportExceptionHandler)
|
||||
return false
|
||||
defaultUncaughtExceptionHandler = ueh
|
||||
Thread.setDefaultUncaughtExceptionHandler(this)
|
||||
return true
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.dslul.openboard.inputmethod.latin;
|
|||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
||||
import org.dslul.openboard.inputmethod.keyboard.Keyboard;
|
||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardId;
|
||||
import org.dslul.openboard.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||
|
@ -203,8 +204,6 @@ public final class Suggest {
|
|||
keyboard.mId.mMode,
|
||||
wordComposer,
|
||||
suggestionResults,
|
||||
mDictionaryFacilitator,
|
||||
mAutoCorrectionThreshold,
|
||||
firstOccurrenceOfTypedWordInSuggestions,
|
||||
typedWordFirstOccurrenceWordInfo
|
||||
);
|
||||
|
@ -282,7 +281,8 @@ public final class Suggest {
|
|||
}
|
||||
|
||||
// returns [allowsToBeAutoCorrected, hasAutoCorrection]
|
||||
static boolean[] shouldBeAutoCorrected(
|
||||
@UsedForTesting
|
||||
boolean[] shouldBeAutoCorrected(
|
||||
final int trailingSingleQuotesCount,
|
||||
final String typedWordString,
|
||||
final List<SuggestedWordInfo> suggestionsContainer,
|
||||
|
@ -293,8 +293,6 @@ public final class Suggest {
|
|||
final int keyboardIdMode,
|
||||
final WordComposer wordComposer,
|
||||
final SuggestionResults suggestionResults,
|
||||
final DictionaryFacilitator dictionaryFacilitator,
|
||||
final float autoCorrectionThreshold,
|
||||
final int firstOccurrenceOfTypedWordInSuggestions,
|
||||
final SuggestedWordInfo typedWordFirstOccurrenceWordInfo
|
||||
) {
|
||||
|
@ -365,7 +363,7 @@ public final class Suggest {
|
|||
// list, "will" would always auto-correct to "Will" which is unwanted. Hence, no
|
||||
// main dict => no auto-correct. Also, it would probably get obnoxious quickly.
|
||||
// TODO: now that we have personalization, we may want to re-evaluate this decision
|
||||
|| !dictionaryFacilitator.hasAtLeastOneInitializedMainDictionary()) {
|
||||
|| !mDictionaryFacilitator.hasAtLeastOneInitializedMainDictionary()) {
|
||||
hasAutoCorrection = false;
|
||||
} else {
|
||||
final SuggestedWordInfo firstSuggestion = suggestionResults.first();
|
||||
|
@ -376,7 +374,7 @@ public final class Suggest {
|
|||
return new boolean[]{ true, true };
|
||||
}
|
||||
if (!AutoCorrectionUtils.suggestionExceedsThreshold(
|
||||
firstSuggestion, consideredWord, autoCorrectionThreshold)) {
|
||||
firstSuggestion, consideredWord, mAutoCorrectionThreshold)) {
|
||||
// todo: maybe also do something here depending on ngram context?
|
||||
// Score is too low for autocorrect
|
||||
return new boolean[]{ true, false };
|
||||
|
@ -390,7 +388,7 @@ public final class Suggest {
|
|||
// typed word is valid and has good score
|
||||
// do not auto-correct if typed word is better match than first suggestion
|
||||
final SuggestedWordInfo first = firstSuggestionInContainer != null ? firstSuggestionInContainer : firstSuggestion;
|
||||
final Locale dictLocale = dictionaryFacilitator.getCurrentLocale();
|
||||
final Locale dictLocale = mDictionaryFacilitator.getCurrentLocale();
|
||||
|
||||
if (first.mScore < scoreLimit) {
|
||||
// don't allow if suggestion has too low score
|
||||
|
|
|
@ -16,18 +16,11 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin.utils;
|
||||
|
||||
import static android.view.KeyEvent.KEYCODE_SPACE;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
|
||||
|
||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
||||
import org.dslul.openboard.inputmethod.latin.BuildConfig;
|
||||
import org.dslul.openboard.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||
import org.dslul.openboard.inputmethod.latin.common.StringUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.define.DebugFlags;
|
||||
|
||||
public final class AutoCorrectionUtils {
|
||||
|
@ -38,7 +31,6 @@ public final class AutoCorrectionUtils {
|
|||
// Purely static class: can't instantiate.
|
||||
}
|
||||
|
||||
@SuppressLint("ObsoleteSdkInt") // SDK_INT is 0 in unit tests
|
||||
public static boolean suggestionExceedsThreshold(final SuggestedWordInfo suggestion,
|
||||
final String consideredWord, final float threshold) {
|
||||
if (null != suggestion) {
|
||||
|
@ -53,13 +45,7 @@ public final class AutoCorrectionUtils {
|
|||
final int autoCorrectionSuggestionScore = suggestion.mScore;
|
||||
// TODO: when the normalized score of the first suggestion is nearly equals to
|
||||
// the normalized score of the second suggestion, behave less aggressive.
|
||||
final float normalizedScore;
|
||||
if (BuildConfig.DEBUG && Build.VERSION.SDK_INT == 0)
|
||||
normalizedScore = calcNormalizedScore(StringUtils.toCodePointArray(consideredWord),
|
||||
StringUtils.toCodePointArray(suggestion.mWord), autoCorrectionSuggestionScore,
|
||||
editDistance(consideredWord, suggestion.mWord));
|
||||
else
|
||||
normalizedScore = BinaryDictionaryUtils.calcNormalizedScore(
|
||||
final float normalizedScore = BinaryDictionaryUtils.calcNormalizedScore(
|
||||
consideredWord, suggestion.mWord, autoCorrectionSuggestionScore);
|
||||
if (DBG) {
|
||||
Log.d(TAG, "Normalized " + consideredWord + "," + suggestion + ","
|
||||
|
@ -75,72 +61,4 @@ public final class AutoCorrectionUtils {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// below is normalized score calculation in java, to allow unit tests involving suggestionExceedsThreshold
|
||||
@UsedForTesting
|
||||
private static float calcNormalizedScore(final int[] before,
|
||||
final int[] after, final int score, final int distance) {
|
||||
final int beforeLength = before.length;
|
||||
final int afterLength = after.length;
|
||||
if (0 == beforeLength || 0 == afterLength)
|
||||
return 0.0f;
|
||||
|
||||
int spaceCount = 0;
|
||||
for (int j : after) {
|
||||
if (j == KEYCODE_SPACE)
|
||||
++spaceCount;
|
||||
}
|
||||
|
||||
if (spaceCount == afterLength)
|
||||
return 0.0f;
|
||||
|
||||
if (score <= 0 || distance >= afterLength) {
|
||||
// normalizedScore must be 0.0f (the minimum value) if the score is less than or equal to 0,
|
||||
// or if the edit distance is larger than or equal to afterLength.
|
||||
return 0.0f;
|
||||
}
|
||||
// add a weight based on edit distance.
|
||||
final float weight = 1.0f - (float) distance / (float) afterLength;
|
||||
|
||||
return ((float) score / 1000000.0f) * weight;
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
private static int editDistance(String x, String y) {
|
||||
int[][] dp = new int[x.length() + 1][y.length() + 1];
|
||||
|
||||
for (int i = 0; i <= x.length(); i++) {
|
||||
for (int j = 0; j <= y.length(); j++) {
|
||||
if (i == 0) {
|
||||
dp[i][j] = j;
|
||||
}
|
||||
else if (j == 0) {
|
||||
dp[i][j] = i;
|
||||
}
|
||||
else {
|
||||
dp[i][j] = min(dp[i - 1][j - 1]
|
||||
+ costOfSubstitution(x.charAt(i - 1), y.charAt(j - 1)),
|
||||
dp[i - 1][j] + 1,
|
||||
dp[i][j - 1] + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dp[x.length()][y.length()];
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
private static int min(int... numbers) {
|
||||
int min = Integer.MAX_VALUE;
|
||||
for (int n : numbers) {
|
||||
if (n < min)
|
||||
min = n;
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
private static int costOfSubstitution(char a, char b) {
|
||||
return a == b ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue