refactor: Roman2Kana関連の特定テーブル前提の処理を削除 (#225)

* refactor: possibleNextsを手動で列挙せず、自動で列挙できるようにした

* refactor: remove table-specific implementation
This commit is contained in:
Miwa
2025-07-21 02:50:56 -07:00
committed by GitHub
4 changed files with 95 additions and 75 deletions

View File

@ -1028,58 +1028,14 @@ public final class DicdataStore {
return true return true
} }
static let possibleNexts: [String: [String]] = [ static let possibleNexts: [String: [String]] = {
"x": ["", "", "", "", "", "", "", "", "", ""], var results: [String: [String]] = [:]
"l": ["", "", "", "", "", "", "", "", "", ""], for (key, value) in Roman2Kana.katakanaChanges {
"xt": [""], for prefixCount in 0 ..< key.count where 0 < prefixCount {
"lt": [""], let prefix = String(key.prefix(prefixCount))
"xts": [""], results[prefix, default: []].append(value)
"lts": [""], }
"xy": ["", "", ""], }
"ly": ["", "", ""], return results
"xw": [""], }()
"lw": [""],
"v": [""],
"k": ["", "", "", "", ""],
"q": ["クァ", "クィ", "クゥ", "クェ", "クォ"],
"qy": ["クャ", "クィ", "クュ", "クェ", "クョ"],
"qw": ["クヮ", "クィ", "クゥ", "クェ", "クォ"],
"ky": ["キャ", "キィ", "キュ", "キェ", "キョ"],
"g": ["", "", "", "", ""],
"gy": ["ギャ", "ギィ", "ギュ", "ギェ", "ギョ"],
"s": ["", "", "", "", ""],
"sy": ["シャ", "シィ", "シュ", "シェ", "ショ"],
"sh": ["シャ", "シィ", "シュ", "シェ", "ショ"],
"z": ["", "", "", "", ""],
"zy": ["ジャ", "ジィ", "ジュ", "ジェ", "ジョ"],
"j": [""],
"t": ["", "", "", "", ""],
"ty": ["チャ", "チィ", "チュ", "チェ", "チョ"],
"ts": [""],
"th": ["テャ", "ティ", "テュ", "テェ", "テョ"],
"tw": ["トァ", "トィ", "トゥ", "トェ", "トォ"],
"cy": ["チャ", "チィ", "チュ", "チェ", "チョ"],
"ch": [""],
"d": ["", "", "", "", ""],
"dy": ["ヂャ", "ヂィ", "ヂュ", "ヂェ", "ヂョ"],
"dh": ["デャ", "ディ", "デュ", "デェ", "デョ"],
"dw": ["ドァ", "ドィ", "ドゥ", "ドェ", "ドォ"],
"n": ["", "", "", "", "", ""],
"ny": ["ニャ", "ニィ", "ニュ", "ニェ", "ニョ"],
"h": ["", "", "", "", ""],
"hy": ["ヒャ", "ヒィ", "ヒュ", "ヒェ", "ヒョ"],
"hw": ["ファ", "フィ", "フェ", "フォ"],
"f": [""],
"b": ["", "", "", "", ""],
"by": ["ビャ", "ビィ", "ビュ", "ビェ", "ビョ"],
"p": ["", "", "", "", ""],
"py": ["ピャ", "ピィ", "ピュ", "ピェ", "ピョ"],
"m": ["", "", "", "", ""],
"my": ["ミャ", "ミィ", "ミュ", "ミェ", "ミョ"],
"y": ["", "", "イェ", ""],
"r": ["", "", "", "", ""],
"ry": ["リャ", "リィ", "リュ", "リェ", "リョ"],
"w": ["", "ウィ", "ウェ", ""],
"wy": ["", ""]
]
} }

View File

