Penut commited on
Commit
259f80e
·
1 Parent(s): d811247

update layout

Browse files
Files changed (1) hide show
  1. app.py +93 -52
app.py CHANGED
@@ -5,50 +5,36 @@ import gradio as gr
5
  from romkan import to_hiragana, to_katakana, to_roma
6
 
7
  a_base = ["a", "k", "s", "t", "n", "h", "m", "y", "r", "w", "nn"]
8
- a_ext1 = ["g", "z", "d", "b"]
9
- a_ext2 = ["p"]
10
-
11
  b_base = ["a", "i", "u", "e", "o"]
12
- b_ext = ["ya", "yo", "yu"]
13
-
14
- c_opt = ["濁音", "半濁音", "拗音"]
15
 
16
  invalid = ["yi", "ye", "wi", "wu", "we"]
17
  spec_map = {"cya": "cha", "cyu": "chu", "cyo": "cho"}
18
 
19
 
20
- def next_question(hira, kata, c, quiz_list):
21
- info_flag = False
22
-
23
  if not quiz_list:
24
- info_flag = True
25
- quiz_list = init_question(hira, kata, c)
26
 
27
  if not quiz_list:
28
  gr.Info("請選擇至少一項測驗!")
29
  return None, quiz_list
30
 
31
- if info_flag:
32
- gr.Info("已完成一輪測試!")
33
-
34
  return quiz_list.pop(), quiz_list
35
 
36
 
37
- def init_question(hira, kata, c):
38
- curr_hira = deepcopy(hira)
39
- curr_hira += deepcopy(a_ext1) if "濁音" in c else []
40
- curr_hira += deepcopy(a_ext2) if "半濁音" in c else []
41
 
42
- curr_kata = deepcopy(kata)
43
- if curr_kata:
44
- curr_kata += deepcopy(a_ext1) if "濁音" in c else []
45
- curr_kata += deepcopy(a_ext2) if "半濁音" in c else []
46
 
47
- curr_b = deepcopy(b_base)
48
- curr_b += deepcopy(b_ext) if "拗音" in c else []
49
 
50
- hira_list = [to_hira(a, b) for a in curr_hira for b in curr_b if is_valid(a, b)]
51
- kata_list = [to_kata(a, b) for a in curr_kata for b in curr_b if is_valid(a, b)]
52
 
53
  quiz_list = hira_list + kata_list
54
  quiz_list = list(set(quiz_list))
@@ -57,6 +43,12 @@ def init_question(hira, kata, c):
57
  return quiz_list
58
 
59
 
 
 
 
 
 
 
60
  def is_valid(aa: str, bb: str):
61
  if f"{aa}{bb}" in invalid:
62
  return False
@@ -69,6 +61,9 @@ def is_valid(aa: str, bb: str):
69
  if bb == "":
70
  return False
71
 
 
 
 
72
  return True
73
 
74
 
@@ -88,7 +83,7 @@ def combine(a, b):
88
  return f"{a}{b}"
89
 
90
 
91
- def check(kana: str, roma: str, correct, total):
92
  roma = roma.lower()
93
 
94
  kana_roma = to_roma(kana)
@@ -111,67 +106,113 @@ def check(kana: str, roma: str, correct, total):
111
  info = "正確" if ans_correct else f"錯誤 - {kana} ({kana_roma})"
112
  msg = f"{correct}/{total} - " + info
113
 
114
- return correct, total, msg, ""
 
 
 
 
 
 
 
 
 
115
 
116
 
117
  def reset_score():
118
- return 0, 0, "0/0", ""
119
 
120
 
121
  def select_all():
122
- return a_base, a_base, c_opt
123
 
124
 
125
  def deselect_all():
126
- return [], [], []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
 
129
  font = gr.themes.GoogleFont("NotoSans CJK")
130
- theme = gr.themes.Soft(font=font)
131
 
132
  with gr.Blocks(theme=theme, title="假名小測驗") as app:
133
  correct = gr.State(0)
134
  total = gr.State(0)
135
- quiz_list = gr.State(init_question(a_base[:5], [], []))
136
 
137
  with gr.Row():
