shuang_pin_tutorial 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +42 -0
- data/exe/shuang_pin_tutorial +10 -0
- data/lib/shuang_pin_tutorial/data.rb +264 -0
- data/lib/shuang_pin_tutorial/handler.rb +136 -0
- data/lib/shuang_pin_tutorial/main.rb +37 -0
- data/lib/shuang_pin_tutorial.rb +21 -0
- metadata +57 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e4a10efd89f18dd8b4cd10dd74e7f3fcda75c89765b7fadea755e17f560b3847
|
4
|
+
data.tar.gz: f88c8a9c0a893c4d89247cd79d90147444a61d4c73386d57324d96cb891c59ad
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f710a194ea96bae7d148e17017fef7c0514a7fc2ab3d15b832a7788775838cf3815ea23d38cf405f17b8c53fc68789b9d68ff0e96ab1d64d46016eea1ad760d1
|
7
|
+
data.tar.gz: 69b963816a2c38794280ee9882de3d8200543d3222de3f7c8320102803f6a72edd17f853868196e986b8bdd0ab8c012c00274623f96cdd7d7a69803b374482ac
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2020 David N
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# 幫助你快速學習雙拼 —— 微軟雙拼(繁體中文版)
|
2
|
+
|
3
|
+
### 程序簡介:
|
4
|
+
|
5
|
+
一個萌妹子風格的輸入法學習套件,參考新華字典的設定,每次隨機出現出合理的拼音組合。<br>
|
6
|
+
根據輸出的拼音組合中打出對應的雙拼,每個字用空格隔開,按 Enter 提交,輸入 ```exit``` 提交或者按下 Ctrl+c 退出練習。
|
7
|
+
|
8
|
+
快速學習雙拼 程序畫面:\
|
9
|
+
![image][shuang_pin_tutorial_console]
|
10
|
+
|
11
|
+
微軟雙拼鍵盤方案圖:\
|
12
|
+
![image][shuang_pin_keyboard]
|
13
|
+
|
14
|
+
<br>另外,[參考文件夾][folder_img]中附上:
|
15
|
+
|
16
|
+
* [普通話聲韻配合表][pthtable]
|
17
|
+
* [漢語拼音與通用拼音對照表][shuang_pin_200_words_sample]
|
18
|
+
* [雙拼鍵盤口訣][shuang_pin_keyboard_quote]
|
19
|
+
* [速成雙拼需學200字][zhuyin_pinyin_conversion_table]
|
20
|
+
|
21
|
+
---
|
22
|
+
|
23
|
+
### 執行步驟:
|
24
|
+
|
25
|
+
如果沒有安裝 Ruby 的情況下,需要先[安裝 Ruby][rubychina_install_ruby]。
|
26
|
+
|
27
|
+
安裝與運行:
|
28
|
+
```bash
|
29
|
+
gem install shuang_pin_tutorial # 透過 Gem 安裝學習雙拼套件
|
30
|
+
|
31
|
+
shuang_pin_tutorial # 運行套件
|
32
|
+
```
|
33
|
+
|
34
|
+
[shuang_pin_tutorial_console]: ./img/shuang_pin_tutorial_console.png "shuang pin tutorial console"
|
35
|
+
[shuang_pin_keyboard]: ./img/shuang_pin_keyboard.png "shuang pin keyboard"
|
36
|
+
[rubychina_install_ruby]: https://ruby-china.org/wiki/install_ruby_guide "ruby-china install ruby method"
|
37
|
+
|
38
|
+
[folder_img]: https://github.com/jsdnhk/shuang-pin-tutorial-tw/tree/master/ref
|
39
|
+
[pthtable]: ./ref/PTHtable_cuhk.pdf
|
40
|
+
[shuang_pin_200_words_sample]: ./ref/shuang_pin_200_words_sample.txt
|
41
|
+
[shuang_pin_keyboard_quote]: ./ref/shuang_pin_keyboard_quote.txt
|
42
|
+
[zhuyin_pinyin_conversion_table]: ./ref/zhuyin_pinyin_conversion_table.pdf
|
@@ -0,0 +1,264 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module ShuangPinTutorial
|
4
|
+
class Data
|
5
|
+
# 聲母列表 23 個 + 一個特殊的聲母 o 用來輸入單音節的韻母字
|
6
|
+
SHENG_MU = {
|
7
|
+
# 雙唇、齒唇音
|
8
|
+
b: "ㄅ", p: "ㄆ", m: "ㄇ", f: "ㄈ",
|
9
|
+
# 舌尖中音
|
10
|
+
d: "ㄉ", t: "ㄊ", n: "ㄋ", l: "ㄌ",
|
11
|
+
# 舌根音
|
12
|
+
g: "ㄍ", k: "ㄎ", h: "ㄏ",
|
13
|
+
# 舌面前音
|
14
|
+
j: "ㄐ", q: "ㄑ", x: "ㄒ",
|
15
|
+
# 舌尖後音
|
16
|
+
zh: "ㄓ", ch: "ㄔ", sh: "ㄕ", r: "ㄖ",
|
17
|
+
# 舌尖前音
|
18
|
+
z: "ㄗ", c: "ㄘ", s: "ㄙ",
|
19
|
+
# 無聲母
|
20
|
+
y: "ㄧ", w: "ㄨ", o: ""
|
21
|
+
}
|
22
|
+
|
23
|
+
# 韻母列表 35 個
|
24
|
+
YUN_MU = {
|
25
|
+
# 開口呼
|
26
|
+
a: "ㄚ", o: "ㄛ", e: "ㄜ", er: "ㄦ",
|
27
|
+
ai: "ㄞ", ei: "ㄟ", ao: "ㄠ", ou: "ㄡ",
|
28
|
+
an: "ㄢ", en: "ㄣ", ang: "ㄤ", eng: "ㄥ",
|
29
|
+
# 齊齒呼
|
30
|
+
i: "ㄧ", ia: "ㄧㄚ", ie: "ㄧㄝ", iao: "ㄧㄠ",
|
31
|
+
iu: "ㄧㄡ", ian: "ㄧㄢ", in: "ㄧㄣ", iang: "ㄧㄤ",
|
32
|
+
ing: "ㄧㄥ",
|
33
|
+
# 合口呼
|
34
|
+
u: "ㄨ", ua: "ㄨㄚ", uo: "ㄨㄛ", uai: "ㄨㄞ",
|
35
|
+
ui: "ㄨㄟ", uan: "ㄨㄢ", un: "ㄨㄣ", uang: "ㄨㄤ",
|
36
|
+
ong: "ㄨㄥ",
|
37
|
+
# 撮口呼
|
38
|
+
ü: "ㄩ", üe: "ㄩㄝ", üan: "ㄩㄢ", ün: "ㄩㄣ",
|
39
|
+
iong: "ㄩㄥ"
|
40
|
+
}
|
41
|
+
|
42
|
+
=begin
|
43
|
+
'y' and 'w' is not included because 'ㄧ' and 'ㄨ' are already
|
44
|
+
mapped to 'i' and 'u'
|
45
|
+
"ㄧ": "y", "ㄨ": "w",
|
46
|
+
=end
|
47
|
+
|
48
|
+
# 聲母對應合法的韻母組合
|
49
|
+
LEGAL_COMPOSITE = {
|
50
|
+
:b => %w(a ai an ang ao ei en eng i ian iao ie in ing o u),
|
51
|
+
:p => %w(a ai an ang ao ei en eng i ian iao ie in ing o ou u),
|
52
|
+
:m => %w(a ai an ang ao e ei en eng i ian iao ie in ing iu o ou u),
|
53
|
+
:f => %w(a an ang ei en eng o ou u),
|
54
|
+
:d => %w(a ai an ang ao e ei eng i ian iao ie ing iu ong ou u uan ui un uo),
|
55
|
+
:t => %w(a ai an ang ao e eng i ian iao ie ing ong ou u uan ui un uo),
|
56
|
+
:n => %w(a ai an ang ao e ei en eng i ian iang iao ie in ing iu ong u uan uo ü üe),
|
57
|
+
:l => %w(a ai an ang ao e ei eng i ia ian iang iao ie in ing iu ong ou u uan un uo ü üe),
|
58
|
+
:g => %w(a ai an ang ao e ei en eng ong ou u ua uai uan uang ui un uo),
|
59
|
+
:k => %w(a ai an ang ao e en eng ong ou u ua uai uan uang ui un uo),
|
60
|
+
:h => %w(a ai an ang ao e ei en eng ong ou u ua uai uan uang ui un uo),
|
61
|
+
:j => %w(i ia ian iang iao ie in ing iu u üe üan ün iong), # ü as u
|
62
|
+
:q => %w(i ia ian iang iao ie in ing iu u üe üan ün iong), # ü as u
|
63
|
+
:x => %w(i ia ian iang iao ie in ing iu u üe üan ün iong), # ü as u
|
64
|
+
:zh => %w(a ai an ang ao e ei en eng i ong ou u ua uai uan uang ui un uo),
|
65
|
+
:ch => %w(a ai an ang ao e en eng i ong ou u uai uan uang ui un uo),
|
66
|
+
:sh => %w(a ai an ang ao e ei en eng i ou u ua uai uan uang ui un uo),
|
67
|
+
:r => %w(an ang ao e en eng i ong ou u uan ui un uo),
|
68
|
+
:z => %w(a ai an ang ao e ei en eng i ong ou u uan ui un uo),
|
69
|
+
:c => %w(a ai an ang ao e en eng i ong ou u uan ui un uo),
|
70
|
+
:s => %w(a ai an ang ao e en eng i ong ou u uan ui un uo),
|
71
|
+
:y => %w(a an ang ao e i in ing ong ou u üan üe ün), # ü as u
|
72
|
+
:w => %w(a ai an ang ei en eng o u),
|
73
|
+
:o => %w(a o e an ao ai ei en eng er ang ou)
|
74
|
+
}
|
75
|
+
|
76
|
+
# 普通話聲韻配合表
|
77
|
+
SHENG_YUN_WORD_TABLE = {
|
78
|
+
:b => {:a=>"巴", :o=>"玻", :ai=>"白", :ei=>"杯", :ao=>"包", :an=>"般", :en=>"奔", :ang=>"幫", :eng=>"崩", :i=>"逼", :ie=>"別", :iao=>"標", :ian=>"邊", :in=>"濱", :ing=>"冰", :u=>"不"},
|
79
|
+
:p => {:a=>"趴", :o=>"坡", :ai=>"拍", :ei=>"培", :ao=>"拋", :ou=>"剖", :an=>"潘", :en=>"噴", :ang=>"旁", :eng=>"烹", :i=>"批", :ie=>"撇", :iao=>"飄", :ian=>"篇", :in=>"拼", :ing=>"乒", :u=>"鋪"},
|
80
|
+
:m => {:a=>"媽", :o=>"摸", :e=>"麼", :ai=>"埋", :ei=>"眉", :ao=>"貓", :ou=>"謀", :an=>"蠻", :en=>"悶", :ang=>"忙", :eng=>"盟", :i=>"迷", :ie=>"滅", :iao=>"苗", :iu=>"謬", :ian=>"棉", :in=>"民", :ing=>"明", :u=>"木"},
|
81
|
+
:f => {:a=>"發", :o=>"佛", :ei=>"飛", :ou=>"否", :an=>"翻", :en=>"分", :ang=>"方", :eng=>"風", :u=>"夫"},
|
82
|
+
:d => {:a=>"搭", :e=>"得", :ai=>"呆", :ei=>"得", :ao=>"刀", :ou=>"兜", :an=>"單", :ang=>"當", :eng=>"登", :i=>"低", :ie=>"爹", :iao=>"雕", :iu=>"丟", :ian=>"顛", :ing=>"㆜", :u=>"都", :uo=>"多", :ui=>"堆", :uan=>"端", :un=>"蹲", :ong=>"東"},
|
83
|
+
:t => {:a=>"他", :e=>"特", :ai=>"胎", :ao=>"滔", :ou=>"偷", :an=>"攤", :ang=>"湯", :eng=>"疼", :i=>"梯", :ie=>"貼", :iao=>"挑", :ian=>"㆝", :ing=>"聽", :u=>"禿", :uo=>"脫", :ui=>"推", :uan=>"團", :un=>"吞", :ong=>"通"},
|
84
|
+
:n => {:a=>"拿", :e=>"訥", :ai=>"奶", :ei=>"內", :ao=>"腦", :an=>"南", :en=>"嫩", :ang=>"囊", :eng=>"能", :i=>"泥", :ie=>"捏", :iao=>"鳥", :iu=>"牛", :ian=>"年", :in=>"您", :iang=>"娘", :ing=>"寧", :u=>"奴", :uo=>"挪", :uan=>"暖", :ong=>"農", :ü=>"女", :üe=>"虐"},
|
85
|
+
:l => {:a=>"拉", :e=>"勒", :ai=>"來", :ei=>"累", :ao=>"老", :ou=>"樓", :an=>"蘭", :ang=>"郎", :eng=>"冷", :i=>"黎", :ia=>"倆", :ie=>"列", :iao=>"了", :iu=>"流", :ian=>"連", :in=>"林", :iang=>"涼", :ing=>"零", :u=>"爐", :uo=>"鑼", :uan=>"亂", :un=>"輪", :ong=>"龍", :ü=>"呂", :üe=>"略"},
|
86
|
+
:g => {:a=>"嘎", :e=>"哥", :ai=>"該", :ei=>"給", :ao=>"高", :ou=>"溝", :an=>"甘", :en=>"根", :ang=>"剛", :eng=>"更", :u=>"姑", :ua=>"瓜", :uo=>"鍋", :uai=>"拐", :ui=>"規", :uan=>"關", :un=>"滾", :uang=>"光", :ong=>"工"},
|
87
|
+
:k => {:a=>"咖", :e=>"科", :ai=>"開", :ao=>"考", :ou=>"口", :an=>"刊", :en=>"肯", :ang=>"康", :eng=>"坑", :u=>"枯", :ua=>"誇", :uo=>"闊", :uai=>"快", :ui=>"虧", :uan=>"寬", :un=>"昆", :uang=>"筐", :ong=>"空"},
|
88
|
+
:h => {:a=>"哈", :e=>"喝", :ai=>"海", :ei=>"黑", :ao=>"好", :ou=>"後", :an=>"寒", :en=>"很", :ang=>"杭", :eng=>"哼", :u=>"呼", :ua=>"花", :uo=>"火", :uai=>"懷", :ui=>"灰", :uan=>"歡", :un=>"婚", :uang=>"荒", :ong=>"轟"},
|
89
|
+
:j => {:i=>"基", :ia=>"家", :ie=>"街", :iao=>"交", :iu=>"究", :ian=>"堅", :in=>"今", :iang=>"江", :ing=>"京", :u=>"居", :üe=>"決", :üan=>"捐", :ün=>"軍", :iong=>"窘"},
|
90
|
+
:q => {:i=>"欺", :ia=>"搯", :ie=>"切", :iao=>"敲", :iu=>"秋", :ian=>"千", :in=>"親", :iang=>"腔", :ing=>"清", :u=>"區", :üe=>"缺", :üan=>"圈", :ün=>"群", :iong=>"窮"},
|
91
|
+
:x => {:i=>"希", :ia=>"瞎", :ie=>"些", :iao=>"消", :iu=>"休", :ian=>"先", :in=>"新", :iang=>"香", :ing=>"星", :u=>"虛", :üe=>"靴", :üan=>"宣", :ün=>"詢", :iong=>"兄"},
|
92
|
+
:zh => {:a=>"渣", :e=>"遮", :i=>"知", :ai=>"窄", :ei=>"這", :ao=>"招", :ou=>"周", :an=>"沾", :en=>"真", :ang=>"張", :eng=>"爭", :u=>"珠", :ua=>"抓", :uo=>"桌", :uai=>"拽", :ui=>"追", :uan=>"專", :un=>"準", :uang=>"裝", :ong=>"㆗"},
|
93
|
+
:ch => {:a=>"插", :e=>"車", :i=>"吃", :ai=>"拆", :ao=>"超", :ou=>"抽", :an=>"攙", :en=>"陳", :ang=>"昌", :eng=>"稱", :u=>"初", :uo=>"戳", :uai=>"揣", :ui=>"吹", :uan=>"穿", :un=>"春", :uang=>"窗", :ong=>"充"},
|
94
|
+
:sh => {:a=>"沙", :e=>"奢", :i=>"詩", :ai=>"篩", :ei=>"誰", :ao=>"燒", :ou=>"收", :an=>"山", :en=>"伸", :ang=>"傷", :eng=>"生", :u=>"書", :ua=>"刷", :uo=>"說", :uai=>"衰", :ui=>"水", :uan=>"栓", :un=>"順", :uang=>"雙"},
|
95
|
+
:r => {:e=>"熱", :i=>"日", :ao=>"繞", :ou=>"柔", :an=>"然", :en=>"㆟", :ang=>"讓", :eng=>"扔", :u=>"如", :uo=>"若", :ui=>"瑞", :uan=>"軟", :un=>"潤", :ong=>"榮"},
|
96
|
+
:z => {:a=>"雜", :e=>"則", :i=>"資", :ai=>"災", :ei=>"賊", :ao=>"遭", :ou=>"鄒", :an=>"咱", :en=>"怎", :ang=>"髒", :eng=>"增", :u=>"租", :uo=>"昨", :ui=>"最", :uan=>"鑽", :un=>"尊", :ong=>"宗"},
|
97
|
+
:c => {:a=>"擦", :e=>"測", :i=>"雌", :ai=>"猜", :ao=>"曹", :ou=>"湊", :an=>"參", :en=>"岑", :ang=>"倉", :eng=>"層", :u=>"粗", :uo=>"錯", :ui=>"催", :uan=>"篡", :un=>"村", :ong=>"聰"},
|
98
|
+
:s => {:a=>"撒", :e=>"色", :i=>"私", :ai=>"腮", :ao=>"搔", :ou=>"搜", :an=>"㆔", :en=>"森", :ang=>"桑", :eng=>"僧", :u=>"蘇", :uo=>"索", :ui=>"雖", :uan=>"酸", :un=>"孫", :ong=>"鬆"},
|
99
|
+
:y => {:i=>"衣", :a=>"呀", :e=>"耶", :ao=>"腰", :ou=>"優", :an=>"煙", :in=>"因", :ang=>"央", :ing=>"英", :u=>"迂", :üe=>"約", :üan=>"冤", :ün=>"暈", :ong=>"庸"},
|
100
|
+
:w => {:u=>"烏", :a=>"蛙", :o=>"窩", :ai=>"歪", :ei=>"威", :an=>"彎", :en=>"溫", :ang=>"汪", :eng=>"翁"},
|
101
|
+
:o => {:a=>"啊", :o=>"喔", :e=>"鵝", :er=>"兒", :ai=>"哀", :ei=>"欸", :ao=>"熬", :ou=>"歐", :an=>"安", :en=>"恩", :ang=>"昂", :eng=>"鞥"}
|
102
|
+
}
|
103
|
+
|
104
|
+
# 每個按鍵對應的雙拼表
|
105
|
+
VALID_COMPOSITE = {
|
106
|
+
:Q => %w(q iu),
|
107
|
+
:W => %w(w ia ua),
|
108
|
+
:E => %w(e),
|
109
|
+
:R => %w(r uan üan er),
|
110
|
+
:T => %w(t ue üe),
|
111
|
+
:Y => %w(y uai), #also accept ü, but by 'v' button in general
|
112
|
+
:U => %w(u sh),
|
113
|
+
:I => %w(i ch),
|
114
|
+
:O => %w(o uo),
|
115
|
+
:P => %w(p un ün),
|
116
|
+
:A => %w(a),
|
117
|
+
:S => %w(s ong iong),
|
118
|
+
:D => %w(d uang iang),
|
119
|
+
:F => %w(f en),
|
120
|
+
:G => %w(g eng),
|
121
|
+
:H => %w(h ang),
|
122
|
+
:J => %w(j an),
|
123
|
+
:K => %w(k ao),
|
124
|
+
:L => %w(l ai),
|
125
|
+
:';' => %w(ing),
|
126
|
+
:Z => %w(z ei),
|
127
|
+
:X => %w(x ie),
|
128
|
+
:C => %w(c iao),
|
129
|
+
:V => %w(zh ui ü),
|
130
|
+
:B => %w(b ou),
|
131
|
+
:N => %w(n in),
|
132
|
+
:M => %w(m ian),
|
133
|
+
}
|
134
|
+
|
135
|
+
def initialize()
|
136
|
+
SHENG_MU.freeze
|
137
|
+
YUN_MU.freeze
|
138
|
+
LEGAL_COMPOSITE.freeze
|
139
|
+
SHENG_YUN_WORD_TABLE.freeze
|
140
|
+
VALID_COMPOSITE.freeze
|
141
|
+
end
|
142
|
+
|
143
|
+
# 提取隨機文字部分
|
144
|
+
def get_rand_sheng_yun_sym()
|
145
|
+
sheng = SHENG_MU.keys.sample.to_sym
|
146
|
+
yun = LEGAL_COMPOSITE[sheng].sample.to_sym
|
147
|
+
[sheng, yun]
|
148
|
+
end
|
149
|
+
|
150
|
+
def get_sheng_yun_zy(sheng, yun)
|
151
|
+
sheng_zy = SHENG_MU[sheng.to_sym].to_s.strip
|
152
|
+
yun_zy = YUN_MU[yun.to_sym].to_s.strip
|
153
|
+
[sheng_zy, yun_zy]
|
154
|
+
end
|
155
|
+
|
156
|
+
def get_zy(sheng, yun) #sheng, yun: sym
|
157
|
+
shengyun = get_sy(sheng, yun)
|
158
|
+
sheng_zy, yun_zy = get_sheng_yun_zy(sheng, yun)
|
159
|
+
case shengyun # special cases for zhuyin required to fine-adjust
|
160
|
+
when 'zhi'
|
161
|
+
SHENG_MU[:zh]
|
162
|
+
when 'chi'
|
163
|
+
SHENG_MU[:ch]
|
164
|
+
when 'shi'
|
165
|
+
SHENG_MU[:sh]
|
166
|
+
when 'ri'
|
167
|
+
SHENG_MU[:r]
|
168
|
+
when 'zi'
|
169
|
+
SHENG_MU[:z]
|
170
|
+
when 'ci'
|
171
|
+
SHENG_MU[:c]
|
172
|
+
when 'si'
|
173
|
+
SHENG_MU[:s]
|
174
|
+
when 'yu', 'yü'
|
175
|
+
YUN_MU[:ü]
|
176
|
+
when 'yuan', 'yüan'
|
177
|
+
YUN_MU[:üan]
|
178
|
+
when 'yue', 'yüe'
|
179
|
+
YUN_MU[:üe]
|
180
|
+
when 'yun', 'yün'
|
181
|
+
YUN_MU[:ün]
|
182
|
+
when 'yong'
|
183
|
+
YUN_MU[:iong]
|
184
|
+
when 'ju', 'jü', 'qu', 'qü', 'xu', 'xü'
|
185
|
+
(SHENG_MU[sheng] + YUN_MU[:ü]).chars.uniq.join
|
186
|
+
else
|
187
|
+
(sheng_zy + yun_zy).chars.uniq.join
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def get_sy(sheng, yun) #sheng, yun: sym
|
192
|
+
(sheng.to_s.strip + yun.to_s.strip).sub(/^o/,'')
|
193
|
+
end
|
194
|
+
|
195
|
+
def get_cw(sheng, yun) #sheng, yun: sym
|
196
|
+
cw = SHENG_YUN_WORD_TABLE.fetch(sheng.to_sym).fetch(yun.to_sym) rescue puts("內部錯誤:資料中查無此字 【#{sheng}#{yun}】")
|
197
|
+
cw ||= ''
|
198
|
+
end
|
199
|
+
|
200
|
+
# 計算拼音輸入碼答案部分
|
201
|
+
# recursive way
|
202
|
+
def get_correct_keys(input_pinyin)
|
203
|
+
return get_correct_keys_helper(input_pinyin, 2)
|
204
|
+
end
|
205
|
+
|
206
|
+
def get_correct_keys_helper(input_pinyin, output_keys)
|
207
|
+
press_keys = nil
|
208
|
+
input_pinyin = input_pinyin.downcase.strip
|
209
|
+
if output_keys == 0
|
210
|
+
return press_keys.to_s
|
211
|
+
elsif output_keys == 1
|
212
|
+
VALID_COMPOSITE.each do |key, value|
|
213
|
+
press_keys = key.to_s if value.include?(input_pinyin)
|
214
|
+
break if press_keys
|
215
|
+
end
|
216
|
+
return press_keys.to_s
|
217
|
+
elsif output_keys == 2
|
218
|
+
if LEGAL_COMPOSITE[:o].include?(input_pinyin) # 韻母單音節字
|
219
|
+
press_keys = 'O' + get_correct_keys_helper(input_pinyin, 1)
|
220
|
+
elsif input_pinyin.start_with?('zh', 'ch', 'sh')
|
221
|
+
press_keys = get_correct_keys_helper(input_pinyin[0,2], 1) + get_correct_keys_helper(input_pinyin[2..input_pinyin.length], 1)
|
222
|
+
else
|
223
|
+
press_keys = get_correct_keys_helper(input_pinyin[0,1], 1) + get_correct_keys_helper(input_pinyin[1..input_pinyin.length], 1)
|
224
|
+
end
|
225
|
+
else
|
226
|
+
raise(RangeError, '未需支援兩個以上拼音碼')
|
227
|
+
end
|
228
|
+
press_keys.to_s
|
229
|
+
end
|
230
|
+
|
231
|
+
=begin
|
232
|
+
# iterative way
|
233
|
+
def get_correct_keys(input_pinyin)
|
234
|
+
press_keys=''
|
235
|
+
input_pinyin = input_pinyin.downcase.strip
|
236
|
+
if LEGAL_COMPOSITE[:o].include?(input_pinyin)
|
237
|
+
# 韻母單音節字
|
238
|
+
press_keys << 'O'
|
239
|
+
get_a_press_key(input_pinyin, press_keys) # yun only
|
240
|
+
return press_keys
|
241
|
+
end
|
242
|
+
|
243
|
+
if input_pinyin.start_with?('zh', 'ch', 'sh')
|
244
|
+
get_a_press_key(input_pinyin[0,2], press_keys) # sheng
|
245
|
+
get_a_press_key(input_pinyin[2,input_pinyin.length], press_keys) # yun
|
246
|
+
else
|
247
|
+
get_a_press_key(input_pinyin[0,1], press_keys) # sheng
|
248
|
+
get_a_press_key(input_pinyin[1,input_pinyin.length], press_keys) # yun
|
249
|
+
end
|
250
|
+
|
251
|
+
press_keys
|
252
|
+
end
|
253
|
+
|
254
|
+
def get_a_press_key(word, press_keys)
|
255
|
+
VALID_COMPOSITE.each do |key, value|
|
256
|
+
if value.include?(word)
|
257
|
+
press_keys << key.to_s
|
258
|
+
break
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
=end
|
263
|
+
end
|
264
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
require_relative 'data'
|
5
|
+
|
6
|
+
module ShuangPinTutorial
|
7
|
+
INT_WORDS_DISPLAYED = 6
|
8
|
+
STR_TIPS_SEPARATOR='———'
|
9
|
+
IS_ENABLE_TIPS = true
|
10
|
+
IS_DISPLAY_ZHUYIN = true
|
11
|
+
IS_DISPLAY_CWORD = true
|
12
|
+
|
13
|
+
class Handler
|
14
|
+
def initialize()
|
15
|
+
end
|
16
|
+
|
17
|
+
def start()
|
18
|
+
# 初始化
|
19
|
+
@sp_data = Data.new()
|
20
|
+
@words_counts = [0, 0, 0]
|
21
|
+
@start_time = DateTime.now
|
22
|
+
@end_time = nil
|
23
|
+
puts "歡迎使用 快速學習雙拼 -- 微軟雙拼(繁體中文版)!要好好練習哦!(#{VERSION} 版)"
|
24
|
+
puts "要輸入下面中文字對應雙拼字碼哦!使用空格隔開,要休息請輸入 'exit' 或按 Ctrl+c 吧!\n"
|
25
|
+
# looping
|
26
|
+
while true
|
27
|
+
result = get_question_lines
|
28
|
+
result_words = result[0]
|
29
|
+
result_display = result[1]
|
30
|
+
print "\n#{result_display.join("\n")}\n"
|
31
|
+
|
32
|
+
input_answers = gets
|
33
|
+
|
34
|
+
if input_answers.respond_to?(:to_str)
|
35
|
+
raise(Interrupt, "用戶退出") if input_answers.strip.downcase == 'exit'
|
36
|
+
eval_result(input_answers, result_words)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_words_showlines(num = INT_WORDS_DISPLAYED, display_delim: "|") # return [words(str), [display line(s)]]
|
42
|
+
result = []
|
43
|
+
display = []
|
44
|
+
display_py = []
|
45
|
+
display_zy = []
|
46
|
+
display_cw = []
|
47
|
+
num.times do
|
48
|
+
sheng, yun = @sp_data.get_rand_sheng_yun_sym()
|
49
|
+
shengyun = @sp_data.get_sy(sheng, yun)
|
50
|
+
zy = @sp_data.get_zy(sheng, yun)
|
51
|
+
cw = @sp_data.get_cw(sheng, yun)
|
52
|
+
result.push(shengyun)
|
53
|
+
display_py.push(shengyun + "\t")
|
54
|
+
display_zy.push(zy + "\t")
|
55
|
+
display_cw.push(cw + "\t")
|
56
|
+
end
|
57
|
+
display << display_py.join(display_delim)
|
58
|
+
display << display_zy.join(display_delim) if IS_DISPLAY_ZHUYIN
|
59
|
+
display << display_cw.join(display_delim) if IS_DISPLAY_CWORD
|
60
|
+
[result.join(" "), display]
|
61
|
+
end
|
62
|
+
|
63
|
+
def eval_result(input_answer, result_words)
|
64
|
+
# 尋找打錯了的字
|
65
|
+
incorrect = {}
|
66
|
+
correct = 0
|
67
|
+
is_all_finished = input_answer.split.length >= result_words.split.length
|
68
|
+
input_answer.split.each_with_index do |input_keys, index|
|
69
|
+
break if index >= result_words.split.length # ignore the extra input part
|
70
|
+
|
71
|
+
if input_keys.length != 2
|
72
|
+
incorrect[index + 1] = "#{input_keys}: 雙拼只能由兩個字母組合而成!"
|
73
|
+
next
|
74
|
+
end
|
75
|
+
|
76
|
+
res = result_words.split[index]
|
77
|
+
right_answer = @sp_data.get_correct_keys(res)
|
78
|
+
unless right_answer.casecmp(input_keys.to_s) == 0
|
79
|
+
incorrect[index + 1] = "#{input_keys}: 不能得到 #{res} 哦!或許你可以試試 #{right_answer}"
|
80
|
+
else
|
81
|
+
correct += 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# 編出成績
|
86
|
+
@words_counts[0] += result_words.split.length
|
87
|
+
@words_counts[1] += correct
|
88
|
+
@words_counts[2] += result_words.split.length - correct
|
89
|
+
|
90
|
+
if !is_all_finished
|
91
|
+
puts "你好像寫不齊哦!共有:#{result_words.split.length},已輸入:#{input_answer.split.length}"
|
92
|
+
elsif incorrect.length == 0
|
93
|
+
puts '恭喜你全對耶!'
|
94
|
+
end
|
95
|
+
incorrect.each { |key, value| puts "#{key}) 錯誤 => #{value}"}
|
96
|
+
end
|
97
|
+
|
98
|
+
def get_question_lines
|
99
|
+
result = get_words_showlines
|
100
|
+
result_words = result[0]
|
101
|
+
result_display = result[1]
|
102
|
+
result_tips = []
|
103
|
+
if IS_ENABLE_TIPS
|
104
|
+
result_words.split.each { |res| result_tips.push(@sp_data.get_correct_keys(res)) }
|
105
|
+
result_display[0] = "#{result_display[0]} #{STR_TIPS_SEPARATOR} 【#{result_tips.join(" ")}】"
|
106
|
+
end
|
107
|
+
result
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_total_time_str
|
111
|
+
@end_time = DateTime.now
|
112
|
+
@total_time = ((@end_time - @start_time) * 24 * 60 * 60).to_i
|
113
|
+
str_total_time_s = Time.at(@total_time).utc.strftime("%S").gsub(/^0/, '')
|
114
|
+
str_total_time_m = Time.at(@total_time).utc.strftime("%M").gsub(/^0/, '')
|
115
|
+
str_total_time_h = Time.at(@total_time).utc.strftime("%H").gsub(/^0+/, '')
|
116
|
+
str_total_time =
|
117
|
+
case @total_time
|
118
|
+
when 0...60
|
119
|
+
"#{str_total_time_s} 秒"
|
120
|
+
when 60...3600
|
121
|
+
"#{str_total_time_m} 分 #{str_total_time_s} 秒"
|
122
|
+
else
|
123
|
+
"#{str_total_time_h} 小時 #{str_total_time_m} 分 #{str_total_time_s} 秒"
|
124
|
+
end
|
125
|
+
str_total_time
|
126
|
+
end
|
127
|
+
|
128
|
+
def get_total_words_result
|
129
|
+
percent_correctness = @words_counts[0].to_f != 0 ? (@words_counts[1].to_f/@words_counts[0].to_f) * 100 : 0
|
130
|
+
str_output = ""
|
131
|
+
str_output += "共有字數: #{@words_counts[0]} 字;正確字數: #{@words_counts[1]} 字;錯誤字數: #{@words_counts[2]} 字" + "\n"
|
132
|
+
str_output += "總正確率: #{percent_correctness.round(2)} %"
|
133
|
+
str_output
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require_relative 'handler'
|
5
|
+
|
6
|
+
module ShuangPinTutorial
|
7
|
+
class Main
|
8
|
+
def initialize()
|
9
|
+
@is_run_success = true
|
10
|
+
@obj_tutorial = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def run()
|
14
|
+
@obj_tutorial = Handler.new()
|
15
|
+
@obj_tutorial.start()
|
16
|
+
rescue Interrupt => ir
|
17
|
+
$stdout.puts('累了就該休息一下吧!')
|
18
|
+
rescue Exception => ex
|
19
|
+
$stderr.puts('執行時發生錯誤哦,信息在下面:')
|
20
|
+
$stderr.puts(ex.message)
|
21
|
+
$stderr.puts(ex.backtrace)
|
22
|
+
@is_run_success = false
|
23
|
+
ensure
|
24
|
+
$stdout.puts('訓練時間:')
|
25
|
+
$stdout.puts(@obj_tutorial.get_total_time_str)
|
26
|
+
$stdout.puts('成果統計:')
|
27
|
+
$stdout.puts(@obj_tutorial.get_total_words_result)
|
28
|
+
$stdout.puts('要努力學習哦,感謝使用!')
|
29
|
+
exit(@is_run_success)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if __FILE__ == $0 # for test-run use
|
35
|
+
main = ShuangPinTutorial::Main.new()
|
36
|
+
main.run()
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# $LOAD_PATH.unshift __dir__ # For use/testing when no gem is installed
|
4
|
+
|
5
|
+
# Require all of the Ruby files in the given directory.
|
6
|
+
def require_all(path)
|
7
|
+
glob = File.join(__dir__, path, "*.rb")
|
8
|
+
Dir[glob].sort.each do |f|
|
9
|
+
require f
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module ShuangPinTutorial
|
14
|
+
MODULE = "ShuangPinTutorial"
|
15
|
+
NAME = "shuang_pin_tutorial"
|
16
|
+
VERSION = "1.1.1"
|
17
|
+
|
18
|
+
autoload(:Main, "#{NAME}/main")
|
19
|
+
autoload(:Handler, "#{NAME}/handler")
|
20
|
+
autoload(:Data, "#{NAME}/data")
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shuang_pin_tutorial
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David N
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-02-25 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: An interesting, featured tutorial application for practicing Microsoft
|
14
|
+
Shuang Pin input method.
|
15
|
+
email: dn@jsdn.hk
|
16
|
+
executables:
|
17
|
+
- shuang_pin_tutorial
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files:
|
20
|
+
- README.md
|
21
|
+
- LICENSE
|
22
|
+
files:
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
- exe/shuang_pin_tutorial
|
26
|
+
- lib/shuang_pin_tutorial.rb
|
27
|
+
- lib/shuang_pin_tutorial/data.rb
|
28
|
+
- lib/shuang_pin_tutorial/handler.rb
|
29
|
+
- lib/shuang_pin_tutorial/main.rb
|
30
|
+
homepage: https://github.com/jsdnhk/shuang_pin_tutorial
|
31
|
+
licenses:
|
32
|
+
- MIT
|
33
|
+
metadata:
|
34
|
+
source_code_uri: https://github.com/jsdnhk/shuang_pin_tutorial
|
35
|
+
changelog_uri: https://github.com/jsdnhk/shuang_pin_tutorial/CHANGELOG.md
|
36
|
+
documentation_uri: https://github.com/jsdnhk/shuang_pin_tutorial/README.md
|
37
|
+
post_install_message: Welcome using Microsoft Shuang Pin tutorial!
|
38
|
+
rdoc_options:
|
39
|
+
- "--charset=UTF-8"
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.4.0
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: 2.7.0
|
52
|
+
requirements: []
|
53
|
+
rubygems_version: 3.1.2
|
54
|
+
signing_key:
|
55
|
+
specification_version: 4
|
56
|
+
summary: A tutorial application for Microsoft Shuang Pin input method.
|
57
|
+
test_files: []
|