File size: 3,861 Bytes
9b1f754
8cef97c
9b1f754
 
 
 
 
 
 
 
 
 
 
 
 
 
8cef97c
 
2a30efc
8cef97c
 
9b1f754
 
 
8cef97c
 
 
9b1f754
8cef97c
 
 
 
9b1f754
8cef97c
 
9b1f754
8cef97c
 
9b1f754
 
 
 
 
 
 
 
 
 
2a30efc
9b1f754
 
 
 
 
 
 
2a30efc
9b1f754
 
 
8cef97c
 
 
 
 
 
 
 
9b1f754
 
 
 
 
 
1dbaa4c
 
 
9b1f754
 
 
1dbaa4c
9b1f754
 
 
 
 
8cef97c
 
 
 
9b1f754
 
 
 
 
 
8cef97c
9b1f754
 
 
 
 
2a30efc
 
9b1f754
 
 
 
 
 
 
 
 
 
 
 
 
 
8cef97c
 
9b1f754
 
8cef97c
 
 
 
 
 
9b1f754
8cef97c
9b1f754
2a30efc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import random
from copy import deepcopy

import gradio as gr
from romkan import to_hiragana, to_katakana, to_roma

a_base = ["a", "k", "s", "t", "n", "h", "m", "y", "r", "w"]
a_ext1 = ["g", "z", "d", "b"]
a_ext2 = ["p"]

b_base = ["a", "i", "u", "e", "o"]
b_ext = ["ya", "yo", "yu"]

invalid = ["yi", "ye", "wi", "wu", "we"]


def next_question(hira, kata, c, quiz_list):
    if not quiz_list:
        gr.Info("已完成一輪測試!")
        quiz_list = init_question(hira, kata, c)
    return quiz_list.pop(), quiz_list


def init_question(hira, kata, c):
    curr_hira = deepcopy(hira)
    curr_hira += deepcopy(a_ext1) if "濁音" in c else []
    curr_hira += deepcopy(a_ext2) if "半濁音" in c else []

    curr_kata = deepcopy(kata)
    if curr_kata:
        curr_kata += deepcopy(a_ext1) if "濁音" in c else []
        curr_kata += deepcopy(a_ext2) if "半濁音" in c else []

    curr_b = deepcopy(b_base)
    curr_b += deepcopy(b_ext) if "拗音" in c else []

    hira_list = [to_hira(a, b) for a in curr_hira for b in curr_b if is_valid(a, b)]
    kata_list = [to_kata(a, b) for a in curr_kata for b in curr_b if is_valid(a, b)]

    quiz_list = hira_list + kata_list
    random.shuffle(quiz_list)

    return quiz_list


def is_valid(aa: str, bb: str):
    if f"{aa}{bb}" in invalid:
        return False

    if aa == "y":
        if bb[0] == "y":
            return False
        if bb[0] == "w":
            return False
        if bb == "":
            return False

    return True


def to_hira(a, b):
    return to_hiragana(combine(a, b))


def to_kata(a, b):
    return to_katakana(combine(a, b))


def combine(a, b):
    if a == "a":
        a = ""
    return f"{a}{b}"


def check(kana: str, roma: str, correct, total):
    kana_roma = to_roma(kana)
    ans_correct = kana_roma == roma.lower()
    correct += ans_correct
    total += 1

    info = "正確" if ans_correct else f"錯誤 - {kana} ({kana_roma})"
    msg = f"{correct}/{total} - " + info

    return correct, total, msg, ""


def reset_score():
    return 0, 0, "0/0", ""


font = gr.themes.GoogleFont("NotoSans CJK")
theme = gr.themes.Soft(font=font)

with gr.Blocks(theme=theme, title="假名小測驗") as app:
    correct = gr.State(0)
    total = gr.State(0)
    quiz_list = gr.State(init_question(a_base[:5], [], []))

    with gr.Row():
        with gr.Column():
            with gr.Tab("測驗"):
                with gr.Row():
                    desc = "完成設定後按下「開始測驗」"
                    question = gr.Textbox(placeholder=desc, label="題目", interactive=False)
                    score = gr.Textbox("0/0", label="分數")
                answer = gr.Textbox(label="作答")

        with gr.Column():
            with gr.Tab("設定"):
                setting_hira = gr.CheckboxGroup(a_base, value=a_base[:5], label="平假名")
                setting_kata = gr.CheckboxGroup(a_base, label="片假名")
                setting_c = gr.CheckboxGroup(["濁音", "半濁音", "拗音"], label="延伸")
                apply_btn = gr.Button("開始測驗")

    chk_inn = [question, answer, correct, total]
    chk_out = [correct, total, score, answer]
    chk_arg = dict(fn=check, inputs=chk_inn, outputs=chk_out, show_progress="hidden")

    nq_inn = [setting_hira, setting_kata, setting_c, quiz_list]
    nq_out = [question, quiz_list]
    nq_arg = dict(fn=next_question, inputs=nq_inn, outputs=nq_out, show_progress="hidden")

    ini_inn = [setting_hira, setting_kata, setting_c]
    ini_out = [quiz_list]
    ini_arg = dict(fn=init_question, inputs=ini_inn, outputs=ini_out, show_progress="hidden")

    reset_arg = dict(fn=reset_score, outputs=chk_out, show_progress="hidden")

    answer.submit(**chk_arg).then(**nq_arg)
    apply_btn.click(**ini_arg).then(**reset_arg).then(**nq_arg)

app.launch(favicon_path="icon.png")