minimal pairs game

This commit is contained in:
adueck 2024-12-18 21:06:16 -05:00
parent acafc4fe79
commit 290c453317
7 changed files with 443 additions and 171 deletions

View File

@ -17,7 +17,7 @@ export default function MinimalPairs({
return ( return (
<div> <div>
<h5 className="my-3" onClick={() => setOpened((x) => !x)}> <h5 className="my-3" onClick={() => setOpened((x) => !x)}>
{opened ? "▼" : "▶"} View Pairs {opened ? "▼" : "▶"} Browse Pairs
</h5> </h5>
<SmoothCollapse expanded={opened}> <SmoothCollapse expanded={opened}>
{section.pairs.map((pairs, i) => ( {section.pairs.map((pairs, i) => (

View File

@ -0,0 +1,11 @@
const minimalPairsSection = [
"t and T",
"d and D",
"r and R",
"n and N",
"a and aa",
"ay and uy",
"ay and e",
"ee and e",
] as const;
export type MinimalPairsSection = (typeof minimalPairsSection)[number];

View File

@ -11,12 +11,23 @@ import psmd from "../../lib/psmd";
import Link from "../../components/Link"; import Link from "../../components/Link";
import MinimalPairs from "./MinimalPairs.tsx"; import MinimalPairs from "./MinimalPairs.tsx";
import minimalPairs from "./minimal-pairs.ts"; import minimalPairs from "./minimal-pairs.ts";
import {
minimalPairsT,
minimalPairsD,
minimalPairsR,
minimalPairsN,
minimalPairsAa,
minimalPairsAyUy,
minimalPairsAyE,
minimalPairsEeE,
} from "../../games/games";
import GameDisplay from "../../games/GameDisplay";
There are certain sounds in Pashto that are quite difficult for some learners to distinguish. There are certain sounds in Pashto that are quite difficult for some learners to distinguish.
For example, English speakers have a very hard time hearing the difference between the dental <InlinePs opts={opts} ps={{ p: "ت", f: "t" }}/> and retroflex <InlinePs opts={opts} ps={{ p: "ټ", f: "T" }}/>. Some of the vowels like <InlinePs opts={opts} ps={{ p: "ي", f: "ee" }}/> and <InlinePs opts={opts} ps={{ p: "ې", f: "e" }}/> can also be very tricky to distinguish. For example, English speakers have a very hard time hearing the difference between the dental <InlinePs opts={opts} ps={{ p: "ت", f: "t" }}/> and retroflex <InlinePs opts={opts} ps={{ p: "ټ", f: "T" }}/>. Some of the vowels like <InlinePs opts={opts} ps={{ p: "ي", f: "ee" }}/> and <InlinePs opts={opts} ps={{ p: "ې", f: "e" }}/> can also be very tricky to distinguish.
Here are some examples of words that vary by these different sounds. Listen to them to train your ear to the difference, and then use the games to see if you can hear the difference yourself. (Games coming soon! 🚧) Here are some examples of words that vary by these different sounds. Listen to them to train your ear to the difference, and then use the games to see if you can hear the difference yourself.
## ت - t and ټ - T ## ت - t and ټ - T
@ -25,6 +36,8 @@ Here are some examples of words that vary by these different sounds. Listen to t
section={minimalPairs.find((x) => x.title === "t and T")} section={minimalPairs.find((x) => x.title === "t and T")}
/> />
<GameDisplay record={minimalPairsT} />
## د - d and ډ - D ## د - d and ډ - D
<MinimalPairs <MinimalPairs
@ -32,6 +45,8 @@ Here are some examples of words that vary by these different sounds. Listen to t
section={minimalPairs.find((x) => x.title === "d and D")} section={minimalPairs.find((x) => x.title === "d and D")}
/> />
<GameDisplay record={minimalPairsD} />
## ر - r and ړ - R ## ر - r and ړ - R
<MinimalPairs <MinimalPairs
@ -39,6 +54,8 @@ Here are some examples of words that vary by these different sounds. Listen to t
section={minimalPairs.find((x) => x.title === "r and R")} section={minimalPairs.find((x) => x.title === "r and R")}
/> />
<GameDisplay record={minimalPairsR} />
## ن - n and ڼ - N ## ن - n and ڼ - N
<MinimalPairs <MinimalPairs
@ -46,6 +63,8 @@ Here are some examples of words that vary by these different sounds. Listen to t
section={minimalPairs.find((x) => x.title === "n and N")} section={minimalPairs.find((x) => x.title === "n and N")}
/> />
<GameDisplay record={minimalPairsN} />
## ه - a and ا - aa ## ه - a and ا - aa
<MinimalPairs <MinimalPairs
@ -53,6 +72,8 @@ Here are some examples of words that vary by these different sounds. Listen to t
section={minimalPairs.find((x) => x.title === "a and aa")} section={minimalPairs.find((x) => x.title === "a and aa")}
/> />
<GameDisplay record={minimalPairsAa} />
## ی - ay and ۍ - uy ## ی - ay and ۍ - uy
<MinimalPairs <MinimalPairs
@ -60,6 +81,8 @@ Here are some examples of words that vary by these different sounds. Listen to t
section={minimalPairs.find((x) => x.title === "ay and uy")} section={minimalPairs.find((x) => x.title === "ay and uy")}
/> />
<GameDisplay record={minimalPairsAyUy} />
## ی - ay and ې - e ## ی - ay and ې - e
<MinimalPairs <MinimalPairs
@ -67,9 +90,13 @@ Here are some examples of words that vary by these different sounds. Listen to t
section={minimalPairs.find((x) => x.title === "ay and e")} section={minimalPairs.find((x) => x.title === "ay and e")}
/> />
<GameDisplay record={minimalPairsAyE} />
## ي - ee and ې - e ## ي - ee and ې - e
<MinimalPairs <MinimalPairs
opts={opts} opts={opts}
section={minimalPairs.find((x) => x.title === "ee and e")} section={minimalPairs.find((x) => x.title === "ee and e")}
/> />
<GameDisplay record={minimalPairsEeE} />

View File

@ -1,4 +1,13 @@
export default [ import { Types as T } from "@lingdocs/ps-react";
import { MinimalPairsSection } from "./minimal-pairs-type";
const minimalPairs: {
title: MinimalPairsSection;
pairs: [
{ f: string; entry: T.DictionaryEntry },
{ f: string; entry: T.DictionaryEntry }
][];
}[] = [
{ {
title: "t and T", title: "t and T",
pairs: [ pairs: [
@ -60,7 +69,7 @@ export default [
i: 2267, i: 2267,
g: "boT,booT", g: "boT,booT",
}, },
f: "boT, booT", f: "booT",
}, },
], ],
[ [
@ -136,7 +145,7 @@ export default [
i: 3979, i: 3979,
g: "tapos,tupoos,tapoos", g: "tapos,tupoos,tapoos",
}, },
f: "tapós, tupóos, tapóos", f: "tapóos",
}, },
{ {
entry: { entry: {
@ -388,7 +397,7 @@ export default [
i: 5165, i: 5165,
g: "Tang,Tung", g: "Tang,Tung",
}, },
f: "Tang, Tung", f: "Tang",
}, },
], ],
[ [
@ -527,7 +536,7 @@ export default [
i: 4901, i: 4901,
g: "twalawul,tolawul", g: "twalawul,tolawul",
}, },
f: "twalawúl, tolawúl", f: "tolawúl",
}, },
{ {
entry: { entry: {
@ -559,7 +568,7 @@ export default [
i: 4904, i: 4904,
g: "tawluy,toluy", g: "tawluy,toluy",
}, },
f: "tawlúy, tolúy", f: "tolúy",
}, },
{ {
entry: { entry: {
@ -785,34 +794,6 @@ export default [
f: "khuT", f: "khuT",
}, },
], ],
[
{
entry: {
ts: 1672406384728,
p: "سکړوته",
f: "skaRwáta",
e: "hot coal, ember",
c: "n. f.",
a: 2,
i: 10010,
g: "skaRwata",
},
f: "skaRwáta",
},
{
entry: {
ts: 1708187795248,
p: "سکروټه",
f: "skarwáTa",
e: "hot coal, ember",
c: "n. f.",
a: 3,
i: 10008,
g: "skarwaTa",
},
f: "skarwáTa",
},
],
[ [
{ {
entry: { entry: {
@ -994,7 +975,7 @@ export default [
i: 13209, i: 13209,
g: "kanTrol,kunTrol", g: "kanTrol,kunTrol",
}, },
f: "kanTról, kunTról", f: "kanTról",
}, },
], ],
[ [
@ -1226,7 +1207,7 @@ export default [
i: 1707, i: 1707,
g: "bud,bad", g: "bud,bad",
}, },
f: "bud, bad", f: "bud",
}, },
{ {
entry: { entry: {
@ -1315,7 +1296,7 @@ export default [
i: 3533, i: 3533,
g: "podar,pawdar", g: "podar,pawdar",
}, },
f: "podár, pawdár", f: "podár",
}, },
{ {
entry: { entry: {
@ -1328,7 +1309,7 @@ export default [
i: 3535, i: 3535,
g: "poDar,pawDar", g: "poDar,pawDar",
}, },
f: "poDár, pawDár", f: "poDár",
}, },
], ],
[ [
@ -1599,7 +1580,7 @@ export default [
i: 8268, i: 8268,
g: "DaD,DuD", g: "DaD,DuD",
}, },
f: "DaD, DuD", f: "DaD",
}, },
], ],
[ [
@ -1778,7 +1759,7 @@ export default [
i: 8344, i: 8344,
g: "DanDa,DanDa", g: "DanDa,DanDa",
}, },
f: "DanDá, DánDa", f: "DánDa",
}, },
], ],
[ [
@ -1991,7 +1972,7 @@ export default [
i: 14474, i: 14474,
g: "lanDawul,lunDawul", g: "lanDawul,lunDawul",
}, },
f: "lanDawúl, lunDawúl", f: "lanDawúl",
}, },
], ],
[ [
@ -2114,7 +2095,7 @@ export default [
i: 501, i: 501,
g: "aRa,aRa", g: "aRa,aRa",
}, },
f: "áRa, aRá", f: "aRá",
}, },
], ],
[ [
@ -2444,7 +2425,7 @@ export default [
i: 4299, i: 4299,
g: "tRapawul,taRpawul", g: "tRapawul,taRpawul",
}, },
f: "tRapawúl, taRpawúl", f: "taRpawúl",
}, },
], ],
[ [
@ -2460,7 +2441,7 @@ export default [
i: 4160, i: 4160,
g: "trapedul,tarpedul", g: "trapedul,tarpedul",
}, },
f: "trapedúl, tarpedúl", f: "tarpedúl",
}, },
{ {
entry: { entry: {
@ -2474,7 +2455,7 @@ export default [
i: 4300, i: 4300,
g: "tRapedul,taRpedul", g: "tRapedul,taRpedul",
}, },
f: "tRapedúl, taRpedúl", f: "taRpedúl",
}, },
], ],
[ [
@ -2520,7 +2501,7 @@ export default [
i: 6034, i: 6034,
g: "char,chur", g: "char,chur",
}, },
f: "char, chur", f: "chur",
}, },
{ {
entry: { entry: {
@ -2534,7 +2515,7 @@ export default [
i: 6071, i: 6071,
g: "chaR,chuR", g: "chaR,chuR",
}, },
f: "chaR, chuR", f: "chuR",
}, },
], ],
[ [
@ -2642,7 +2623,7 @@ export default [
i: 7006, i: 7006,
g: "khrawul,khurawul", g: "khrawul,khurawul",
}, },
f: "khrawúl, khurawúl", f: "khurawúl",
}, },
{ {
entry: { entry: {
@ -2673,7 +2654,7 @@ export default [
i: 7010, i: 7010,
g: "khUredul,khuredul", g: "khUredul,khuredul",
}, },
f: "khUredúl, khuredúl", f: "khuredúl",
}, },
{ {
entry: { entry: {
@ -2734,7 +2715,7 @@ export default [
i: 7827, i: 7827,
g: "dara,darra", g: "dara,darra",
}, },
f: "dará, darrá", f: "dará",
}, },
{ {
entry: { entry: {
@ -2795,7 +2776,7 @@ export default [
i: 8092, i: 8092,
g: "doredul,dauredul,dooredul", g: "doredul,dauredul,dooredul",
}, },
f: "doredúl, dauredúl, dooredúl", f: "dooredúl",
}, },
{ {
entry: { entry: {
@ -2869,7 +2850,7 @@ export default [
i: 8992, i: 8992,
g: "Rung,Rang", g: "Rung,Rang",
}, },
f: "Rung, Rang", f: "Rang",
}, },
], ],
[ [
@ -2967,7 +2948,7 @@ export default [
i: 9332, i: 9332,
g: "zeeR,zyaR", g: "zeeR,zyaR",
}, },
f: "zeeR, zyaR", f: "zeeR",
}, },
], ],
[ [
@ -3027,7 +3008,7 @@ export default [
i: 9337, i: 9337,
g: "zeRay,zeRay", g: "zeRay,zeRay",
}, },
f: "zeRáy, zéRay", f: "zéRay",
}, },
], ],
[ [
@ -3043,7 +3024,7 @@ export default [
i: 9475, i: 9475,
g: "saaree,saaree", g: "saaree,saaree",
}, },
f: "saarée, sáaree", f: "sáaree",
}, },
{ {
entry: { entry: {
@ -3122,7 +3103,7 @@ export default [
i: 10266, i: 10266,
g: "soR,sooR", g: "soR,sooR",
}, },
f: "soR, sooR", f: "sooR",
}, },
], ],
[ [
@ -3216,7 +3197,7 @@ export default [
i: 10663, i: 10663,
g: "shRamawul,shaRmawul", g: "shRamawul,shaRmawul",
}, },
f: "shRamawúl, shaRmawúl", f: "shaRmawúl",
}, },
], ],
[ [
@ -3236,7 +3217,7 @@ export default [
i: 11647, i: 11647,
g: "ghar,ghur", g: "ghar,ghur",
}, },
f: "ghar, ghur", f: "ghar",
}, },
{ {
entry: { entry: {
@ -3250,7 +3231,7 @@ export default [
i: 11691, i: 11691,
g: "ghuR,ghaR", g: "ghuR,ghaR",
}, },
f: "ghuR, ghaR", f: "ghaR",
}, },
], ],
[ [
@ -3325,7 +3306,7 @@ export default [
i: 12826, i: 12826,
g: "karbezee,karbeezee", g: "karbezee,karbeezee",
}, },
f: "karbézee, karbeezee", f: "karbeezee",
}, },
{ {
entry: { entry: {
@ -3339,7 +3320,7 @@ export default [
i: 12918, i: 12918,
g: "kaRbezee,kaRbezee", g: "kaRbezee,kaRbezee",
}, },
f: "kaRbézee, kaRbezee", f: "kaRbezee",
}, },
], ],
[ [
@ -3384,7 +3365,7 @@ export default [
i: 13066, i: 13066,
g: "kakar,kakur", g: "kakar,kakur",
}, },
f: "kakár, kakúr", f: "kakúr",
}, },
{ {
entry: { entry: {
@ -3398,7 +3379,7 @@ export default [
i: 13068, i: 13068,
g: "kakuR,kakaR", g: "kakuR,kakaR",
}, },
f: "kakúR, kakáR", f: "kakúR",
}, },
], ],
[ [
@ -3474,7 +3455,7 @@ export default [
i: 13381, i: 13381,
g: "kora,koora", g: "kora,koora",
}, },
f: "korá, koorá", f: "korá",
}, },
{ {
entry: { entry: {
@ -3517,7 +3498,7 @@ export default [
i: 13985, i: 13985,
g: "gooR,gwuR", g: "gooR,gwuR",
}, },
f: "gooR, gwuR", f: "gooR",
}, },
], ],
[ [
@ -3716,7 +3697,7 @@ export default [
i: 14291, i: 14291,
g: "lara,lara", g: "lara,lara",
}, },
f: "lára, lará", f: "lára",
}, },
{ {
entry: { entry: {
@ -3762,7 +3743,7 @@ export default [
i: 14573, i: 14573,
g: "lawuR,lUwuR,looR", g: "lawuR,lUwuR,looR",
}, },
f: "lawúR, lUwúR, looR", f: "looR",
}, },
], ],
[ [
@ -3778,7 +3759,7 @@ export default [
i: 15300, i: 15300,
g: "mUr,mur", g: "mUr,mur",
}, },
f: "mUr, mur", f: "mur",
}, },
{ {
entry: { entry: {
@ -3856,7 +3837,7 @@ export default [
i: 15440, i: 15440,
g: "maRuz,maRz", g: "maRuz,maRz",
}, },
f: "maRúz, maRz", f: "maRz",
}, },
], ],
[ [
@ -3968,7 +3949,7 @@ export default [
i: 16859, i: 16859,
g: "nur,nar", g: "nur,nar",
}, },
f: "nur, nar", f: "nur",
}, },
{ {
entry: { entry: {
@ -4010,7 +3991,7 @@ export default [
i: 17038, i: 17038,
g: "nghuRul,nughuRul", g: "nghuRul,nughuRul",
}, },
f: "nghuRúl, nughuRúl", f: "nughuRúl",
}, },
], ],
[ [
@ -4216,7 +4197,7 @@ export default [
i: 4916, i: 4916,
g: "toman,tooman", g: "toman,tooman",
}, },
f: "tomán, toomán", f: "tomán",
}, },
{ {
entry: { entry: {
@ -4263,35 +4244,6 @@ export default [
f: "chaaN", f: "chaaN",
}, },
], ],
[
{
entry: {
ts: 1573768771851,
p: "چنه",
f: "chúna, chína",
e: "jaw; province, district, region",
r: 2,
c: "n. f.",
a: 2,
i: 6192,
g: "chuna,china",
},
f: "chúna, chína",
},
{
entry: {
ts: 1708352960073,
p: "چڼه",
f: "chuNá",
e: "chickpea",
c: "n. f.",
a: 3,
i: 6207,
g: "chuNa",
},
f: "chuNá",
},
],
[ [
{ {
entry: { entry: {
@ -4481,7 +4433,7 @@ export default [
i: 16189, i: 16189,
g: "mana,mana", g: "mana,mana",
}, },
f: "mána', mána'", f: "mána'",
}, },
{ {
entry: { entry: {
@ -4608,7 +4560,7 @@ export default [
i: 207, i: 207,
g: "asar,asar", g: "asar,asar",
}, },
f: "asár, ásar", f: "ásar",
}, },
{ {
entry: { entry: {
@ -4858,7 +4810,7 @@ export default [
i: 923, i: 923,
g: "ilghaa,alghaa", g: "ilghaa,alghaa",
}, },
f: "ilgháa, algháa", f: "algháa",
}, },
], ],
[ [
@ -5112,7 +5064,7 @@ export default [
i: 1688, i: 1688,
g: "bahr,bahar", g: "bahr,bahar",
}, },
f: "bahr, báhar", f: "báhar",
}, },
{ {
entry: { entry: {
@ -5141,7 +5093,7 @@ export default [
i: 1707, i: 1707,
g: "bud,bad", g: "bud,bad",
}, },
f: "bud, bad", f: "bud",
}, },
{ {
entry: { entry: {
@ -5408,7 +5360,7 @@ export default [
i: 2017, i: 2017,
g: "bus,bas", g: "bus,bas",
}, },
f: "bus, bas", f: "bas",
}, },
{ {
entry: { entry: {
@ -5804,7 +5756,7 @@ export default [
i: 3023, i: 3023,
g: "purhar,parhar", g: "purhar,parhar",
}, },
f: "purhár, parhár", f: "parhár",
}, },
{ {
entry: { entry: {
@ -5818,7 +5770,7 @@ export default [
i: 3020, i: 3020,
g: "parhaar,purhaar", g: "parhaar,purhaar",
}, },
f: "parháar, purháar", f: "parháar",
}, },
], ],
[ [
@ -5894,7 +5846,7 @@ export default [
i: 3216, i: 3216,
g: "pal,pul", g: "pal,pul",
}, },
f: "pal, pul", f: "pal",
}, },
{ {
entry: { entry: {
@ -5984,7 +5936,7 @@ export default [
i: 3344, i: 3344,
g: "paNa,paNa", g: "paNa,paNa",
}, },
f: "paNá, páNa", f: "páNa",
}, },
{ {
entry: { entry: {
@ -6166,7 +6118,7 @@ export default [
i: 4257, i: 4257,
g: "traha,turha", g: "traha,turha",
}, },
f: "traha, turha", f: "tarha",
}, },
{ {
entry: { entry: {
@ -6180,7 +6132,7 @@ export default [
i: 4252, i: 4252,
g: "trahaa,tarhaa", g: "trahaa,tarhaa",
}, },
f: "traháa, tarháa", f: "tarháa",
}, },
], ],
[ [
@ -6374,7 +6326,7 @@ export default [
i: 4777, i: 4777,
g: "twaanee,tuwaanee,tawaanee", g: "twaanee,tuwaanee,tawaanee",
}, },
f: "twaanée, tuwaanée, tawaanée", f: "tawaanée",
}, },
{ {
entry: { entry: {
@ -6404,7 +6356,7 @@ export default [
i: 4912, i: 4912,
g: "toliya,tawliya", g: "toliya,tawliya",
}, },
f: "toliyá, tawliyá", f: "tawliyá",
}, },
{ {
entry: { entry: {
@ -6554,7 +6506,7 @@ export default [
i: 5165, i: 5165,
g: "Tang,Tung", g: "Tang,Tung",
}, },
f: "Tang, Tung", f: "Tang",
}, },
{ {
entry: { entry: {
@ -6688,7 +6640,7 @@ export default [
i: 5397, i: 5397,
g: "jaama,jaama", g: "jaama,jaama",
}, },
f: "jáama, jaamá", f: "jáama",
}, },
], ],
[ [
@ -7195,7 +7147,7 @@ export default [
i: 6494, i: 6494,
g: "tsanga,tsunga,tsinga", g: "tsanga,tsunga,tsinga",
}, },
f: "tsánga, tsúnga, tsínga", f: "tsánga",
}, },
{ {
entry: { entry: {
@ -7524,7 +7476,7 @@ export default [
i: 7827, i: 7827,
g: "dara,darra", g: "dara,darra",
}, },
f: "dará, darrá", f: "dará",
}, },
{ {
entry: { entry: {
@ -7810,7 +7762,7 @@ export default [
i: 8250, i: 8250,
g: "Dibbaa,Dabaa", g: "Dibbaa,Dabaa",
}, },
f: "Dibbáa, Dabáa", f: "Dabáa",
}, },
], ],
[ [
@ -7826,7 +7778,7 @@ export default [
i: 8268, i: 8268,
g: "DaD,DuD", g: "DaD,DuD",
}, },
f: "DaD, DuD", f: "DaD",
}, },
{ {
entry: { entry: {
@ -7916,7 +7868,7 @@ export default [
i: 8307, i: 8307,
g: "Daka,Daka", g: "Daka,Daka",
}, },
f: "Daká, Dáka", f: "Dáka",
}, },
{ {
entry: { entry: {
@ -7930,7 +7882,7 @@ export default [
i: 8221, i: 8221,
g: "Daaka,Daaka", g: "Daaka,Daaka",
}, },
f: "Daaká, Dáaka", f: "Dáaka",
}, },
], ],
[ [
@ -8006,7 +7958,7 @@ export default [
i: 8344, i: 8344,
g: "DanDa,DanDa", g: "DanDa,DanDa",
}, },
f: "DanDá, DánDa", f: "DánDa",
}, },
{ {
entry: { entry: {
@ -8066,7 +8018,7 @@ export default [
i: 8750, i: 8750,
g: "rikat,rakat", g: "rikat,rakat",
}, },
f: "riqát, raqát", f: "raqát",
}, },
{ {
entry: { entry: {
@ -8189,7 +8141,7 @@ export default [
i: 9235, i: 9235,
g: "zuna,zina", g: "zuna,zina",
}, },
f: "zúna, zína", f: "zína",
}, },
{ {
entry: { entry: {
@ -8280,7 +8232,7 @@ export default [
i: 9809, i: 9809,
g: "sUda,sada", g: "sUda,sada",
}, },
f: "sUdá, sadá", f: "sadá",
}, },
{ {
entry: { entry: {
@ -8555,7 +8507,7 @@ export default [
i: 10846, i: 10846,
g: "shoopa,shopa", g: "shoopa,shopa",
}, },
f: "shoopá, shopá", f: "shoopá",
}, },
{ {
entry: { entry: {
@ -8771,7 +8723,7 @@ export default [
i: 11647, i: 11647,
g: "ghar,ghur", g: "ghar,ghur",
}, },
f: "ghar, ghur", f: "ghar",
}, },
{ {
entry: { entry: {
@ -8844,7 +8796,7 @@ export default [
i: 11721, i: 11721,
g: "ghuzaa,ghazaa", g: "ghuzaa,ghazaa",
}, },
f: "ghuzáa, ghazáa", f: "ghazáa",
}, },
], ],
[ [
@ -8860,7 +8812,7 @@ export default [
i: 11864, i: 11864,
g: "ghawr,ghor,ghawur", g: "ghawr,ghor,ghawur",
}, },
f: "ghawr, ghor, gháwur", f: "gháwur",
}, },
{ {
entry: { entry: {
@ -8874,7 +8826,7 @@ export default [
i: 11604, i: 11604,
g: "ghaawur,ghaawir", g: "ghaawur,ghaawir",
}, },
f: "ghaawúr, ghaawír", f: "ghaawúr",
}, },
], ],
[ [
@ -8903,7 +8855,7 @@ export default [
i: 11835, i: 11835,
g: "ghwaayay,ghwaayay", g: "ghwaayay,ghwaayay",
}, },
f: "ghwáayay, ghwaayáy", f: "ghwaayáy",
}, },
], ],
[ [
@ -9129,7 +9081,7 @@ export default [
i: 13178, i: 13178,
g: "kamara,kamra", g: "kamara,kamra",
}, },
f: "kamará, kamrá", f: "kamrá",
}, },
{ {
entry: { entry: {
@ -9491,7 +9443,7 @@ export default [
i: 13902, i: 13902,
g: "gangoR,gangwUR", g: "gangoR,gangwUR",
}, },
f: "gangóR, gangwÚR", f: "gangóR",
}, },
{ {
entry: { entry: {
@ -9505,7 +9457,7 @@ export default [
i: 13617, i: 13617,
g: "gaangoR,gaangwUR", g: "gaangoR,gaangwUR",
}, },
f: "gaangóR, gaangwÚR", f: "gaangóR",
}, },
], ],
[ [
@ -9611,7 +9563,7 @@ export default [
i: 14291, i: 14291,
g: "lara,lara", g: "lara,lara",
}, },
f: "lára, lará", f: "lára",
}, },
{ {
entry: { entry: {
@ -9730,7 +9682,7 @@ export default [
i: 14336, i: 14336,
g: "las,lus", g: "las,lus",
}, },
f: "las, lus", f: "las",
}, },
{ {
entry: { entry: {
@ -10049,7 +10001,7 @@ export default [
i: 14821, i: 14821,
g: "maalika,maalika", g: "maalika,maalika",
}, },
f: "maalíka, maaliká", f: "maaliká",
}, },
], ],
[ [
@ -10154,7 +10106,7 @@ export default [
i: 16717, i: 16717,
g: "naakara,naakara", g: "naakara,naakara",
}, },
f: "naakára, naakará", f: "naakará",
}, },
{ {
entry: { entry: {
@ -11091,7 +11043,7 @@ export default [
i: 2072, i: 2072,
g: "bagharay,baghray", g: "bagharay,baghray",
}, },
f: "bagharáy, baghráy", f: "baghráy",
}, },
{ {
entry: { entry: {
@ -11241,7 +11193,7 @@ export default [
i: 3333, i: 3333,
g: "panDay,punDay", g: "panDay,punDay",
}, },
f: "panDáy, punDáy", f: "panDáy",
}, },
{ {
entry: { entry: {
@ -11255,7 +11207,7 @@ export default [
i: 3336, i: 3336,
g: "pUnDuy,punDuy", g: "pUnDuy,punDuy",
}, },
f: "pUnDúy, punDúy", f: "punDúy",
}, },
], ],
[ [
@ -11271,7 +11223,7 @@ export default [
i: 3519, i: 3519,
g: "pooTay,poTay", g: "pooTay,poTay",
}, },
f: "póoTay, póTay", f: "póTay",
}, },
{ {
entry: { entry: {
@ -11408,7 +11360,7 @@ export default [
i: 4293, i: 4293,
g: "treengluy,treenguluy", g: "treengluy,treenguluy",
}, },
f: "treenglúy, treengulúy", f: "treengulúy",
}, },
], ],
[ [
@ -11483,7 +11435,7 @@ export default [
i: 5213, i: 5213,
g: "Tokray,Tookray", g: "Tokray,Tookray",
}, },
f: "Tokráy, Tookráy", f: "Tookráy",
}, },
{ {
entry: { entry: {
@ -11497,7 +11449,7 @@ export default [
i: 5214, i: 5214,
g: "Tokruy,Tookruy", g: "Tokruy,Tookruy",
}, },
f: "Tokrúy, Tookrúy", f: "Tookrúy",
}, },
], ],
[ [
@ -11543,7 +11495,7 @@ export default [
i: 7884, i: 7884,
g: "daRay,daRay", g: "daRay,daRay",
}, },
f: "dáRay, daRáy", f: "dáRay",
}, },
{ {
entry: { entry: {
@ -11721,7 +11673,7 @@ export default [
i: 9803, i: 9803,
g: "skhay", g: "skhay",
}, },
f: "skháy", f: "sakhúy",
}, },
{ {
entry: { entry: {
@ -11735,7 +11687,7 @@ export default [
i: 9805, i: 9805,
g: "skhuy,sakhuy", g: "skhuy,sakhuy",
}, },
f: "skhúy, sakhúy", f: "sakhúy",
}, },
], ],
[ [
@ -11781,7 +11733,7 @@ export default [
i: 10299, i: 10299,
g: "swakay,sokay", g: "swakay,sokay",
}, },
f: "swakáy, sokáy", f: "sokáy",
}, },
{ {
entry: { entry: {
@ -11795,7 +11747,7 @@ export default [
i: 10300, i: 10300,
g: "suwakuy,swukuy,sokuy", g: "suwakuy,swukuy,sokuy",
}, },
f: "suwakúy, swukúy, sokúy", f: "sokúy",
}, },
], ],
[ [
@ -11960,7 +11912,7 @@ export default [
i: 13448, i: 13448,
g: "kokay,kookay", g: "kokay,kookay",
}, },
f: "kokáy, kookáy", f: "kookáy",
}, },
{ {
entry: { entry: {
@ -11990,7 +11942,7 @@ export default [
i: 13599, i: 13599,
g: "gaaDay,gaaDay", g: "gaaDay,gaaDay",
}, },
f: "gáaDay, gaaDáy", f: "gaaDáy",
}, },
{ {
entry: { entry: {
@ -12112,7 +12064,7 @@ export default [
i: 14453, i: 14453,
g: "lmasay,lamsay", g: "lmasay,lamsay",
}, },
f: "lmasáy, lamsáy", f: "lamsáy",
}, },
{ {
entry: { entry: {
@ -12126,7 +12078,7 @@ export default [
i: 14454, i: 14454,
g: "lmasuy,lamsuy", g: "lmasuy,lamsuy",
}, },
f: "lmasúy, lamsúy", f: "lamsúy",
}, },
], ],
[ [
@ -12233,7 +12185,7 @@ export default [
i: 17140, i: 17140,
g: "nmasay,namsay", g: "nmasay,namsay",
}, },
f: "nmasáy, namsáy", f: "namsáy",
}, },
{ {
entry: { entry: {
@ -12247,7 +12199,7 @@ export default [
i: 17141, i: 17141,
g: "nmasuy,namsuy", g: "nmasuy,namsuy",
}, },
f: "nmasúy, namsúy", f: "namsúy",
}, },
], ],
[ [
@ -12263,7 +12215,7 @@ export default [
i: 17248, i: 17248,
g: "nwusay,nwasay,nosay", g: "nwusay,nwasay,nosay",
}, },
f: "nwusáy, nwasáy, nosáy", f: "nawsáy",
}, },
{ {
entry: { entry: {
@ -12277,7 +12229,7 @@ export default [
i: 17249, i: 17249,
g: "nwusuy,nwasuy,nawsuy", g: "nwusuy,nwasuy,nawsuy",
}, },
f: "nwusúy, nwasúy, nawsúy", f: "nawsúy",
}, },
], ],
[ [
@ -12902,7 +12854,7 @@ export default [
i: 4286, i: 4286,
g: "treelay,treelay", g: "treelay,treelay",
}, },
f: "treeláy, tréelay", f: "tréelay",
}, },
{ {
entry: { entry: {
@ -12916,7 +12868,7 @@ export default [
i: 4287, i: 4287,
g: "trelay,trelay", g: "trelay,trelay",
}, },
f: "treláy, trélay", f: "trélay",
}, },
], ],
[ [
@ -13121,7 +13073,7 @@ export default [
i: 7344, i: 7344,
g: "khwushe,khooshe", g: "khwushe,khooshe",
}, },
f: "khwúshe, khóoshe", f: "khwúshe",
}, },
], ],
[ [
@ -13285,7 +13237,7 @@ export default [
i: 9332, i: 9332,
g: "zeeR,zyaR", g: "zeeR,zyaR",
}, },
f: "zeeR, zyaR", f: "zeeR",
}, },
{ {
entry: { entry: {
@ -13314,7 +13266,7 @@ export default [
i: 9336, i: 9336,
g: "zeeRay,zyeRay,zeeRay", g: "zeeRay,zyeRay,zeeRay",
}, },
f: "zeeRáy, zyeRáy, zéeRay", f: "zéeRay",
}, },
{ {
entry: { entry: {
@ -13328,7 +13280,7 @@ export default [
i: 9337, i: 9337,
g: "zeRay,zeRay", g: "zeRay,zeRay",
}, },
f: "zeRáy, zéRay", f: "zéRay",
}, },
], ],
[ [
@ -13913,7 +13865,7 @@ export default [
i: 18374, i: 18374,
g: "wye,we", g: "wye,we",
}, },
f: "wye, we", f: "we",
}, },
], ],
[ [
@ -13978,3 +13930,5 @@ export default [
], ],
}, },
]; ];
export default minimalPairs;

