File size: 3,213 Bytes
9b1f754
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import random

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, question_list):
    if not question_list:
        question_list = init_question(hira, kata, c)
    return question_list.pop(), question_list


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

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

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

    hira_list = [to_hiragana(combine(a, b)) for a in curr_hira for b in curr_b if is_valid(a, b)]
    kata_list = [to_katakana(combine(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 combine(a, b):
    if a == "a":
        a = ""
    return f"{a}{b}"


def check(question, answer, correct, total):
    groundtruth = to_roma(question)
    ans_correct = groundtruth == answer
    correct += ans_correct
    total += 1

    info = "正確" if ans_correct else f"錯誤,答案 {groundtruth}"
    msg = f"{correct}/{total} - " + info

    return correct, total, msg, ""


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)
    question_list = gr.State(init_question(a_base[:5], [], []))

    with gr.Row():
        with gr.Column():
            with gr.Tab("測驗"):
                with gr.Row():
                    question = gr.Textbox(label="題目")
                    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, question_list]
    nq_out = [question, question_list]
    nq_arg = dict(fn=next_question, inputs=nq_inn, outputs=nq_out, show_progress="hidden")

    answer.submit(**chk_arg).then(**nq_arg)
    apply_btn.click(init_question, nq_inn[:3], question_list).then(**nq_arg)

app.launch(share=True)