Skip to content

Commit

Permalink
Add Wade-Giles pinyin input support. (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
ShikiSuen authored Mar 31, 2023
1 parent 7292943 commit 8cb9edf
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 84 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@

Tekkon Engine is a module made for processing combo-composition of stroke-based Mandarin Chinese phonetics (i.e. Zhuyin / Bopomofo). This repository is part of Operation Longinus of The vChewing Project.

羅馬拼音輸入目前僅支援漢語拼音、國音二式、耶魯拼音、華羅拼音、通用拼音。
羅馬拼音輸入目前僅支援漢語拼音、國音二式、耶魯拼音、華羅拼音、通用拼音、韋氏拼音(威妥瑪拼音)

- 因為**韋氏拼音(威妥瑪拼音)輔音清濁不分的問題非常嚴重**、無法與注音符號形成逐一對應,故鐵恨引擎在技術上無法實現對韋氏拼音的支援
- 因為**趙元任國語羅馬字拼音「無法製作通用的聲調確認鍵」**,故鐵恨引擎在技術上無法實現對趙元任國語羅馬字拼音的支援

Regarding pinyin input support, we only support: Hanyu Pinyin, Secondary Pinyin, Yale Pinyin, Hualuo Pinyin, and Universal Pinyin.
Regarding pinyin input support, we only support: Hanyu Pinyin, Secondary Pinyin, Yale Pinyin, Hualuo Pinyin, Wade-Giles Pinyin and Universal Pinyin.

- **Tekkon is unable to provide Wade–Giles Pinyin support** since it is impossible to make one-to-one mappings to all possible phonabet combinations (especially it cannot distinguish "k" and "g").
- **Tekkon is unable to provide support for Zhao Yuan-Ren's Gwoyeu Romatzyh at this moment** because there is no consistent method to check whether the intonation key has been pressed. Tekkon is designed to confirm input with intonation keys.


## 著作權 (Credits)
Expand Down
2 changes: 1 addition & 1 deletion Tekkon.Tests/Tekkon.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<ReleaseVersion>1.3.2</ReleaseVersion>
<ReleaseVersion>1.4.0</ReleaseVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
56 changes: 56 additions & 0 deletions Tekkon.Tests/TekkonTests_Intermediate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -350,5 +350,61 @@ public void TestUniversalPinyinKeyReceivingAndCompositions() {
toneMarkerIndicator = composer.HasIntonation(withNothingElse: true);
Assert.True(toneMarkerIndicator);
}

[Test]
public void TestWadeGilesPinyinKeyReceivingAndCompositions() {
Composer composer = new(arrange: MandarinParser.OfWadeGilesPinyin);

// Test Key Receiving
composer.ReceiveKey(99); // c
composer.ReceiveKey("h");
composer.ReceiveKey("'"); // 韋氏拼音清濁分辨鍵
composer.ReceiveKey("i");
composer.ReceiveKey("u");
composer.ReceiveKey("n");
composer.ReceiveKey("g");

// Testing missing tone markers
bool toneMarkerIndicator = composer.HasIntonation();
Assert.True(!toneMarkerIndicator);

composer.ReceiveKey("2"); // 陽平
Assert.AreEqual(actual: composer.Value, expected: "ㄑㄩㄥˊ");
composer.DoBackSpace();
composer.ReceiveKey(" "); // 陰平
Assert.AreEqual(actual: composer.Value,
expected: "ㄑㄩㄥ "); // 這裡回傳的結果的陰平是空格

// Test Getting Displayed Composition
Assert.AreEqual(actual: composer.GetComposition(), expected: "ㄑㄩㄥ");
Assert.AreEqual(actual: composer.GetComposition(isHanyuPinyin: true),
expected: "qiong1");
Assert.AreEqual(actual: composer.GetComposition(isHanyuPinyin: true,
isTextBookStyle: true),
expected: "qiōng");
Assert.AreEqual(
actual: composer.GetInlineCompositionForDisplay(isHanyuPinyin: true),
expected: "ch'iung1");

// Test Tone 5
composer.ReceiveKey("7"); // 輕聲
Assert.AreEqual(actual: composer.GetComposition(), expected: "ㄑㄩㄥ˙");
Assert.AreEqual(actual: composer.GetComposition(isTextBookStyle: true),
expected: "˙ㄑㄩㄥ");

// Testing having tone markers
toneMarkerIndicator = composer.HasIntonation();
Assert.True(toneMarkerIndicator);

// Testing having not-only tone markers
toneMarkerIndicator = composer.HasIntonation(withNothingElse: true);
Assert.True(!toneMarkerIndicator);

// Testing having only tone markers
composer.Clear();
composer.ReceiveKey("3"); // 上聲
toneMarkerIndicator = composer.HasIntonation(withNothingElse: true);
Assert.True(toneMarkerIndicator);
}
}
}
2 changes: 1 addition & 1 deletion Tekkon.sln
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ Global
$0.DotNetNamingPolicy = $4
$4.DirectoryNamespaceAssociation = PrefixedHierarchical
$0.StandardHeader = $5
version = 1.3.2
version = 1.4.0
EndGlobalSection
EndGlobal
109 changes: 40 additions & 69 deletions Tekkon/Composer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,12 @@ public string GetInlineCompositionForDisplay(bool isHanyuPinyin = false) {
case MandarinParser.OfYalePinyin:
case MandarinParser.OfHualuoPinyin:
case MandarinParser.OfUniversalPinyin:
case MandarinParser.OfWadeGilesPinyin:
string toneReturned =
Intonation.Value switch { " " => "1", "ˊ" => "2", "ˇ" => "3",
"ˋ" => "4", "˙" => "5",
_ => "" };
return RomajiBuffer + toneReturned;
return RomajiBuffer.Replace("v", "ü") + toneReturned;
case MandarinParser.OfDachen:
case MandarinParser.OfDachen26:
case MandarinParser.OfETen:
Expand All @@ -127,6 +128,7 @@ public bool IsEmpty {
case MandarinParser.OfYalePinyin:
case MandarinParser.OfHualuoPinyin:
case MandarinParser.OfUniversalPinyin:
case MandarinParser.OfWadeGilesPinyin:
return Intonation.IsEmpty && RomajiBuffer == "";
case MandarinParser.OfDachen:
case MandarinParser.OfDachen26:
Expand Down Expand Up @@ -214,6 +216,8 @@ public bool InputValidityCheck(int inputCharCode) {
return Shared.MapFakeSeigyou.ContainsKey(inputKey.ToString());
case MandarinParser.OfStarlight:
return Shared.MapStarlightStaticKeys.ContainsKey(inputKey.ToString());
case MandarinParser.OfWadeGilesPinyin:
return Shared.MapWadeGilesPinyinKeys.Contains(inputKey);
case MandarinParser.OfHanyuPinyin:
case MandarinParser.OfSecondaryPinyin:
case MandarinParser.OfYalePinyin:
Expand Down Expand Up @@ -247,13 +251,15 @@ public void ReceiveKey(string input) {
case MandarinParser.OfYalePinyin:
case MandarinParser.OfHualuoPinyin:
case MandarinParser.OfUniversalPinyin:
case MandarinParser.OfWadeGilesPinyin:
if (Shared.MapArayuruPinyinIntonation.ContainsKey(input)) {
string theTone = Shared.MapArayuruPinyinIntonation[input];
Intonation = new(theTone);
} else {
// 為了防止 RomajiBuffer 越敲越長帶來算力負擔,
// 這裡讓它在要溢出時自動丟掉最早輸入的音頭。
if (RomajiBuffer.Length > 5) {
int maxCount = (Parser == MandarinParser.OfWadeGilesPinyin) ? 7 : 6;
if (RomajiBuffer.Length > maxCount - 1) {
RomajiBuffer = RomajiBuffer.Skip(1).ToString();
}
string romajiBufferBackup = RomajiBuffer + input;
Expand Down Expand Up @@ -381,74 +387,38 @@ public void ReceiveSequence(string givenSequence = "",
bool isRomaji = false) {
Clear();
if (!isRomaji) {
foreach (char key in givenSequence) {
ReceiveKey(key);
}
} else {
switch (Parser) {
case MandarinParser.OfHanyuPinyin:
string dictResult1 = "";
if (Shared.MapHanyuPinyin.ContainsKey(givenSequence))
dictResult1 = Shared.MapHanyuPinyin[givenSequence];
if (dictResult1 != "") {
foreach (char phonabet in dictResult1) {
ReceiveKeyFromPhonabet(phonabet.ToString());
}
}
break;
case MandarinParser.OfSecondaryPinyin:
string dictResult2 = "";
if (Shared.MapSecondaryPinyin.ContainsKey(givenSequence))
dictResult2 = Shared.MapSecondaryPinyin[givenSequence];
if (dictResult2 != "") {
foreach (char phonabet in dictResult2) {
ReceiveKeyFromPhonabet(phonabet.ToString());
}
}
break;
case MandarinParser.OfYalePinyin:
string dictResult3 = "";
if (Shared.MapYalePinyin.ContainsKey(givenSequence))
dictResult3 = Shared.MapYalePinyin[givenSequence];
if (dictResult3 != "") {
foreach (char phonabet in dictResult3) {
ReceiveKeyFromPhonabet(phonabet.ToString());
}
}
break;
case MandarinParser.OfHualuoPinyin:
string dictResult4 = "";
if (Shared.MapHualuoPinyin.ContainsKey(givenSequence))
dictResult4 = Shared.MapHualuoPinyin[givenSequence];
if (dictResult4 != "") {
foreach (char phonabet in dictResult4) {
ReceiveKeyFromPhonabet(phonabet.ToString());
}
}
break;
case MandarinParser.OfUniversalPinyin:
string dictResult5 = "";
if (Shared.MapUniversalPinyin.ContainsKey(givenSequence))
dictResult5 = Shared.MapUniversalPinyin[givenSequence];
if (dictResult5 != "") {
foreach (char phonabet in dictResult5) {
ReceiveKeyFromPhonabet(phonabet.ToString());
}
}
break;
case MandarinParser.OfDachen:
case MandarinParser.OfDachen26:
case MandarinParser.OfETen:
case MandarinParser.OfETen26:
case MandarinParser.OfHsu:
case MandarinParser.OfIBM:
case MandarinParser.OfMiTAC:
case MandarinParser.OfSeigyou:
case MandarinParser.OfFakeSeigyou:
default:
break;
}
foreach (char key in givenSequence) ReceiveKey(key);
return;
}
string dictResult = "";
switch (Parser) {
case MandarinParser.OfHanyuPinyin:
if (Shared.MapHanyuPinyin.ContainsKey(givenSequence))
dictResult = Shared.MapHanyuPinyin[givenSequence];
break;
case MandarinParser.OfSecondaryPinyin:
if (Shared.MapSecondaryPinyin.ContainsKey(givenSequence))
dictResult = Shared.MapSecondaryPinyin[givenSequence];
break;
case MandarinParser.OfYalePinyin:
if (Shared.MapYalePinyin.ContainsKey(givenSequence))
dictResult = Shared.MapYalePinyin[givenSequence];
break;
case MandarinParser.OfHualuoPinyin:
if (Shared.MapHualuoPinyin.ContainsKey(givenSequence))
dictResult = Shared.MapHualuoPinyin[givenSequence];
break;
case MandarinParser.OfUniversalPinyin:
if (Shared.MapUniversalPinyin.ContainsKey(givenSequence))
dictResult = Shared.MapUniversalPinyin[givenSequence];
break;
case MandarinParser.OfWadeGilesPinyin:
if (Shared.MapWadeGilesPinyin.ContainsKey(givenSequence))
dictResult = Shared.MapWadeGilesPinyin[givenSequence];
break;
}
foreach (char phonabet in dictResult)
ReceiveKeyFromPhonabet(phonabet.ToString());
}

/// <summary>
Expand Down Expand Up @@ -549,6 +519,7 @@ private string Translate(string key) {
case MandarinParser.OfYalePinyin:
case MandarinParser.OfHualuoPinyin:
case MandarinParser.OfUniversalPinyin:
case MandarinParser.OfWadeGilesPinyin:
default:
break;
}
Expand Down
4 changes: 3 additions & 1 deletion Tekkon/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ public enum MandarinParser {
/// <summary>拼音:華羅拼音排列。</summary>
OfHualuoPinyin = 103,
/// <summary>拼音:通用拼音排列。</summary>
OfUniversalPinyin = 104
OfUniversalPinyin = 104,
/// <summary>拼音:韋氏拼音排列。</summary>
OfWadeGilesPinyin = 105
// C# 似乎不支援在這裡直接給一個動態 var。
// 所以,針對每個輸入模式的 token 轉換需要寫在輸入法內。
}
Expand Down
Loading

0 comments on commit 8cb9edf

Please sign in to comment.