Pre Merge pull request !63 from ShikiSuen/upd/1.8.1

This commit is contained in:
ShikiSuen 2022-07-18 07:19:13 +00:00 committed by Gitee
commit bda9fafbae
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
44 changed files with 584 additions and 579 deletions

View File

@ -60,9 +60,9 @@ extension String {
// MARK: -
// Ref: https://stackoverflow.com/a/32581409/4162914
extension Float {
fileprivate func rounded(toPlaces places: Int) -> Float {
let divisor = pow(10.0, Float(places))
extension Double {
fileprivate func rounded(toPlaces places: Int) -> Double {
let divisor = pow(10.0, Double(places))
return (self * divisor).rounded() / divisor
}
}
@ -81,17 +81,16 @@ func ** (_ base: Double, _ exp: Double) -> Double {
pow(base, exp)
}
func ** (_ base: Float, _ exp: Float) -> Float {
pow(base, exp)
}
// MARK: -
struct Entry {
var valPhone: String = ""
var valPhrase: String = ""
var valWeight: Float = -1.0
var valCount: Int = 0
struct Unigram: CustomStringConvertible {
var key: String = ""
var value: String = ""
var score: Double = -1.0
var count: Int = 0
var description: String {
"(\(key), \(value), \(score))"
}
}
// MARK: - plist
@ -105,8 +104,8 @@ func cnvPhonabetToASCII(_ incoming: String) -> String {
]
var strOutput = incoming
if !strOutput.contains("_") {
for entry in dicPhonabet2ASCII {
strOutput = strOutput.replacingOccurrences(of: entry.key, with: entry.value)
for Unigram in dicPhonabet2ASCII {
strOutput = strOutput.replacingOccurrences(of: Unigram.key, with: Unigram.value)
}
}
return strOutput
@ -146,8 +145,8 @@ private let urlPlistCHT: String = "./data-cht.plist"
// MARK: -
func rawDictForPhrases(isCHS: Bool) -> [Entry] {
var arrEntryRAW: [Entry] = []
func rawDictForPhrases(isCHS: Bool) -> [Unigram] {
var arrUnigramRAW: [Unigram] = []
var strRAW = ""
let urlCustom: String = isCHS ? urlCHSforCustom : urlCHTforCustom
let urlTABE: String = isCHS ? urlCHSforTABE : urlCHTforTABE
@ -195,7 +194,7 @@ func rawDictForPhrases(isCHS: Bool) -> [Entry] {
varLineDataProcessed += currentCell
}
}
// Entry
// Unigram
let arrCells: [String] = varLineDataProcessed.components(separatedBy: "\t")
count = 0 //
var phone = ""
@ -211,22 +210,22 @@ func rawDictForPhrases(isCHS: Bool) -> [Entry] {
}
}
if phrase != "" { //
arrEntryRAW += [
Entry(
valPhone: phone, valPhrase: phrase, valWeight: 0.0,
valCount: occurrence
arrUnigramRAW += [
Unigram(
key: phone, value: phrase, score: 0.0,
count: occurrence
)
]
}
}
NSLog(" - \(i18n): 成功生成詞語語料辭典(權重待計算)。")
return arrEntryRAW
return arrUnigramRAW
}
// MARK: -
func rawDictForKanjis(isCHS: Bool) -> [Entry] {
var arrEntryRAW: [Entry] = []
func rawDictForKanjis(isCHS: Bool) -> [Unigram] {
var arrUnigramRAW: [Unigram] = []
var strRAW = ""
let i18n: String = isCHS ? "簡體中文" : "繁體中文"
//
@ -272,7 +271,7 @@ func rawDictForKanjis(isCHS: Bool) -> [Entry] {
varLineDataProcessed += currentCell
}
}
// Entry
// Unigram
let arrCells: [String] = varLineDataProcessed.components(separatedBy: "\t")
count = 0 //
var phone = ""
@ -288,22 +287,22 @@ func rawDictForKanjis(isCHS: Bool) -> [Entry] {
}
}
if phrase != "" { //
arrEntryRAW += [
Entry(
valPhone: phone, valPhrase: phrase, valWeight: 0.0,
valCount: occurrence
arrUnigramRAW += [
Unigram(
key: phone, value: phrase, score: 0.0,
count: occurrence
)
]
}
}
NSLog(" - \(i18n): 成功生成單字語料辭典(權重待計算)。")
return arrEntryRAW
return arrUnigramRAW
}
// MARK: -
func rawDictForNonKanjis(isCHS: Bool) -> [Entry] {
var arrEntryRAW: [Entry] = []
func rawDictForNonKanjis(isCHS: Bool) -> [Unigram] {
var arrUnigramRAW: [Unigram] = []
var strRAW = ""
let i18n: String = isCHS ? "簡體中文" : "繁體中文"
//
@ -347,7 +346,7 @@ func rawDictForNonKanjis(isCHS: Bool) -> [Entry] {
varLineDataProcessed += currentCell
}
}
// Entry
// Unigram
let arrCells: [String] = varLineDataProcessed.components(separatedBy: "\t")
count = 0 //
var phone = ""
@ -363,60 +362,60 @@ func rawDictForNonKanjis(isCHS: Bool) -> [Entry] {
}
}
if phrase != "" { //
arrEntryRAW += [
Entry(
valPhone: phone, valPhrase: phrase, valWeight: 0.0,
valCount: occurrence
arrUnigramRAW += [
Unigram(
key: phone, value: phrase, score: 0.0,
count: occurrence
)
]
}
}
NSLog(" - \(i18n): 成功生成非漢字語料辭典(權重待計算)。")
return arrEntryRAW
return arrUnigramRAW
}
func weightAndSort(_ arrStructUncalculated: [Entry], isCHS: Bool) -> [Entry] {
func weightAndSort(_ arrStructUncalculated: [Unigram], isCHS: Bool) -> [Unigram] {
let i18n: String = isCHS ? "簡體中文" : "繁體中文"
var arrStructCalculated: [Entry] = []
let fscale: Float = 2.7
var norm: Float = 0.0
for entry in arrStructUncalculated {
if entry.valCount >= 0 {
norm += fscale ** (Float(entry.valPhrase.count) / 3.0 - 1.0)
* Float(entry.valCount)
var arrStructCalculated: [Unigram] = []
let fscale = 2.7
var norm = 0.0
for unigram in arrStructUncalculated {
if unigram.count >= 0 {
norm += fscale ** (Double(unigram.value.count) / 3.0 - 1.0)
* Double(unigram.count)
}
}
// norm norm
//
// 1 0 0.5
for entry in arrStructUncalculated {
var weight: Float = 0
switch entry.valCount {
for unigram in arrStructUncalculated {
var weight: Double = 0
switch unigram.count {
case -2: //
weight = -13
case -1: //
weight = -13
case 0: //
weight = log10(
fscale ** (Float(entry.valPhrase.count) / 3.0 - 1.0) * 0.25 / norm)
fscale ** (Double(unigram.value.count) / 3.0 - 1.0) * 0.25 / norm)
default:
weight = log10(
fscale ** (Float(entry.valPhrase.count) / 3.0 - 1.0)
* Float(entry.valCount) / norm) // Credit: MJHsieh.
fscale ** (Double(unigram.value.count) / 3.0 - 1.0)
* Double(unigram.count) / norm) // Credit: MJHsieh.
}
let weightRounded: Float = weight.rounded(toPlaces: 3) //
let weightRounded: Double = weight.rounded(toPlaces: 3) //
arrStructCalculated += [
Entry(
valPhone: entry.valPhone, valPhrase: entry.valPhrase, valWeight: weightRounded,
valCount: entry.valCount
Unigram(
key: unigram.key, value: unigram.value, score: weightRounded,
count: unigram.count
)
]
}
NSLog(" - \(i18n): 成功計算權重。")
// ==========================================
//
let arrStructSorted: [Entry] = arrStructCalculated.sorted(by: { lhs, rhs -> Bool in
(lhs.valPhone, rhs.valCount) < (rhs.valPhone, lhs.valCount)
let arrStructSorted: [Unigram] = arrStructCalculated.sorted(by: { lhs, rhs -> Bool in
(lhs.key, rhs.count) < (rhs.key, lhs.count)
})
NSLog(" - \(i18n): 排序整理完畢,準備編譯要寫入的檔案內容。")
return arrStructSorted
@ -434,9 +433,11 @@ func fileOutput(isCHS: Bool) {
//
do {
strPunctuation = try String(contentsOfFile: urlPunctuation, encoding: .utf8).replacingOccurrences(
of: "\t", with: " ")
of: "\t", with: " "
)
strPrintLine += try String(contentsOfFile: urlPunctuation, encoding: .utf8).replacingOccurrences(
of: "\t", with: " ")
of: "\t", with: " "
)
} catch {
NSLog(" - \(i18n): Exception happened when reading raw punctuation data.")
}
@ -453,18 +454,33 @@ func fileOutput(isCHS: Bool) {
}
}
}
var arrStructUnified: [Entry] = []
var arrStructUnified: [Unigram] = []
arrStructUnified += rawDictForKanjis(isCHS: isCHS)
arrStructUnified += rawDictForNonKanjis(isCHS: isCHS)
arrStructUnified += rawDictForPhrases(isCHS: isCHS)
//
arrStructUnified = weightAndSort(arrStructUnified, isCHS: isCHS)
for entry in arrStructUnified {
let theKey = entry.valPhone
let theValue = (String(entry.valWeight) + " " + entry.valPhrase)
//
NSLog(" - \(i18n): 執行資料重複性檢查,會在之後再給出對應的檢查結果。")
var setAlreadyInserted = Set<String>()
var arrFoundedDuplications = [String]()
//
NSLog(" - \(i18n): 執行資料健康狀況檢查。")
print(healthCheck(arrStructUnified))
for unigram in arrStructUnified {
if setAlreadyInserted.contains(unigram.value + "\t" + unigram.key) {
arrFoundedDuplications.append(unigram.value + "\t" + unigram.key)
} else {
setAlreadyInserted.insert(unigram.value + "\t" + unigram.key)
}
let theKey = unigram.key
let theValue = (String(unigram.score) + " " + unigram.value)
rangeMap[cnvPhonabetToASCII(theKey), default: []].append(theValue.data(using: .utf8)!)
strPrintLine +=
entry.valPhone + " " + entry.valPhrase + " " + String(entry.valWeight)
unigram.key + " " + unigram.value + " " + String(unigram.score)
+ "\n"
}
NSLog(" - \(i18n): 要寫入檔案的 txt 內容編譯完畢。")
@ -476,6 +492,12 @@ func fileOutput(isCHS: Bool) {
NSLog(" - \(i18n): Error on writing strings to file: \(error)")
}
NSLog(" - \(i18n): 寫入完成。")
if !arrFoundedDuplications.isEmpty {
NSLog(" - \(i18n): 尋得下述重複項目,請務必手動排查:")
print("-------------------")
print(arrFoundedDuplications.joined(separator: "\n"))
}
print("===================")
}
func commonFileOutput() {
@ -555,3 +577,268 @@ func main() {
}
main()
// MARK: -
func healthCheck(_ data: [Unigram]) -> String {
var result = ""
var unigramMonoChar = [String: Unigram]()
var valueToScore = [String: Double]()
let unigramMonoCharCounter = data.filter { $0.score > -14 && $0.key.split(separator: "-").count == 1 }.count
let unigramPolyCharCounter = data.filter { $0.score > -14 && $0.key.split(separator: "-").count > 1 }.count
// -10
for neta in data.filter({ $0.score > -14 }) {
valueToScore[neta.value] = max(neta.score, valueToScore[neta.value] ?? -14)
let theKeySliceArr = neta.key.split(separator: "-")
guard let theKey = theKeySliceArr.first, theKeySliceArr.count == 1 else { continue }
if unigramMonoChar.keys.contains(String(theKey)), let theRecord = unigramMonoChar[String(theKey)] {
if neta.score > theRecord.score { unigramMonoChar[String(theKey)] = neta }
} else {
unigramMonoChar[String(theKey)] = neta
}
}
var faulty = [Unigram]()
var indifferents: [(String, String, Double, [Unigram], Double)] = []
var insufficients: [(String, String, Double, [Unigram], Double)] = []
var competingUnigrams = [(String, Double, String, Double)]()
for neta in data.filter({ $0.key.split(separator: "-").count >= 2 && $0.score > -14 }) {
var competants = [Unigram]()
var tscore: Double = 0
var bad = false
for x in neta.key.split(separator: "-") {
if !unigramMonoChar.keys.contains(String(x)) {
bad = true
break
}
guard let u = unigramMonoChar[String(x)] else { continue }
tscore += u.score
competants.append(u)
}
if bad {
faulty.append(neta)
continue
}
if tscore >= neta.score {
let instance = (neta.key, neta.value, neta.score, competants, neta.score - tscore)
let valueJoined = String(competants.map(\.value).joined(separator: ""))
if neta.value == valueJoined {
indifferents.append(instance)
} else {
if valueToScore.keys.contains(valueJoined), neta.value != valueJoined {
if let valueJoinedScore = valueToScore[valueJoined], neta.score < valueJoinedScore {
competingUnigrams.append((neta.value, neta.score, valueJoined, valueJoinedScore))
}
}
insufficients.append(instance)
}
}
}
insufficients = insufficients.sorted(by: { lhs, rhs -> Bool in
(lhs.2) > (rhs.2)
})
competingUnigrams = competingUnigrams.sorted(by: { lhs, rhs -> Bool in
(lhs.1 - lhs.3) > (rhs.1 - rhs.3)
})
let separator: String = {
var result = ""
for _ in 0..<72 { result += "-" }
return result
}()
func printl(_ input: String) {
result += input + "\n"
}
printl(separator)
printl("持單個字符的有效單元圖數量:\(unigramMonoCharCounter)")
printl("持多個字符的有效單元圖數量:\(unigramPolyCharCounter)")
printl(separator)
printl("總結一下那些容易被單個漢字的字頻干擾輸入的詞組單元圖:")
printl("因干擾組件和字詞本身完全重疊、而不需要處理的單元圖的數量:\(indifferents.count)")
printl(
"\(insufficients.count) 個複字單元圖被自身成分讀音對應的其它單字單元圖奪權,約佔全部有效單元圖的 \(insufficients.count / unigramPolyCharCounter * 100)%"
)
printl("\n其中有:")
var insufficientsMap = [Int: [(String, String, Double, [Unigram], Double)]]()
for x in 2...10 {
insufficientsMap[x] = insufficients.filter { $0.0.split(separator: "-").count == x }
}
printl(" \(insufficientsMap[2]?.count ?? 0) 個有效雙字單元圖")
printl(" \(insufficientsMap[3]?.count ?? 0) 個有效三字單元圖")
printl(" \(insufficientsMap[4]?.count ?? 0) 個有效四字單元圖")
printl(" \(insufficientsMap[5]?.count ?? 0) 個有效五字單元圖")
printl(" \(insufficientsMap[6]?.count ?? 0) 個有效六字單元圖")
printl(" \(insufficientsMap[7]?.count ?? 0) 個有效七字單元圖")
printl(" \(insufficientsMap[8]?.count ?? 0) 個有效八字單元圖")
printl(" \(insufficientsMap[9]?.count ?? 0) 個有效九字單元圖")
printl(" \(insufficientsMap[10]?.count ?? 0) 個有效十字單元圖")
if let insufficientsMap2 = insufficientsMap[2], !insufficientsMap2.isEmpty {
printl(separator)
printl("前二十五個被奪權的有效雙字單元圖")
for (i, content) in insufficientsMap2.enumerated() {
if i == 25 { break }
var contentToPrint = "{"
contentToPrint += content.0 + ","
contentToPrint += content.1 + ","
contentToPrint += String(content.2) + ","
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
contentToPrint += String(content.4) + "}"
printl(contentToPrint)
}
}
if let insufficientsMap3 = insufficientsMap[3], !insufficientsMap3.isEmpty {
printl(separator)
printl("前二十五個被奪權的有效三字單元圖")
for (i, content) in insufficientsMap3.enumerated() {
if i == 25 { break }
var contentToPrint = "{"
contentToPrint += content.0 + ","
contentToPrint += content.1 + ","
contentToPrint += String(content.2) + ","
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
contentToPrint += String(content.4) + "}"
printl(contentToPrint)
}
}
if let insufficientsMap4 = insufficientsMap[4], !insufficientsMap4.isEmpty {
printl(separator)
printl("前二十五個被奪權的有效四字單元圖")
for (i, content) in insufficientsMap4.enumerated() {
if i == 25 { break }
var contentToPrint = "{"
contentToPrint += content.0 + ","
contentToPrint += content.1 + ","
contentToPrint += String(content.2) + ","
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
contentToPrint += String(content.4) + "}"
printl(contentToPrint)
}
}
if let insufficientsMap5 = insufficientsMap[5], !insufficientsMap5.isEmpty {
printl(separator)
printl("前二十五個被奪權的有效五字單元圖")
for (i, content) in insufficientsMap5.enumerated() {
if i == 25 { break }
var contentToPrint = "{"
contentToPrint += content.0 + ","
contentToPrint += content.1 + ","
contentToPrint += String(content.2) + ","
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
contentToPrint += String(content.4) + "}"
printl(contentToPrint)
}
}
if let insufficientsMap6 = insufficientsMap[6], !insufficientsMap6.isEmpty {
printl(separator)
printl("前二十五個被奪權的有效六字單元圖")
for (i, content) in insufficientsMap6.enumerated() {
if i == 25 { break }
var contentToPrint = "{"
contentToPrint += content.0 + ","
contentToPrint += content.1 + ","
contentToPrint += String(content.2) + ","
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
contentToPrint += String(content.4) + "}"
printl(contentToPrint)
}
}
if let insufficientsMap7 = insufficientsMap[7], !insufficientsMap7.isEmpty {
printl(separator)
printl("前二十五個被奪權的有效七字單元圖")
for (i, content) in insufficientsMap7.enumerated() {
if i == 25 { break }
var contentToPrint = "{"
contentToPrint += content.0 + ","
contentToPrint += content.1 + ","
contentToPrint += String(content.2) + ","
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
contentToPrint += String(content.4) + "}"
printl(contentToPrint)
}
}
if let insufficientsMap8 = insufficientsMap[8], !insufficientsMap8.isEmpty {
printl(separator)
printl("前二十五個被奪權的有效八字單元圖")
for (i, content) in insufficientsMap8.enumerated() {
if i == 25 { break }
var contentToPrint = "{"
contentToPrint += content.0 + ","
contentToPrint += content.1 + ","
contentToPrint += String(content.2) + ","
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
contentToPrint += String(content.4) + "}"
printl(contentToPrint)
}
}
if let insufficientsMap9 = insufficientsMap[9], !insufficientsMap9.isEmpty {
printl(separator)
printl("前二十五個被奪權的有效九字單元圖")
for (i, content) in insufficientsMap9.enumerated() {
if i == 25 { break }
var contentToPrint = "{"
contentToPrint += content.0 + ","
contentToPrint += content.1 + ","
contentToPrint += String(content.2) + ","
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
contentToPrint += String(content.4) + "}"
printl(contentToPrint)
}
}
if let insufficientsMap10 = insufficientsMap[10], !insufficientsMap10.isEmpty {
printl(separator)
printl("前二十五個被奪權的有效十字單元圖")
for (i, content) in insufficientsMap10.enumerated() {
if i == 25 { break }
var contentToPrint = "{"
contentToPrint += content.0 + ","
contentToPrint += content.1 + ","
contentToPrint += String(content.2) + ","
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
contentToPrint += String(content.4) + "}"
printl(contentToPrint)
}
}
if !competingUnigrams.isEmpty {
printl(separator)
printl("也發現有 \(competingUnigrams.count) 個複字單元圖被某些由高頻單字組成的複字單元圖奪權的情況,")
printl("例如(前二十五例):")
for (i, content) in competingUnigrams.enumerated() {
if i == 25 { break }
var contentToPrint = "{"
contentToPrint += content.0 + ","
contentToPrint += String(content.1) + ","
contentToPrint += content.2 + ","
contentToPrint += String(content.3) + "}"
printl(contentToPrint)
}
}
if !faulty.isEmpty {
printl(separator)
printl("下述單元圖用到了漢字核心表當中尚未收錄的讀音,可能無法正常輸入:")
for content in faulty {
printl(content.description)
}
}
result += "\n"
return result
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 430 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 KiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -114,7 +114,7 @@
## 參與研發時的注意事項
歡迎參與威注音的研發。論及相關細則,請洽請洽該倉庫內的「[CONTRIBUTING.md](./CONTRIBUTING.md)」檔案、以及《[常見問題解答](./FAQ.md)》。
歡迎參與威注音的研發。論及相關細則,請洽該倉庫內的「[CONTRIBUTING.md](./CONTRIBUTING.md)」檔案、以及《[常見問題解答](./FAQ.md)》。
敝專案採用了《[貢獻者品行準則承約書 v2.1](./code-of-conduct.md)》。考慮到上游鏈接給出的中文版翻譯與英文原文嚴重不符合的情況(會出現因執法與被執法雙方的認知偏差導致的矛盾,非常容易變成敵我矛盾),敝專案使用了自行翻譯的版本、且新增了一些能促進雙方共識的註解。

View File

@ -114,7 +114,7 @@
## 参与研发时的注意事项
欢迎参与威注音的研发。论及相关细则,请洽请洽该仓库内的「[CONTRIBUTING.md](./CONTRIBUTING.md)」档案、以及《[常见问题解答](./FAQ.md)》。
欢迎参与威注音的研发。论及相关细则,请洽该仓库内的「[CONTRIBUTING.md](./CONTRIBUTING.md)」档案、以及《[常见问题解答](./FAQ.md)》。
敝专案采用了《[贡献者品行准则承约书 v2.1](./code-of-conduct.md)》。考虑到上游链接给出的中文版翻译与英文原文严重不符合的情况(会出现因执法与被执法双方的认知偏差导致的矛盾,非常容易变成敌我矛盾),敝专案使用了自行翻译的版本、且新增了一些能促进双方共识的注解。

@ -1 +1 @@
Subproject commit 50250d970a3481ec7653a71120413708a76224d8
Subproject commit 345b21db6510caf63184716178837c5563e68123

View File

@ -149,10 +149,10 @@ class KeyHandler {
/// - Parameter key:
/// - Returns:
/// nil
func buildAssociatePhraseArray(withKey key: String) -> [(String, String)] {
func buildAssociatePhraseArray(withPair pair: Megrez.KeyValuePaired) -> [(String, String)] {
var arrResult: [(String, String)] = []
if currentLM.hasAssociatedPhrasesFor(key: key) {
arrResult = currentLM.associatedPhrasesFor(key: key).map { ("", $0) }
if currentLM.hasAssociatedPhrasesFor(pair: pair) {
arrResult = currentLM.associatedPhrasesFor(pair: pair).map { ("", $0) }
}
return arrResult
}

View File

@ -78,11 +78,6 @@ extension KeyHandler {
// MARK: Enter
if input.isEnter {
if state is InputState.AssociatedPhrases {
clear()
stateCallback(InputState.EmptyIgnoringPreviousState())
return true
}
delegate!.keyHandler(
self,
didSelectCandidateAt: ctlCandidateCurrent.selectedCandidateIndex,

View File

@ -225,6 +225,7 @@ extension KeyHandler {
)
if choosingCandidates.candidates.count == 1 {
clear()
let reading: String = choosingCandidates.candidates.first?.0 ?? ""
let text: String = choosingCandidates.candidates.first?.1 ?? ""
stateCallback(InputState.Committing(textToCommit: text))
@ -233,7 +234,7 @@ extension KeyHandler {
} else {
if let associatedPhrases =
buildAssociatePhraseState(
withKey: text,
withPair: .init(key: reading, value: text),
isTypingVertical: input.isTypingVertical
), !associatedPhrases.candidates.isEmpty
{
@ -261,7 +262,7 @@ extension KeyHandler {
// MARK: (Calling candidate window using Up / Down or PageUp / PageDn.)
if let currentState = state as? InputState.NotEmpty, composer.isEmpty,
if let currentState = state as? InputState.NotEmpty, composer.isEmpty, !input.isOptionHold,
input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse || input.isSpace
|| input.isPageDown || input.isPageUp || (input.isTab && mgrPrefs.specifyShiftTabKeyBehavior)
|| (input.isTypingVertical && (input.isVerticalTypingOnlyChooseCandidateKey))
@ -353,6 +354,17 @@ extension KeyHandler {
// MARK: AbsorbedArrowKey
if input.isAbsorbedArrowKey || input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse {
if input.isOptionHold, state.type == .ofInputting {
if input.isExtraChooseCandidateKey {
return handleInlineCandidateRotation(
state: state, reverseModifier: false, stateCallback: stateCallback, errorCallback: errorCallback
)
} else if input.isExtraChooseCandidateKeyReverse {
return handleInlineCandidateRotation(
state: state, reverseModifier: true, stateCallback: stateCallback, errorCallback: errorCallback
)
}
}
return handleAbsorbedArrowKey(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
}

View File

@ -198,12 +198,12 @@ extension KeyHandler {
/// - isTypingVertical:
/// - Returns:
func buildAssociatePhraseState(
withKey key: String!,
withPair pair: Megrez.KeyValuePaired,
isTypingVertical: Bool
) -> InputState.AssociatedPhrases! {
//  Xcode
InputState.AssociatedPhrases(
candidates: buildAssociatePhraseArray(withKey: key), isTypingVertical: isTypingVertical
candidates: buildAssociatePhraseArray(withPair: pair), isTypingVertical: isTypingVertical
)
}

View File

@ -122,7 +122,8 @@ extension ctlInputMethod: ctlCandidateDelegate {
handle(state: InputState.Committing(textToCommit: composingBuffer))
if mgrPrefs.associatedPhrasesEnabled,
let associatePhrases = keyHandler.buildAssociatePhraseState(
withKey: composingBuffer, isTypingVertical: state.isTypingVertical
withPair: .init(key: selectedValue.0, value: selectedValue.1),
isTypingVertical: state.isTypingVertical
), !associatePhrases.candidates.isEmpty
{
handle(state: associatePhrases)
@ -140,7 +141,8 @@ extension ctlInputMethod: ctlCandidateDelegate {
handle(state: InputState.Committing(textToCommit: selectedValue.1))
if mgrPrefs.associatedPhrasesEnabled,
let associatePhrases = keyHandler.buildAssociatePhraseState(
withKey: selectedValue.1, isTypingVertical: state.isTypingVertical
withPair: .init(key: selectedValue.0, value: selectedValue.1),
isTypingVertical: state.isTypingVertical
), !associatePhrases.candidates.isEmpty
{
handle(state: associatePhrases)

View File

@ -117,15 +117,18 @@ extension ctlInputMethod {
action: #selector(openExcludedPhrases(_:)), keyEquivalent: ""
)
if optionKeyPressed || mgrPrefs.associatedPhrasesEnabled {
menu.addItem(
withTitle: NSLocalizedString("Edit Associated Phrases…", comment: ""),
action: #selector(openAssociatedPhrases(_:)), keyEquivalent: ""
)
}
if optionKeyPressed {
menu.addItem(
withTitle: NSLocalizedString("Edit Phrase Replacement Table…", comment: ""),
action: #selector(openPhraseReplacement(_:)), keyEquivalent: ""
)
menu.addItem(
withTitle: NSLocalizedString("Edit Associated Phrases…", comment: ""),
action: #selector(openAssociatedPhrases(_:)), keyEquivalent: ""
)
menu.addItem(
withTitle: NSLocalizedString("Edit User Symbol & Emoji Data…", comment: ""),
action: #selector(openUserSymbols(_:)), keyEquivalent: ""
@ -139,6 +142,8 @@ extension ctlInputMethod {
)
}
menu.addItem(NSMenuItem.separator()) // ---------------------
menu.addItem(
withTitle: NSLocalizedString("Optimize Memorized Phrases", comment: ""),
action: #selector(removeUnigramsFromUOM(_:)), keyEquivalent: ""

View File

@ -88,6 +88,8 @@ public enum IME {
// MARK: - Initializing Language Models.
static func initLangModels(userOnly: Bool) {
mgrLangModel.chkUserLMFilesExist(.imeModeCHT)
mgrLangModel.chkUserLMFilesExist(.imeModeCHS)
// mgrLangModel loadUserPhrases dataFolderPath
//
//

View File

@ -82,7 +82,7 @@ extension vChewing {
// 使
// 使使
var lmUserPhrases = LMCoreEX(
reverse: true, consolidate: true, defaultScore: 0, forceDefaultScore: true
reverse: true, consolidate: true, defaultScore: 0, forceDefaultScore: false
)
var lmFiltered = LMCoreEX(
reverse: true, consolidate: true, defaultScore: 0, forceDefaultScore: true
@ -249,13 +249,21 @@ extension vChewing {
}
public func associatedPhrasesFor(key: String) -> [String] {
lmAssociates.valuesFor(key: key) ?? []
lmAssociates.valuesFor(key: key)
}
public func hasAssociatedPhrasesFor(key: String) -> Bool {
lmAssociates.hasValuesFor(key: key)
}
public func associatedPhrasesFor(pair: Megrez.KeyValuePaired) -> [String] {
lmAssociates.valuesFor(pair: pair)
}
public func hasAssociatedPhrasesFor(pair: Megrez.KeyValuePaired) -> Bool {
lmAssociates.hasValuesFor(pair: pair)
}
/// 滿 LangModelProtocol
public func bigramsFor(precedingKey _: String, key _: String) -> [Megrez.Bigram] { .init() }

View File

@ -27,7 +27,7 @@ import Foundation
extension vChewing {
@frozen public struct LMAssociates {
var rangeMap: [String: [Range<String.Index>]] = [:]
var rangeMap: [String: [(Range<String.Index>, Int)]] = [:]
var strData: String = ""
public var count: Int {
@ -52,13 +52,16 @@ extension vChewing {
do {
strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ")
strData.ranges(splitBy: "\n").forEach {
strData = strData.replacingOccurrences(of: "\r", with: "\n")
strData.ranges(splitBy: "\n").filter({ !$0.isEmpty }).forEach {
let neta = strData[$0].split(separator: " ")
if neta.count >= 2 {
let theKey = String(neta[0])
if !neta[0].isEmpty, !neta[1].isEmpty, theKey.first != "#" {
let theValue = $0
rangeMap[theKey, default: []].append(theValue)
if !theKey.isEmpty, theKey.first != "#" {
for (i, _) in neta.filter({ $0.first != "#" && !$0.isEmpty }).enumerated() {
if i == 0 { continue }
rangeMap[theKey, default: []].append(($0, i))
}
}
}
}
@ -78,24 +81,16 @@ extension vChewing {
}
public func dump() {
var strDump = ""
for entry in rangeMap {
let netaRanges: [Range<String.Index>] = entry.value
for netaRange in netaRanges {
let neta = strData[netaRange]
let addline = neta + "\n"
strDump += addline
}
}
IME.prtDebugIntel(strDump)
// We remove this function in order to reduce out maintenance workload.
// This function will be implemented only if further hard-necessity comes.
}
public func valuesFor(key: String) -> [String]? {
public func valuesFor(key: String) -> [String] {
var pairs: [String] = []
if let arrRangeRecords: [Range<String.Index>] = rangeMap[key] {
for netaRange in arrRangeRecords {
if let arrRangeRecords: [(Range<String.Index>, Int)] = rangeMap[key] {
for (netaRange, index) in arrRangeRecords {
let neta = strData[netaRange].split(separator: " ")
let theValue: String = .init(neta[1])
let theValue: String = .init(neta[index])
pairs.append(theValue)
}
}
@ -105,6 +100,40 @@ extension vChewing {
public func hasValuesFor(key: String) -> Bool {
rangeMap[key] != nil
}
public func valuesFor(pair: Megrez.KeyValuePaired) -> [String] {
var pairPinyin = pair
pairPinyin.key = Tekkon.cnvPhonaToHanyuPinyin(target: pairPinyin.key)
var pairs: [String] = []
if let arrRangeRecords: [(Range<String.Index>, Int)] = rangeMap[pair.toNGramKey] {
for (netaRange, index) in arrRangeRecords {
let neta = strData[netaRange].split(separator: " ")
let theValue: String = .init(neta[index])
pairs.append(theValue)
}
}
if let arrRangeRecords: [(Range<String.Index>, Int)] = rangeMap[pairPinyin.toNGramKey] {
for (netaRange, index) in arrRangeRecords {
let neta = strData[netaRange].split(separator: " ")
let theValue: String = .init(neta[index])
pairs.append(theValue)
}
}
if let arrRangeRecords: [(Range<String.Index>, Int)] = rangeMap[pair.value] {
for (netaRange, index) in arrRangeRecords {
let neta = strData[netaRange].split(separator: " ")
let theValue: String = .init(neta[index])
pairs.append(theValue)
}
}
var set = Set<String>()
return pairs.filter { set.insert($0).inserted }
}
public func hasValuesFor(pair: Megrez.KeyValuePaired) -> Bool {
if rangeMap[pair.toNGramKey] != nil { return true }
return rangeMap[pair.value] != nil
}
}
}

View File

@ -86,11 +86,13 @@ extension vChewing {
do {
strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ")
strData.ranges(splitBy: "\n").forEach {
strData = strData.replacingOccurrences(of: "\r", with: "\n")
strData.ranges(splitBy: "\n").filter({ !$0.isEmpty }).forEach {
let neta = strData[$0].split(separator: " ")
if neta.count >= 2, String(neta[0]).first != "#" {
if !neta[0].isEmpty, !neta[1].isEmpty {
let theKey = shouldReverse ? String(neta[1]) : String(neta[0])
var theKey = shouldReverse ? String(neta[1]) : String(neta[0])
theKey.cnvPinyinToPhonabet()
let theValue = $0
rangeMap[theKey, default: []].append(theValue)
}
@ -153,7 +155,7 @@ extension vChewing {
let theValue: String = shouldReverse ? String(neta[0]) : String(neta[1])
let kvPair = Megrez.KeyValuePaired(key: key, value: theValue)
var theScore = defaultScore
if neta.count >= 3, !shouldForceDefaultScore {
if neta.count >= 3, !shouldForceDefaultScore, !neta[2].contains("#") {
theScore = .init(String(neta[2])) ?? defaultScore
}
if theScore > 0 {
@ -190,3 +192,19 @@ extension String {
}
}
}
// MARK: -
extension String {
fileprivate mutating func cnvPinyinToPhonabet() {
if contains("_") { return }
for key in Tekkon.mapHanyuPinyin.keys {
guard let value = Tekkon.mapHanyuPinyin[key] else { continue }
self = replacingOccurrences(of: key, with: value)
}
for key in Tekkon.mapArayuruPinyinIntonation.keys {
guard let value = Tekkon.mapArayuruPinyinIntonation[key] else { continue }
self = replacingOccurrences(of: key, with: value)
}
}
}

View File

@ -52,7 +52,8 @@ extension vChewing {
do {
strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ")
strData.ranges(splitBy: "\n").forEach {
strData = strData.replacingOccurrences(of: "\r", with: "\n")
strData.ranges(splitBy: "\n").filter({ !$0.isEmpty }).forEach {
let neta = strData[$0].split(separator: " ")
if neta.count >= 2 {
let theKey = String(neta[0])

View File

@ -36,6 +36,14 @@ private var gLangModelCHT = vChewing.LMInstantiator()
private var gUserOverrideModelCHS = vChewing.LMUserOverride()
private var gUserOverrideModelCHT = vChewing.LMUserOverride()
/// 使
private let kTemplateNameUserPhrases = "template-userphrases"
private let kTemplateNameUserReplacements = "template-replacements"
private let kTemplateNameUserExclusions = "template-exclusions"
private let kTemplateNameUserSymbolPhrases = "template-usersymbolphrases"
private let kTemplateNameUserAssociatesCHS = "template-associatedPhrases-chs"
private let kTemplateNameUserAssociatesCHT = "template-associatedPhrases-cht"
enum mgrLangModel {
/// fileprivate
public static var lmCHS: vChewing.LMInstantiator { gLangModelCHS }
@ -307,18 +315,20 @@ enum mgrLangModel {
return true
}
static func chkUserLMFilesExist(_ mode: InputMode) -> Bool {
@discardableResult static func chkUserLMFilesExist(_ mode: InputMode) -> Bool {
if !userDataFolderExists {
return false
}
/// SymbolNode UserOverrideModel
///
///
if !ensureFileExists(userPhrasesDataURL(mode))
|| !ensureFileExists(userAssociatesDataURL(mode))
|| !ensureFileExists(userFilteredDataURL(mode))
|| !ensureFileExists(userReplacementsDataURL(mode))
|| !ensureFileExists(userSymbolDataURL(mode))
if !ensureFileExists(userPhrasesDataURL(mode), populateWithTemplate: kTemplateNameUserPhrases)
|| !ensureFileExists(
userAssociatesDataURL(mode),
populateWithTemplate: mode == .imeModeCHS ? kTemplateNameUserAssociatesCHS : kTemplateNameUserAssociatesCHT)
|| !ensureFileExists(userFilteredDataURL(mode), populateWithTemplate: kTemplateNameUserExclusions)
|| !ensureFileExists(userReplacementsDataURL(mode), populateWithTemplate: kTemplateNameUserReplacements)
|| !ensureFileExists(userSymbolDataURL(mode), populateWithTemplate: kTemplateNameUserSymbolPhrases)
{
return false
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -1,17 +1,17 @@
{
"images" : [
{
"filename" : "64X64.png",
"filename" : "64.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "128X128.png",
"filename" : "128.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "192x192.png",
"filename" : "192.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

View File

@ -0,0 +1,12 @@
# 𝙵𝙾𝚁𝙼𝙰𝚃 𝚘𝚛𝚐.𝚊𝚝𝚎𝚕𝚒𝚎𝚛𝙸𝚗𝚖𝚞.𝚟𝚌𝚑𝚎𝚠𝚒𝚗𝚐.𝚞𝚜𝚎𝚛𝙻𝚊𝚗𝚐𝚞𝚊𝚐𝚎𝙼𝚘𝚍𝚎𝚕𝙳𝚊𝚝𝚊.𝚏𝚘𝚛𝚖𝚊𝚝𝚝𝚎𝚍
# 按照下述格式「字詞 注音-注音」的方式在本文內添入的字詞記錄會被輸入法的所有辭典都排除掉。
# 按照下述格式「字词 注音-注音」的方式在本文内添入的字词记录会被输入法的所有辞典都排除掉。
# 下記の格式「候補 注音-注音」のよう、このファイルで登録した入力候補は、全辞書から排除されます。
# By using the format "Candidate Reading-Reading", all candidate pairs registered in this file will be blocked among all dictionaries.
#
# 北七 ㄅㄟˇ-ㄑㄧ
#
# 如果任何一行以半形英數「#」或者空格開頭,則該行將被忽略。
# 如果任何一行以半角英数「#」或者空格开头,则该行将被忽略。
# 頭文字が半角英数「#」或いは「スペース」の行は効けません。
# Lines begin with an ASCII sharp symbol or a space will be omitted.

View File

@ -0,0 +1,12 @@
# 𝙵𝙾𝚁𝙼𝙰𝚃 𝚘𝚛𝚐.𝚊𝚝𝚎𝚕𝚒𝚎𝚛𝙸𝚗𝚖𝚞.𝚟𝚌𝚑𝚎𝚠𝚒𝚗𝚐.𝚞𝚜𝚎𝚛𝙻𝚊𝚗𝚐𝚞𝚊𝚐𝚎𝙼𝚘𝚍𝚎𝚕𝙳𝚊𝚝𝚊.𝚏𝚘𝚛𝚖𝚊𝚝𝚝𝚎𝚍
# 按照下述格式「字詞 新字詞」的方式在本文內添入的字詞記錄才會生效。
# 按照下述格式「字词 新字词」的方式在本文内添入的字词记录才会生效。
# 下記の格式「候補 新候補」のよう、このファイルで登録した入力候補は効きます。
# By using the format "Candidate NewCandidate", all entries registered in this file will be effective.
#
# 歐陽修 歐陽脩
#
# 如果任何一行以半形英數「#」或者空格開頭,則該行將被忽略。
# 如果任何一行以半角英数「#」或者空格开头,则该行将被忽略。
# 頭文字が半角英数「#」或いは「スペース」の行は効けません。
# Lines begin with an ASCII sharp symbol or a space will be omitted.

View File

@ -0,0 +1,12 @@
# 𝙵𝙾𝚁𝙼𝙰𝚃 𝚘𝚛𝚐.𝚊𝚝𝚎𝚕𝚒𝚎𝚛𝙸𝚗𝚖𝚞.𝚟𝚌𝚑𝚎𝚠𝚒𝚗𝚐.𝚞𝚜𝚎𝚛𝙻𝚊𝚗𝚐𝚞𝚊𝚐𝚎𝙼𝚘𝚍𝚎𝚕𝙳𝚊𝚝𝚊.𝚏𝚘𝚛𝚖𝚊𝚝𝚝𝚎𝚍
# 按照下述格式「字詞 注音-注音」的方式在本文內添入的字詞記錄才會生效。
# 按照下述格式「字词 注音-注音」的方式在本文内添入的字词记录才会生效。
# 下記の格式「候補 注音-注音」のよう、このファイルで登録した入力候補は効きます。
# By using the format "Candidate Reading-Reading", all entries registered in this file will be effective.
#
# 我是自訂語彙 ㄨㄛˇ-ㄕˋ-ㄗˋ-ㄉㄧㄥˋ-ㄩˇ-ㄏㄨㄟˋ
#
# 如果任何一行以半形英數「#」或者空格開頭,則該行將被忽略。
# 如果任何一行以半角英数「#」或者空格开头,则该行将被忽略。
# 頭文字が半角英数「#」或いは「スペース」の行は効けません。
# Lines begin with an ASCII sharp symbol or a space will be omitted.

View File

@ -0,0 +1,12 @@
# 𝙵𝙾𝚁𝙼𝙰𝚃 𝚘𝚛𝚐.𝚊𝚝𝚎𝚕𝚒𝚎𝚛𝙸𝚗𝚖𝚞.𝚟𝚌𝚑𝚎𝚠𝚒𝚗𝚐.𝚞𝚜𝚎𝚛𝙻𝚊𝚗𝚐𝚞𝚊𝚐𝚎𝙼𝚘𝚍𝚎𝚕𝙳𝚊𝚝𝚊.𝚏𝚘𝚛𝚖𝚊𝚝𝚝𝚎𝚍
# 按照下述格式「字詞 注音-注音」的方式在本文內添入的字詞記錄才會生效。
# 按照下述格式「字词 注音-注音」的方式在本文内添入的字词记录才会生效。
# 下記の格式「候補 注音-注音」のよう、このファイルで登録した入力候補は効きます。
# By using the format "Candidate Reading-Reading", all entries registered in this file will be effective.
#
# ⚠︎ ㄐㄧㄥˇ-ㄍㄠˋ
#
# 如果任何一行以半形英數「#」或者空格開頭,則該行將被忽略。
# 如果任何一行以半角英数「#」或者空格开头,则该行将被忽略。
# 頭文字が半角英数「#」或いは「スペース」の行は効けません。
# Lines begin with an ASCII sharp symbol or a space will be omitted.

View File

@ -3,9 +3,9 @@
<plist version="1.0">
<dict>
<key>CFBundleShortVersionString</key>
<string>1.8.0</string>
<string>1.8.1</string>
<key>CFBundleVersion</key>
<string>1980</string>
<string>1981</string>
<key>UpdateInfoEndpoint</key>
<string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string>
<key>UpdateInfoSite</key>

View File

@ -78,7 +78,7 @@ class Document: NSDocument {
/// - Tag: readExample
override func read(from data: Data, ofType _: String) throws {
var strToDealWith = String(decoding: data, as: UTF8.self)
strToDealWith.formatConsolidate(cnvHYPYtoBPMF: false)
strToDealWith.formatConsolidate()
let processedIncomingData = Data(strToDealWith.utf8)
content.read(from: processedIncomingData)
}
@ -86,7 +86,7 @@ class Document: NSDocument {
/// - Tag: writeExample
override func data(ofType _: String) throws -> Data {
var strToDealWith = content.contentString
strToDealWith.formatConsolidate(cnvHYPYtoBPMF: true)
strToDealWith.formatConsolidate()
let outputData = Data(strToDealWith.utf8)
return outputData
}

View File

@ -42,7 +42,7 @@ extension String {
self = replacingOccurrences(of: strOf, with: strWith)
}
mutating func formatConsolidate(cnvHYPYtoBPMF: Bool) {
mutating func formatConsolidate() {
// Step 1: Consolidating formats per line.
var strProcessed = self
//
@ -64,442 +64,6 @@ extension String {
strProcessed.removeLast()
}
if cnvHYPYtoBPMF {
// Step 2: Convert HanyuPinyin to Bopomofo.
//
//
// 調
strProcessed.selfReplace("chuang", "ㄔㄨㄤ")
strProcessed.selfReplace("shuang", "ㄕㄨㄤ")
strProcessed.selfReplace("zhuang", "ㄓㄨㄤ")
strProcessed.selfReplace("chang", "ㄔㄤ")
strProcessed.selfReplace("cheng", "ㄔㄥ")
strProcessed.selfReplace("chong", "ㄔㄨㄥ")
strProcessed.selfReplace("chuai", "ㄔㄨㄞ")
strProcessed.selfReplace("chuan", "ㄔㄨㄢ")
strProcessed.selfReplace("guang", "ㄍㄨㄤ")
strProcessed.selfReplace("huang", "ㄏㄨㄤ")
strProcessed.selfReplace("jiang", "ㄐㄧㄤ")
strProcessed.selfReplace("jiong", "ㄐㄩㄥ")
strProcessed.selfReplace("kuang", "ㄎㄨㄤ")
strProcessed.selfReplace("liang", "ㄌㄧㄤ")
strProcessed.selfReplace("niang", "ㄋㄧㄤ")
strProcessed.selfReplace("qiang", "ㄑㄧㄤ")
strProcessed.selfReplace("qiong", "ㄑㄩㄥ")
strProcessed.selfReplace("shang", "ㄕㄤ")
strProcessed.selfReplace("sheng", "ㄕㄥ")
strProcessed.selfReplace("shuai", "ㄕㄨㄞ")
strProcessed.selfReplace("shuan", "ㄕㄨㄢ")
strProcessed.selfReplace("xiang", "ㄒㄧㄤ")
strProcessed.selfReplace("xiong", "ㄒㄩㄥ")
strProcessed.selfReplace("zhang", "ㄓㄤ")
strProcessed.selfReplace("zheng", "ㄓㄥ")
strProcessed.selfReplace("zhong", "ㄓㄨㄥ")
strProcessed.selfReplace("zhuai", "ㄓㄨㄞ")
strProcessed.selfReplace("zhuan", "ㄓㄨㄢ")
strProcessed.selfReplace("bang", "ㄅㄤ")
strProcessed.selfReplace("beng", "ㄅㄥ")
strProcessed.selfReplace("bian", "ㄅㄧㄢ")
strProcessed.selfReplace("biao", "ㄅㄧㄠ")
strProcessed.selfReplace("bing", "ㄅㄧㄥ")
strProcessed.selfReplace("cang", "ㄘㄤ")
strProcessed.selfReplace("ceng", "ㄘㄥ")
strProcessed.selfReplace("chai", "ㄔㄞ")
strProcessed.selfReplace("chan", "ㄔㄢ")
strProcessed.selfReplace("chao", "ㄔㄠ")
strProcessed.selfReplace("chen", "ㄔㄣ")
strProcessed.selfReplace("chou", "ㄔㄡ")
strProcessed.selfReplace("chua", "ㄔㄨㄚ")
strProcessed.selfReplace("chui", "ㄔㄨㄟ")
strProcessed.selfReplace("chun", "ㄔㄨㄣ")
strProcessed.selfReplace("chuo", "ㄔㄨㄛ")
strProcessed.selfReplace("cong", "ㄘㄨㄥ")
strProcessed.selfReplace("cuan", "ㄘㄨㄢ")
strProcessed.selfReplace("dang", "ㄉㄤ")
strProcessed.selfReplace("deng", "ㄉㄥ")
strProcessed.selfReplace("dian", "ㄉㄧㄢ")
strProcessed.selfReplace("diao", "ㄉㄧㄠ")
strProcessed.selfReplace("ding", "ㄉㄧㄥ")
strProcessed.selfReplace("dong", "ㄉㄨㄥ")
strProcessed.selfReplace("duan", "ㄉㄨㄢ")
strProcessed.selfReplace("fang", "ㄈㄤ")
strProcessed.selfReplace("feng", "ㄈㄥ")
strProcessed.selfReplace("fiao", "ㄈㄧㄠ")
strProcessed.selfReplace("fong", "ㄈㄨㄥ")
strProcessed.selfReplace("gang", "ㄍㄤ")
strProcessed.selfReplace("geng", "ㄍㄥ")
strProcessed.selfReplace("giao", "ㄍㄧㄠ")
strProcessed.selfReplace("gong", "ㄍㄨㄥ")
strProcessed.selfReplace("guai", "ㄍㄨㄞ")
strProcessed.selfReplace("guan", "ㄍㄨㄢ")
strProcessed.selfReplace("hang", "ㄏㄤ")
strProcessed.selfReplace("heng", "ㄏㄥ")
strProcessed.selfReplace("hong", "ㄏㄨㄥ")
strProcessed.selfReplace("huai", "ㄏㄨㄞ")
strProcessed.selfReplace("huan", "ㄏㄨㄢ")
strProcessed.selfReplace("jian", "ㄐㄧㄢ")
strProcessed.selfReplace("jiao", "ㄐㄧㄠ")
strProcessed.selfReplace("jing", "ㄐㄧㄥ")
strProcessed.selfReplace("juan", "ㄐㄩㄢ")
strProcessed.selfReplace("kang", "ㄎㄤ")
strProcessed.selfReplace("keng", "ㄎㄥ")
strProcessed.selfReplace("kong", "ㄎㄨㄥ")
strProcessed.selfReplace("kuai", "ㄎㄨㄞ")
strProcessed.selfReplace("kuan", "ㄎㄨㄢ")
strProcessed.selfReplace("lang", "ㄌㄤ")
strProcessed.selfReplace("leng", "ㄌㄥ")
strProcessed.selfReplace("lian", "ㄌㄧㄢ")
strProcessed.selfReplace("liao", "ㄌㄧㄠ")
strProcessed.selfReplace("ling", "ㄌㄧㄥ")
strProcessed.selfReplace("long", "ㄌㄨㄥ")
strProcessed.selfReplace("luan", "ㄌㄨㄢ")
strProcessed.selfReplace("lvan", "ㄌㄩㄢ")
strProcessed.selfReplace("mang", "ㄇㄤ")
strProcessed.selfReplace("meng", "ㄇㄥ")
strProcessed.selfReplace("mian", "ㄇㄧㄢ")
strProcessed.selfReplace("miao", "ㄇㄧㄠ")
strProcessed.selfReplace("ming", "ㄇㄧㄥ")
strProcessed.selfReplace("nang", "ㄋㄤ")
strProcessed.selfReplace("neng", "ㄋㄥ")
strProcessed.selfReplace("nian", "ㄋㄧㄢ")
strProcessed.selfReplace("niao", "ㄋㄧㄠ")
strProcessed.selfReplace("ning", "ㄋㄧㄥ")
strProcessed.selfReplace("nong", "ㄋㄨㄥ")
strProcessed.selfReplace("nuan", "ㄋㄨㄢ")
strProcessed.selfReplace("pang", "ㄆㄤ")
strProcessed.selfReplace("peng", "ㄆㄥ")
strProcessed.selfReplace("pian", "ㄆㄧㄢ")
strProcessed.selfReplace("piao", "ㄆㄧㄠ")
strProcessed.selfReplace("ping", "ㄆㄧㄥ")
strProcessed.selfReplace("qian", "ㄑㄧㄢ")
strProcessed.selfReplace("qiao", "ㄑㄧㄠ")
strProcessed.selfReplace("qing", "ㄑㄧㄥ")
strProcessed.selfReplace("quan", "ㄑㄩㄢ")
strProcessed.selfReplace("rang", "ㄖㄤ")
strProcessed.selfReplace("reng", "ㄖㄥ")
strProcessed.selfReplace("rong", "ㄖㄨㄥ")
strProcessed.selfReplace("ruan", "ㄖㄨㄢ")
strProcessed.selfReplace("sang", "ㄙㄤ")
strProcessed.selfReplace("seng", "ㄙㄥ")
strProcessed.selfReplace("shai", "ㄕㄞ")
strProcessed.selfReplace("shan", "ㄕㄢ")
strProcessed.selfReplace("shao", "ㄕㄠ")
strProcessed.selfReplace("shei", "ㄕㄟ")
strProcessed.selfReplace("shen", "ㄕㄣ")
strProcessed.selfReplace("shou", "ㄕㄡ")
strProcessed.selfReplace("shua", "ㄕㄨㄚ")
strProcessed.selfReplace("shui", "ㄕㄨㄟ")
strProcessed.selfReplace("shun", "ㄕㄨㄣ")
strProcessed.selfReplace("shuo", "ㄕㄨㄛ")
strProcessed.selfReplace("song", "ㄙㄨㄥ")
strProcessed.selfReplace("suan", "ㄙㄨㄢ")
strProcessed.selfReplace("tang", "ㄊㄤ")
strProcessed.selfReplace("teng", "ㄊㄥ")
strProcessed.selfReplace("tian", "ㄊㄧㄢ")
strProcessed.selfReplace("tiao", "ㄊㄧㄠ")
strProcessed.selfReplace("ting", "ㄊㄧㄥ")
strProcessed.selfReplace("tong", "ㄊㄨㄥ")
strProcessed.selfReplace("tuan", "ㄊㄨㄢ")
strProcessed.selfReplace("wang", "ㄨㄤ")
strProcessed.selfReplace("weng", "ㄨㄥ")
strProcessed.selfReplace("xian", "ㄒㄧㄢ")
strProcessed.selfReplace("xiao", "ㄒㄧㄠ")
strProcessed.selfReplace("xing", "ㄒㄧㄥ")
strProcessed.selfReplace("xuan", "ㄒㄩㄢ")
strProcessed.selfReplace("yang", "ㄧㄤ")
strProcessed.selfReplace("ying", "ㄧㄥ")
strProcessed.selfReplace("yong", "ㄩㄥ")
strProcessed.selfReplace("yuan", "ㄩㄢ")
strProcessed.selfReplace("zang", "ㄗㄤ")
strProcessed.selfReplace("zeng", "ㄗㄥ")
strProcessed.selfReplace("zhai", "ㄓㄞ")
strProcessed.selfReplace("zhan", "ㄓㄢ")
strProcessed.selfReplace("zhao", "ㄓㄠ")
strProcessed.selfReplace("zhei", "ㄓㄟ")
strProcessed.selfReplace("zhen", "ㄓㄣ")
strProcessed.selfReplace("zhou", "ㄓㄡ")
strProcessed.selfReplace("zhua", "ㄓㄨㄚ")
strProcessed.selfReplace("zhui", "ㄓㄨㄟ")
strProcessed.selfReplace("zhun", "ㄓㄨㄣ")
strProcessed.selfReplace("zhuo", "ㄓㄨㄛ")
strProcessed.selfReplace("zong", "ㄗㄨㄥ")
strProcessed.selfReplace("zuan", "ㄗㄨㄢ")
strProcessed.selfReplace("jun", "ㄐㄩㄣ")
strProcessed.selfReplace("ang", "")
strProcessed.selfReplace("bai", "ㄅㄞ")
strProcessed.selfReplace("ban", "ㄅㄢ")
strProcessed.selfReplace("bao", "ㄅㄠ")
strProcessed.selfReplace("bei", "ㄅㄟ")
strProcessed.selfReplace("ben", "ㄅㄣ")
strProcessed.selfReplace("bie", "ㄅㄧㄝ")
strProcessed.selfReplace("bin", "ㄅㄧㄣ")
strProcessed.selfReplace("cai", "ㄘㄞ")
strProcessed.selfReplace("can", "ㄘㄢ")
strProcessed.selfReplace("cao", "ㄘㄠ")
strProcessed.selfReplace("cei", "ㄘㄟ")
strProcessed.selfReplace("cen", "ㄘㄣ")
strProcessed.selfReplace("cha", "ㄔㄚ")
strProcessed.selfReplace("che", "ㄔㄜ")
strProcessed.selfReplace("chi", "")
strProcessed.selfReplace("chu", "ㄔㄨ")
strProcessed.selfReplace("cou", "ㄘㄡ")
strProcessed.selfReplace("cui", "ㄘㄨㄟ")
strProcessed.selfReplace("cun", "ㄘㄨㄣ")
strProcessed.selfReplace("cuo", "ㄘㄨㄛ")
strProcessed.selfReplace("dai", "ㄉㄞ")
strProcessed.selfReplace("dan", "ㄉㄢ")
strProcessed.selfReplace("dao", "ㄉㄠ")
strProcessed.selfReplace("dei", "ㄉㄟ")
strProcessed.selfReplace("den", "ㄉㄣ")
strProcessed.selfReplace("dia", "ㄉㄧㄚ")
strProcessed.selfReplace("die", "ㄉㄧㄝ")
strProcessed.selfReplace("diu", "ㄉㄧㄡ")
strProcessed.selfReplace("dou", "ㄉㄡ")
strProcessed.selfReplace("dui", "ㄉㄨㄟ")
strProcessed.selfReplace("dun", "ㄉㄨㄣ")
strProcessed.selfReplace("duo", "ㄉㄨㄛ")
strProcessed.selfReplace("eng", "")
strProcessed.selfReplace("fan", "ㄈㄢ")
strProcessed.selfReplace("fei", "ㄈㄟ")
strProcessed.selfReplace("fen", "ㄈㄣ")
strProcessed.selfReplace("fou", "ㄈㄡ")
strProcessed.selfReplace("gai", "ㄍㄞ")
strProcessed.selfReplace("gan", "ㄍㄢ")
strProcessed.selfReplace("gao", "ㄍㄠ")
strProcessed.selfReplace("gei", "ㄍㄟ")
strProcessed.selfReplace("gin", "ㄍㄧㄣ")
strProcessed.selfReplace("gen", "ㄍㄣ")
strProcessed.selfReplace("gou", "ㄍㄡ")
strProcessed.selfReplace("gua", "ㄍㄨㄚ")
strProcessed.selfReplace("gue", "ㄍㄨㄜ")
strProcessed.selfReplace("gui", "ㄍㄨㄟ")
strProcessed.selfReplace("gun", "ㄍㄨㄣ")
strProcessed.selfReplace("guo", "ㄍㄨㄛ")
strProcessed.selfReplace("hai", "ㄏㄞ")
strProcessed.selfReplace("han", "ㄏㄢ")
strProcessed.selfReplace("hao", "ㄏㄠ")
strProcessed.selfReplace("hei", "ㄏㄟ")
strProcessed.selfReplace("hen", "ㄏㄣ")
strProcessed.selfReplace("hou", "ㄏㄡ")
strProcessed.selfReplace("hua", "ㄏㄨㄚ")
strProcessed.selfReplace("hui", "ㄏㄨㄟ")
strProcessed.selfReplace("hun", "ㄏㄨㄣ")
strProcessed.selfReplace("huo", "ㄏㄨㄛ")
strProcessed.selfReplace("jia", "ㄐㄧㄚ")
strProcessed.selfReplace("jie", "ㄐㄧㄝ")
strProcessed.selfReplace("jin", "ㄐㄧㄣ")
strProcessed.selfReplace("jiu", "ㄐㄧㄡ")
strProcessed.selfReplace("jue", "ㄐㄩㄝ")
strProcessed.selfReplace("kai", "ㄎㄞ")
strProcessed.selfReplace("kan", "ㄎㄢ")
strProcessed.selfReplace("kao", "ㄎㄠ")
strProcessed.selfReplace("ken", "ㄎㄣ")
strProcessed.selfReplace("kiu", "ㄎㄧㄡ")
strProcessed.selfReplace("kou", "ㄎㄡ")
strProcessed.selfReplace("kua", "ㄎㄨㄚ")
strProcessed.selfReplace("kui", "ㄎㄨㄟ")
strProcessed.selfReplace("kun", "ㄎㄨㄣ")
strProcessed.selfReplace("kuo", "ㄎㄨㄛ")
strProcessed.selfReplace("lai", "ㄌㄞ")
strProcessed.selfReplace("lan", "ㄌㄢ")
strProcessed.selfReplace("lao", "ㄌㄠ")
strProcessed.selfReplace("lei", "ㄌㄟ")
strProcessed.selfReplace("lia", "ㄌㄧㄚ")
strProcessed.selfReplace("lie", "ㄌㄧㄝ")
strProcessed.selfReplace("lin", "ㄌㄧㄣ")
strProcessed.selfReplace("liu", "ㄌㄧㄡ")
strProcessed.selfReplace("lou", "ㄌㄡ")
strProcessed.selfReplace("lun", "ㄌㄨㄣ")
strProcessed.selfReplace("luo", "ㄌㄨㄛ")
strProcessed.selfReplace("lve", "ㄌㄩㄝ")
strProcessed.selfReplace("mai", "ㄇㄞ")
strProcessed.selfReplace("man", "ㄇㄢ")
strProcessed.selfReplace("mao", "ㄇㄠ")
strProcessed.selfReplace("mei", "ㄇㄟ")
strProcessed.selfReplace("men", "ㄇㄣ")
strProcessed.selfReplace("mie", "ㄇㄧㄝ")
strProcessed.selfReplace("min", "ㄇㄧㄣ")
strProcessed.selfReplace("miu", "ㄇㄧㄡ")
strProcessed.selfReplace("mou", "ㄇㄡ")
strProcessed.selfReplace("nai", "ㄋㄞ")
strProcessed.selfReplace("nan", "ㄋㄢ")
strProcessed.selfReplace("nao", "ㄋㄠ")
strProcessed.selfReplace("nei", "ㄋㄟ")
strProcessed.selfReplace("nen", "ㄋㄣ")
strProcessed.selfReplace("nie", "ㄋㄧㄝ")
strProcessed.selfReplace("nin", "ㄋㄧㄣ")
strProcessed.selfReplace("niu", "ㄋㄧㄡ")
strProcessed.selfReplace("nou", "ㄋㄡ")
strProcessed.selfReplace("nui", "ㄋㄨㄟ")
strProcessed.selfReplace("nun", "ㄋㄨㄣ")
strProcessed.selfReplace("nuo", "ㄋㄨㄛ")
strProcessed.selfReplace("nve", "ㄋㄩㄝ")
strProcessed.selfReplace("pai", "ㄆㄞ")
strProcessed.selfReplace("pan", "ㄆㄢ")
strProcessed.selfReplace("pao", "ㄆㄠ")
strProcessed.selfReplace("pei", "ㄆㄟ")
strProcessed.selfReplace("pen", "ㄆㄣ")
strProcessed.selfReplace("pia", "ㄆㄧㄚ")
strProcessed.selfReplace("pie", "ㄆㄧㄝ")
strProcessed.selfReplace("pin", "ㄆㄧㄣ")
strProcessed.selfReplace("pou", "ㄆㄡ")
strProcessed.selfReplace("qia", "ㄑㄧㄚ")
strProcessed.selfReplace("qie", "ㄑㄧㄝ")
strProcessed.selfReplace("qin", "ㄑㄧㄣ")
strProcessed.selfReplace("qiu", "ㄑㄧㄡ")
strProcessed.selfReplace("que", "ㄑㄩㄝ")
strProcessed.selfReplace("qun", "ㄑㄩㄣ")
strProcessed.selfReplace("ran", "ㄖㄢ")
strProcessed.selfReplace("rao", "ㄖㄠ")
strProcessed.selfReplace("ren", "ㄖㄣ")
strProcessed.selfReplace("rou", "ㄖㄡ")
strProcessed.selfReplace("rui", "ㄖㄨㄟ")
strProcessed.selfReplace("run", "ㄖㄨㄣ")
strProcessed.selfReplace("ruo", "ㄖㄨㄛ")
strProcessed.selfReplace("sai", "ㄙㄞ")
strProcessed.selfReplace("san", "ㄙㄢ")
strProcessed.selfReplace("sao", "ㄙㄠ")
strProcessed.selfReplace("sei", "ㄙㄟ")
strProcessed.selfReplace("sen", "ㄙㄣ")
strProcessed.selfReplace("sha", "ㄕㄚ")
strProcessed.selfReplace("she", "ㄕㄜ")
strProcessed.selfReplace("shi", "")
strProcessed.selfReplace("shu", "ㄕㄨ")
strProcessed.selfReplace("sou", "ㄙㄡ")
strProcessed.selfReplace("sui", "ㄙㄨㄟ")
strProcessed.selfReplace("sun", "ㄙㄨㄣ")
strProcessed.selfReplace("suo", "ㄙㄨㄛ")
strProcessed.selfReplace("tai", "ㄊㄞ")
strProcessed.selfReplace("tan", "ㄊㄢ")
strProcessed.selfReplace("tao", "ㄊㄠ")
strProcessed.selfReplace("tie", "ㄊㄧㄝ")
strProcessed.selfReplace("tou", "ㄊㄡ")
strProcessed.selfReplace("tui", "ㄊㄨㄟ")
strProcessed.selfReplace("tun", "ㄊㄨㄣ")
strProcessed.selfReplace("tuo", "ㄊㄨㄛ")
strProcessed.selfReplace("wai", "ㄨㄞ")
strProcessed.selfReplace("wan", "ㄨㄢ")
strProcessed.selfReplace("wei", "ㄨㄟ")
strProcessed.selfReplace("wen", "ㄨㄣ")
strProcessed.selfReplace("xia", "ㄒㄧㄚ")
strProcessed.selfReplace("xie", "ㄒㄧㄝ")
strProcessed.selfReplace("xin", "ㄒㄧㄣ")
strProcessed.selfReplace("xiu", "ㄒㄧㄡ")
strProcessed.selfReplace("xue", "ㄒㄩㄝ")
strProcessed.selfReplace("xun", "ㄒㄩㄣ")
strProcessed.selfReplace("yai", "ㄧㄞ")
strProcessed.selfReplace("yan", "ㄧㄢ")
strProcessed.selfReplace("yao", "ㄧㄠ")
strProcessed.selfReplace("yin", "ㄧㄣ")
strProcessed.selfReplace("you", "ㄧㄡ")
strProcessed.selfReplace("yue", "ㄩㄝ")
strProcessed.selfReplace("yun", "ㄩㄣ")
strProcessed.selfReplace("zai", "ㄗㄞ")
strProcessed.selfReplace("zan", "ㄗㄢ")
strProcessed.selfReplace("zao", "ㄗㄠ")
strProcessed.selfReplace("zei", "ㄗㄟ")
strProcessed.selfReplace("zen", "ㄗㄣ")
strProcessed.selfReplace("zha", "ㄓㄚ")
strProcessed.selfReplace("zhe", "ㄓㄜ")
strProcessed.selfReplace("zhi", "")
strProcessed.selfReplace("zhu", "ㄓㄨ")
strProcessed.selfReplace("zou", "ㄗㄡ")
strProcessed.selfReplace("zui", "ㄗㄨㄟ")
strProcessed.selfReplace("zun", "ㄗㄨㄣ")
strProcessed.selfReplace("zuo", "ㄗㄨㄛ")
strProcessed.selfReplace("ai", "")
strProcessed.selfReplace("an", "")
strProcessed.selfReplace("ao", "")
strProcessed.selfReplace("ba", "ㄅㄚ")
strProcessed.selfReplace("bi", "ㄅㄧ")
strProcessed.selfReplace("bo", "ㄅㄛ")
strProcessed.selfReplace("bu", "ㄅㄨ")
strProcessed.selfReplace("ca", "ㄘㄚ")
strProcessed.selfReplace("ce", "ㄘㄜ")
strProcessed.selfReplace("ci", "")
strProcessed.selfReplace("cu", "ㄘㄨ")
strProcessed.selfReplace("da", "ㄉㄚ")
strProcessed.selfReplace("de", "ㄉㄜ")
strProcessed.selfReplace("di", "ㄉㄧ")
strProcessed.selfReplace("du", "ㄉㄨ")
strProcessed.selfReplace("eh", "")
strProcessed.selfReplace("ei", "")
strProcessed.selfReplace("en", "")
strProcessed.selfReplace("er", "")
strProcessed.selfReplace("fa", "ㄈㄚ")
strProcessed.selfReplace("fo", "ㄈㄛ")
strProcessed.selfReplace("fu", "ㄈㄨ")
strProcessed.selfReplace("ga", "ㄍㄚ")
strProcessed.selfReplace("ge", "ㄍㄜ")
strProcessed.selfReplace("gi", "ㄍㄧ")
strProcessed.selfReplace("gu", "ㄍㄨ")
strProcessed.selfReplace("ha", "ㄏㄚ")
strProcessed.selfReplace("he", "ㄏㄜ")
strProcessed.selfReplace("hu", "ㄏㄨ")
strProcessed.selfReplace("ji", "ㄐㄧ")
strProcessed.selfReplace("ju", "ㄐㄩ")
strProcessed.selfReplace("ka", "ㄎㄚ")
strProcessed.selfReplace("ke", "ㄎㄜ")
strProcessed.selfReplace("ku", "ㄎㄨ")
strProcessed.selfReplace("la", "ㄌㄚ")
strProcessed.selfReplace("le", "ㄌㄜ")
strProcessed.selfReplace("li", "ㄌㄧ")
strProcessed.selfReplace("lo", "ㄌㄛ")
strProcessed.selfReplace("lu", "ㄌㄨ")
strProcessed.selfReplace("lv", "ㄌㄩ")
strProcessed.selfReplace("ma", "ㄇㄚ")
strProcessed.selfReplace("me", "ㄇㄜ")
strProcessed.selfReplace("mi", "ㄇㄧ")
strProcessed.selfReplace("mo", "ㄇㄛ")
strProcessed.selfReplace("mu", "ㄇㄨ")
strProcessed.selfReplace("na", "ㄋㄚ")
strProcessed.selfReplace("ne", "ㄋㄜ")
strProcessed.selfReplace("ni", "ㄋㄧ")
strProcessed.selfReplace("nu", "ㄋㄨ")
strProcessed.selfReplace("nv", "ㄋㄩ")
strProcessed.selfReplace("ou", "")
strProcessed.selfReplace("pa", "ㄆㄚ")
strProcessed.selfReplace("pi", "ㄆㄧ")
strProcessed.selfReplace("po", "ㄆㄛ")
strProcessed.selfReplace("pu", "ㄆㄨ")
strProcessed.selfReplace("qi", "ㄑㄧ")
strProcessed.selfReplace("qu", "ㄑㄩ")
strProcessed.selfReplace("re", "ㄖㄜ")
strProcessed.selfReplace("ri", "")
strProcessed.selfReplace("ru", "ㄖㄨ")
strProcessed.selfReplace("sa", "ㄙㄚ")
strProcessed.selfReplace("se", "ㄙㄜ")
strProcessed.selfReplace("si", "")
strProcessed.selfReplace("su", "ㄙㄨ")
strProcessed.selfReplace("ta", "ㄊㄚ")
strProcessed.selfReplace("te", "ㄊㄜ")
strProcessed.selfReplace("ti", "ㄊㄧ")
strProcessed.selfReplace("tu", "ㄊㄨ")
strProcessed.selfReplace("wa", "ㄨㄚ")
strProcessed.selfReplace("wo", "ㄨㄛ")
strProcessed.selfReplace("wu", "")
strProcessed.selfReplace("xi", "ㄒㄧ")
strProcessed.selfReplace("xu", "ㄒㄩ")
strProcessed.selfReplace("ya", "ㄧㄚ")
strProcessed.selfReplace("ye", "ㄧㄝ")
strProcessed.selfReplace("yi", "")
strProcessed.selfReplace("yo", "ㄧㄛ")
strProcessed.selfReplace("yu", "")
strProcessed.selfReplace("za", "ㄗㄚ")
strProcessed.selfReplace("ze", "ㄗㄜ")
strProcessed.selfReplace("zi", "")
strProcessed.selfReplace("zu", "ㄗㄨ")
strProcessed.selfReplace("a", "")
strProcessed.selfReplace("e", "")
strProcessed.selfReplace("o", "")
strProcessed.selfReplace("q", "")
strProcessed.selfReplace("2", "ˊ")
strProcessed.selfReplace("3", "ˇ")
strProcessed.selfReplace("4", "ˋ")
strProcessed.selfReplace("5", "˙")
strProcessed.selfReplace("1", "")
}
// Step 3: Add Formatted Pragma, the Sorted Header:
let hdrFormatted = "# 𝙵𝙾𝚁𝙼𝙰𝚃 𝚘𝚛𝚐.𝚊𝚝𝚎𝚕𝚒𝚎𝚛𝙸𝚗𝚖𝚞.𝚟𝚌𝚑𝚎𝚠𝚒𝚗𝚐.𝚞𝚜𝚎𝚛𝙻𝚊𝚗𝚐𝚞𝚊𝚐𝚎𝙼𝚘𝚍𝚎𝚕𝙳𝚊𝚝𝚊.𝚏𝚘𝚛𝚖𝚊𝚝𝚝𝚎𝚍\n"
strProcessed = hdrFormatted + strProcessed // Add Sorted Header

View File

@ -726,7 +726,7 @@
<key>USE_HFS+_COMPRESSION</key>
<false/>
<key>VERSION</key>
<string>1.8.0</string>
<string>1.8.1</string>
</dict>
<key>TYPE</key>
<integer>0</integer>

View File

@ -109,6 +109,12 @@
5BEDB723283B4C250078EB25 /* data-cht.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB720283B4AEA0078EB25 /* data-cht.plist */; };
5BEDB724283B4C250078EB25 /* data-symbols.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB71E283B4AEA0078EB25 /* data-symbols.plist */; };
5BEDB725283B4C250078EB25 /* data-chs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB71C283B4AEA0078EB25 /* data-chs.plist */; };
5BF9DA2728840E6200DBD48E /* template-usersymbolphrases.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2228840E6200DBD48E /* template-usersymbolphrases.txt */; };
5BF9DA2828840E6200DBD48E /* template-exclusions.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2328840E6200DBD48E /* template-exclusions.txt */; };
5BF9DA2928840E6200DBD48E /* template-associatedPhrases-chs.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2428840E6200DBD48E /* template-associatedPhrases-chs.txt */; };
5BF9DA2A28840E6200DBD48E /* template-replacements.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2528840E6200DBD48E /* template-replacements.txt */; };
5BF9DA2B28840E6200DBD48E /* template-userphrases.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2628840E6200DBD48E /* template-userphrases.txt */; };
5BF9DA2D288427E000DBD48E /* template-associatedPhrases-cht.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2C2884247800DBD48E /* template-associatedPhrases-cht.txt */; };
6A187E2616004C5900466B2E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6A187E2816004C5900466B2E /* MainMenu.xib */; };
6A225A1F23679F2600F685C6 /* NotarizedArchives in Resources */ = {isa = PBXBuildFile; fileRef = 6A225A1E23679F2600F685C6 /* NotarizedArchives */; };
6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6A2E40F5253A69DA00D1AE1D /* Images.xcassets */; };
@ -306,6 +312,12 @@
5BEDB71E283B4AEA0078EB25 /* data-symbols.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "data-symbols.plist"; path = "Data/data-symbols.plist"; sourceTree = "<group>"; };
5BEDB71F283B4AEA0078EB25 /* data-zhuyinwen.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "data-zhuyinwen.plist"; path = "Data/data-zhuyinwen.plist"; sourceTree = "<group>"; };
5BEDB720283B4AEA0078EB25 /* data-cht.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "data-cht.plist"; path = "Data/data-cht.plist"; sourceTree = "<group>"; };
5BF9DA2228840E6200DBD48E /* template-usersymbolphrases.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-usersymbolphrases.txt"; sourceTree = "<group>"; usesTabs = 0; };
5BF9DA2328840E6200DBD48E /* template-exclusions.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-exclusions.txt"; sourceTree = "<group>"; usesTabs = 0; };
5BF9DA2428840E6200DBD48E /* template-associatedPhrases-chs.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; name = "template-associatedPhrases-chs.txt"; path = "../Data/components/chs/template-associatedPhrases-chs.txt"; sourceTree = "<group>"; usesTabs = 0; };
5BF9DA2528840E6200DBD48E /* template-replacements.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-replacements.txt"; sourceTree = "<group>"; usesTabs = 0; };
5BF9DA2628840E6200DBD48E /* template-userphrases.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-userphrases.txt"; sourceTree = "<group>"; usesTabs = 0; };
5BF9DA2C2884247800DBD48E /* template-associatedPhrases-cht.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; name = "template-associatedPhrases-cht.txt"; path = "../Data/components/cht/template-associatedPhrases-cht.txt"; sourceTree = "<group>"; };
5BFDF48C27B51867009523B6 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Main.strings"; sourceTree = "<group>"; };
6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = vChewing.app; sourceTree = BUILT_PRODUCTS_DIR; };
6A0D4EF515FC0DA600ABF4B3 /* IME-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "IME-Info.plist"; sourceTree = "<group>"; };
@ -502,6 +514,12 @@
5B62A33027AE78E500A19448 /* Resources */ = {
isa = PBXGroup;
children = (
5BF9DA2428840E6200DBD48E /* template-associatedPhrases-chs.txt */,
5BF9DA2C2884247800DBD48E /* template-associatedPhrases-cht.txt */,
5BF9DA2328840E6200DBD48E /* template-exclusions.txt */,
5BF9DA2528840E6200DBD48E /* template-replacements.txt */,
5BF9DA2628840E6200DBD48E /* template-userphrases.txt */,
5BF9DA2228840E6200DBD48E /* template-usersymbolphrases.txt */,
6A0D4EEE15FC0DA600ABF4B3 /* Images */,
5BBBB76E27AED70B0023B93A /* MenuIcons */,
5BBBB75C27AED54C0023B93A /* SoundFiles */,
@ -860,9 +878,9 @@
isa = PBXNativeTarget;
buildConfigurationList = 6A0D4EC015FC0D2E00ABF4B3 /* Build configuration list for PBXNativeTarget "vChewing" */;
buildPhases = (
5B9A5A00285184BB001FFCAF /* ShellScript */,
6A0D4E9E15FC0D2D00ABF4B3 /* Sources */,
6A0D4E9F15FC0D2D00ABF4B3 /* Frameworks */,
5B9A5A00285184BB001FFCAF /* ShellScript */,
6A0D4EA015FC0D2D00ABF4B3 /* Resources */,
5BDC5CBE27C28E8B00E1CCE2 /* Embed Foundation Extensions */,
);
@ -984,6 +1002,7 @@
5B84579E2871AD2200C93B01 /* convdict.plist in Resources */,
5BBBB77427AED70B0023B93A /* MenuIcon-SCVIM@2x.png in Resources */,
D4E33D8A27A838CF006DB1CF /* Localizable.strings in Resources */,
5BF9DA2828840E6200DBD48E /* template-exclusions.txt in Resources */,
5BDCBB2E27B4E67A00D0CC59 /* vChewingPhraseEditor.app in Resources */,
5BBBB76027AED54C0023B93A /* Fart.m4a in Resources */,
6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */,
@ -991,12 +1010,17 @@
5BBBB76B27AED5DB0023B93A /* frmNonModalAlertWindow.xib in Resources */,
5BEDB723283B4C250078EB25 /* data-cht.plist in Resources */,
5BEDB721283B4C250078EB25 /* data-cns.plist in Resources */,
5BF9DA2D288427E000DBD48E /* template-associatedPhrases-cht.txt in Resources */,
5BEDB725283B4C250078EB25 /* data-chs.plist in Resources */,
5BF9DA2928840E6200DBD48E /* template-associatedPhrases-chs.txt in Resources */,
5BBBB76D27AED5DB0023B93A /* frmAboutWindow.xib in Resources */,
5BF9DA2B28840E6200DBD48E /* template-userphrases.txt in Resources */,
5BBBB77527AED70B0023B93A /* MenuIcon-SCVIM.png in Resources */,
5BEDB722283B4C250078EB25 /* data-zhuyinwen.plist in Resources */,
5BF9DA2728840E6200DBD48E /* template-usersymbolphrases.txt in Resources */,
5BEDB724283B4C250078EB25 /* data-symbols.plist in Resources */,
5B7BC4B027AFFBE800F66C24 /* frmPrefWindow.xib in Resources */,
5BF9DA2A28840E6200DBD48E /* template-replacements.txt in Resources */,
5BBBB77327AED70B0023B93A /* MenuIcon-TCVIM@2x.png in Resources */,
5BBBB77627AED70B0023B93A /* MenuIcon-TCVIM.png in Resources */,
6A187E2616004C5900466B2E /* MainMenu.xib in Resources */,
@ -1365,7 +1389,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1980;
CURRENT_PROJECT_VERSION = 1981;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
@ -1375,7 +1399,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.8.0;
MARKETING_VERSION = 1.8.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
@ -1404,13 +1428,13 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1980;
CURRENT_PROJECT_VERSION = 1981;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.8.0;
MARKETING_VERSION = 1.8.1;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
@ -1441,7 +1465,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1980;
CURRENT_PROJECT_VERSION = 1981;
DEAD_CODE_STRIPPING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
@ -1462,7 +1486,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.0;
MARKETING_VERSION = 1.8.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1491,7 +1515,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1980;
CURRENT_PROJECT_VERSION = 1981;
DEAD_CODE_STRIPPING = YES;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1508,7 +1532,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.0;
MARKETING_VERSION = 1.8.1;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1618,7 +1642,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1980;
CURRENT_PROJECT_VERSION = 1981;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
@ -1649,7 +1673,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.0;
MARKETING_VERSION = 1.8.1;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1676,7 +1700,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1980;
CURRENT_PROJECT_VERSION = 1981;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
@ -1701,7 +1725,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.0;
MARKETING_VERSION = 1.8.1;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -1723,7 +1747,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1980;
CURRENT_PROJECT_VERSION = 1981;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1744,7 +1768,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.0;
MARKETING_VERSION = 1.8.1;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1766,7 +1790,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1980;
CURRENT_PROJECT_VERSION = 1981;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1781,7 +1805,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.0;
MARKETING_VERSION = 1.8.1;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";