@ -283,6 +283,45 @@ enum Roman2Kana {
"whu": "", "whu": "",
"whe": "うぇ", "whe": "うぇ",
"who": "うぉ", "who": "うぉ",
"bb": "っb",
"cc": "っc",
"dd": "っd",
"ff": "っf",
"gg": "っg",
"hh": "っh",
"jj": "っj",
"kk": "っk",
"ll": "っl",
"mm": "っm",
"pp": "っp",
"qq": "っq",
"rr": "っr",
"ss": "っs",
"tt": "っt",
"vv": "っv",
"ww": "っw",
"xx": "っx",
"yy": "っy",
"zz": "っz",
"nb": "んb",
"nc": "んc",
"nd": "んd",
"nf": "んf",
"ng": "んg",
"nh": "んh",
"nj": "んj",
"nk": "んk",
"nl": "んl",
"nm": "んm",
"np": "んp",
"nq": "んq",
"nr": "んr",
"ns": "んs",
"nt": "んt",
"nv": "んv",
"nw": "んw",
"nx": "んx",
"nz": "んz",
"xn": "", "xn": "",
"zh": "", "zh": "",
"zj": "", "zj": "",
@ -290,28 +329,20 @@ enum Roman2Kana {
"zl": "" "zl": ""
].map {(Array($0.key), Array($0.value))}) ].map {(Array($0.key), Array($0.value))})
static func toHiragana(currentText: [Character], added: Character) -> [Character] { static let maxKeyCount = hiraganaChanges.lazy.map { $0.key.count }.max() ?? 0
let last_3 = currentText.suffix(3)
if let kana = Roman2Kana.hiraganaChanges[last_3 + [added]] {
return currentText.prefix(currentText.count - last_3.count) + kana
}
let last_2 = currentText.suffix(2)
if let kana = Roman2Kana.hiraganaChanges[last_2 + [added]] {
return currentText.prefix(currentText.count - last_2.count) + kana
}
let last_1 = currentText.suffix(1)
if let kana = Roman2Kana.hiraganaChanges[last_1 + [added]] {
return currentText.prefix(currentText.count - last_1.count) + kana
}
if last_1 == [added] && String(added).onlyRomanAlphabet {
return currentText.prefix(currentText.count - last_1.count) + ["", added]
}
if last_1 == ["n"] && added != "y"{
return currentText.prefix(currentText.count - last_1.count) + ["", added]
}
if let kana = Roman2Kana.hiraganaChanges[[added]] { static func toHiragana(currentText: [Character], added: Character) -> [Character] {
return currentText + kana for n in (0 ..< maxKeyCount).reversed() {
if n == 0 {
if let kana = Roman2Kana.hiraganaChanges[[added]] {
return currentText + kana
}
} else {
let last = currentText.suffix(n)
if let kana = Roman2Kana.hiraganaChanges[last + [added]] {
return currentText.prefix(currentText.count - last.count) + kana
}
}
} }
return currentText + [added] return currentText + [added]
} }

View File

@ -0,0 +1,26 @@
@testable import KanaKanjiConverterModule
import XCTest
final class Roman2KanaTests: XCTestCase {
func testToHiragana() throws {
// xtsu ->
XCTAssertEqual(Roman2Kana.toHiragana(currentText: Array(""), added: "x"), Array("x"))
XCTAssertEqual(Roman2Kana.toHiragana(currentText: Array("x"), added: "t"), Array("xt"))
XCTAssertEqual(Roman2Kana.toHiragana(currentText: Array("xt"), added: "s"), Array("xts"))
XCTAssertEqual(Roman2Kana.toHiragana(currentText: Array("xts"), added: "u"), Array(""))
// kanto ->
XCTAssertEqual(Roman2Kana.toHiragana(currentText: Array(""), added: "k"), Array("k"))
XCTAssertEqual(Roman2Kana.toHiragana(currentText: Array("k"), added: "a"), Array(""))
XCTAssertEqual(Roman2Kana.toHiragana(currentText: Array(""), added: "n"), Array("かn"))
XCTAssertEqual(Roman2Kana.toHiragana(currentText: Array("かn"), added: "t"), Array("かんt"))
XCTAssertEqual(Roman2Kana.toHiragana(currentText: Array("かんt"), added: "o"), Array("かんと"))
// zl ->
XCTAssertEqual(Roman2Kana.toHiragana(currentText: Array(""), added: "z"), Array("z"))
XCTAssertEqual(Roman2Kana.toHiragana(currentText: Array("z"), added: "l"), Array(""))
// TT -> TT
XCTAssertEqual(Roman2Kana.toHiragana(currentText: Array("T"), added: "T"), Array("TT"))
}
}

View File

@ -329,4 +329,11 @@ final class DicdataStoreTests: XCTestCase {
XCTAssertEqual(dynamicUserDictResult?.data.metadata, .isFromUserDictionary) XCTAssertEqual(dynamicUserDictResult?.data.metadata, .isFromUserDictionary)
} }
} }
func testPossibleNexts() throws {
let possibleNexts = DicdataStore.possibleNexts
XCTAssertEqual(Set(possibleNexts["f", default: []]).symmetricDifference(["ファ", "フィ", "", "フェ", "フォ", "フャ", "フュ", "フョ", "フゥ", "ッf"]), [])
XCTAssertEqual(Set(possibleNexts["xy", default: []]).symmetricDifference(["", "", ""]), [])
XCTAssertEqual(possibleNexts["", default: []], [])
}
} }