add imperative game

This commit is contained in:
lingdocs 2022-08-30 16:18:35 +04:00
parent 3d89b9bbef
commit d767341b36
6 changed files with 80 additions and 19 deletions

View File

@ -7,7 +7,7 @@
"@formkit/auto-animate": "^1.0.0-beta.1", "@formkit/auto-animate": "^1.0.0-beta.1",
"@fortawesome/fontawesome-free": "^5.15.4", "@fortawesome/fontawesome-free": "^5.15.4",
"@lingdocs/lingdocs-main": "^0.3.1", "@lingdocs/lingdocs-main": "^0.3.1",
"@lingdocs/pashto-inflector": "^3.8.3", "@lingdocs/pashto-inflector": "^3.8.4",
"@testing-library/jest-dom": "^5.11.4", "@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0", "@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10", "@testing-library/user-event": "^12.1.10",

View File

@ -17,6 +17,10 @@ import shuffleArray from "../../lib/shuffle-array";
import imperfectiveImperative from "./imperfective-imperative.svg"; import imperfectiveImperative from "./imperfective-imperative.svg";
import perfectiveImperative from "./perfective-imperative.svg"; import perfectiveImperative from "./perfective-imperative.svg";
import BasicVerbShowCase from "../../components/BasicVerbShowCase"; import BasicVerbShowCase from "../../components/BasicVerbShowCase";
import {
imperativeVerbGame,
} from "../../games/games";
import GameDisplay from "../../games/GameDisplay";
The imperative form is used for **giving commands** (telling people to do things). The imperative form is used for **giving commands** (telling people to do things).
@ -178,6 +182,8 @@ You will notice there are only two <Link to="/verbs/verb-endings/#imperative-ver
</table> </table>
</div> </div>
<GameDisplay record={imperativeVerbGame} />
## Negative Imperatives ## Negative Imperatives
**In the negative form of commands** (ie. *"Don't ____"*), **the aspect choice dissapears**. There is no imperfective/perfective option with negative imperatives, there's only one form. **In the negative form of commands** (ie. *"Don't ____"*), **the aspect choice dissapears**. There is no imperfective/perfective option with negative imperatives, there's only one form.

View File

@ -80,7 +80,7 @@ function ChapterDisplay({ chapter, user, handleClick, expanded }: {
function ChapterProgress({ progress }: { progress: "not logged in" | number }) { function ChapterProgress({ progress }: { progress: "not logged in" | number }) {
if (progress === "not logged in") { if (progress === "not logged in") {
return <div className="small text-muted">Log in to see progress</div>; return <div className="small text-muted"><Link to="/account">Log in</Link> to see progress</div>;
} }
return <div> return <div>
<div className="small text-muted">{progress}% mastered</div> <div className="small text-muted">{progress}% mastered</div>

View File

@ -35,6 +35,12 @@ export const futureVerbGame = makeGameRecord(
"/verbs/future-verbs/", "/verbs/future-verbs/",
(id, link) => () => <VerbGame id={id} level="futureVerb" link={link} /> (id, link) => () => <VerbGame id={id} level="futureVerb" link={link} />
); );
export const imperativeVerbGame = makeGameRecord(
"Write the imperative verb",
"imperative-verbs-write",
"/verbs/imperative-verbs/",
(id, link) => () => <VerbGame id={id} level="imperative" link={link} />
);
export const nounGenderGame1 = makeGameRecord( export const nounGenderGame1 = makeGameRecord(
"Identify Noun Genders - Level 1", "Identify Noun Genders - Level 1",
@ -163,6 +169,7 @@ const games: { chapter: string, items: GameRecord[] }[] = [
presentVerbGame, presentVerbGame,
subjunctiveVerbGame, subjunctiveVerbGame,
futureVerbGame, futureVerbGame,
imperativeVerbGame,
], ],
} }
]; ];

View File

