require a minimum frequency value in history before adding a word to personal dictionary

This commit is contained in:
Helium314 2024-09-29 19:30:12 +02:00
parent d754e7ca7f
commit 71d98e1e4f
2 changed files with 32 additions and 34 deletions

View file

@ -605,25 +605,30 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
} }
// main and secondary isValid provided to avoid duplicate lookups // main and secondary isValid provided to avoid duplicate lookups
private void addToPersonalDictionaryIfInvalidButInHistory(String suggestion, boolean[] validWordForDictionary) { private void addToPersonalDictionaryIfInvalidButInHistory(String word, boolean[] validWordForDictionary) {
final DictionaryGroup dictionaryGroup = getClearlyPreferredDictionaryGroupOrNull(); final DictionaryGroup dictionaryGroup = getClearlyPreferredDictionaryGroupOrNull();
if (dictionaryGroup == null) return; if (dictionaryGroup == null) return;
if (validWordForDictionary == null if (validWordForDictionary == null
? isValidWord(suggestion, ALL_DICTIONARY_TYPES, dictionaryGroup) ? isValidWord(word, ALL_DICTIONARY_TYPES, dictionaryGroup)
: validWordForDictionary[mDictionaryGroups.indexOf(dictionaryGroup)] : validWordForDictionary[mDictionaryGroups.indexOf(dictionaryGroup)]
) )
return; return;
final ExpandableBinaryDictionary userDict = dictionaryGroup.getSubDict(Dictionary.TYPE_USER); final ExpandableBinaryDictionary userDict = dictionaryGroup.getSubDict(Dictionary.TYPE_USER);
final Dictionary userHistoryDict = dictionaryGroup.getSubDict(Dictionary.TYPE_USER_HISTORY); final Dictionary userHistoryDict = dictionaryGroup.getSubDict(Dictionary.TYPE_USER_HISTORY);
if (userDict == null || userHistoryDict == null) return;
// user history always reports words as invalid, so here we need to check isInDictionary instead // user history always reports words as invalid, so here we need to check isInDictionary instead
// update: now getFrequency returns the correct value instead of -1, so better use that
// a little testing shows that after 2 times adding, the frequency is 111, and then rises slowly with usage
// 120 is after 3 uses of the word, so we simply require more than that.
// also maybe a problem: words added to dictionaries (user and history) are apparently found // also maybe a problem: words added to dictionaries (user and history) are apparently found
// only after some delay. but this is not too bad, it just delays adding // only after some delay. but this is not too bad, it just delays adding
if (userDict != null && userHistoryDict.isInDictionary(suggestion)) { if (userHistoryDict.getFrequency(word) > 120) {
if (userDict.isInDictionary(suggestion)) // is this check necessary? if (userDict.isInDictionary(word)) // is this check necessary?
return; return;
ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute(() -> ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute(() ->
UserDictionary.Words.addWord(userDict.mContext, suggestion, UserDictionary.Words.addWord(userDict.mContext, word,
250 /*FREQUENCY_FOR_USER_DICTIONARY_ADDS*/, null, dictionaryGroup.mLocale)); 250 /*FREQUENCY_FOR_USER_DICTIONARY_ADDS*/, null, dictionaryGroup.mLocale));
} }
} }
@ -659,8 +664,10 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
if (userHistoryDictionary == null || !hasLocale(userHistoryDictionary.mLocale)) { if (userHistoryDictionary == null || !hasLocale(userHistoryDictionary.mLocale)) {
return; return;
} }
final int maxFreq = getFrequency(word, dictionaryGroup); final int mainFreq = dictionaryGroup.hasDict(Dictionary.TYPE_MAIN, null)
if (maxFreq == 0 && blockPotentiallyOffensive) { ? dictionaryGroup.getDict(Dictionary.TYPE_MAIN).getFrequency(word)
: Dictionary.NOT_A_PROBABILITY;
if (mainFreq == 0 && blockPotentiallyOffensive) {
return; return;
} }
if (mTryChangingWords) if (mTryChangingWords)
@ -693,11 +700,10 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
// consolidation is done. // consolidation is done.
// TODO: Remove this hack when ready. // TODO: Remove this hack when ready.
final String lowerCasedWord = word.toLowerCase(dictionaryGroup.mLocale); final String lowerCasedWord = word.toLowerCase(dictionaryGroup.mLocale);
final int lowerCaseFreqInMainDict = dictionaryGroup.hasDict(Dictionary.TYPE_MAIN, final int lowerCaseFreqInMainDict = dictionaryGroup.hasDict(Dictionary.TYPE_MAIN, null)
null /* account */) ? ? dictionaryGroup.getDict(Dictionary.TYPE_MAIN).getFrequency(lowerCasedWord)
dictionaryGroup.getDict(Dictionary.TYPE_MAIN).getFrequency(lowerCasedWord) : : Dictionary.NOT_A_PROBABILITY;
Dictionary.NOT_A_PROBABILITY; if (mainFreq < lowerCaseFreqInMainDict
if (maxFreq < lowerCaseFreqInMainDict
&& lowerCaseFreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT) { && lowerCaseFreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT) {
// Use lower cased word as the word can be a distracter of the popular word. // Use lower cased word as the word can be a distracter of the popular word.
secondWord = lowerCasedWord; secondWord = lowerCasedWord;
@ -707,7 +713,8 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
} }
// We demote unrecognized words (frequency < 0, below) by specifying them as "invalid". // We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
// We don't add words with 0-frequency (assuming they would be profanity etc.). // We don't add words with 0-frequency (assuming they would be profanity etc.).
final boolean isValid = maxFreq > 0; // comment: so this means words not in main dict are always invalid... weird (but still works)
final boolean isValid = mainFreq > 0;
UserHistoryDictionary.addToDictionary(userHistoryDictionary, ngramContext, secondWord, UserHistoryDictionary.addToDictionary(userHistoryDictionary, ngramContext, secondWord,
isValid, timeStampInSeconds); isValid, timeStampInSeconds);
} }
@ -1007,27 +1014,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
} }
// called from addWordToUserHistory with a specified dictionary, so provide this dictionary
private int getFrequency(final String word, DictionaryGroup dictGroup) {
if (TextUtils.isEmpty(word)) {
return Dictionary.NOT_A_PROBABILITY;
}
int maxFreq = Dictionary.NOT_A_PROBABILITY;
// ExpandableBinaryDictionary (means: all except main) always return NOT_A_PROBABILITY
// because it doesn't override getFrequency()
// So why is it checked anyway?
// Is this a bug, or intended by AOSP devs?
for (final String dictType : ALL_DICTIONARY_TYPES) {
final Dictionary dictionary = dictGroup.getDict(dictType);
if (dictionary == null) continue;
final int tempFreq = dictionary.getFrequency(word);
if (tempFreq >= maxFreq) {
maxFreq = tempFreq;
}
}
return maxFreq;
}
@Override @Override
public boolean clearUserHistoryDictionary(final Context context) { public boolean clearUserHistoryDictionary(final Context context) {
for (DictionaryGroup dictionaryGroup : mDictionaryGroups) { for (DictionaryGroup dictionaryGroup : mDictionaryGroups) {

View file

@ -169,6 +169,18 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
return mBinaryDictionary; return mBinaryDictionary;
} }
@Override
public int getFrequency(final String word) {
if (mLock.readLock().tryLock()) {
try {
return mBinaryDictionary.getFrequency(word);
} finally {
mLock.readLock().unlock();
}
}
return NOT_A_PROBABILITY;
}
void closeBinaryDictionary() { void closeBinaryDictionary() {
if (mBinaryDictionary != null) { if (mBinaryDictionary != null) {
mBinaryDictionary.close(); mBinaryDictionary.close();