Skip to content

Commit 2060fbc

Browse files
committed
Kana Typer 1st version done
1 parent c4b1315 commit 2060fbc

File tree

2 files changed

+118
-4
lines changed

2 files changed

+118
-4
lines changed

src/japanese/exercises/kana-typer/KanaTyper.tsx

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ const game = makeAutoObservable({
2828
timeLimitMs: 0,
2929
finished: false,
3030
enabledKanas: [] as string[],
31+
dakuten: true,
32+
handakuten: true,
3133

3234
reset(): void {
3335
this.currentInput = "";
@@ -100,9 +102,22 @@ const game = makeAutoObservable({
100102

101103
if (!this.enabledKanas.length) return result;
102104

105+
const pool = new Set([...this.enabledKanas]);
106+
107+
if (this.dakuten) {
108+
for (const dakuten of [...pool.values()].map(KanaUtils.toDakuten))
109+
pool.add(dakuten);
110+
}
111+
112+
if (this.handakuten) {
113+
for (const handakuten of [...pool.values()].map(KanaUtils.toHandakuten))
114+
pool.add(handakuten);
115+
}
116+
117+
const poolArr = Array.from(pool);
118+
103119
for (let i = 0; i < 10; i++) {
104-
const selectedKana =
105-
this.enabledKanas[Math.floor(Math.random() * this.enabledKanas.length)];
120+
const selectedKana = poolArr[Math.floor(Math.random() * poolArr.length)];
106121

107122
result.push({
108123
idx: startingIdx + i,
@@ -123,10 +138,10 @@ export function KanaTyper() {
123138
return (
124139
<ContentBox>
125140
<Flex itemsPlacement="center" gap={12}>
126-
<h1>Kana typer</h1>
127141
<Dropdown trigger="click" content={<KanaTyperSettings />}>
128142
<span className="clickable">&#128736;</span>
129143
</Dropdown>
144+
<h1>Kana typer</h1>
130145
</Flex>
131146
<div>
132147
{!game.timer
@@ -215,6 +230,26 @@ function KanaTyperSettings() {
215230
style={{ minWidth: 350 }}
216231
>
217232
<h3>Selected Kana</h3>
233+
<Flex>
234+
<CheckBox
235+
checked={game.dakuten}
236+
onChange={(val) => {
237+
game.dakuten = val;
238+
game.reset();
239+
}}
240+
>
241+
Dakuten
242+
</CheckBox>
243+
<CheckBox
244+
checked={game.handakuten}
245+
onChange={(val) => {
246+
game.handakuten = val;
247+
game.reset();
248+
}}
249+
>
250+
Handakuten
251+
</CheckBox>
252+
</Flex>
218253
<Flex gap={12}>
219254
<Flex down>
220255
{Object.entries(kanaTables.hiragana).map(([rowName, kanas]) => (

src/japanese/utils/kana-utils.ts

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@ export namespace KanaUtils {
1212
export function toAll(input: string) {
1313
return [toRomaji(input), toHiragana(input), toKatakana(input)];
1414
}
15+
export function toDakuten(input: string) {
16+
return transpileLangSymbol(toDakutenLookup, 3, input);
17+
}
18+
export function toHandakuten(input: string) {
19+
return transpileLangSymbol(toHandakutenLookup, 3, input);
20+
}
21+
export function fromDakuten(input: string) {
22+
return transpileLangSymbol(fromDakutenLookup, 3, input);
23+
}
24+
export function fromHandakuten(input: string) {
25+
return transpileLangSymbol(fromHandakutenLookup, 3, input);
26+
}
1527
}
1628

1729
(window as any).KanaUtils = KanaUtils;
@@ -52,6 +64,69 @@ function transpileLangSymbol(
5264
return transpiled;
5365
}
5466

67+
function initDiacriticMaps() {
68+
if (toDakutenLookup.size !== 0) return;
69+
70+
const dakutenChars = [
71+
["が", "か"],
72+
["ぎ", "き"],
73+
["ぐ", "く"],
74+
["げ", "け"],
75+
["ご", "こ"],
76+
["ざ", "さ"],
77+
["じ", "し"],
78+
["ず", "す"],
79+
["ぜ", "せ"],
80+
["ぞ", "そ"],
81+
["だ", "た"],
82+
["ぢ", "ち"],
83+
["づ", "つ"],
84+
["で", "て"],
85+
["ど", "と"],
86+
["ば", "な"],
87+
["び", "ひ"],
88+
["ぶ", "ふ"],
89+
["べ", "へ"],
90+
["ぼ", "ほ"],
91+
];
92+
93+
for (const [hiraganaDakuten, hiraganaNormal] of dakutenChars) {
94+
const katakanaDakuten = KanaUtils.toKatakana(hiraganaDakuten);
95+
const katakanaNormal = KanaUtils.toKatakana(hiraganaNormal);
96+
const romajiDakuten = KanaUtils.toRomaji(hiraganaDakuten);
97+
const romajiNormal = KanaUtils.toRomaji(hiraganaNormal);
98+
99+
toDakutenLookup.set(hiraganaNormal, hiraganaDakuten);
100+
toDakutenLookup.set(katakanaNormal, katakanaDakuten);
101+
toDakutenLookup.set(romajiNormal, romajiDakuten);
102+
fromDakutenLookup.set(hiraganaDakuten, hiraganaNormal);
103+
fromDakutenLookup.set(katakanaDakuten, katakanaNormal);
104+
fromDakutenLookup.set(romajiDakuten, romajiNormal);
105+
}
106+
107+
const handakutenChars = [
108+
["ぱ ", "は"],
109+
["ぴ ", "ひ"],
110+
["ぷ ", "ふ"],
111+
["ぺ ", "へ"],
112+
["ぽ ", "ほ"],
113+
];
114+
for (const [hiraganaDakuten, hiraganaNormal] of handakutenChars) {
115+
const katakanaDakuten = KanaUtils.toKatakana(hiraganaDakuten);
116+
const katakanaNormal = KanaUtils.toKatakana(hiraganaNormal);
117+
const romajiDakuten = KanaUtils.toRomaji(hiraganaDakuten);
118+
const romajiNormal = KanaUtils.toRomaji(hiraganaNormal);
119+
120+
toHandakutenLookup.set(hiraganaNormal, hiraganaDakuten);
121+
toHandakutenLookup.set(katakanaNormal, katakanaDakuten);
122+
toHandakutenLookup.set(romajiNormal, romajiDakuten);
123+
fromHandakutenLookup.set(hiraganaDakuten, hiraganaNormal);
124+
fromHandakutenLookup.set(katakanaDakuten, katakanaNormal);
125+
fromHandakutenLookup.set(romajiDakuten, romajiNormal);
126+
}
127+
}
128+
129+
/* [hiragana, katakana, romaji] */
55130
const symbolGroupings: [string, string, string][] = [
56131
["あ", "ア", "a"],
57132
["い", "イ", "i"],
@@ -213,4 +288,8 @@ const katakanaLookup = new Map<string, string>([
213288
...symbolGroupings.map(([, katakana, romaji]) => [romaji, katakana]),
214289
] as [string, string][]);
215290

216-
console.log(katakanaLookup);
291+
let toDakutenLookup = new Map<string, string>();
292+
let toHandakutenLookup = new Map<string, string>();
293+
let fromDakutenLookup = new Map<string, string>();
294+
let fromHandakutenLookup = new Map<string, string>();
295+
initDiacriticMaps();

0 commit comments

Comments
 (0)