mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-16 08:36:07 +09:00
97 lines
3.0 KiB
Kotlin
97 lines
3.0 KiB
Kotlin
package net.torvald.terrarum.gamecontroller
|
|
|
|
import net.torvald.terrarum.App.printdbg
|
|
import net.torvald.util.SortedArrayList
|
|
import org.graalvm.polyglot.HostAccess
|
|
import java.io.File
|
|
import java.io.FileReader
|
|
|
|
class IMEProviderDelegate(val ime: IME) {
|
|
|
|
private val dictionaries = HashMap<String, IMEDictionary>()
|
|
|
|
@HostAccess.Export
|
|
fun requestDictionary(filename: String): IMEDictionary {
|
|
return dictionaries.getOrPut(filename) { IMEDictionary(filename) }
|
|
}
|
|
|
|
}
|
|
|
|
class IMEDictionary(private val filename: String) {
|
|
|
|
companion object {
|
|
const val CAND_DELIM = '\u001E'
|
|
}
|
|
|
|
private val candidates = HashMap<String, String>(16384)
|
|
private val keys = SortedArrayList<String>(16384) // keys on the .han file are absofreakinlutely not sorted
|
|
|
|
private var dictLoaded = false
|
|
|
|
private fun loadDict() {
|
|
val reader = FileReader(File("assets/keylayout/", filename))
|
|
reader.forEachLine {
|
|
if (it.contains(',')) {
|
|
val (key, value) = it.split(',')
|
|
if (candidates.containsKey(key)) {
|
|
candidates[key] += "$CAND_DELIM$value"
|
|
}
|
|
else {
|
|
candidates[key] = value
|
|
keys.add(key)
|
|
}
|
|
}
|
|
}
|
|
|
|
printdbg(this, "Dictionary loaded: $filename")
|
|
|
|
dictLoaded = true
|
|
}
|
|
|
|
init {
|
|
loadDict() // loading the dict doesn't take too long so no need to do it lazily
|
|
}
|
|
|
|
@HostAccess.Export
|
|
fun getCangjie(key: String): String {
|
|
//if (!dictLoaded) loadDict()
|
|
|
|
val out = StringBuilder()
|
|
var outsize = 0
|
|
var index = keys.searchForInterval(key) { it }.second
|
|
|
|
val allRelevantKeys = ArrayList<String>() // oh, oha, ohag, ohbt, ohby, ...
|
|
for (k in 0 until 400) { // lookahead for length-first sorting, longest lookahead possible is around 300, so I'll give it 400
|
|
if (index + k >= keys.size) break
|
|
val keysym = keys[index + k]
|
|
if (!keysym.startsWith(key)) break
|
|
allRelevantKeys.add(keysym)
|
|
}
|
|
|
|
// printdbg(this, "lookup key: $key")
|
|
|
|
// sort allRelevantKeys so that short sequences come first
|
|
// e.g. oh, oha, ohg, ohj, ohn, ohq, ohag, ohbt, ...
|
|
allRelevantKeys.sortWith { it, other ->
|
|
if (it.length == other.length) it.compareTo(other)
|
|
else it.length.compareTo(other.length)
|
|
}
|
|
|
|
// printdbg(this, "predictions: (${allRelevantKeys.size}) ${allRelevantKeys.joinToString()}")
|
|
|
|
index = 0 // now this is an index for the allRelevantKeys
|
|
while (outsize < 10 && index < allRelevantKeys.size) {
|
|
val keysym = allRelevantKeys[index]
|
|
if (!keysym.startsWith(key)) break
|
|
|
|
val outstr = "$CAND_DELIM${candidates[keysym]}"
|
|
outsize += outstr.count { it == CAND_DELIM }
|
|
out.append(outstr)
|
|
|
|
index += 1
|
|
}
|
|
|
|
return if (out.isNotEmpty()) out.substring(1) else ""
|
|
}
|
|
|
|
} |