add unisex gender game

This commit is contained in:
lingdocs 2021-09-02 17:09:07 +04:00
parent 0410642492
commit 2fa773ab60
10 changed files with 240 additions and 21 deletions

View File

@ -4,7 +4,7 @@
"private": true,
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.2",
"@lingdocs/pashto-inflector": "^0.8.3",
"@lingdocs/pashto-inflector": "^0.9.3",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",

View File

@ -16,7 +16,7 @@ const pConsonants = ["ب", "پ", "ت", "ټ", "ث", "ج", "چ", "ح", "خ", "څ",
fetch(process.env.LINGDOCS_DICTIONARY_URL).then(res => res.arrayBuffer()).then(data => {
const { entries } = readDictionary(data);
const filtered = entries.filter(e => (
e.c === "n. m." && ["ا", "ه", "ي"].includes(e.p.slice(-1)) && (!["u", "h"].includes(e.g.slice(-1)))
e.c?.includes("n. m. unisex")
));
const content = `module.exports = [
${filtered.reduce((text, entry) => (

View File

@ -56,7 +56,10 @@ export default function({level}: { level: 1 | 2 }) {
? wordPool
: getRandomFromList([wordPool, exceptions]);
const gender = getRandomFromList(Object.keys(base));
const typeToUse = getRandomFromList(Object.keys(base[gender]));
let typeToUse: string;
do {
typeToUse = getRandomFromList(Object.keys(base[gender]));
} while (!base[gender].length);
const question = getRandomFromList(base[gender][typeToUse]).entry;
base[gender][typeToUse] = base[gender][typeToUse].filter(({ entry }) => entry.ts !== question.ts);
yield {

View File

@ -0,0 +1,128 @@
import React, { useState } from "react";
import {
getRandomFromList,
makeProgress,
} from "../lib/game-utils";
import genderColors from "../lib/gender-colors";
import Game from "./Game";
import {
Types as T,
Examples,
defaultTextOptions as opts,
inflectWord,
standardizePashto,
removeAccents,
// pashtoConsonants,
} from "@lingdocs/pashto-inflector";
import words from "../words/nouns-adjs";
import {
firstVariation,
} from "../lib/text-tools";
const nouns = words.filter((w) => w.category === "nouns-unisex").map(x => x.entry);
// type NType = "consonant" | "eyUnstressed" | "eyStressed" | "pashtun" | "withu"
// const types: Record<NType, T.DictionaryEntry[]> = {
// consonant: nouns.filter((w) => pashtoConsonants.includes(w.p.slice(-1))),
// eyUnstressed: nouns.filter((w) => w.f.slice(-2) === "ey"),
// eyStressed: nouns.filter((w) => w.f.slice(-2) === "éy"),
// pashtun: nouns.filter((w) => w.infaf?.includes("aa")),
// withu: nouns.filter((w) => w.infaf?.slice(-1) === "u" && !!w.infaf?.includes("aa")),
// }
const genders: T.Gender[] = ["masc", "fem"];
const amount = 20;
type Question = { entry: T.DictionaryEntry, gender: T.Gender };
export default function() {
function* questions (): Generator<Current<Question>> {
let pool = [...nouns];
for (let i = 0; i < amount; i++) {
// const keys = Object.keys(types) as NType[];
// let type: NType
// do {
// type = getRandomFromList(keys);
// } while (!pool[type].length);
const entry = getRandomFromList(pool);
const gender = getRandomFromList(genders) as T.Gender;
pool = pool.filter((x) => x.ts !== entry.ts);
yield {
progress: makeProgress(i, amount),
question: {
entry,
gender,
},
};
}
}
function Display({ question, callback }: QuestionDisplayProps<Question>) {
function flipGender(g: T.Gender): T.Gender {
return g === "masc" ? "fem" : "masc";
}
const [answer, setAnswer] = useState<string>("");
const inflected = inflectWord(question.entry) as T.UnisexInflections;
const givenGender = question.gender === "masc" ? "masculine" : "feminine";
const requiredGender = question.gender === "fem" ? "masculine" : "feminine";
if (!inflected || !inflected.masc || !inflected.fem) {
return <div>WORD ERROR</div>;
}
function handleInput({ target: { value }}: React.ChangeEvent<HTMLInputElement>) {
setAnswer(value);
}
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const given = standardizePashto(answer.trim());
const correct = inflected[flipGender(question.gender)][0].some((ps) => (
(given === ps.p) || (removeAccents(given) === removeAccents(ps.f))
));
if (correct) {
setAnswer("");
}
callback(correct);
}
return <div>
<div className="pt-2 pb-1 mb-2" style={{ maxWidth: "300px", margin: "0 auto", backgroundColor: genderColors[question.gender === "masc" ? "m" : "f"]}}>
<Examples opts={opts}>{[
{
...inflected[question.gender][0][0],
e: firstVariation(question.entry.e),
}
]}</Examples>
</div>
<div>Is {givenGender}. Make it <span style={{ background: genderColors[requiredGender === "masculine" ? "m" : "f"]}}>{requiredGender}</span>.</div>
<form onSubmit={handleSubmit}>
<div className="my-3" style={{ maxWidth: "200px", margin: "0 auto" }}>
<input
type="text"
className="form-control"
autoComplete="off"
autoCapitalize="off"
spellCheck="false"
dir="auto"
value={answer}
onChange={handleInput}
/>
</div>
<div>
<button type="submit" className="btn btn-primary">Check</button>
</div>
</form>
</div>
}
function Instructions() {
return <div>
Change the gender of a given word
</div>
}
return <Game
questions={questions}
Display={Display}
timeLimit={125}
Instructions={Instructions}
/>
};

View File

@ -73,15 +73,24 @@ Notice how it does not use the first feminine inflection <InlinePs opts={opts} p
## 3. Words ending in a stressed <InlinePs opts={opts} ps={{ p: "ی", f: "éy" }} />
This is very similar to pattern #2, but with the stress on the last syllable the feminine inflection changes.
<InflectionCarousel items={startingWord(words, "ey-stressed-unisex", "لومړی")} />
## 4. Words with the "Pashtun" pattern
These words are a little irregular but you can see a common patten based around:
- lengthening the 1st masculine inflection with <InlinePs opts={opts} ps={{ p: "ا ـ ـه", f: "aa _ u" }} />
- shortening the other forms and adding the <InlinePs opts={opts} ps={{ p: "ـه", f: "-a" }} />, <InlinePs opts={opts} ps={{ p: "ـې", f: "-e" }} />, <InlinePs opts={opts} ps={{ p: "ـو", f: "-o" }} /> endings
<InflectionCarousel items={startingWord(words, "aanu-unisex", "پښتون")} />
**Note**: Nouns in this pattern will often only use the first inflection for the plural. Adjectives will use the 1st inflection for all 3 reasons.
## 5. Shorter irregular words
## 5. Shorter words that take <InlinePs opts={opts} ps={{ p: "ـه", f: "-u" }} />
These are also a little irregular but instead of lengthening the 1st masculine inflection they compress it as well and take just an <InlinePs opts={opts} ps={{ p: "ـه", f: "-u" }} /> on the end.
<InflectionCarousel items={startingWord(words, "short-irreg-unisex", "غل")} />

View File

@ -10,6 +10,7 @@ import {
import Table from "../../components/Table";
import Link from "../../components/Link";
import GenderTable from "../../components/GenderTable";
import UnisexNounGame from "../../components/UnisexNounGame";
There are many words for people and animals in Pashto that can be used in both masculine and feminine forms.
@ -104,8 +105,6 @@ If the accent comes on the end of the word, the femine form is a little differen
### 4. Words with the "Pashtun" pattern
Well...
<GenderTable rows={[
{
masc: {
@ -173,9 +172,7 @@ Well...
}
]} />
### 5. Shorter irregular words
You get the idea...
### 5. Shorter words that take <InlinePs opts={opts} ps={{ p: "ـه", f: "-u" }} />
<GenderTable rows={[
{
@ -212,6 +209,10 @@ You get the idea...
}
]} />
**🕹 Here's a game to practice changing the genders of nouns**
<UnisexNounGame />
<!--
{
masc: {

View File

@ -26,7 +26,6 @@ module.exports = [
// { ts: 1527815845, e: "life" }, // ژوندون
{ ts: 1527815300, e: "rider, mounted" }, // سپور
{ ts: 1527819505, e: "being (in a place after returning, coming back etc.)" }, // ستون
{ ts: 1527813293, e: "red; hot" }, // سور
{ ts: 1600080053835, e: "riding, mounted" }, // سور
{ ts: 1527813068, e: "cold" }, // سوړ
{ ts: 1575924767041, e: "shepherd" }, // شپون

View File

@ -0,0 +1,79 @@
module.exports = [
{ ts: 1527821744, e: `cook, chef` }, // آشپز - aashpáz
{ ts: 1527812156, e: `officer` }, // افسر - afsar
{ ts: 1591872915426, e: `Afghan (person)` }, // افغانی - afghaanéy
{ ts: 1527815137, e: `instigator, insurgent, terrorist` }, // اورپکی - orpakey
{ ts: 1582853867682, e: `resident` }, // اوسېدونکی - osedóonkey
{ ts: 1527812476, e: `child, offspring` }, // بچی - bachéy
{ ts: 1623044005072, e: `insurrectionist, rebel` }, // بلواګر - balwaagar
{ ts: 1612616237182, e: `Pakistani (person)` }, // پاکستانی - paakistaanéy
{ ts: 1527817965, e: `keeper, one who brings up, raises (cattle etc.)` }, // پالونکی - paaloonkey
{ ts: 1527815197, e: `Pashtun` }, // پښتون - puxtoon
{ ts: 1527819228, e: `inspector, detective, person checking people at the doors etc.` }, // پلټونکی - pulaToonkey
{ ts: 1527820130, e: `adherent, supporter; the outside or further ox in a team of oxes grinding or threshing` }, // پلوی - palawéy
{ ts: 1527815924, e: `customer` }, // پېرودونکی - perodoonkey
{ ts: 1527816431, e: `cousin (of paternal aunt)` }, // ترورزی - trorzéy
{ ts: 1527820820, e: `follower` }, // تعقیبوونکی - ta'qeebawóonkey
{ ts: 1586270915475, e: `mammal` }, // تي لرونکی - tee laroonkey
{ ts: 1613563994424, e: `joker, jester, mocker` }, // ټوقمار - Toqmaar
{ ts: 1610793723568, e: `ram, goat` }, // چېلی - cheléy
{ ts: 1527811466, e: `researcher` }, // څېړونکی - tseRoonkey
{ ts: 1527812795, e: `relative` }, // خپلوان - khpulwaan
{ ts: 1527812802, e: `donkey` }, // خر - khur
{ ts: 1527813282, e: `seller` }, // خرڅوونکی - khartsawóonkey
{ ts: 1527819362, e: `calf (animal)` }, // خوسی - khooséy
{ ts: 1527822535, e: `tailor` }, // خیاط - khayáat
{ ts: 1590052667427, e: `witness` }, // درستی - drustéy, drastéy
{ ts: 1622873938137, e: `crook, swindler, criminal` }, // درغلګر - darghalgar
{ ts: 1527820656, e: `mediator, arbitrator` }, // دریمګړی - driyamgúRey
{ ts: 1614081825855, e: `priest, monk/nun` }, // راهب - raahib
{ ts: 1527813758, e: `student, learner, pupil` }, // زدکوونکی - zdakawóonkey
{ ts: 1527819587, e: `translator` }, // ژباړونکی - jzbaaRoonkey
{ ts: 1527815299, e: `dog` }, // سپی - spéy
{ ts: 1610447830096, e: `calf; bull-calf` }, // سخی - skhey
{ ts: 1527816932, e: `soldier` }, // سرتېری - sărtérey
{ ts: 1527811519, e: `embassador, ambassador` }, // سفیر - safeer
{ ts: 1622366208373, e: `secretary` }, // سکرتر - sakratár
{ ts: 1527820170, e: `singer` }, // سندرغاړی - sandurgháaRey
{ ts: 1566468540788, e: `rabbit` }, // سوی - sooy
{ ts: 1527819801, e: `tourist, sightseer, visitor` }, // سیلانی - seylaanéy
{ ts: 1575924767041, e: `shepherd` }, // شپون - shpoon
{ ts: 1527815279, e: `shepherd` }, // شپونکی - shpoonkey
{ ts: 1527819173, e: `analyst, examiner` }, // شنونکی - shanóonkey
{ ts: 1612614411126, e: `teacher` }, // ښووونکی - xowóonkey
{ ts: 1527815436, e: `tyrant, oppressor, cruel person` }, // ظالم - zaalim
{ ts: 1527818632, e: `twin` }, // غبرګونی - ghbargoney
{ ts: 1527812624, e: `thief` }, // غل - ghul
{ ts: 1613561408232, e: `guilty, at fault` }, // قصوروار - qUsoorwáar
{ ts: 1527812724, e: `of Kabul (a person)` }, // کابلی - kaabuley
{ ts: 1527814715, e: `user` }, // کاروونکی - kaarawoonkey
{ ts: 1527816256, e: `great-grandson` }, // کړوسی - kaRwaséy
{ ts: 1594906790729, e: `child` }, // ککی - kakéy
{ ts: 1527819244, e: `host, hostess; master of house` }, // کوربه - korba
{ ts: 1527812174, e: `neighbour` }, // ګاونډی - gaawanDéy
{ ts: 1579030083953, e: `sinner, sinful` }, // ګناه ګار - gUnaahgáar
{ ts: 1527816249, e: `grandchild` }, // لمسی - lmaséy
{ ts: 1527822661, e: `athlete, player; actor; mischevious, playful (of a child)` }, // لوبغاړی - lobgháaRey
{ ts: 1589885143650, e: `fox` }, // لومبړ - loombáR
{ ts: 1527812043, e: `writer, author` }, // لیکوال - leekwaal
{ ts: 1527820680, e: `crazy, insane, mad person` }, // لېونی - lewanéy
{ ts: 1527812881, e: `child, kid` }, // ماشوم - maashoom
{ ts: 1527814445, e: `assigned, appointed, given orders or istructions (Arabic), authorized, sent on business; officer (as in government worker)` }, // مامور - maamóor
{ ts: 1527818760, e: `civil activist` }, // مدني فاعل - madanee faa'al
{ ts: 1527821523, e: `slave, servant` }, // مریی - mrayéy
{ ts: 1527814159, e: `friend, companion` }, // ملګری - malgúrey
{ ts: 1527820661, e: `mediator, go-between, arbitrator` }, // مېنځګړی - mendzgúRey
{ ts: 1527823403, e: `fan, someone who loves or appreciates someone or something` }, // مینه وال - meenawáal
{ ts: 1527815127, e: `nurse` }, // نرس - nurs
{ ts: 1527816254, e: `grandson` }, // نوسی - nwaséy
{ ts: 1527814806, e: `peer, someone of the same age` }, // همځولی - hamdzoléy ??
{ ts: 1527812684, e: `co-worker, fellow worker, collaborator, aid` }, // همکار - hamkaar
{ ts: 1527811732, e: `artist, performer` }, // هنر مند - hUnarmand
{ ts: 1527821373, e: `deer` }, // هوسی - hoséy
{ ts: 1591027046896, e: `goat` }, // وز - wuz
{ ts: 1611395180139, e: `fellow countryman, person from the same country` }, // وطندار - watandáar
{ ts: 1527811296, e: `lawyer, proxy holder` }, // وکیل - wakeel
{ ts: 1527813585, e: `person, human being, creature` }, // وګړی - wagúRey
{ ts: 1527814672, e: `spokesperson, spokesman, newcaster` }, // ویاند - wayaand
{ ts: 1586454081484, e: `orphan` }, // یتیم - yateem
];

File diff suppressed because one or more lines are too long

View File

@ -1566,10 +1566,10 @@
"@types/yargs" "^15.0.0"
chalk "^4.0.0"
"@lingdocs/pashto-inflector@^0.8.3":
version "0.8.3"
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-0.8.3.tgz#427cf38a2c8ae81a65dc8bd0d65445d317e8ad36"
integrity sha512-+8S5fEiJo3fC2/gp+IP09j3NZNBc5NuCV5FOWAGINEmg8NBKDVMa1gXnmuca6nVQsV2G4ZTk3UJyLwizq1RzDg==
"@lingdocs/pashto-inflector@^0.9.3":
version "0.9.4"
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-0.9.4.tgz#a05aa5151ec57550e1364377dff1b593039be76c"
integrity sha512-sn1TMGf8myoBr0NfRF5JtP//Y3A6cxwhVC8PtrZYgocYWA6lyB3H/R+ZblcUx7TCPwoH/aHIA365oKOpRDNMgw==
dependencies:
classnames "^2.2.6"
pbf "^3.2.1"
@ -9559,9 +9559,9 @@ property-information@^5.0.0, property-information@^5.3.0:
xtend "^4.0.0"
protocol-buffers-schema@^3.3.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.5.1.tgz#8388e768d383ac8cbea23e1280dfadb79f4122ad"
integrity sha512-YVCvdhxWNDP8/nJDyXLuM+UFsuPk4+1PB7WGPVDzm3HTHbzFLxQYeW2iZpS4mmnXrQJGBzt230t/BbEb7PrQaw==
version "3.5.2"
resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.5.2.tgz#38ad35ba768607a5ed2375f8db4c2ecc5ea293c8"
integrity sha512-LPzSaBYp/TcbuSlpGwqT5jR9kvJ3Zp5ic2N5c2ybx6XB/lSfEHq2D7ja8AgoxHoMD91wXFALJoXsvshKPuXyew==
proxy-addr@~2.0.5:
version "2.0.6"
@ -9679,9 +9679,9 @@ raf@^3.4.1:
performance-now "^2.1.0"
rambda@^6.7.0:
version "6.7.0"
resolved "https://registry.yarnpkg.com/rambda/-/rambda-6.7.0.tgz#50322efdd23a108b61eb6ac4e0868d10dd95b4aa"
integrity sha512-qg2atEwhAS4ipYoNfggkIP7qBUbY2OqdW17n25VqZIz5YC1MIwSpIToQ7XacvqSCZz16efM8Y8QKLx+Js1Sybg==
version "6.9.0"
resolved "https://registry.yarnpkg.com/rambda/-/rambda-6.9.0.tgz#17cd0b0c427295e00e8fe12de5bd63884502a9a4"
integrity sha512-yosVdGg1hNGkXPzqGiOYNEpXKjEOxzUCg2rB0l+NKdyCaSf4z+i5ojbN0IqDSezMMf71YEglI+ZUTgTffn5afw==
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
version "2.1.0"