138
- with gr.Column():
139
- with gr.Tab("測驗"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  with gr.Row():
141
  desc = "完成設定後按下「開始測驗」"
142
  question = gr.Textbox(placeholder=desc, label="題目", interactive=False)
143
  score = gr.Textbox("0/0", label="分數")
144
  answer = gr.Textbox(label="作答")
145
 
146
- with gr.Column():
147
- with gr.Tab("設定"):
148
- setting_hira = gr.CheckboxGroup(a_base, value=a_base[:5], label="平假名")
149
- setting_kata = gr.CheckboxGroup(a_base, label="片假名")
150
- setting_c = gr.CheckboxGroup(c_opt, label="延伸")
151
  with gr.Row():
152
- select_all_btn = gr.Button("全選")
153
- deselect_all_btn = gr.Button("全不選")
154
- apply_btn = gr.Button("開始測驗")
155
 
156
- chk_inn = [question, answer, correct, total]
157
- chk_out = [correct, total, score, answer]
 
 
 
 
 
158
  chk_arg = dict(fn=check, inputs=chk_inn, outputs=chk_out, show_progress="hidden")
159
 
160
- nq_inn = [setting_hira, setting_kata, setting_c, quiz_list]
161
  nq_out = [question, quiz_list]
162
  nq_arg = dict(fn=next_question, inputs=nq_inn, outputs=nq_out, show_progress="hidden")
163
 
164
- ini_inn = [setting_hira, setting_kata, setting_c]
165
- ini_out = [quiz_list]
166
  ini_arg = dict(fn=init_question, inputs=ini_inn, outputs=ini_out, show_progress="hidden")
167
 
168
  reset_arg = dict(fn=reset_score, outputs=chk_out, show_progress="hidden")
169
 
170
- opt_out = [setting_hira, setting_kata, setting_c]
171
-
172
  answer.submit(**chk_arg).then(**nq_arg)
173
  apply_btn.click(**ini_arg).then(**reset_arg).then(**nq_arg)
174
- select_all_btn.click(select_all, outputs=opt_out, show_progress="hidden")
175
- deselect_all_btn.click(deselect_all, outputs=opt_out, show_progress="hidden")
 
 
 
 
176
 
177
  app.launch(favicon_path="icon.png")
 
5
  from romkan import to_hiragana, to_katakana, to_roma
6
 
7
  a_base = ["a", "k", "s", "t", "n", "h", "m", "y", "r", "w", "nn"]
 
 
 
8
  b_base = ["a", "i", "u", "e", "o"]
9
+ ext = ["g", "z", "d", "b", "p", "ya", "yo", "yu"]
 
 
10
 
11
  invalid = ["yi", "ye", "wi", "wu", "we"]
12
  spec_map = {"cya": "cha", "cyu": "chu", "cyo": "cho"}
13
 
14
 
15
+ def next_question(hira, hira_ext, kata, kata_ext, quiz_list: list):
 
 
16
  if not quiz_list:
17
+ quiz_list = init_question_list(hira, hira_ext, kata, kata_ext)
 
18
 
19
  if not quiz_list:
20
  gr.Info("請選擇至少一項測驗!")
21
  return None, quiz_list
22
 
 
 
 
23
  return quiz_list.pop(), quiz_list
24
 
25
 
26
+ def init_question_list(hira, hira_ext, kata, kata_ext):
27
+ hira_ext_a, hira_ext_b = split_ext(hira_ext)
28
+ kata_ext_a, kata_ext_b = split_ext(kata_ext)
 
29
 
30
+ curr_hira_a = deepcopy(hira) + deepcopy(hira_ext_a)
31
+ curr_kata_a = deepcopy(kata) + deepcopy(kata_ext_a)
 
 
32
 
33
+ curr_hira_b = deepcopy(b_base) + deepcopy(hira_ext_b)
34
+ curr_kata_b = deepcopy(b_base) + deepcopy(kata_ext_b)
35
 
36
+ hira_list = [to_hira(a, b) for a in curr_hira_a for b in curr_hira_b if is_valid(a, b)]
37
+ kata_list = [to_kata(a, b) for a in curr_kata_a for b in curr_kata_b if is_valid(a, b)]
38
 
39
  quiz_list = hira_list + kata_list
40
  quiz_list = list(set(quiz_list))
 
43
  return quiz_list
44
 
45
 
46
+ def split_ext(ext: list):
47
+ ext_a = [a for a in ext if a[0] != "y"]
48
+ ext_b = [b for b in ext if b[0] == "y"]
49
+ return ext_a, ext_b
50
+
51
+
52
  def is_valid(aa: str, bb: str):
53
  if f"{aa}{bb}" in invalid:
54
  return False
 
61
  if bb == "":
62
  return False
63
 
64
+ if aa == "a" and bb[0] == "y":
65
+ return False
66
+
67
  return True
68
 
69
 
 
83
  return f"{a}{b}"
84
 
85
 
86
+ def check(kana: str, roma: str, correct, total, record, quiz_list):
87
  roma = roma.lower()
88
 
89
  kana_roma = to_roma(kana)
 
106
  info = "正確" if ans_correct else f"錯誤 - {kana} ({kana_roma})"
107
  msg = f"{correct}/{total} - " + info
108
 
109
+ if not ans_correct:
110
+ record = f"{record}{info}\n"
111
+
112
+ tab_idx = gr.Tabs(selected=1)
113
+ if not quiz_list:
114
+ record = f"{record}此輪得分 - {correct}/{total}\n\n"
115
+ correct, total = 0, 0
116
+ tab_idx = gr.Tabs(selected=2)
117
+
118
+ return correct, total, msg, None, record, tab_idx
119
 
120
 
121
  def reset_score():
122
+ return 0, 0, "0/0", None, None, gr.Tabs()
123
 
124
 
125
  def select_all():
126
+ return a_base, ext, a_base, ext
127
 
128
 
129
  def deselect_all():
130
+ return [], [], [], []
131
+
132
+
133
+ def select_all_hira():
134
+ return a_base, ext, [], []
135
+
136
+
137
+ def select_all_kata():
138
+ return [], [], a_base, ext
139
+
140
+
141
+ def select_init():
142
+ return a_base[:5], [], [], []
143
+
144
+
145
+ def back_to_setting():
146
+ return gr.Tabs(selected=0)
147
 
148
 
149
  font = gr.themes.GoogleFont("NotoSans CJK")
150
+ theme = gr.themes.Soft(font=font, text_size=gr.themes.sizes.text_lg)
151
 
152
  with gr.Blocks(theme=theme, title="假名小測驗") as app:
153
  correct = gr.State(0)
154
  total = gr.State(0)
155
+ quiz_list = gr.State(init_question_list(*select_init()))
156
 
157
  with gr.Row():
158
+ with gr.Tabs() as tabs:
159
+ with gr.Tab("設定", id=0):
160
+ with gr.Tab("平假名"):
161
+ setting_hira = gr.CheckboxGroup(a_base, value=a_base[:5], label="基本")
162
+ setting_hira_ext = gr.CheckboxGroup(ext, label="濁音、半濁音、拗音")
163
+
164
+ with gr.Tab("片假名"):
165
+ setting_kata = gr.CheckboxGroup(a_base, label="基本")
166
+ setting_kata_ext = gr.CheckboxGroup(ext, label="濁音、半濁音、拗音")
167
+
168
+ with gr.Row():
169
+ select_all_hira_btn = gr.Button("平假名全選")
170
+ select_all_kata_btn = gr.Button("片假名全選")
171
+ with gr.Row():
172
+ select_all_btn = gr.Button("全選")
173
+ deselect_all_btn = gr.Button("全不選")
174
+ with gr.Row():
175
+ apply_btn = gr.Button("開始測驗")
176
+
177
+ with gr.Tab("測驗", id=1):
178
  with gr.Row():
179
  desc = "完成設定後按下「開始測驗」"
180
  question = gr.Textbox(placeholder=desc, label="題目", interactive=False)
181
  score = gr.Textbox("0/0", label="分數")
182
  answer = gr.Textbox(label="作答")
183
 
184
+ with gr.Tab("紀錄", id=2):
185
+ record = gr.TextArea(show_label=False)
 
 
 
186
  with gr.Row():
187
+ again_btn = gr.Button("再次測驗")
188
+ back_to_setting_btn = gr.Button("回到設定")
 
189
 
190
+ def init_question(set_hira, set_hira_ext, set_kata, set_kata_ext):
191
+ quiz_list = init_question_list(set_hira, set_hira_ext, set_kata, set_kata_ext)
192
+ select = gr.Tabs(selected=1) if quiz_list else gr.Tabs(selected=0)
193
+ return quiz_list, select
194
+
195
+ chk_inn = [question, answer, correct, total, record, quiz_list]
196
+ chk_out = [correct, total, score, answer, record, tabs]
197
  chk_arg = dict(fn=check, inputs=chk_inn, outputs=chk_out, show_progress="hidden")
198
 
199
+ nq_inn = [setting_hira, setting_hira_ext, setting_kata, setting_kata_ext, quiz_list]
200
  nq_out = [question, quiz_list]
201
  nq_arg = dict(fn=next_question, inputs=nq_inn, outputs=nq_out, show_progress="hidden")
202
 
203
+ ini_inn = [setting_hira, setting_hira_ext, setting_kata, setting_kata_ext]
204
+ ini_out = [quiz_list, tabs]
205
  ini_arg = dict(fn=init_question, inputs=ini_inn, outputs=ini_out, show_progress="hidden")
206
 
207
  reset_arg = dict(fn=reset_score, outputs=chk_out, show_progress="hidden")
208
 
 
 
209
  answer.submit(**chk_arg).then(**nq_arg)
210
  apply_btn.click(**ini_arg).then(**reset_arg).then(**nq_arg)
211
+ again_btn.click(**ini_arg).then(**reset_arg).then(**nq_arg)
212
+ select_all_hira_btn.click(select_all_hira, outputs=ini_inn, show_progress="hidden")
213
+ select_all_kata_btn.click(select_all_kata, outputs=ini_inn, show_progress="hidden")
214
+ select_all_btn.click(select_all, outputs=ini_inn, show_progress="hidden")
215
+ deselect_all_btn.click(deselect_all, outputs=ini_inn, show_progress="hidden")
216
+ back_to_setting_btn.click(back_to_setting, None, tabs, show_progress="hidden")
217
 
218
  app.launch(favicon_path="icon.png")