View File

@ -3,6 +3,7 @@ import VerbGame from "./sub-cores/VerbGame";
import GenderGame from "./sub-cores/GenderGame"; import GenderGame from "./sub-cores/GenderGame";
import PluralNounGame from "./sub-cores/PluralNounGame"; import PluralNounGame from "./sub-cores/PluralNounGame";
import UnisexNounGame from "./sub-cores/UnisexNounGame"; import UnisexNounGame from "./sub-cores/UnisexNounGame";
import MinimalPairsGame from "./sub-cores/MinimalPairsGame";
import EquativeSituations from "./sub-cores/EquativeSituations"; import EquativeSituations from "./sub-cores/EquativeSituations";
import VerbSituations from "./sub-cores/VerbSituations"; import VerbSituations from "./sub-cores/VerbSituations";
import EquativeIdentify from "./sub-cores/EquativeIdentify"; import EquativeIdentify from "./sub-cores/EquativeIdentify";
@ -13,6 +14,64 @@ import PerfectVerbsIntransitive from "./sub-cores/PerfectGame";
import NPAdjWriting from "./sub-cores/NPAdjGame"; import NPAdjWriting from "./sub-cores/NPAdjGame";
import EPAdjGame from "./sub-cores/EPAdjGame"; import EPAdjGame from "./sub-cores/EPAdjGame";
// MINIMAL PAIRS
export const minimalPairsT = makeGameRecord({
title: "Minimal Pairs - t and T",
id: "minimal-pairs-t",
link: "/writing/minimal-pairs/#ت---t-and-ټ---t",
level: "t and T",
SubCore: MinimalPairsGame,
});
export const minimalPairsD = makeGameRecord({
title: "Minimal Pairs - d and D",
id: "minimal-pairs-d",
link: "/writing/minimal-pairs/#د---d-and-ډ---d",
level: "d and D",
SubCore: MinimalPairsGame,
});
export const minimalPairsR = makeGameRecord({
title: "Minimal Pairs - r and R",
id: "minimal-pairs-r",
link: "/writing/minimal-pairs/#ر---r-and-ړ---r",
level: "r and R",
SubCore: MinimalPairsGame,
});
export const minimalPairsN = makeGameRecord({
title: "Minimal Pairs - n and N",
id: "minimal-pairs-n",
link: "/writing/aiilmmn - pairs / #ن-- - n - and - ڼ-- - n",
level: "n and N",
SubCore: MinimalPairsGame,
});
export const minimalPairsAa = makeGameRecord({
title: "Minimal Pairs - a and aa",
id: "minimal-pairs-aa",
link: "/writing/minimal-pairs/#ه---a-and-ا---aa",
level: "a and aa",
SubCore: MinimalPairsGame,
});
export const minimalPairsAyUy = makeGameRecord({
title: "Minimal Pairs - ay and uy",
id: "minimal-pairs-ay-uy",
link: "/writing/minimal-pairs/#ی---ay-and-ۍ---uy",
level: "ay and uy",
SubCore: MinimalPairsGame,
});
export const minimalPairsAyE = makeGameRecord({
title: "Minimal Pairs - ay and e",
id: "minimal-pairs-ay-e",
link: "/writing/minimal-pairs/#ی---ay-and-ې---e",
level: "ay and e",
SubCore: MinimalPairsGame,
});
export const minimalPairsEeE = makeGameRecord({
title: "Minimal Pairs - ee and e",
id: "minimal-pairs-ee-e",
link: "ي - ee and ې - e",
level: "ee and e",
SubCore: MinimalPairsGame,
});
// NOUNS // NOUNS
export const nounGenderGame1 = makeGameRecord({ export const nounGenderGame1 = makeGameRecord({
title: "Identify Noun Genders - Level 1", title: "Identify Noun Genders - Level 1",
@ -443,6 +502,19 @@ export const npWithAdjectivesInSandwiches = makeGameRecord({
}); });
const games: { chapter: string; items: GameRecord[] }[] = [ const games: { chapter: string; items: GameRecord[] }[] = [
{
chapter: "Minimal Pairs",
items: [
minimalPairsT,
minimalPairsD,
minimalPairsR,
minimalPairsN,
minimalPairsAa,
minimalPairsAyUy,
minimalPairsAyE,
minimalPairsEeE,
],
},
{ {
chapter: "Nouns", chapter: "Nouns",
items: [nounGenderGame1, nounGenderGame2, unisexNounGame, pluralNounGame], items: [nounGenderGame1, nounGenderGame2, unisexNounGame, pluralNounGame],

View File

@ -0,0 +1,206 @@
import GameCore from "../GameCore";
import {
Types as T,
defaultTextOptions as opts,
randFromArray,
removeAccents,
} from "@lingdocs/ps-react";
import minimalPairs from "../../content/writing/minimal-pairs";
import { makePool } from "../../lib/pool";
import { useEffect, useRef } from "react";
import { MinimalPairsSection } from "../../content/writing/minimal-pairs-type";
// is it removing from the pool properly ? or is it a problem with strict mode doing double?
const amount = 20;
type EntryWF = { f: string; entry: T.DictionaryEntry };
type MinimalPair = [EntryWF, EntryWF];
type Question = {
pair: MinimalPair;
selected: 0 | 1;
};
export default function MinimalPairsGame({
level,
id,
link,
inChapter,
}: {
inChapter: boolean;
level: MinimalPairsSection;
id: string;
link: string;
}) {
const getPair = makePool<MinimalPair>(
// @ts-ignore
minimalPairs.find((x) => x.title === level)?.pairs || []
);
function getQuestion(): Question {
const pair = getPair();
const selected: 0 | 1 = randFromArray([0, 1]);
return { pair, selected };
}
function Display({ question, callback }: QuestionDisplayProps<Question>) {
const audioRef = useRef<HTMLAudioElement>();
useEffect(() => {
if (audioRef && audioRef.current) {
audioRef.current.play();
}
}, [question]);
const selected = getSelected(question);
const audioSrc = getAudioSrc(selected);
function playAudio() {
if (audioRef && audioRef.current) {
audioRef.current.play();
}
}
function check(guess: 0 | 1) {
return () => callback(question.selected === guess);
}
return (
<div>
<audio
src={audioSrc}
// @ts-expect-error // typing not playing nice here
ref={audioRef}
/>
<div>
<button className="btn btn-lg btn-primary mt-3" onClick={playAudio}>
<i className="fas fa-play" />
</button>
</div>
<PairButtons
renderButton={(n) => (
<WordButton
entry={question.pair[n]}
handleClick={check(n)}
type="guess"
hideAccents={true}
/>
)}
/>
</div>
);
}
function Instructions() {
return (
<div>
<h5>Listen and identify the correct word in a minimal pair</h5>
</div>
);
}
function DisplayCorrectAnswer({ question }: { question: Question }) {
const audioRef0 = useRef<HTMLAudioElement>();
const audioRef1 = useRef<HTMLAudioElement>();
const [audioSrc0, audioSrc1] = question.pair.map(getAudioSrc);
const playAudio = (n: 0 | 1) => () => {
const audio = n === 0 ? audioRef0 : audioRef1;
audio.current?.play();
};
return (
<div>
<audio
src={audioSrc0}
// @ts-expect-error // typing not playing nice here
ref={audioRef0}
preload="auto"
/>
<audio
src={audioSrc1}
// @ts-expect-error // typing not playing nice here
ref={audioRef1}
preload="auto"
/>
<PairButtons
renderButton={(n) => (
<WordButton
entry={question.pair[n]}
handleClick={playAudio(n)}
key={`answer-${n}`}
type={question.selected === n ? "correct" : "incorrect"}
hideAccents={false}
/>
)}
/>
</div>
);
}
return (
<GameCore
inChapter={inChapter}
studyLink={link}
getQuestion={getQuestion}
id={id}
Display={Display}
DisplayCorrectAnswer={DisplayCorrectAnswer}
amount={amount}
timeLimit={90}
Instructions={Instructions}
/>
);
}
function PairButtons({
renderButton,
}: {
renderButton: (n: 0 | 1) => JSX.Element;
}) {
return (
<div
className="mt-4 d-flex justify-content-center"
style={{ margin: "0 auto", gap: "2.5rem" }}
>
{([0, 1] as const).map(renderButton)}
</div>
);
}
function WordButton({
entry,
handleClick,
type,
hideAccents,
}: {
entry: EntryWF;
handleClick: () => void;
type: "guess" | "correct" | "incorrect";
hideAccents: boolean;
}) {
const btnColor =
type === "guess" ? "light" : type === "correct" ? "success" : "danger";
return (
<button
className={`btn btn-lg btn-${btnColor} mr-3`}
style={{ minWidth: "8rem" }}
onClick={handleClick}
>
<div className="d-flex justify-content-around">
{type === "guess" ? null : (
<div className="mr-3 d-flex flex-column justify-content-around">
<i className={`fas fa-${type === "correct" ? "check" : "times"}`} />
<i className="fas fa-play" />
</div>
)}
<div>
<div>{hideAccents ? removeAccents(entry.f) : entry.f}</div>
<div>{entry.entry.p}</div>
</div>
</div>
</button>
);
}
function getAudioSrc(entry: EntryWF): string {
const tag = entry.entry.a === 1 ? "" : "f";
return `https://storage.lingdocs.com/audio/${entry.entry.ts}${tag}.mp3`;
}
function getSelected(question: Question): {
f: string;
entry: T.DictionaryEntry;
} {
return question.pair[question.selected];
}

View File

@ -6,14 +6,16 @@ import equal from "fast-deep-equal";
* @param poolBase an array of things you want to use as the pool to pick from * @param poolBase an array of things you want to use as the pool to pick from
* @param removalLaxity If set, thery will be a n% chance that the pick will NOT * @param removalLaxity If set, thery will be a n% chance that the pick will NOT
* be removed after use. Defaults to 0, meaning that every time an item is picked * be removed after use. Defaults to 0, meaning that every time an item is picked
* it is removed from the. 100 means that items will never be removed from the pool. * it is removed from the pool. 100 means that items will never be removed from the pool.
* @returns * @returns
*/ */
export function makePool<P>(poolBase: P[], removalLaxity = 0): () => P { export function makePool<P>(poolBase: P[], removalLaxity = 0): () => P {
let pool = [...poolBase]; let pool = [...poolBase];
function shouldStillKeepIt() { function shouldStillKeepIt() {
if (!removalLaxity) return false; if (!removalLaxity) return false;
return Math.random() < removalLaxity / 100; const r = Math.random() < removalLaxity / 100;
console.log({ r });
return r;
} }
function pickRandomFromPool(): P { function pickRandomFromPool(): P {
// Pick an item from the pool; // Pick an item from the pool;