added dynamic word positions limit when searching to prevent some words being inaccessible in languages with many letters per key
This commit is contained in:
parent
f8e6668281
commit
ac4e5c597c
4 changed files with 83 additions and 3 deletions
|
|
@ -0,0 +1,44 @@
|
|||
package io.github.sspanak.tt9.db.entities;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||
|
||||
public class LongPositionsCache {
|
||||
private final HashMap<Integer, HashMap<String, Integer>> positions = new HashMap<>();
|
||||
|
||||
public boolean contains(@NonNull Language language) {
|
||||
return positions.containsKey(language.getId());
|
||||
}
|
||||
|
||||
public void put(@NonNull Language language, @NonNull String sequence, int wordCount) {
|
||||
if (wordCount < SettingsStore.SUGGESTIONS_POSITIONS_LIMIT && !contains(language)) {
|
||||
positions.put(language.getId(), null);
|
||||
return;
|
||||
}
|
||||
|
||||
HashMap<String, Integer> words = positions.get(language.getId());
|
||||
if (words == null) {
|
||||
words = new HashMap<>();
|
||||
positions.put(language.getId(), words);
|
||||
}
|
||||
words.put(sequence, wordCount);
|
||||
}
|
||||
|
||||
public int get(@NonNull Language language, @NonNull String sequence) {
|
||||
if (!contains(language)) {
|
||||
return SettingsStore.SUGGESTIONS_POSITIONS_LIMIT;
|
||||
}
|
||||
|
||||
HashMap<String, Integer> words = positions.get(language.getId());
|
||||
if (words == null) {
|
||||
return SettingsStore.SUGGESTIONS_POSITIONS_LIMIT;
|
||||
}
|
||||
|
||||
Integer wordCount = words.get(sequence);
|
||||
return wordCount == null ? SettingsStore.SUGGESTIONS_POSITIONS_LIMIT : wordCount;
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import androidx.annotation.Nullable;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import io.github.sspanak.tt9.db.entities.LongPositionsCache;
|
||||
import io.github.sspanak.tt9.db.entities.NormalizationList;
|
||||
import io.github.sspanak.tt9.db.entities.WordList;
|
||||
import io.github.sspanak.tt9.db.entities.WordPositionsStringBuilder;
|
||||
|
|
@ -20,10 +21,12 @@ import io.github.sspanak.tt9.db.words.SlowQueryStats;
|
|||
import io.github.sspanak.tt9.db.words.WordStore;
|
||||
import io.github.sspanak.tt9.languages.EmojiLanguage;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||
import io.github.sspanak.tt9.util.Logger;
|
||||
|
||||
public class ReadOps {
|
||||
private final String LOG_TAG = "ReadOperations";
|
||||
private final LongPositionsCache longPositionsCache = new LongPositionsCache();
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -253,7 +256,7 @@ public class ReadOps {
|
|||
.append(sequence)
|
||||
.append("' OR sequence BETWEEN '").append(sequence).append("1' AND '").append(sequence).append(rangeEnd).append("'");
|
||||
sql.append(" ORDER BY `start` ");
|
||||
sql.append(" LIMIT 100");
|
||||
sql.append(" LIMIT ").append(longPositionsCache.get(language, sequence));
|
||||
}
|
||||
|
||||
String positionsSql = sql.toString();
|
||||
|
|
@ -336,4 +339,31 @@ public class ReadOps {
|
|||
|
||||
return pairs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the sequences that result in more words than the standard performance-balanced limit of 100.
|
||||
*/
|
||||
public void cacheLongPositionsIfMissing(@NonNull SQLiteDatabase db, @NonNull Language language) {
|
||||
if (longPositionsCache.contains(language)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String[] select = new String[]{"sequence", "`end` - `start`"};
|
||||
String table = Tables.getWordPositions(language.getId());
|
||||
String where = "LENGTH(sequence) > " + SettingsStore.SUGGESTIONS_POSITIONS_LIMIT;
|
||||
|
||||
boolean hasResults = false;
|
||||
|
||||
try (Cursor cursor = db.query(table, select, where, null, null, null, null)) {
|
||||
while (cursor.moveToNext()) {
|
||||
hasResults = true;
|
||||
longPositionsCache.put(language, cursor.getString(0), cursor.getInt(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasResults) {
|
||||
longPositionsCache.put(language, "", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,10 @@ public class WordStore extends BaseSyncStore {
|
|||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
Timer.start("cache_long_positions");
|
||||
readOps.cacheLongPositionsIfMissing(sqlite.getDb(), language);
|
||||
long longPositionsTime = Timer.stop("cache_long_positions");
|
||||
|
||||
final int minWords = Math.max(minimumWords, 0);
|
||||
final int maxWords = Math.max(maximumWords, minWords);
|
||||
final String filter = wordFilter == null ? "" : wordFilter;
|
||||
|
|
@ -90,7 +94,7 @@ public class WordStore extends BaseSyncStore {
|
|||
ArrayList<String> words = readOps.getWords(sqlite.getDb(), cancel, language, positions, filter, maxWords, false).toStringList();
|
||||
long wordsTime = Timer.stop("get_words");
|
||||
|
||||
printLoadingSummary(sequence, words, positionsTime, wordsTime);
|
||||
printLoadingSummary(sequence, words, longPositionsTime, positionsTime, wordsTime);
|
||||
if (!cancel.isCanceled()) { // do not cache empty results from aborted queries
|
||||
SlowQueryStats.add(SlowQueryStats.generateKey(language, sequence, wordFilter, minWords), (int) (positionsTime + wordsTime), positions);
|
||||
}
|
||||
|
|
@ -259,7 +263,7 @@ public class WordStore extends BaseSyncStore {
|
|||
}
|
||||
|
||||
|
||||
private void printLoadingSummary(String sequence, ArrayList<String> words, long positionIndexTime, long wordsTime) {
|
||||
private void printLoadingSummary(String sequence, ArrayList<String> words, long longPositionsTime, long positionIndexTime, long wordsTime) {
|
||||
if (!Logger.isDebugLevel()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -269,6 +273,7 @@ public class WordStore extends BaseSyncStore {
|
|||
.append("\nWord Count: ").append(words.size())
|
||||
.append(".\nTime: ").append(positionIndexTime + wordsTime)
|
||||
.append(" ms (positions: ").append(positionIndexTime)
|
||||
.append(" ms, long positions: ").append(longPositionsTime)
|
||||
.append(" ms, words: ").append(wordsTime).append(" ms).");
|
||||
|
||||
if (words.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ public class SettingsStore extends SettingsUI {
|
|||
public final static float SOFT_KEY_COMPLEX_LABEL_SUB_TITLE_RELATIVE_SIZE = 0.8f;
|
||||
public final static int SUGGESTIONS_MAX = 20;
|
||||
public final static int SUGGESTIONS_MIN = 8;
|
||||
public final static int SUGGESTIONS_POSITIONS_LIMIT = 100;
|
||||
public final static int SUGGESTIONS_SELECT_ANIMATION_DURATION = 66;
|
||||
public final static int SUGGESTIONS_TRANSLATE_ANIMATION_DURATION = 0;
|
||||
public final static int TEXT_INPUT_DEBOUNCE_TIME = 500; // ms
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue