diff --git a/app/src/main/java/org/jyutping/jyutping/extensions/CharCode.kt b/app/src/main/java/org/jyutping/jyutping/extensions/CharCode.kt new file mode 100644 index 0000000..6e3c772 --- /dev/null +++ b/app/src/main/java/org/jyutping/jyutping/extensions/CharCode.kt @@ -0,0 +1,52 @@ +package org.jyutping.jyutping.extensions + +fun String.charcode(): Int? { + if (this.length >= 10) return null + val codes = this.mapNotNull { it.intercode() } + if (codes.size != this.length) return null + return codes.combined() +} +fun String.shortcutCharcode(): Int? { + if (this.length >= 10) return null + val codes = this.mapNotNull { it.intercode() } + if (codes.size != this.length) return null + val code = codes + .map { if (it == 44) 29 else it } // Replace 'y' with 'j' + .combined() + return code +} + +fun Iterable.combined(): Int { + if (this.count() >= 10) return 0 + return this.fold(0) { acc, i -> acc * 100 + i } +} + +fun Char.intercode(): Int? = when (this) { + 'a' -> 20 + 'b' -> 21 + 'c' -> 22 + 'd' -> 23 + 'e' -> 24 + 'f' -> 25 + 'g' -> 26 + 'h' -> 27 + 'i' -> 28 + 'j' -> 29 + 'k' -> 30 + 'l' -> 31 + 'm' -> 32 + 'n' -> 33 + 'o' -> 34 + 'p' -> 35 + 'q' -> 36 + 'r' -> 37 + 's' -> 38 + 't' -> 39 + 'u' -> 40 + 'v' -> 41 + 'w' -> 42 + 'x' -> 43 + 'y' -> 44 + 'z' -> 45 + else -> null +} diff --git a/app/src/main/java/org/jyutping/jyutping/extensions/StringExtensions.kt b/app/src/main/java/org/jyutping/jyutping/extensions/StringExtensions.kt index b1c5c0e..23fe494 100644 --- a/app/src/main/java/org/jyutping/jyutping/extensions/StringExtensions.kt +++ b/app/src/main/java/org/jyutping/jyutping/extensions/StringExtensions.kt @@ -13,45 +13,3 @@ val String.Companion.space: String val String.Companion.separator: String get() = "'" - -fun String.charcode(): Int? { - if (this.length >= 10) return null - val codes = this.mapNotNull { it.intercode() } - if (codes.size != this.length) return null - return codes.combined() -} - -private fun Iterable.combined(): Int { - if (this.count() >= 10) return 0 - return this.fold(0) { acc, i -> acc * 100 + i } -} - -private fun Char.intercode(): Int? = when (this) { - 'a' -> 20 - 'b' -> 21 - 'c' -> 22 - 'd' -> 23 - 'e' -> 24 - 'f' -> 25 - 'g' -> 26 - 'h' -> 27 - 'i' -> 28 - 'j' -> 29 - 'k' -> 30 - 'l' -> 31 - 'm' -> 32 - 'n' -> 33 - 'o' -> 34 - 'p' -> 35 - 'q' -> 36 - 'r' -> 37 - 's' -> 38 - 't' -> 39 - 'u' -> 40 - 'v' -> 41 - 'w' -> 42 - 'x' -> 43 - 'y' -> 44 - 'z' -> 45 - else -> null -} diff --git a/app/src/main/java/org/jyutping/jyutping/keyboard/Engine.kt b/app/src/main/java/org/jyutping/jyutping/keyboard/Engine.kt index ca2a7c4..fd79255 100644 --- a/app/src/main/java/org/jyutping/jyutping/keyboard/Engine.kt +++ b/app/src/main/java/org/jyutping/jyutping/keyboard/Engine.kt @@ -6,14 +6,18 @@ import org.jyutping.jyutping.utilities.DatabaseHelper object Engine { fun suggest(text: String, segmentation: Segmentation, db: DatabaseHelper): List { + if (db.canProcess(text).not()) return emptyList() + if (segmentation.maxLength() < 1) return processVerbatim(text, db) return process(text, segmentation, db) } private fun processVerbatim(text: String, db: DatabaseHelper): List { - val rounds = text.indices.map { number -> + val rounds: MutableList> = mutableListOf() + for (number in text.indices) { val leading = text.dropLast(number) - return db.match(text = leading, input = leading) + db.shortcut(text = leading) + val round = db.match(text = leading, input = leading) + db.shortcut(text = leading) + rounds.add(round) } - return rounds.flatten().distinct() + return rounds.flatten().distinct() } private fun process(text: String, segmentation: Segmentation, db: DatabaseHelper): List { val primary = query(text, segmentation, db) diff --git a/app/src/main/java/org/jyutping/jyutping/utilities/DatabaseHelper.kt b/app/src/main/java/org/jyutping/jyutping/utilities/DatabaseHelper.kt index 3a9c669..ca1ac55 100644 --- a/app/src/main/java/org/jyutping/jyutping/utilities/DatabaseHelper.kt +++ b/app/src/main/java/org/jyutping/jyutping/utilities/DatabaseHelper.kt @@ -5,7 +5,9 @@ import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper import org.jyutping.jyutping.extensions.charcode import org.jyutping.jyutping.extensions.convertedS2T +import org.jyutping.jyutping.extensions.intercode import org.jyutping.jyutping.extensions.isIdeographic +import org.jyutping.jyutping.extensions.shortcutCharcode import org.jyutping.jyutping.keyboard.Candidate import org.jyutping.jyutping.keyboard.SegmentToken import org.jyutping.jyutping.search.CantoneseLexicon @@ -334,10 +336,23 @@ class DatabaseHelper(context: Context, databaseName: String) : SQLiteOpenHelper( return null } + fun canProcess(text: String): Boolean { + val value = text.firstOrNull()?.intercode() ?: 0 + if (value == 0) return false + val code = if (value == 44) 29 else value // Replace 'y' with 'j' + val command = "SELECT rowid FROM lexicontable WHERE shortcut = $code LIMIT 1;" + val cursor = this.readableDatabase.rawQuery(command, null) + if (cursor.moveToFirst()) { + cursor.close() + return true + } else { + return false + } + } fun shortcut(text: String): List { + val code: Int = text.shortcutCharcode() ?: 0 + if (code == 0) return emptyList() val candidates: MutableList = mutableListOf() - if (text.isBlank()) return candidates - val code: Int = text.charcode() ?: 0 val command = "SELECT rowid, word, romanization FROM lexicontable WHERE shortcut = $code LIMIT 50;" val cursor = this.readableDatabase.rawQuery(command, null) while (cursor.moveToNext()) { @@ -350,10 +365,10 @@ class DatabaseHelper(context: Context, databaseName: String) : SQLiteOpenHelper( cursor.close() return candidates } - fun match(text: String, input: String, mark: String? = null, limit: Int? = null): List { - val candidates: MutableList = mutableListOf() - if (text.isBlank()) return candidates + fun match(text: String, input: String, mark: String? = null): List { + if (text.isBlank()) return emptyList() val code: Int = text.hashCode() + val candidates: MutableList = mutableListOf() val command = "SELECT rowid, word, romanization FROM lexicontable WHERE ping = ${code};" val cursor = this.readableDatabase.rawQuery(command, null) while (cursor.moveToNext()) {