@ -26,15 +26,19 @@ import {
getVerbInfo, getVerbInfo,
defaultTextOptions, defaultTextOptions,
humanReadableVerbForm, humanReadableVerbForm,
blank,
kidsBlank,
isPashtoScript,
} from "@lingdocs/pashto-inflector"; } from "@lingdocs/pashto-inflector";
import { isThirdPerson } from "@lingdocs/pashto-inflector/dist/lib/phrase-building/vp-tools"; import { isThirdPerson } from "@lingdocs/pashto-inflector/dist/lib/phrase-building/vp-tools";
import { maybeShuffleArray } from "../../lib/shuffle-array"; import { maybeShuffleArray } from "../../lib/shuffle-array";
import { getVerbFromBlocks } from "@lingdocs/pashto-inflector/dist/lib/phrase-building/blocks-utils"; import { getVerbFromBlocks } from "@lingdocs/pashto-inflector/dist/lib/phrase-building/blocks-utils";
import { baParticle } from "@lingdocs/pashto-inflector/dist/lib/grammar-units";
const kidsColor = "#017BFE"; const kidsColor = "#017BFE";
const amount = 10; const amount = 10;
const timeLimit = 150; const timeLimit = 200;
type Question = { type Question = {
rendered: T.VPRendered, rendered: T.VPRendered,
@ -48,6 +52,8 @@ const verbs: T.VerbEntry[] = [
{"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"}, {"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"},
{"ts":1527812790,"i":5813,"p":"خوړل","f":"khoRul","g":"khoRul","e":"to eat, to bite","c":"v. trans.","psp":"خور","psf":"khor","tppp":"خوړ","tppf":"khoR","ec":"eat,eats,eating,ate,eaten"}, {"ts":1527812790,"i":5813,"p":"خوړل","f":"khoRul","g":"khoRul","e":"to eat, to bite","c":"v. trans.","psp":"خور","psf":"khor","tppp":"خوړ","tppf":"khoR","ec":"eat,eats,eating,ate,eaten"},
{"ts":1527812447,"i":292,"p":"اخستل","f":"akhistúl, akhustúl","g":"akhistul,akhustul","e":"to take, buy, purchase, receive; to shave, cut with scissors","c":"v. trans.","psp":"اخل","psf":"akhl","tppp":"اخست","tppf":"akhist","ec":"take,takes,taking,took,taken"}, {"ts":1527812447,"i":292,"p":"اخستل","f":"akhistúl, akhustúl","g":"akhistul,akhustul","e":"to take, buy, purchase, receive; to shave, cut with scissors","c":"v. trans.","psp":"اخل","psf":"akhl","tppp":"اخست","tppf":"akhist","ec":"take,takes,taking,took,taken"},
{"ts":1527812751,"i":10083,"p":"کتل","f":"katul","g":"katul","e":"to look, see, watch, examine; to meet with","c":"v. trans./gramm. trans.","psp":"ګور","psf":"gor","tppp":"کوت","tppf":"kot","ec":"look"},
{"ts":1527813994,"i":11654,"p":"لوېدل","f":"lwedul","g":"lwedul","e":"to fall, to tumble, go down, settle","c":"v. intrans.","ec":"fall,falls,falling,fell,fallen"},
].map(entry => ({ entry })) as T.VerbEntry[]; ].map(entry => ({ entry })) as T.VerbEntry[];
// @ts-ignore // @ts-ignore
const nouns: T.NounEntry[] = [ const nouns: T.NounEntry[] = [
@ -70,15 +76,24 @@ const pronounTypes = [
[T.Person.ThirdPlurMale, T.Person.ThirdPlurFemale], [T.Person.ThirdPlurMale, T.Person.ThirdPlurFemale],
]; ];
type VerbGameLevel = "presentVerb" | "subjunctiveVerb" | "futureVerb"; const secondPersonPronounTypes = [
[T.Person.SecondSingMale, T.Person.SecondSingFemale],
[T.Person.SecondPlurMale, T.Person.SecondPlurFemale],
];
type VerbGameLevel = "presentVerb" | "subjunctiveVerb" | "futureVerb" | "imperative";
export default function VerbGame({ id, link, level }: { export default function VerbGame({ id, link, level }: {
id: string, id: string,
link: string, link: string,
level: VerbGameLevel, level: VerbGameLevel,
}) { }) {
const poolBase = level === "imperative"
? secondPersonPronounTypes
: pronounTypes;
console.log({ poolBase })
function* questions (): Generator<Current<Question>> { function* questions (): Generator<Current<Question>> {
let pool = [...pronounTypes]; let pool = [...poolBase];
function getRandPersFromPool(): T.Person { function getRandPersFromPool(): T.Person {
let person: T.Person; let person: T.Person;
do { do {
@ -87,7 +102,7 @@ export default function VerbGame({ id, link, level }: {
} while (!pool.some(p => p.includes(person))); } while (!pool.some(p => p.includes(person)));
pool = pool.filter(p => !p.includes(person)); pool = pool.filter(p => !p.includes(person));
if (pool.length === 0) { if (pool.length === 0) {
pool = pronounTypes; pool = poolBase;
} }
return person; return person;
} }
@ -99,9 +114,9 @@ export default function VerbGame({ id, link, level }: {
number: n.numberCanChange ? randFromArray(["singular", "plural"]) : n.number, number: n.numberCanChange ? randFromArray(["singular", "plural"]) : n.number,
}; };
} }
function makeRandomVPS(l: T.VerbTense): T.VPSelectionComplete { function makeRandomVPS(l: T.VerbTense | T.ImperativeTense): T.VPSelectionComplete {
function personToNPSelection(p: T.Person): T.NPSelection { function personToNPSelection(p: T.Person): T.NPSelection {
if (!isThirdPerson(p)) { if (isThirdPerson(p)) {
return { return {
type: "NP", type: "NP",
selection: randFromArray([ selection: randFromArray([
@ -185,7 +200,10 @@ export default function VerbGame({ id, link, level }: {
// if (level === "allProduce") setWithBa(false); // if (level === "allProduce") setWithBa(false);
// }, [question]); // }, [question]);
return <div> return <div>
<QuestionDisplay question={question} /> <QuestionDisplay question={question} userAnswer={{
withBa,
answer,
}} />
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div className="form-check mt-1"> <div className="form-check mt-1">
<input <input
@ -239,8 +257,14 @@ export default function VerbGame({ id, link, level }: {
/> />
}; };
function QuestionDisplay({ question }: { question: Question }) { function QuestionDisplay({ question, userAnswer }: {
const ps = flattenLengths(question.phrase.ps)[0]; question: Question,
userAnswer: { withBa: boolean, answer: string },
}) {
const ps = addUserAnswer(
userAnswer,
flattenLengths(question.phrase.ps)[0]
);
const v = getVerbFromBlocks(question.rendered.blocks); const v = getVerbFromBlocks(question.rendered.blocks);
const vEntry = v.block.verb.entry; const vEntry = v.block.verb.entry;
const infoV = getVerbInfo(vEntry) const infoV = getVerbInfo(vEntry)
@ -297,28 +321,52 @@ function makeCorrectAnswer(question: Question): JSX.Element {
// }); // });
// } // }
function addUserAnswer(a: { withBa: boolean, answer: string }, ps: T.PsString): T.PsString {
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),
}
}
function addAnswer(x: T.PsString): T.PsString {
if (!a.answer) return x;
const field = isPashtoScript(a.answer) ? "p" : "f";
return {
...x,
[field]: x[field].replace(blank[field], a.answer),
};
}
return addAnswer(addBa(ps));
}
function levelToDescription(level: VerbGameLevel): string { function levelToDescription(level: VerbGameLevel): string {
return level === "presentVerb" return level === "presentVerb"
? "present" ? "present"
: level === "subjunctiveVerb" : level === "subjunctiveVerb"
? "subjunctive" ? "subjunctive"
: "imperfective future or perfective future" : level === "futureVerb"
? "imperfective future or perfective future"
: "imperfective imperative or perfective imperative";
} }
function levelToTense(level: VerbGameLevel): T.VerbTense { function levelToTense(level: VerbGameLevel): T.VerbTense | T.ImperativeTense {
return level === "presentVerb" return level === "presentVerb"
? level ? level
: level === "subjunctiveVerb" : level === "subjunctiveVerb"
? level ? level
: randFromArray(["perfectiveFuture", "imperfectiveFuture"]); : level === "futureVerb"
? randFromArray(["perfectiveFuture", "imperfectiveFuture"])
// : level === "imperative"
: randFromArray(["perfectiveImperative", "imperfectiveImperative"]);
} }
function makeVPS({ verb, subject, object, tense }: { function makeVPS({ verb, subject, object, tense }: {
verb: T.VerbEntry, verb: T.VerbEntry,
subject: T.NPSelection, subject: T.NPSelection,
object: T.NPSelection, object: T.NPSelection,
tense: T.VerbTense, tense: T.VerbTense | T.ImperativeTense,
}): T.VPSelectionComplete { }): T.VPSelectionComplete {
const vps = makeVPSelectionState(verb); const vps = makeVPSelectionState(verb);
const transitivity = (vps.verb.transitivity === "transitive" && vps.verb.canChangeTransitivity) const transitivity = (vps.verb.transitivity === "transitive" && vps.verb.canChangeTransitivity)

View File

@ -1803,10 +1803,10 @@
rambda "^6.7.0" rambda "^6.7.0"
react-select "^5.2.2" react-select "^5.2.2"
"@lingdocs/pashto-inflector@^3.8.3": "@lingdocs/pashto-inflector@^3.8.4":
version "3.8.3" version "3.8.4"
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-3.8.3.tgz#c549a3f3d33efc3ab18fab79160b9db8558e4a10" resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-3.8.4.tgz#2a29b04c541f3d12842ae2dabc3bc1e71a1b77ad"
integrity sha512-gvvKiiIeBXVaua84Fj+F3F+ZgHWIMV393NgTX1Kt48bQWU+704igiClZmOu6p1lxWOsOwdVslER1rCoYhvnSbQ== integrity sha512-YVH+LFX4UslcQnNfYbmE9vX+bsq/LFylnxk3lEMLDLRW/abRmWlcPcElJr2wXYm3VR5uoLCK463ulS7IhQoUeQ==
dependencies: dependencies:
"@formkit/auto-animate" "^1.0.0-beta.1" "@formkit/auto-animate" "^1.0.0-beta.1"
classnames "^2.2.6" classnames "^2.2.6"