diff --git a/src/games/sub-cores/InflectionsWriting.tsx b/src/games/sub-cores/InflectionsWriting.tsx index e5b544d..c245179 100644 --- a/src/games/sub-cores/InflectionsWriting.tsx +++ b/src/games/sub-cores/InflectionsWriting.tsx @@ -1,14 +1,14 @@ import GameCore from "../GameCore"; import { - Types as T, - getInflectionPattern, - Examples, - defaultTextOptions as opts, - firstVariation, - inflectWord, - HumanReadableInflectionPattern, - isUnisexSet, - InflectionsTable, + Types as T, + getInflectionPattern, + Examples, + defaultTextOptions as opts, + firstVariation, + inflectWord, + HumanReadableInflectionPattern, + isUnisexSet, + InflectionsTable, } from "@lingdocs/ps-react"; import { makePool } from "../../lib/pool"; import { nouns, adjectives } from "../../words/words"; @@ -20,188 +20,240 @@ const amount = 8; const timeLimit = 300; type Question = { - entry: T.NounEntry | T.AdjectiveEntry, - inflections: T.Inflections, + entry: T.NounEntry | T.AdjectiveEntry; + inflections: T.Inflections; }; type InfFormContent = { - masc: [string, string, string], - fem: [string, string, string], + masc: [string, string, string]; + fem: [string, string, string]; }; -export default function InflectionsWriting({ inChapter, id, link, level }: { - inChapter: boolean, - id: string, - link: string, - level: T.InflectionPattern, +export default function InflectionsWriting({ + inChapter, + id, + link, + level, +}: { + inChapter: boolean; + id: string; + link: string; + level: T.InflectionPattern; }) { - const wordPool = makePool( - [...nouns, ...adjectives] - .filter(x => { - if (isAdverbEntry(x)) return false; - const infs = inflectWord(x); - if (!infs || !infs.inflections) return false; - return (getInflectionPattern(x) === level); - }) - ); + const wordPool = makePool( + [...nouns, ...adjectives].filter((x) => { + if (isAdverbEntry(x)) return false; + const infs = inflectWord(x); + if (!infs || !infs.inflections) return false; + return getInflectionPattern(x) === level; + }) + ); - function getQuestion(): Question { - const word = wordPool(); - const r = inflectWord(word); - if (!r || !r.inflections) { - throw new Error(`error getting inflections for ${word.f}`); - } - return { - entry: word, - inflections: r.inflections, - }; + function getQuestion(): Question { + const word = wordPool(); + const r = inflectWord(word); + if (!r || !r.inflections) { + throw new Error(`error getting inflections for ${word.f}`); + } + return { + entry: word, + inflections: r.inflections, }; - - function Display({ question, callback }: QuestionDisplayProps) { - function handleAnswer(inf: InfFormContent) { - callback(infAnswerCorrect(inf, question.inflections)); - } - return
-
- {[ - { - p: firstVariation(question.entry.p), - f: firstVariation(question.entry.f), - e: `${firstVariation(question.entry.e)} - ${question.entry.c}`, - } - ]} -
- -
- } - - function Instructions() { - return
-

Complete the inflections for the {HumanReadableInflectionPattern(level, opts)} pattern word

-
- } + } - return ) { + function handleAnswer(inf: InfFormContent) { + callback(infAnswerCorrect(inf, question.inflections)); + } + return ( +
+
+ + {[ + { + p: firstVariation(question.entry.p), + f: firstVariation(question.entry.f), + e: `${firstVariation(question.entry.e)} - ${question.entry.c}`, + }, + ]} + +
+ +
+ ); + } + + function Instructions() { + return ( +
+

+ Complete the inflections for the{" "} + {HumanReadableInflectionPattern(level, opts)} pattern + word +

+
+ ); + } + + return ( + -}; - -function InflectionTableForm({ onSubmit, genders, question }: { - onSubmit: (i: InfFormContent) => void, - genders: T.Gender | "unisex", - question: Question, -}) { - const [inf, setInf] = useState({ fem: ["", "", ""], masc: ["", "", ""] }); - const mascInputRef = useRef(null); - const femInputRef = useRef(null); - useEffect(() => { - setInf({ fem: ["", "", ""], masc: ["", "", ""] }); - femInputRef.current && femInputRef.current.focus(); - mascInputRef.current && mascInputRef.current.focus(); - }, [question, setInf]); - - function handleClearInf() { - setInf({ fem: ["", "", ""], masc: ["", "", ""] }); - } - function handleInfInput(gender: T.Gender, inflection: number) { - return ({ target: { value }}: ChangeEvent) => { - inf[gender][inflection] = value; - setInf({...inf}); - }; - } - function handleSubmit(e: FormEvent) { - e.preventDefault(); - onSubmit(inf); - } - return
- - - - - {genders !== "fem" && } - {genders !== "masc" && } - - - - {["Plain", "1st", "2nd"].map((title, i) => ( - - - {genders !== "fem" && } - {genders !== "masc" && } - - ))} - -
MasculineFeminine
{title} - - - -
-
- - -
-
; + ); } -function DisplayCorrectAnswer({ question }: { question: Question }): JSX.Element { - return
- -
; +function InflectionTableForm({ + onSubmit, + genders, + question, +}: { + onSubmit: (i: InfFormContent) => void; + genders: T.Gender | "unisex"; + question: Question; +}) { + const [inf, setInf] = useState({ + fem: ["", "", ""], + masc: ["", "", ""], + }); + const mascInputRef = useRef(null); + const femInputRef = useRef(null); + useEffect(() => { + setInf({ fem: ["", "", ""], masc: ["", "", ""] }); + femInputRef.current && femInputRef.current.focus(); + mascInputRef.current && mascInputRef.current.focus(); + }, [question, setInf]); + + function handleClearInf() { + setInf({ fem: ["", "", ""], masc: ["", "", ""] }); + } + function handleInfInput(gender: T.Gender, inflection: number) { + return ({ target: { value } }: ChangeEvent) => { + inf[gender][inflection] = value; + setInf({ ...inf }); + }; + } + function handleSubmit(e: FormEvent) { + e.preventDefault(); + onSubmit(inf); + } + return ( +
+ + + + + {genders !== "fem" && ( + + )} + {genders !== "masc" && ( + + )} + + + + {["Plain", "1st", "2nd"].map((title, i) => ( + + + {genders !== "fem" && ( + + )} + {genders !== "masc" && ( + + )} + + ))} + +
+ Masculine + + Feminine +
{title} + + + +
+
+ + +
+
+ ); +} + +function DisplayCorrectAnswer({ + question, +}: { + question: Question; +}): JSX.Element { + return ( +
+ +
+ ); } function infAnswerCorrect(answer: InfFormContent, inf: T.Inflections): boolean { - function genInfCorrect(gender: T.Gender): boolean { - // @ts-ignore - const genInf = inf[gender] as T.InflectionSet; - return genInf.every((x, i) => ( - x.some(ps => comparePs(answer[gender][i], ps)) - )); - } - if (isUnisexSet(inf)) { - return genInfCorrect("masc") && genInfCorrect("fem"); - } - return genInfCorrect("masc" in inf ? "masc": "fem"); + function genInfCorrect(gender: T.Gender): boolean { + // @ts-ignore + const genInf = inf[gender] as T.InflectionSet; + return genInf.every((x, i) => + x.some((ps) => comparePs(answer[gender][i], [ps])) + ); + } + if (isUnisexSet(inf)) { + return genInfCorrect("masc") && genInfCorrect("fem"); + } + return genInfCorrect("masc" in inf ? "masc" : "fem"); } - diff --git a/src/games/sub-cores/VerbGame.tsx b/src/games/sub-cores/VerbGame.tsx index 6ea4f15..91e63ae 100644 --- a/src/games/sub-cores/VerbGame.tsx +++ b/src/games/sub-cores/VerbGame.tsx @@ -414,8 +414,8 @@ function addUserAnswer( function addBa(x: T.PsString) { if (!a.withBa) return x; return { - p: x.p.replace(kidsBlank.p, baParticle.p), - f: x.f.replace(kidsBlank.f, baParticle.f), + p: x.p.replace(kidsBlank.p, baParticle.p + " "), + f: x.f.replace(kidsBlank.f, baParticle.f + " "), }; } function addAnswer(x: T.PsString): T.PsString { diff --git a/src/lib/game-utils.ts b/src/lib/game-utils.ts index 362b8d3..01c5078 100644 --- a/src/lib/game-utils.ts +++ b/src/lib/game-utils.ts @@ -1,46 +1,44 @@ import { - removeAccents, - hasAccents, - Types as T, - standardizePashto, - standardizePhonetics, - flattenLengths, + removeAccents, + hasAccents, + Types as T, + standardizePashto, + standardizePhonetics, + flattenLengths, } from "@lingdocs/ps-react"; import { removeAShort } from "./misc-helpers"; export function getPercentageDone(current: number, total: number): number { - return Math.round( - (current / (total + 1)) * 100 - ); + return Math.round((current / (total + 1)) * 100); } /** - * Says if an input written in phonetics by the user is correct/the same as a given answer - * - * The user is allowed to leave out the accents, but if they include them they must be the same as the answer - * + * Says if an input written in phonetics by the user is correct/the same as a given answer + * + * The user is allowed to leave out the accents, but if they include them they must be the same as the answer + * * @param input - the answer given by the user in phonetics * @param answer - the correct answer in phonetics */ export function compareF(input: string, answer: string): boolean { - const inp = removeAShort(input); - const ans = removeAShort(answer); - return inp === (hasAccents(inp) ? ans : removeAccents(ans)); + const inp = removeAShort(input); + const ans = removeAShort(answer); + return inp === (hasAccents(inp) ? ans : removeAccents(ans)); } -export function comparePs(inputRaw: string, answer: T.SingleOrLengthOpts): boolean { - function cleanSpaces(s: string): string { - return s.replace(/\s+/g, " "); - } - const input = cleanSpaces(inputRaw); - if ("long" in answer) { - return comparePs(input, flattenLengths(answer)); - } - if (Array.isArray(answer)) { - return answer.some(a => comparePs(input, a)); - } - const stand = standardizePhonetics( - standardizePashto(input) - ).trim(); - return stand === cleanSpaces(answer.p) || compareF(stand, cleanSpaces(answer.f)); -} \ No newline at end of file +export function comparePs( + inputRaw: string, + answer: T.SingleOrLengthOpts +): boolean { + function cleanSpaces(s: string): string { + return s.replace(/\s+/g, " "); + } + const input = cleanSpaces(inputRaw); + if ("long" in answer) { + return comparePs(input, flattenLengths(answer)); + } + return answer.some((a) => { + const stand = standardizePhonetics(standardizePashto(input)).trim(); + return stand === cleanSpaces(a.p) || compareF(stand, cleanSpaces(a.f)); + }); +}