diff --git a/package.json b/package.json index 74b16c7..2738666 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.3", - "@lingdocs/ps-react": "^5.3.1", + "@lingdocs/ps-react": "^5.3.3", "@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/WordCard.tsx b/src/components/WordCard.tsx new file mode 100644 index 0000000..cf00d0e --- /dev/null +++ b/src/components/WordCard.tsx @@ -0,0 +1,48 @@ +import { + Types as T, + Examples, + defaultTextOptions as opts, + firstVariation, + removeFVarients, + getInflectionPattern, + HumanReadableInflectionPattern, +} from "@lingdocs/ps-react"; + +function WordCard({ showHint, entry, selection }: { + showHint: boolean +} & ({ + entry: T.AdjectiveEntry, + selection: undefined, +} | { + entry: T.NounEntry, + selection: T.NounSelection, +})) { + const e = removeFVarients(entry); + return
+
+ {[ + { + p: e.p, + f: e.f, + e: `${firstVariation(e.e)} - ${e.c}`, + } + ]} + {selection &&
+ {selection.genderCanChange && selection.gender === "fem" + && feminine} + {selection.numberCanChange && selection.number === "plural" + && plural} +
} + {showHint && } +
+
; +} + +function EntryCategoryTip({ entry }: { entry: T.AdjectiveEntry | T.NounEntry }) { + const pattern = getInflectionPattern(entry); + return
+ {HumanReadableInflectionPattern(pattern, opts)} +
; +} + +export default WordCard; \ No newline at end of file diff --git a/src/games/games.tsx b/src/games/games.tsx index ee2b57c..73a90f1 100644 --- a/src/games/games.tsx +++ b/src/games/games.tsx @@ -10,6 +10,7 @@ import InflectionPatterns from "./sub-cores/InflectionPatterns"; import InflectionsWriting from "./sub-cores/InflectionsWriting"; import PerfectVerbsIntransitive from "./sub-cores/PerfectGame"; import NPAdjWriting from "./sub-cores/NPAdjGame"; +import EPAdjGame from "./sub-cores/EPAdjGame"; // NOUNS @@ -398,8 +399,22 @@ export const perfectGameMix = makeGameRecord({ }); // ADJECTIVES +export const epWithAdjectivesHints = makeGameRecord({ + title: "Write the adjective to match the subject (with inf. pattern hints)", + id: "adjective-predicate-hints", + link: "/inflection/inflection-patterns/", + level: "hints", + SubCore: EPAdjGame, +}); +export const epWithAdjectives = makeGameRecord({ + title: "Write the predicate adjective to match the subject", + id: "adjective-predicate", + link: "/inflection/inflection-patterns/", + level: "no-hints", + SubCore: EPAdjGame, +}); export const npWithAdjectivesHints = makeGameRecord({ - title: "Write the adjective and noun togehter (with inflection hints)", + title: "Write the adjective and noun togehter (with inf. pattern hints)", id: "adjective-nps-hints", link: "/phrase-structure/np/", level: "hints", @@ -493,6 +508,8 @@ const games: { chapter: string, items: GameRecord[] }[] = [ { chapter: "Adjectives", items: [ + epWithAdjectivesHints, + epWithAdjectives, npWithAdjectivesHints, npWithAdjectivesNoHints, ], diff --git a/src/games/sub-cores/EPAdjGame.tsx b/src/games/sub-cores/EPAdjGame.tsx new file mode 100644 index 0000000..04bb8d3 --- /dev/null +++ b/src/games/sub-cores/EPAdjGame.tsx @@ -0,0 +1,224 @@ +import { useState } from "react"; +import { + comparePs, +} from "../../lib/game-utils"; +import GameCore from "../GameCore"; +import { + Types as T, + renderEP, + compileEP, + randFromArray, + defaultTextOptions as opts, + Examples, + blank, + isPashtoScript, +} from "@lingdocs/ps-react"; +import { wordQuery } from "../../words/words"; +import { makePool } from "../../lib/pool"; +import { getPredicateSelectionFromBlocks } from "@lingdocs/ps-react/dist/lib/src/phrase-building/blocks-utils"; +import WordCard from "../../components/WordCard"; + +const amount = 12; +const timeLimit = 140; + +const pronouns: T.Person[] = [ + 0, 1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 11, +]; + +const adjectives = wordQuery("adjectives", [ + "muR", + "sheen", + "soor", + "rixtooney", + "stuRey", + "ghuT", + "xu", + "khufa", + "takRa", + "puT", + "tuGey", + "koochney", + "pradey", + "zoR", + "moR", + "khoG", + "droond", + "loomRey", + "Roond", + "prot", + "soR", + "post", + "pokh", + "rooN", + "woR", + "kooN", + "koG", +]); + +type Question = { + EPS: T.EPSelectionComplete, + phrase: { ps: T.PsString[], e?: string[] }, + adjective: T.Rendered, +}; + +export default function EPAdjGame({ inChapter, id, link, level }: { inChapter: boolean, id: string, link: string, level: "hints" | "no-hints" }) { + const pronounPool = makePool(pronouns); + const adjPool = makePool(adjectives); + function getQuestion(): Question { + const subject: T.NPSelection = { + type: "NP", + selection: { + type: "pronoun", + person: pronounPool(), + distance: randFromArray(["far", "far", "near"]), + }, + }; + const EPS = makeEPS(subject, adjPool(), "present"); + const EP = renderEP(EPS); + const compiled = compileEP( + EP, + true, + { predicate: true }, + ); + const phrase = { + ps: compiled.ps, + e: compiled.e, + }; + return { + EPS, + phrase, + adjective: getAdjectiveFromRendered(EP), + }; + }; + + function Display({ question, callback }: QuestionDisplayProps) { + const [answer, setAnswer] = useState(""); + const handleInput = ({ target: { value }}: React.ChangeEvent) => { + setAnswer(value); + } + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + const correct = comparePs(answer, question.adjective.ps); + if (correct) { + setAnswer(""); + } + callback(correct); + } + + return
+
+ { + addUserAnswer(answer, question.phrase.ps[0]) + } + {question.phrase.e && question.phrase.e.map((e, i) => ( +
{e}
+ ))} +
+
+ +
+
+
+ +
+
+ +
+
+
+ } + + function Instructions() { + return
+

+ Fill in the blank with the correct inflection of the adjective +

+
; + } + + return +}; + +function DisplayCorrectAnswer({ question }: { question: Question }): JSX.Element { + return
+
+ {question.adjective.ps.reduce(((accum, curr, i): JSX.Element[] => ( + [ + ...accum, + ...i > 0 ? [ or ] : [], + {curr.p}, + ] + )), [] as JSX.Element[])} +
+
; +} + +function addUserAnswer(a: string, ps: T.PsString): T.PsString { + if (!a) return ps; + const field = isPashtoScript(a) ? "p" : "f"; + return { + ...ps, + [field]: ps[field].replace(blank[field], a), + }; +} + +function getAdjectiveFromRendered(EP: T.EPRendered): T.Rendered { + const pred = getPredicateSelectionFromBlocks(EP.blocks); + if (pred.selection.type !== "complement" || pred.selection.selection.type !== "adjective") { + throw new Error("adjective not found in predicate"); + } + return pred.selection.selection; +} + +function makeEPS(subject: T.NPSelection, predicate: T.AdjectiveEntry, tense: T.EquativeTense): T.EPSelectionComplete { + return { + blocks: [ + { + key: Math.random(), + block: { + type: "subjectSelection", + selection: subject, + }, + }, + ], + predicate: { + type: "predicateSelection", + selection: { + type: "complement", + selection: { + type: "adjective", + entry: predicate, + sandwich: undefined, + }, + }, + }, + equative: { + tense, + negative: false, + }, + omitSubject: false, + }; +} \ No newline at end of file diff --git a/src/games/sub-cores/NPAdjGame.tsx b/src/games/sub-cores/NPAdjGame.tsx index 19c9558..4240bfd 100644 --- a/src/games/sub-cores/NPAdjGame.tsx +++ b/src/games/sub-cores/NPAdjGame.tsx @@ -1,19 +1,14 @@ import GameCore from "../GameCore"; import { Types as T, - Examples, - defaultTextOptions as opts, - firstVariation, renderNPSelection, getEnglishFromRendered, - removeFVarients, concatPsString, - getInflectionPattern, - HumanReadableInflectionPattern, } from "@lingdocs/ps-react"; import { makeNPAdjGenerator } from "../../lib/np-adj-generator"; import { useState } from "react"; import { comparePs } from "../../lib/game-utils"; +import WordCard from "../../components/WordCard"; const amount = 15; const timeLimit = 230; @@ -38,9 +33,6 @@ const NPAdjWriting: GameSubCore = ({ inChapter, id, link, level }: { }) => { const npPool = makeNPAdjGenerator(); - // todo زړې ډاکټرې should work! - // feminineplural space issue - function getQuestion(): Question { const np = npPool(); const rendered = renderNPSelection(np, false, false, "subject", "none", false); @@ -153,41 +145,4 @@ function DisplayCorrectAnswer({ question }: { question: Question }): JSX.Element ; } -function WordCard({ showHint, entry, selection }: { - showHint: boolean -} & ({ - entry: T.AdjectiveEntry, - selection: undefined, -} | { - entry: T.NounEntry, - selection: T.NounSelection, -})) { - const e = removeFVarients(entry); - return
-
- {[ - { - p: e.p, - f: e.f, - e: `${firstVariation(e.e)} - ${e.c}`, - } - ]} - {selection &&
- {selection.genderCanChange && selection.gender === "fem" - && feminine} - {selection.numberCanChange && selection.number === "plural" - && plural} -
} - {showHint && } -
-
; -} - -function EntryCategoryTip({ entry }: { entry: T.AdjectiveEntry | T.NounEntry }) { - const pattern = getInflectionPattern(entry); - return
- {HumanReadableInflectionPattern(pattern, opts)} -
; -} - export default NPAdjWriting; diff --git a/src/games/sub-cores/VerbGame.tsx b/src/games/sub-cores/VerbGame.tsx index 5f32145..2aab711 100644 --- a/src/games/sub-cores/VerbGame.tsx +++ b/src/games/sub-cores/VerbGame.tsx @@ -350,22 +350,7 @@ function DisplayCorrectAnswer({ question }: { 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 addUserAnswer(a: { withBa: boolean, answer: string }, ps: T.PsString): T.PsString { function addBa(x: T.PsString) { diff --git a/src/lib/np-adj-generator.ts b/src/lib/np-adj-generator.ts index dc3019e..dc6b9d3 100644 --- a/src/lib/np-adj-generator.ts +++ b/src/lib/np-adj-generator.ts @@ -58,7 +58,6 @@ const adjectives = wordQuery("adjectives", [ "droond", "loomRey", "Roond", - "droond", "prot", "soR", "post", diff --git a/yarn.lock b/yarn.lock index 4b320bd..f1a4306 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2726,10 +2726,10 @@ rambda "^6.7.0" react-select "^5.2.2" -"@lingdocs/ps-react@^5.3.1": - version "5.3.1" - resolved "https://npm.lingdocs.com/@lingdocs%2fps-react/-/ps-react-5.3.1.tgz#a8836d00df5ca884d8b26dd4caae7c720269ce26" - integrity sha512-JY0BQLnxKNjxqHlf7uvmH2ehmbbPvGoWdcxK68ZEZbwbXP0WXHmyFUji6hB9oRHtwrE8MS7guVX0e3/eZTolEA== +"@lingdocs/ps-react@^5.3.3": + version "5.3.3" + resolved "https://npm.lingdocs.com/@lingdocs%2fps-react/-/ps-react-5.3.3.tgz#05066c27059b5133dc0028d733d6dddfbfc9f9b0" + integrity sha512-qsX9iRqSc62JGDuBNvddfZgX3Skk5MM8XtuaydnyK3A7LZrP9VuiJZ0+k6zvi2shi+Gg52aAEPJstEieycBKrA== dependencies: "@formkit/auto-animate" "^1.0.0-beta.3" classnames "^2.2.6"