From 55512ce7887ab65beeb360bb1ec020942c923f32 Mon Sep 17 00:00:00 2001 From: lingdocs <71590811+lingdocs@users.noreply.github.com> Date: Tue, 23 Aug 2022 17:31:48 +0400 Subject: [PATCH] u p --- package.json | 2 +- src/games/games.tsx | 14 ++ src/games/sub-cores/VerbGame.tsx | 323 +++++++++++++++++++++++++++++++ yarn.lock | 8 +- 4 files changed, 342 insertions(+), 5 deletions(-) create mode 100644 src/games/sub-cores/VerbGame.tsx diff --git a/package.json b/package.json index eb9baa3..aa38dc4 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "@formkit/auto-animate": "^1.0.0-beta.1", "@fortawesome/fontawesome-free": "^5.15.4", "@lingdocs/lingdocs-main": "^0.3.1", - "@lingdocs/pashto-inflector": "^3.7.3", + "@lingdocs/pashto-inflector": "^3.7.6", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", diff --git a/src/games/games.tsx b/src/games/games.tsx index 6928bed..1edf539 100644 --- a/src/games/games.tsx +++ b/src/games/games.tsx @@ -1,4 +1,5 @@ import EquativeGame from "./sub-cores/EquativeGame"; +import VerbGame from "./sub-cores/VerbGame"; import GenderGame from "./sub-cores/GenderGame"; import UnisexNounGame from "./sub-cores/UnisexNounGame"; @@ -16,6 +17,13 @@ function makeGameRecord( } } +export const presentVerbGame = makeGameRecord( + "Write the present verb", + "present-verbs-write", + "/verbs/present-verbs/", + (id, link) => () => +) + export const nounGenderGame1 = makeGameRecord( "Identify Noun Genders - Level 1", "gender-nouns-1", @@ -137,6 +145,12 @@ const games: { chapter: string, items: GameRecord[] }[] = [ equativeGameAllProduce, ], }, + { + chapter: "Verbs", + items: [ + presentVerbGame, + ], + } ]; export default games; diff --git a/src/games/sub-cores/VerbGame.tsx b/src/games/sub-cores/VerbGame.tsx new file mode 100644 index 0000000..f3b4fe1 --- /dev/null +++ b/src/games/sub-cores/VerbGame.tsx @@ -0,0 +1,323 @@ +import { useEffect, useState } from "react"; +import { + comparePs, + makeProgress, +} from "../../lib/game-utils"; +import GameCore from "../GameCore"; +import { + Types as T, + Examples, + defaultTextOptions as opts, + typePredicates as tp, + makeNounSelection, + randFromArray, + renderEP, + compileEP, + flattenLengths, + randomPerson, + InlinePs, + grammarUnits, + randomSubjObj, + renderVP, + makeVPSelectionState, + compileVP, + blockUtils, + concatPsString, +} from "@lingdocs/pashto-inflector"; +import { basicVerbs, intransitivePast } from "../../content/verbs/basic-present-verbs"; +import { psStringEquals } from "@lingdocs/pashto-inflector/dist/lib/p-text-helpers"; + +const kidsColor = "#017BFE"; + +const amount = 10; +const timeLimit = 80; + +type Question = { + rendered: T.VPRendered, + phrase: { ps: T.SingleOrLengthOpts, e?: string[] }, +}; + +// @ts-ignore +const nouns: T.NounEntry[] = [ + {"ts":1527815251,"i":7790,"p":"سړی","f":"saRéy","g":"saRey","e":"man","c":"n. m.","ec":"man","ep":"men"}, + {"ts":1527812797,"i":8605,"p":"ښځه","f":"xúdza","g":"xudza","e":"woman, wife","c":"n. f.","ec":"woman","ep":"women"}, + {"ts":1527812881,"i":11691,"p":"ماشوم","f":"maashoom","g":"maashoom","e":"child, kid","c":"n. m. anim. unisex","ec":"child","ep":"children"}, + {"ts":1527815197,"i":2503,"p":"پښتون","f":"puxtoon","g":"puxtoon","e":"Pashtun","c":"n. m. anim. unisex / adj.","infap":"پښتانه","infaf":"puxtaanu","infbp":"پښتن","infbf":"puxtan"}, + {"ts":1527815737,"i":484,"p":"استاذ","f":"Ustaaz","g":"Ustaaz","e":"teacher, professor, expert, master (in a field)","c":"n. m. anim. unisex anim.","ec":"teacher"}, + {"ts":1527816747,"i":6418,"p":"ډاکټر","f":"DaakTar","g":"DaakTar","e":"doctor","c":"n. m."}, + {"ts":1527812661,"i":13938,"p":"هلک","f":"halík, halúk","g":"halik,haluk","e":"boy, young lad","c":"n. m. anim."}, +].filter(tp.isNounEntry); + +const pronounTypes = [ + [T.Person.FirstSingMale, T.Person.FirstSingFemale], + [T.Person.SecondSingMale, T.Person.SecondSingFemale], + [T.Person.ThirdSingMale], + [T.Person.ThirdSingFemale], + [T.Person.FirstPlurMale, T.Person.FirstPlurFemale], + [T.Person.SecondPlurMale, T.Person.SecondPlurFemale], + [T.Person.ThirdPlurMale, T.Person.ThirdPlurFemale], +]; + +export default function VerbGame({ id, link, level }: { id: string, link: string, level: T.VerbTense }) { + function* questions (): Generator> { + let pool = [...pronounTypes]; + function makeRandPronoun(): T.PronounSelection { + let person: T.Person; + do { + person = randomPerson(); + // eslint-disable-next-line + } while (!pool.some(p => p.includes(person))); + pool = pool.filter(p => !p.includes(person)); + if (pool.length === 0) { + pool = pronounTypes; + } + return { + type: "pronoun", + distance: "far", + person, + }; + } + function makeRandomNoun(): T.NounSelection { + const n = makeNounSelection(randFromArray(nouns), undefined); + return { + ...n, + gender: n.genderCanChange ? randFromArray(["masc", "fem"]) : n.gender, + number: n.numberCanChange ? randFromArray(["singular", "plural"]) : n.number, + }; + } + function makeRandomVPS(l: T.VerbTense): T.VPSelectionComplete { + function makePronoun(p: T.Person): T.PronounSelection { + return { + type: "pronoun", + person: p, + distance: "far", + }; + } + function makeNPSelection(pr: T.PronounSelection): T.NPSelection { + return { + type: "NP", + selection: pr, + }; + } + const verb = randFromArray(basicVerbs); + const { subj, obj } = randomSubjObj(); + // const subj: T.NPSelection = { + // type: "NP", + // selection: randFromArray([ + // makeRandPronoun, + // makeRandPronoun, + // makeRandomNoun, + // makeRandPronoun, + // ])(), + // }; + // const tense = (l === "allIdentify" || l === "allProduce") + // ? randFromArray(tenses) + // : l; + const tense = l; + return makeVPS({ + verb, + subject: makeNPSelection(makePronoun(subj)), + object: makeNPSelection(makePronoun(obj)), + tense, + }); + } + for (let i = 0; i < amount; i++) { + const VPS = makeRandomVPS("presentVerb"); + const VP = renderVP(VPS); + const compiled = compileVP( + VP, + { removeKing: false, shrinkServant: false }, + true, + "verb", + ); + const phrase = { + ps: compiled.ps, + e: compiled.e, + }; + yield { + progress: makeProgress(i, amount), + question: { + rendered: VP, + phrase, + }, + }; + }; + } + + + function Display({ question, callback }: QuestionDisplayProps) { + const [answer, setAnswer] = useState(""); + const [withBa, setWithBa] = useState(false); + const handleInput = ({ target: { value }}: React.ChangeEvent) => { + setAnswer(value); + } + const handleSubmit = (e: React.FormEvent) => { + if ("situation" in question) { + return; + } + e.preventDefault(); + const correct = comparePs(answer, getVerbPs(question.rendered)) + && (withBa === verbHasBa(question.rendered)); + if (correct) { + setAnswer(""); + } + callback(!correct ? makeCorrectAnswer(question) : true); + } + // useEffect(() => { + // if (level === "allProduce") setWithBa(false); + // }, [question]); + return
+ +
+
+ setWithBa(e.target.checked)} + /> + +
+
+ +
+
+ {/*
*/} + + {/*
*/} + {/*
+ Type Enter to check +
*/} +
+
+
+ } + + function Instructions() { + return
+

Write the present verb to complete the phrase

+
+ } + + return +}; + +function QuestionDisplay(question: Question) { + const ps = flattenLengths(question.phrase.ps)[0]; + return
+
{ps.p}
+
{ps.f}
+ {question.phrase.e &&
+ {question.phrase.e.map(x =>
+ {x} +
)} +
} +
; +} + +function makeCorrectAnswer(question: Question): JSX.Element { + return
+
+ {getVerbPs(question.rendered).reduce(((accum, curr, i): JSX.Element[] => ( + [ + ...accum, + ...i > 0 ? [ or ] : [], + {curr.p}, + ] + )), [] as JSX.Element[])} +
+
{verbHasBa(question.rendered) ? "with" : "without"} a {grammarUnits.baParticle} in the kids' section.
+
; +} +function modExs(exs: T.PsString[], withBa: boolean): { p: JSX.Element, f: JSX.Element }[] { + return exs.map(ps => { + if (!ps.p.includes(" ___ ")) { + return { + p: <>{ps.p}, + f: <>{ps.f}, + }; + } + const splitP = ps.p.split(" ___ "); + const splitF = ps.f.split(" ___ "); + return { + p: <>{splitP[0]} {withBa ? "به" : "__"} {splitP[1]}, + f: <>{splitF[0]} {withBa ? "ba" : "__"} {splitF[1]}, + }; + }); +} + +function humanReadableTense(tense: T.EquativeTense | "allProduce"): string { + return tense === "allProduce" + ? "" + : tense === "pastSubjunctive" + ? "past subjunctive" + : tense === "wouldBe" + ? `"would be"` + : tense === "wouldHaveBeen" + ? `"would have been"` + : tense; +} + +function makeVPS({ verb, subject, object, tense }: { + verb: T.VerbEntry, + subject: T.NPSelection, + object: T.NPSelection, + tense: T.VerbTense, +}): T.VPSelectionComplete { + const vps = makeVPSelectionState(verb); + return { + ...vps, + verb: { + ...vps.verb, + tense, + }, + blocks: [ + { + key: Math.random(), + block: { + type: "subjectSelection", + selection: subject, + }, + }, + { + key: Math.random(), + block: { + type: "objectSelection", + selection: object, + }, + }, + ], + }; +} + +function getVerbPs({ blocks }: T.VPRendered): T.PsString[] { + const { perfectiveHead, verb } = blockUtils.getVerbAndHeadFromBlocks(blocks); + if (!perfectiveHead) { + return flattenLengths(verb.block.ps); + } + return flattenLengths(verb.block.ps).map(r => concatPsString(perfectiveHead.ps, r)); +} + +function verbHasBa({ blocks }: T.VPRendered): boolean { + const verb = blockUtils.getVerbFromBlocks(blocks); + return verb.block.hasBa; +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index da9135b..1148a6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1803,10 +1803,10 @@ rambda "^6.7.0" react-select "^5.2.2" -"@lingdocs/pashto-inflector@^3.6.8": - version "3.6.8" - resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-3.6.8.tgz#8e6cde1730d96458117f4efda9874b7ced329c36" - integrity sha512-wgS8AGad1fa+T4rEQRmbP9iV1jyRfLaT18fnFr1WjF4RC/B+U6Imr5ykKXV2pMQd/6yVi26yJFd8iFvRe3KybQ== +"@lingdocs/pashto-inflector@^3.7.5": + version "3.7.5" + resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-3.7.5.tgz#6421b88ccf544cdbc7f4cefc66ff75b3b7f1bb44" + integrity sha512-36ULd7ETZBz9/gs2K1s2XJFzEA3kDZfR9rPPN6B5oJvW9yAZXfgaJg9W2jzhodfu2WS3lpQvizis8zQjPioV8w== dependencies: "@formkit/auto-animate" "^1.0.0-beta.1" classnames "^2.2.6"