From 40089f76a2506bfc559aaced161d84be4c6d1c9a Mon Sep 17 00:00:00 2001 From: lingdocs <71590811+lingdocs@users.noreply.github.com> Date: Tue, 30 Aug 2022 19:08:17 +0400 Subject: [PATCH] up --- package.json | 2 +- src/components/BasicVerbShowCase.tsx | 4 +- src/content/verbs/basic-present-verbs.ts | 2 +- src/games/GamesBrowser.tsx | 6 +- src/games/games.tsx | 14 +++++ src/games/sub-cores/VerbGame.tsx | 80 +++++++++++++----------- src/lib/game-utils.ts | 4 +- src/lib/pool.ts | 39 ++++++++++++ yarn.lock | 8 +-- 9 files changed, 112 insertions(+), 47 deletions(-) create mode 100644 src/lib/pool.ts diff --git a/package.json b/package.json index 6e48740..de58cab 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.8.4", + "@lingdocs/pashto-inflector": "^3.8.7", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", diff --git a/src/components/BasicVerbShowCase.tsx b/src/components/BasicVerbShowCase.tsx index 57a8181..89fd6f3 100644 --- a/src/components/BasicVerbShowCase.tsx +++ b/src/components/BasicVerbShowCase.tsx @@ -16,7 +16,7 @@ import { import { isImperativeTense, isPerfectTense } from "@lingdocs/pashto-inflector/dist/lib/type-predicates"; import { useState } from "react"; import Carousel from "./Carousel"; -import { basicVerbs, intransitivePast } from "../content/verbs/basic-present-verbs"; +import { basicVerbs, intransitivePastVerbs } from "../content/verbs/basic-present-verbs"; import { getLength } from "@lingdocs/pashto-inflector/dist/lib/p-text-helpers"; import { isThirdPerson } from "@lingdocs/pashto-inflector/dist/lib/phrase-building/vp-tools"; @@ -27,7 +27,7 @@ function BasicVerbShowCase({ opts, tense, passive, ability }: { ability?: boolean, }) { const items = isPastTense(tense) - ? intransitivePast + ? intransitivePastVerbs : (passive ? basicVerbs.filter(v => v.entry.p !== "کول") : basicVerbs); return { return { diff --git a/src/content/verbs/basic-present-verbs.ts b/src/content/verbs/basic-present-verbs.ts index 6272635..6d273c3 100644 --- a/src/content/verbs/basic-present-verbs.ts +++ b/src/content/verbs/basic-present-verbs.ts @@ -14,7 +14,7 @@ export const basicVerbs: T.VerbEntry[] = [ ].map(entry => ({ entry })); // @ts-ignore -export const intransitivePast: T.VerbEntry[] = [ +export const intransitivePastVerbs: T.VerbEntry[] = [ {"ts":1527813573,"i":6809,"p":"رسېدل","f":"rasedul","g":"rasedul","e":"arrive, reached; (fig.) understand, attain to; mature, ripen","c":"v. intrans.","shortIntrans":true,"ec":"arrive"}, {"ts":1527812645,"i":10822,"p":"ګرځېدل","f":"gurdzedul","g":"gurdzedul","e":"to walk, wander, turn about; to become, to be","c":"v. intrans.","shortIntrans":true,"ec":"walk"}, {"ts":1527816495,"i":3470,"p":"تښتېدل","f":"tuxtedul","g":"tuxtedul","e":"to run off, escape, flee","c":"v. intrans.","shortIntrans":true,"ec":"escape"}, diff --git a/src/games/GamesBrowser.tsx b/src/games/GamesBrowser.tsx index 0f5bbdb..290df4e 100644 --- a/src/games/GamesBrowser.tsx +++ b/src/games/GamesBrowser.tsx @@ -54,13 +54,13 @@ function ChapterDisplay({ chapter, user, handleClick, expanded }: { return
-

handleTitleClick(id)}> +

handleTitleClick(id)}> {title} {` `} -
+
-

+

{done ? "✅" : {"📚"} diff --git a/src/games/games.tsx b/src/games/games.tsx index c8b14b7..a02d979 100644 --- a/src/games/games.tsx +++ b/src/games/games.tsx @@ -41,6 +41,18 @@ export const imperativeVerbGame = makeGameRecord( "/verbs/imperative-verbs/", (id, link) => () => ); +export const intransitivePerfectivePastVerbGame = makeGameRecord( + "Write the intransitive simple past verb", + "intransitive-perfective-past-verbs-write", + "/verbs/past-verbs/#past-tense-with-transitive-verbs-", + (id, link) => () => +); +export const intransitiveImperfectivePastVerbGame = makeGameRecord( + "Write the intransitive continuous past verb", + "transitive-imperfective-past-verbs-write", + "/verbs/past-verbs/#past-tense-with-transitive-verbs-", + (id, link) => () => +); export const nounGenderGame1 = makeGameRecord( "Identify Noun Genders - Level 1", @@ -170,6 +182,8 @@ const games: { chapter: string, items: GameRecord[] }[] = [ subjunctiveVerbGame, futureVerbGame, imperativeVerbGame, + intransitiveImperfectivePastVerbGame, + intransitivePerfectivePastVerbGame, ], } ]; diff --git a/src/games/sub-cores/VerbGame.tsx b/src/games/sub-cores/VerbGame.tsx index 3edd99d..c56f5c9 100644 --- a/src/games/sub-cores/VerbGame.tsx +++ b/src/games/sub-cores/VerbGame.tsx @@ -34,6 +34,8 @@ import { isThirdPerson } from "@lingdocs/pashto-inflector/dist/lib/phrase-buildi import { maybeShuffleArray } from "../../lib/shuffle-array"; import { getVerbFromBlocks } from "@lingdocs/pashto-inflector/dist/lib/phrase-building/blocks-utils"; import { baParticle } from "@lingdocs/pashto-inflector/dist/lib/grammar-units"; +import { intransitivePastVerbs } from "../../content/verbs/basic-present-verbs"; +import { makePool } from "../../lib/pool"; const kidsColor = "#017BFE"; @@ -66,45 +68,47 @@ const nouns: T.NounEntry[] = [ {"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], +const persons = [ + 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, ]; -const secondPersonPronounTypes = [ - [T.Person.SecondSingMale, T.Person.SecondSingFemale], - [T.Person.SecondPlurMale, T.Person.SecondPlurFemale], +const secondPersons = [ + T.Person.SecondSingMale, + T.Person.SecondSingFemale, + T.Person.SecondPlurMale, + T.Person.SecondPlurFemale, ]; -type VerbGameLevel = "presentVerb" | "subjunctiveVerb" | "futureVerb" | "imperative"; +type VerbGameLevel = "presentVerb" | "subjunctiveVerb" + | "futureVerb" | "imperative" | "intransitivePerfectivePast" | "intransitiveImperfectivePast"; export default function VerbGame({ id, link, level }: { id: string, link: string, level: VerbGameLevel, }) { - const poolBase = level === "imperative" - ? secondPersonPronounTypes - : pronounTypes; function* questions (): Generator> { - let pool = [...poolBase]; - function getRandPersFromPool(): T.Person { - 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 = poolBase; - } - return person; - } + const personPool = makePool(level === "imperative" + ? secondPersons + : persons + ); + const verbPool = makePool( + level.includes("intransitive") + ? intransitivePastVerbs + : verbs, + 30, + ); function makeRandomNoun(): T.NounSelection { const n = makeNounSelection(randFromArray(nouns), undefined); return { @@ -137,8 +141,8 @@ export default function VerbGame({ id, link, level }: { distance: randFromArray(["far", "near", "far"]), }; } - const verb = randFromArray(verbs); - const subj = getRandPersFromPool(); + const verb = verbPool(); + const subj = personPool(); let obj: T.Person; do { obj = randomPerson(); @@ -184,9 +188,6 @@ export default function VerbGame({ id, link, level }: { 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)); @@ -347,6 +348,10 @@ function levelToDescription(level: VerbGameLevel): string { ? "subjunctive" : level === "futureVerb" ? "imperfective future or perfective future" + : level === "intransitivePerfectivePast" + ? "simple past intransitive" + : level === "intransitiveImperfectivePast" + ? "continuous past intransitive" : "imperfective imperative or perfective imperative"; } @@ -357,8 +362,12 @@ function levelToTense(level: VerbGameLevel): T.VerbTense | T.ImperativeTense { ? level : level === "futureVerb" ? randFromArray(["perfectiveFuture", "imperfectiveFuture"]) - // : level === "imperative" - : randFromArray(["perfectiveImperative", "imperfectiveImperative"]); + : level === "imperative" + ? randFromArray(["perfectiveImperative", "imperfectiveImperative"]) + : level.includes("ImperfectivePast") + ? "imperfectivePast" + // : level.includes("perfectivePast") + : "perfectivePast"; } function makeVPS({ verb, subject, object, tense }: { @@ -371,6 +380,7 @@ function makeVPS({ verb, subject, object, tense }: { const transitivity = (vps.verb.transitivity === "transitive" && vps.verb.canChangeTransitivity) ? "grammatically transitive" : vps.verb.transitivity; + console.log({ transitivity }); return { ...vps, verb: { diff --git a/src/lib/game-utils.ts b/src/lib/game-utils.ts index 74529be..5dae75d 100644 --- a/src/lib/game-utils.ts +++ b/src/lib/game-utils.ts @@ -53,6 +53,8 @@ export function comparePs(input: string, answer: T.SingleOrLengthOpts comparePs(input, a)); } - const stand = standardizePhonetics(standardizePashto(input)).trim(); + const stand = standardizePhonetics( + standardizePashto(input) + ).trim(); return stand === answer.p || compareF(stand, answer.f); } \ No newline at end of file diff --git a/src/lib/pool.ts b/src/lib/pool.ts new file mode 100644 index 0000000..ffb9baf --- /dev/null +++ b/src/lib/pool.ts @@ -0,0 +1,39 @@ +import { randFromArray } from "@lingdocs/pashto-inflector"; + +/** + * + * @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 + * 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. + * @returns + */ +export function makePool

(poolBase: P[], removalLaxity = 0): () => P { + let pool = [...poolBase]; + function shouldStillKeepIt() { + return Math.random() < (removalLaxity / 100); + } + function pickRandomFromPool(): P { + // Pick an item from the pool; + const pick = randFromArray(pool); + // Remove the (first occurance of) the item from the pool + // This step might be skipped if the removal laxity is set + if (removalLaxity && !shouldStillKeepIt()) { + const index = pool.findIndex(v => matches(v, pick)) + if (index === -1) throw new Error("could not find pick from pool"); + pool.splice(index, 1); + // If the pool is empty, reset it + if (pool.length === 0) { + pool = [...poolBase]; + } + } + return pick; + } + return pickRandomFromPool; +} + +function matches(a: unknown, b: unknown): boolean { + return JSON.stringify(a) === JSON.stringify(b); +} + + diff --git a/yarn.lock b/yarn.lock index eee0d21..4745212 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1803,10 +1803,10 @@ rambda "^6.7.0" react-select "^5.2.2" -"@lingdocs/pashto-inflector@^3.8.4": - version "3.8.4" - resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-3.8.4.tgz#2a29b04c541f3d12842ae2dabc3bc1e71a1b77ad" - integrity sha512-YVH+LFX4UslcQnNfYbmE9vX+bsq/LFylnxk3lEMLDLRW/abRmWlcPcElJr2wXYm3VR5uoLCK463ulS7IhQoUeQ== +"@lingdocs/pashto-inflector@^3.8.7": + version "3.8.7" + resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-3.8.7.tgz#9f9a28718f82620a74c4d7732232bd716cf0fd85" + integrity sha512-rVjQole0oQpsGBZOqQ7btO80mbL04JhHC6z21G0vLYAswOe4OFdnQyBfKztMclYKiJV2vdtWLXpjjdIPt+Ypbg== dependencies: "@formkit/auto-animate" "^1.0.0-beta.1" classnames "^2.2.6"