From 1c3f9c2f627739688b5f94d69de429ff15cffaf6 Mon Sep 17 00:00:00 2001 From: lingdocs <71590811+lingdocs@users.noreply.github.com> Date: Wed, 24 Aug 2022 16:54:34 +0400 Subject: [PATCH] really basic present and subjunctive verb games --- package.json | 2 +- src/content/verbs/present-verbs.mdx | 6 + src/content/verbs/subjunctive-verbs.mdx | 6 + src/games/games.tsx | 9 +- src/games/sub-cores/VerbGame.tsx | 156 +++++++++++++----------- src/lib/shuffle-array.ts | 10 ++ yarn.lock | 8 +- 7 files changed, 122 insertions(+), 75 deletions(-) diff --git a/package.json b/package.json index aa38dc4..b0e5210 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.6", + "@lingdocs/pashto-inflector": "^3.7.9", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", diff --git a/src/content/verbs/present-verbs.mdx b/src/content/verbs/present-verbs.mdx index d450e10..aac828b 100644 --- a/src/content/verbs/present-verbs.mdx +++ b/src/content/verbs/present-verbs.mdx @@ -13,6 +13,10 @@ import Formula from "../../components/formula/Formula"; import realityGraph from "./reality-graph.svg"; import presentTime from "./present-time.svg"; import BasicVerbShowCase from "./../../components/BasicVerbShowCase"; +import { + presentVerbGame, +} from "../../games/games"; +import GameDisplay from "../../games/GameDisplay"; The first verb form we'll learn is the **present**. This will be the first tool in our toolbox of verb forms. 🧰 With each verb form we'll learn two things: @@ -118,4 +122,6 @@ Here are some examples of how the present form is used in different situations: }, ])} + + diff --git a/src/content/verbs/subjunctive-verbs.mdx b/src/content/verbs/subjunctive-verbs.mdx index e37af9a..0a09454 100644 --- a/src/content/verbs/subjunctive-verbs.mdx +++ b/src/content/verbs/subjunctive-verbs.mdx @@ -15,6 +15,10 @@ import Formula from "../../components/formula/Formula"; import presentInReality from "./present-in-reality.svg"; import subjunctiveAboveReality from "./subjunctive-above-reality.svg"; import BasicVerbShowCase from "../../components/BasicVerbShowCase"; +import { + subjunctiveVerbGame, +} from "../../games/games"; +import GameDisplay from "../../games/GameDisplay"; The **subjunctive** is a very important verb form in Pashto, but it's often ignored by English-speaking learners because we don't really have anything like it in English. So, we need to understand what it is, and then train our brains to reach for it and use it in the right situations! @@ -103,3 +107,5 @@ As you can see, the subjunctive is often used in [subordinate clauses](https://e - ...etc. + + diff --git a/src/games/games.tsx b/src/games/games.tsx index 1edf539..d559998 100644 --- a/src/games/games.tsx +++ b/src/games/games.tsx @@ -22,7 +22,13 @@ export const presentVerbGame = makeGameRecord( "present-verbs-write", "/verbs/present-verbs/", (id, link) => () => -) +); +export const subjunctiveVerbGame = makeGameRecord( + "Write the subjunctive verb", + "subjunctive-verbs-write", + "/verbs/subjunctive-verbs/", + (id, link) => () => +); export const nounGenderGame1 = makeGameRecord( "Identify Noun Genders - Level 1", @@ -149,6 +155,7 @@ const games: { chapter: string, items: GameRecord[] }[] = [ chapter: "Verbs", items: [ presentVerbGame, + subjunctiveVerbGame, ], } ]; diff --git a/src/games/sub-cores/VerbGame.tsx b/src/games/sub-cores/VerbGame.tsx index f3b4fe1..36d565e 100644 --- a/src/games/sub-cores/VerbGame.tsx +++ b/src/games/sub-cores/VerbGame.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useState } from "react"; import { comparePs, makeProgress, @@ -6,26 +6,23 @@ import { 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, + isInvalidSubjObjCombo, } from "@lingdocs/pashto-inflector"; -import { basicVerbs, intransitivePast } from "../../content/verbs/basic-present-verbs"; -import { psStringEquals } from "@lingdocs/pashto-inflector/dist/lib/p-text-helpers"; +import { isThirdPerson } from "@lingdocs/pashto-inflector/dist/lib/phrase-building/vp-tools"; +import { maybeShuffleArray } from "../../lib/shuffle-array"; const kidsColor = "#017BFE"; @@ -37,6 +34,12 @@ type Question = { phrase: { ps: T.SingleOrLengthOpts, e?: string[] }, }; +const verbs: T.VerbEntry[] = [ + {"ts":1527812856,"i":11630,"p":"لیکل","f":"leekul","g":"leekul","e":"to write, draw","c":"v. trans./gramm. trans.","ec":"write,writes,writing,wrote,written"}, + {"ts":1527815399,"i":14480,"p":"وهل","f":"wahul","g":"wahul","e":"to hit","c":"v. trans.","tppp":"واهه","tppf":"waahu","ec":"hit,hits,hitting,hit,hit"}, + {"ts":1527812275,"i":11608,"p":"لیدل","f":"leedul","g":"leedul","e":"to see","c":"v. trans./gramm. trans.","psp":"وین","psf":"ween","tppp":"لید","tppf":"leed","ec":"see,sees,seeing,saw,seen"}, + {"ts":1577049208257,"i":1068,"p":"اورېدل","f":"awredul","g":"awredul","e":"to hear, listen","c":"v. trans./gramm. trans.","psp":"اور","psf":"awr","tppp":"اورېد","tppf":"awred","ec":"hear,hears,hearing,heard"}, +].map(entry => ({ entry })) as T.VerbEntry[]; // @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"}, @@ -61,7 +64,7 @@ const pronounTypes = [ export default function VerbGame({ id, link, level }: { id: string, link: string, level: T.VerbTense }) { function* questions (): Generator> { let pool = [...pronounTypes]; - function makeRandPronoun(): T.PronounSelection { + function getRandPersFromPool(): T.Person { let person: T.Person; do { person = randomPerson(); @@ -71,11 +74,7 @@ export default function VerbGame({ id, link, level }: { id: string, link: string if (pool.length === 0) { pool = pronounTypes; } - return { - type: "pronoun", - distance: "far", - person, - }; + return person; } function makeRandomNoun(): T.NounSelection { const n = makeNounSelection(randFromArray(nouns), undefined); @@ -86,43 +85,48 @@ export default function VerbGame({ id, link, level }: { id: string, link: string }; } function makeRandomVPS(l: T.VerbTense): T.VPSelectionComplete { - function makePronoun(p: T.Person): T.PronounSelection { + function personToNPSelection(p: T.Person): T.NPSelection { + if (!isThirdPerson(p)) { + return { + type: "NP", + selection: randFromArray([ + () => makePronounS(p), + makeRandomNoun, + () => makePronounS(p), + ])(), + }; + } + return { + type: "NP", + selection: makePronounS(p), + }; + } + function makePronounS(p: T.Person): T.PronounSelection { return { type: "pronoun", person: p, - distance: "far", + distance: randFromArray(["far", "near", "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 verb = randFromArray(verbs); + const subj = getRandPersFromPool(); + let obj: T.Person; + do { + obj = randomPerson(); + } while (isInvalidSubjObjCombo(subj, obj)); // const tense = (l === "allIdentify" || l === "allProduce") // ? randFromArray(tenses) // : l; const tense = l; return makeVPS({ verb, - subject: makeNPSelection(makePronoun(subj)), - object: makeNPSelection(makePronoun(obj)), + subject: personToNPSelection(subj), + object: personToNPSelection(obj), tense, }); } for (let i = 0; i < amount; i++) { - const VPS = makeRandomVPS("presentVerb"); + const VPS = makeRandomVPS(level); const VP = renderVP(VPS); const compiled = compileVP( VP, @@ -144,7 +148,6 @@ export default function VerbGame({ id, link, level }: { id: string, link: string }; } - function Display({ question, callback }: QuestionDisplayProps) { const [answer, setAnswer] = useState(""); const [withBa, setWithBa] = useState(false); @@ -207,7 +210,7 @@ export default function VerbGame({ id, link, level }: { id: string, link: string function Instructions() { return
-

Write the present verb to complete the phrase

+

Write the {humanReadableVerbTense(level)} verb to complete the phrase

} @@ -221,12 +224,12 @@ export default function VerbGame({ id, link, level }: { id: string, link: string /> }; -function QuestionDisplay(question: Question) { +function QuestionDisplay({ question }: { question: Question }) { const ps = flattenLengths(question.phrase.ps)[0]; - return
+ return
{ps.p}
{ps.f}
- {question.phrase.e &&
+ {question.phrase.e &&
{question.phrase.e.map(x =>
{x}
)} @@ -248,33 +251,40 @@ function makeCorrectAnswer(question: Question): 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 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 humanReadableVerbTense(tense: T.VerbTense): string { + return tense === "presentVerb" + ? "present" + : tense === "subjunctiveVerb" + ? "subjunctive" + : tense === "imperfectiveFuture" + ? "imperfective future" + : tense === "perfectiveFuture" + ? "perfective future" + : tense === "perfectivePast" + ? "simple past" + : tense === "imperfectivePast" + ? "continuous past" + : tense === "habitualImperfectivePast" + ? "habitual simple past" + : "habitual continuous past"; } function makeVPS({ verb, subject, object, tense }: { @@ -284,13 +294,17 @@ function makeVPS({ verb, subject, object, tense }: { tense: T.VerbTense, }): T.VPSelectionComplete { const vps = makeVPSelectionState(verb); + const transitivity = (vps.verb.transitivity === "transitive" && vps.verb.canChangeTransitivity) + ? "grammatically transitive" + : vps.verb.transitivity; return { ...vps, verb: { ...vps.verb, + transitivity, tense, }, - blocks: [ + blocks: maybeShuffleArray([ { key: Math.random(), block: { @@ -302,10 +316,14 @@ function makeVPS({ verb, subject, object, tense }: { key: Math.random(), block: { type: "objectSelection", - selection: object, + selection: transitivity === "intransitive" + ? "none" + : transitivity === "grammatically transitive" + ? T.Person.ThirdPlurMale + : object, }, }, - ], + ]), }; } diff --git a/src/lib/shuffle-array.ts b/src/lib/shuffle-array.ts index 9d19bcf..b78e6bd 100644 --- a/src/lib/shuffle-array.ts +++ b/src/lib/shuffle-array.ts @@ -1,5 +1,7 @@ // https://stackoverflow.com/a/2450976 +import { randFromArray } from "@lingdocs/pashto-inflector"; + function shuffleArray(arr: Readonly>): Array { let currentIndex = arr.length, temporaryValue, randomIndex; @@ -21,4 +23,12 @@ function shuffleArray(arr: Readonly>): Array { return array; } +export function maybeShuffleArray(arr: Array): Array { + const shuffle = randFromArray([true, false, true, false, false]); + if (shuffle) { + return shuffleArray(arr); + } + return arr; +} + export default shuffleArray; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 1148a6e..0f8b6d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1803,10 +1803,10 @@ rambda "^6.7.0" react-select "^5.2.2" -"@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== +"@lingdocs/pashto-inflector@^3.7.9": + version "3.7.9" + resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-3.7.9.tgz#a1dc7b6635d9415d8dddfee9a09bb5b95190d7f0" + integrity sha512-2LKY5TRUs9h7nE9gQaUUiNV0eLOh5Tr4eJtYp2RGaxeMZhOZhVbbiXc+FV2BPe9bOEpYK3hy678RLBIx0C18nQ== dependencies: "@formkit/auto-animate" "^1.0.0-beta.1" classnames "^2.2.6"