add perfect verb games
This commit is contained in:
parent
65339221ea
commit
9957e5b024
|
@ -18,7 +18,11 @@ import BasicVerbShowCase from "../../components/BasicVerbShowCase";
|
|||
import perfectDogMeme from "./perfect-dog-meme.jpg";
|
||||
import chemistryPerfect from "./chemistry-perfect.jpg";
|
||||
import BasicBlocks from "../../components/BasicBlocks";
|
||||
|
||||
import GameDisplay from "../../games/GameDisplay";
|
||||
import {
|
||||
perfectGameOne,
|
||||
perfectGameMix,
|
||||
} from "../../games/games";
|
||||
|
||||
In the previous chapter we explained how [perfect](https://en.wikipedia.org/wiki/Perfect_(grammar)) forms are made by combining the <Link to="/verbs/roots-and-stems/#the-past-participle">past participle</Link> of a verb with an equative.
|
||||
|
||||
|
@ -316,4 +320,8 @@ Just like the <Link to="/equatives/other-equatives/#would-have-been-equative">"w
|
|||
f: "no tu ba raaghúle waay ku nu!",
|
||||
e: "Ah, you (f.) should have come!",
|
||||
},
|
||||
])}</Examples>
|
||||
])}</Examples>
|
||||
|
||||
<GameDisplay record={perfectGameOne} />
|
||||
|
||||
<GameDisplay record={perfectGameMix} />
|
||||
|
|
|
@ -20,6 +20,12 @@ import presentPerfect from "./present-perfect.svg";
|
|||
import chemistryPerfect from "./chemistry-perfect.jpg";
|
||||
import BasicBlocks from "../../components/BasicBlocks";
|
||||
import VideoPlayer from "../../components/VideoPlayer";
|
||||
import GameDisplay from "../../games/GameDisplay";
|
||||
import {
|
||||
intransitivePresentPerfectGameOne,
|
||||
intransitivePresentPerfectGameMix,
|
||||
presentPerfectGame,
|
||||
} from "../../games/games";
|
||||
|
||||
## Introduction
|
||||
|
||||
|
@ -236,6 +242,12 @@ With transitive verbs everything works the same, but we follow the <Link to="/ph
|
|||
{"blocks":[{"key":0.48107357509198234,"block":{"type":"subjectSelection","selection":{"type":"NP","selection":{"type":"noun","entry":{"ts":1527812881,"i":11710,"p":"ماشوم","f":"maashoom","g":"maashoom","e":"child, kid","c":"n. m. anim. unisex","ec":"child","ep":"children"},"gender":"masc","genderCanChange":true,"number":"plural","numberCanChange":true,"adjectives":[],"possesor":{"np":{"type":"NP","selection":{"type":"pronoun","person":2,"distance":"far"}},"shrunken":false}}}}},{"key":0.8253773159904139,"block":{"type":"objectSelection","selection":{"type":"NP","selection":{"type":"pronoun","person":0,"distance":"far"}}}}],"verb":{"type":"verb","verb":{"entry":{"ts":1527815399,"i":14484,"p":"وهل","f":"wahul","g":"wahul","e":"to hit","c":"v. trans.","tppp":"واهه","tppf":"waahu","ec":"hit,hits,hitting,hit,hit"}},"verbTense":"perfectivePast","perfectTense":"presentPerfect","imperativeTense":"imperfectiveImperative","tenseCategory":"perfect","transitivity":"transitive","isCompound":false,"voice":"active","negative":false,"canChangeTransitivity":false,"canChangeVoice":true,"canChangeStatDyn":false},"form":{"removeKing":false,"shrinkServant":false}}
|
||||
}</EditableVPEx>
|
||||
|
||||
<GameDisplay record={intransitivePresentPerfectGameOne} />
|
||||
|
||||
<GameDisplay record={intransitivePresentPerfectGameMix} />
|
||||
|
||||
<GameDisplay record={presentPerfectGame} />
|
||||
|
||||
## Negatives with the perfect
|
||||
|
||||
To make perfect forms negative you add a <InlinePs opts={opts} ps={{ p: "نه", f: "nú", e: "" }} /> block, just as you would with any other verb. But interestingly, **the past participle and equative blocks switch places**.
|
||||
|
|
|
@ -8,6 +8,7 @@ import EquativeIdentify from "./sub-cores/EquativeIdentify";
|
|||
import VerbFormulas from "./sub-cores/VerbFormulas";
|
||||
import InflectionPatterns from "./sub-cores/InflectionPatterns";
|
||||
import InflectionsWriting from "./sub-cores/InflectionsWriting";
|
||||
import PerfectVerbsIntransitive from "./sub-cores/PerfectGame";
|
||||
|
||||
|
||||
// NOUNS
|
||||
|
@ -35,42 +36,42 @@ export const unisexNounGame = makeGameRecord({
|
|||
|
||||
// INFLECTIONS
|
||||
export const inflectionTableGame1 = makeGameRecord({
|
||||
title: `Write the inflections - Pattern #1`,
|
||||
title: "Write the inflections - Pattern #1",
|
||||
id: "write-inflections-1",
|
||||
link: "/inflection/inflection-patterns/#1-basic",
|
||||
level: 1,
|
||||
SubCore: InflectionsWriting,
|
||||
});
|
||||
export const inflectionTableGame2 = makeGameRecord({
|
||||
title: `Write the inflections - Pattern #2`,
|
||||
title: "Write the inflections - Pattern #2",
|
||||
id: "write-inflections-2",
|
||||
link: "/inflection/inflection-patterns/#2-words-ending-in-an-unstressed-ی---ey",
|
||||
level: 2,
|
||||
SubCore: InflectionsWriting,
|
||||
});
|
||||
export const inflectionTableGame3 = makeGameRecord({
|
||||
title: `Write the inflections - Pattern #3`,
|
||||
title: "Write the inflections - Pattern #3",
|
||||
id: "write-inflections-3",
|
||||
link: "/inflection/inflection-patterns/#3-words-ending-in-a-stressed-ی---éy",
|
||||
level: 3,
|
||||
SubCore: InflectionsWriting,
|
||||
});
|
||||
export const inflectionTableGame4 = makeGameRecord({
|
||||
title: `Write the inflections - Pattern #4`,
|
||||
title: "Write the inflections - Pattern #4",
|
||||
id: "write-inflections-4",
|
||||
link: "/inflection/inflection-patterns/#4-words-with-the-pashtoon-pattern",
|
||||
level: 4,
|
||||
SubCore: InflectionsWriting,
|
||||
});
|
||||
export const inflectionTableGame5 = makeGameRecord({
|
||||
title: `Write the inflections - Pattern #5`,
|
||||
title: "Write the inflections - Pattern #5",
|
||||
id: "write-inflections-5",
|
||||
link: "/inflection/inflection-patterns/#5-shorter-words-that-squish",
|
||||
level: 5,
|
||||
SubCore: InflectionsWriting,
|
||||
});
|
||||
export const inflectionTableGame6 = makeGameRecord({
|
||||
title: `Write the inflections - Pattern #6`,
|
||||
title: "Write the inflections - Pattern #6",
|
||||
id: "write-inflections-6",
|
||||
link: "/inflection/inflection-patterns/#6-inanimate-feminine-nouns-ending-in-ي---ee",
|
||||
level: 6,
|
||||
|
@ -340,6 +341,61 @@ export const verbFormulasGame = makeGameRecord({
|
|||
SubCore: VerbFormulas,
|
||||
});
|
||||
|
||||
export const intransitivePresentPerfectGameOne = makeGameRecord({
|
||||
title: "Write the present perfect verb - intransitive (one)",
|
||||
id: "present-perfect-intransitive-one",
|
||||
link: "/verbs/perfect-verbs-intro/",
|
||||
level: {
|
||||
level: 1,
|
||||
type: "intransitive",
|
||||
},
|
||||
SubCore: PerfectVerbsIntransitive,
|
||||
});
|
||||
|
||||
export const intransitivePresentPerfectGameMix = makeGameRecord({
|
||||
title: "Write the present perfect verb - intransitive (mix)",
|
||||
id: "present-perfect-intransitive-mix",
|
||||
link: "/verbs/perfect-verbs-intro/",
|
||||
level: {
|
||||
level: 2,
|
||||
type: "intransitive",
|
||||
},
|
||||
SubCore: PerfectVerbsIntransitive,
|
||||
});
|
||||
|
||||
export const presentPerfectGame = makeGameRecord({
|
||||
title: "Write the present perfect verb - transitive/intransitive mix",
|
||||
id: "present-perfect",
|
||||
link: "/verbs/perfect-verbs-intro/",
|
||||
level: {
|
||||
level: 2,
|
||||
type: "transitive-intransitive",
|
||||
},
|
||||
SubCore: PerfectVerbsIntransitive,
|
||||
});
|
||||
|
||||
export const perfectGameOne = makeGameRecord({
|
||||
title: "Write the perfect verb - all perfect tenses (one verb)",
|
||||
id: "all-perfect-one",
|
||||
link: "/verbs/all-perfect-verbs/",
|
||||
level: {
|
||||
level: 1,
|
||||
type: "all-tenses",
|
||||
},
|
||||
SubCore: PerfectVerbsIntransitive,
|
||||
});
|
||||
|
||||
export const perfectGameMix = makeGameRecord({
|
||||
title: "Write the perfect verb - all perfect tenses (mix)",
|
||||
id: "all-perfect-mix",
|
||||
link: "/verbs/all-perfect-verbs/",
|
||||
level: {
|
||||
level: 2,
|
||||
type: "all-tenses",
|
||||
},
|
||||
SubCore: PerfectVerbsIntransitive,
|
||||
});
|
||||
|
||||
const games: { chapter: string, items: GameRecord[] }[] = [
|
||||
{
|
||||
chapter: "Nouns",
|
||||
|
@ -407,6 +463,16 @@ const games: { chapter: string, items: GameRecord[] }[] = [
|
|||
verbFormulasGame,
|
||||
],
|
||||
},
|
||||
{
|
||||
chapter: "Perfect Verbs",
|
||||
items: [
|
||||
intransitivePresentPerfectGameOne,
|
||||
intransitivePresentPerfectGameMix,
|
||||
presentPerfectGame,
|
||||
perfectGameOne,
|
||||
perfectGameMix,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// check to make sure we have no duplicate game keys
|
||||
|
|
|
@ -0,0 +1,453 @@
|
|||
import { useState } from "react";
|
||||
import {
|
||||
comparePs,
|
||||
} from "../../lib/game-utils";
|
||||
import GameCore from "../GameCore";
|
||||
import {
|
||||
Types as T,
|
||||
defaultTextOptions as opts,
|
||||
makeNounSelection,
|
||||
randFromArray,
|
||||
flattenLengths,
|
||||
randomPerson,
|
||||
InlinePs,
|
||||
grammarUnits,
|
||||
renderVP,
|
||||
makeVPSelectionState,
|
||||
compileVP,
|
||||
blockUtils,
|
||||
concatPsString,
|
||||
isInvalidSubjObjCombo,
|
||||
removeFVarients,
|
||||
getEnglishVerb,
|
||||
RootsAndStems,
|
||||
getVerbInfo,
|
||||
defaultTextOptions,
|
||||
humanReadableVerbForm,
|
||||
blank,
|
||||
kidsBlank,
|
||||
isPashtoScript,
|
||||
} from "@lingdocs/ps-react";
|
||||
import { isPastTense, isThirdPerson } from "@lingdocs/ps-react";
|
||||
import { maybeShuffleArray } from "../../lib/shuffle-array";
|
||||
import { getVerbFromBlocks } from "@lingdocs/ps-react/dist/lib/src/phrase-building/blocks-utils";
|
||||
import { baParticle } from "@lingdocs/ps-react/dist/lib/src/grammar-units";
|
||||
import { intransitivePastVerbs } from "../../content/verbs/basic-present-verbs";
|
||||
import { makePool } from "../../lib/pool";
|
||||
import { wordQuery } from "../../words/words";
|
||||
import { isImperativeTense } from "@lingdocs/ps-react/dist/lib/src/type-predicates";
|
||||
|
||||
const kidsColor = "#017BFE";
|
||||
|
||||
const amount = 12;
|
||||
const timeLimit = 140;
|
||||
|
||||
type Question = {
|
||||
rendered: T.VPRendered,
|
||||
phrase: { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string[] },
|
||||
};
|
||||
|
||||
const transitivePastVerbs = wordQuery("verbs", [
|
||||
"leedul",
|
||||
"wahul",
|
||||
"khoRul",
|
||||
"shărmawul",
|
||||
"pejzandul",
|
||||
"taRul",
|
||||
]);
|
||||
|
||||
const verbs = wordQuery("verbs", [
|
||||
"leekul",
|
||||
"wahul",
|
||||
"leedul",
|
||||
"awredul",
|
||||
"khoRul",
|
||||
"akhistul",
|
||||
"katul",
|
||||
"lwedul",
|
||||
]);
|
||||
|
||||
const nouns = wordQuery("nouns", [
|
||||
"saRey",
|
||||
"xudza",
|
||||
"maashoom",
|
||||
"puxtoon",
|
||||
"Ustaaz",
|
||||
"DaakTar",
|
||||
"halik",
|
||||
]);
|
||||
|
||||
const persons: T.Person[] = [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
];
|
||||
|
||||
type PerfectGameLevel = {
|
||||
/* 1 is just a single verb, 2 picks a random verb for every question */
|
||||
level: 1 | 2,
|
||||
type: "intransitive" | "transitive-intransitive" | "all-tenses",
|
||||
}
|
||||
type VerbPoolName = "basic" | "transitivePast" | "intransitivePast" | "mixedPast" | "mixedAll";
|
||||
|
||||
type LevelInfo = {
|
||||
description: string | JSX.Element,
|
||||
tense: T.PerfectTense | "allTenses",
|
||||
pool: VerbPoolName,
|
||||
}
|
||||
|
||||
const levelInfos: Record<PerfectGameLevel["type"], LevelInfo> = {
|
||||
"intransitive": {
|
||||
description: "present perfect form of the verb",
|
||||
tense: "presentPerfect",
|
||||
pool: "intransitivePast",
|
||||
},
|
||||
"transitive-intransitive": {
|
||||
description: "present perfect form of the verb",
|
||||
tense: "presentPerfect",
|
||||
pool: "mixedPast",
|
||||
},
|
||||
"all-tenses": {
|
||||
description: "correct perfect form of the verb",
|
||||
tense: "allTenses",
|
||||
pool: "mixedPast",
|
||||
},
|
||||
}
|
||||
|
||||
// TODO: Level where you create the formulas (seperate file)
|
||||
// level where you choose the right situation
|
||||
|
||||
const VerbGame: GameSubCore<PerfectGameLevel> = ({ id, link, level, inChapter }: {
|
||||
inChapter: boolean,
|
||||
id: string,
|
||||
link: string,
|
||||
level: PerfectGameLevel,
|
||||
}) => {
|
||||
const levelInfo = levelInfos[level.type];
|
||||
const personPool = makePool(persons);
|
||||
const verbPools: Record<VerbPoolName, () => T.VerbEntry> = {
|
||||
basic: makePool(verbs, 15),
|
||||
transitivePast: makePool(transitivePastVerbs, 15),
|
||||
intransitivePast: makePool(intransitivePastVerbs, 15),
|
||||
mixedPast: makePool([...transitivePastVerbs, ...intransitivePastVerbs], 15),
|
||||
mixedAll: makePool([...verbs, ...transitivePastVerbs, ...intransitivePastVerbs], 15),
|
||||
};
|
||||
const tensePool = makePool<T.PerfectTense>([
|
||||
"presentPerfect", "pastPerfect", "subjunctivePerfect", "habitualPerfect",
|
||||
"pastPerfect", "futurePerfect", "wouldBePerfect", "pastSubjunctivePerfect",
|
||||
"wouldHaveBeenPerfect",
|
||||
]);
|
||||
const oneVerb: T.VerbEntry = verbPools[levelInfo.pool]();
|
||||
const getVerb = level.level === 1
|
||||
? () => oneVerb
|
||||
: () => verbPools[levelInfo.pool]();
|
||||
function makeRandomNoun(): T.NounSelection {
|
||||
const n = makeNounSelection(randFromArray(nouns), undefined);
|
||||
return {
|
||||
...n,
|
||||
gender: n.genderCanChange ? randFromArray(["masc", "fem"]) : n.gender,
|
||||
number: n.numberCanChange ? randFromArray(["singular", "plural"]) : n.number,
|
||||
};
|
||||
}
|
||||
function makeRandomVPS(tense: T.PerfectTense): T.VPSelectionComplete {
|
||||
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: randFromArray(["far", "near", "far"]),
|
||||
};
|
||||
}
|
||||
const verb = getVerb();
|
||||
const king = personPool();
|
||||
let servant: T.Person;
|
||||
do {
|
||||
servant = randomPerson();
|
||||
} while (isInvalidSubjObjCombo(king, servant));
|
||||
return makeVPS({
|
||||
verb,
|
||||
king: personToNPSelection(king),
|
||||
servant: personToNPSelection(servant),
|
||||
tense,
|
||||
defaultTransitivity: level.type.startsWith("transitive")
|
||||
? "transitive"
|
||||
: "grammatically transitive",
|
||||
});
|
||||
}
|
||||
function getQuestion(): Question {
|
||||
const VPS = makeRandomVPS(levelInfo.tense === "allTenses"
|
||||
? tensePool()
|
||||
: levelInfo.tense
|
||||
);
|
||||
const VP = renderVP(VPS);
|
||||
const compiled = compileVP(
|
||||
VP,
|
||||
{ removeKing: false, shrinkServant: false },
|
||||
true,
|
||||
{ ba: levelInfo.tense === "allTenses", verb: true, negative: true },
|
||||
);
|
||||
const phrase = {
|
||||
ps: compiled.ps,
|
||||
e: compiled.e,
|
||||
};
|
||||
return {
|
||||
rendered: VP,
|
||||
phrase,
|
||||
};
|
||||
}
|
||||
|
||||
function Display({ question, callback }: QuestionDisplayProps<Question>) {
|
||||
const [answer, setAnswer] = useState<string>("");
|
||||
const [withBa, setWithBa] = useState<boolean>(false);
|
||||
const handleInput = ({ target: { value }}: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (value === "به " || value === "به ") {
|
||||
setWithBa(true);
|
||||
setAnswer("");
|
||||
return;
|
||||
}
|
||||
setAnswer(value);
|
||||
}
|
||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
const correct = comparePs(answer, getVerbPs(question.rendered))
|
||||
&& (withBa === verbHasBa(question.rendered));
|
||||
if (correct) {
|
||||
setAnswer("");
|
||||
}
|
||||
callback(correct);
|
||||
}
|
||||
// useEffect(() => {
|
||||
// if (level === "allProduce") setWithBa(false);
|
||||
// }, [question]);
|
||||
return <div>
|
||||
<QuestionDisplay question={question} userAnswer={{
|
||||
withBa,
|
||||
answer,
|
||||
}} />
|
||||
<form onSubmit={handleSubmit}>
|
||||
{level.type === "all-tenses" && <div className="form-check mt-1">
|
||||
<input
|
||||
id="baCheckbox"
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
checked={withBa}
|
||||
onChange={e => setWithBa(e.target.checked)}
|
||||
/>
|
||||
<label className="form-check-label text-muted" htmlFor="baCheckbox">
|
||||
with <InlinePs opts={opts}>{grammarUnits.baParticle}</InlinePs> in the <span style={{ color: kidsColor }}>kids' section</span>
|
||||
</label>
|
||||
</div>}
|
||||
<div className="my-1" style={{ maxWidth: "200px", margin: "0 auto" }}>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
autoComplete="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck="false"
|
||||
dir="auto"
|
||||
value={answer}
|
||||
onChange={handleInput}
|
||||
/>
|
||||
</div>
|
||||
<div className="text-center my-2">
|
||||
{/* <div> */}
|
||||
<button className="btn btn-primary" type="submit">submit ↵</button>
|
||||
{/* </div> */}
|
||||
{/* <div className="text-muted small text-center mt-2">
|
||||
Type <kbd>Enter</kbd> to check
|
||||
</div> */}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
|
||||
function Instructions() {
|
||||
const desc = levelInfo.description;
|
||||
return <div>
|
||||
<p className="lead">
|
||||
Write the {desc} verb to complete the phrase
|
||||
{desc ? "" : " (all tenses)"}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
return <GameCore
|
||||
inChapter={inChapter}
|
||||
studyLink={link}
|
||||
getQuestion={getQuestion}
|
||||
id={id}
|
||||
Display={Display}
|
||||
DisplayCorrectAnswer={DisplayCorrectAnswer}
|
||||
timeLimit={timeLimit}
|
||||
amount={amount}
|
||||
Instructions={Instructions}
|
||||
/>
|
||||
};
|
||||
|
||||
export default VerbGame;
|
||||
|
||||
function QuestionDisplay({ question, userAnswer }: {
|
||||
question: Question,
|
||||
userAnswer: { withBa: boolean, answer: string },
|
||||
}) {
|
||||
const ps = addUserAnswer(
|
||||
userAnswer,
|
||||
flattenLengths(question.phrase.ps)[0]
|
||||
);
|
||||
const v = getVerbFromBlocks(question.rendered.blocks);
|
||||
const vEntry = v.block.verb.entry;
|
||||
const infoV = getVerbInfo(vEntry)
|
||||
const info = "grammaticallyTransitive" in infoV
|
||||
? infoV.grammaticallyTransitive
|
||||
: "stative" in infoV
|
||||
? infoV.stative
|
||||
: infoV;
|
||||
return <div className="mb-3 mt-2">
|
||||
<div className="mb-2">
|
||||
<div>{vEntry.p} - {removeFVarients(vEntry.f)} <span className="text-muted">{vEntry.c}</span></div>
|
||||
<div>"{getEnglishVerb(vEntry)}"</div>
|
||||
</div>
|
||||
<details style={{ marginBottom: 0 }}>
|
||||
<summary>🌳 Show roots and stems</summary>
|
||||
<RootsAndStems info={info} textOptions={defaultTextOptions} />
|
||||
</details>
|
||||
<div dir="rtl">{ps.p}</div>
|
||||
<div dir="ltr">{ps.f}</div>
|
||||
{question.phrase.e && <div className="text-muted mt-2">
|
||||
{question.phrase.e.map(x => <div key={Math.random()}>
|
||||
{x}
|
||||
</div>)}
|
||||
</div>}
|
||||
<div>{humanReadableVerbForm(v.block.tense)}</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
function DisplayCorrectAnswer({ question }: { question: Question }): JSX.Element {
|
||||
return <div>
|
||||
<div>
|
||||
{getVerbPs(question.rendered).reduce(((accum, curr, i): JSX.Element[] => (
|
||||
[
|
||||
...accum,
|
||||
...i > 0 ? [<span className="text-muted"> or </span>] : [],
|
||||
<span>{curr.p} - {curr.f}</span>,
|
||||
]
|
||||
)), [] as JSX.Element[])}
|
||||
</div>
|
||||
<div><strong>{verbHasBa(question.rendered) ? "with" : "without"}</strong> a <InlinePs opts={opts}>{grammarUnits.baParticle}</InlinePs> in the kids' section.</div>
|
||||
</div>;
|
||||
}
|
||||
// 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]} <span style={{ color: kidsColor }}>{withBa ? "به" : "__"}</span> {splitP[1]}</>,
|
||||
// f: <>{splitF[0]} <span style={{ color: kidsColor }}>{withBa ? "ba" : "__"}</span> {splitF[1]}</>,
|
||||
// };
|
||||
// });
|
||||
// }
|
||||
|
||||
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 makeVPS({ verb, king, servant, tense, defaultTransitivity }: {
|
||||
verb: T.VerbEntry,
|
||||
king: T.NPSelection,
|
||||
servant: T.NPSelection,
|
||||
tense: T.PerfectTense,
|
||||
defaultTransitivity: "transitive" | "grammatically transitive"
|
||||
}): T.VPSelectionComplete {
|
||||
const vps = makeVPSelectionState(verb);
|
||||
const transitivity = (vps.verb.transitivity === "transitive" && vps.verb.canChangeTransitivity)
|
||||
? defaultTransitivity
|
||||
: vps.verb.transitivity;
|
||||
const ergative = vps.verb.transitivity !== "intransitive" && isPastTense(tense);
|
||||
const subject = ergative ? servant : king;
|
||||
const object = ergative ? king : servant;
|
||||
return {
|
||||
...vps,
|
||||
verb: {
|
||||
...vps.verb,
|
||||
negative: isImperativeTense(tense)
|
||||
? randFromArray([false, false, true])
|
||||
: false,
|
||||
transitivity,
|
||||
tense,
|
||||
},
|
||||
blocks: maybeShuffleArray([
|
||||
{
|
||||
key: Math.random(),
|
||||
block: {
|
||||
type: "subjectSelection",
|
||||
selection: subject,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: Math.random(),
|
||||
block: {
|
||||
type: "objectSelection",
|
||||
selection: transitivity === "intransitive"
|
||||
? "none"
|
||||
: transitivity === "grammatically transitive"
|
||||
? T.Person.ThirdPlurMale
|
||||
: object,
|
||||
},
|
||||
},
|
||||
]),
|
||||
};
|
||||
}
|
||||
|
||||
function getVerbPs({ blocks }: T.VPRendered): T.PsString[] {
|
||||
const { perfectiveHead, verb } = blockUtils.getVerbAndHeadFromBlocks(blocks);
|
||||
const mU = blocks[0].find(b => b.block.type === "negative" && b.block.imperative);
|
||||
function vBase() {
|
||||
if (!perfectiveHead) {
|
||||
return flattenLengths(verb.block.ps);
|
||||
}
|
||||
return flattenLengths(verb.block.ps).map(r => concatPsString(perfectiveHead.ps, r));
|
||||
}
|
||||
if (mU) {
|
||||
return vBase().map(b => concatPsString({ p: "مه", f: "mú" }, " ", b));
|
||||
}
|
||||
return vBase();
|
||||
}
|
||||
|
||||
function verbHasBa({ blocks }: T.VPRendered): boolean {
|
||||
const verb = blockUtils.getVerbFromBlocks(blocks);
|
||||
return verb.block.hasBa;
|
||||
}
|
|
@ -266,7 +266,7 @@ const VerbGame: GameSubCore<VerbGameLevel> = ({ id, link, level, inChapter }: {
|
|||
</div>
|
||||
<div className="text-center my-2">
|
||||
{/* <div> */}
|
||||
<button className="btn btn-primary" type="submit">return ↵</button>
|
||||
<button className="btn btn-primary" type="submit">submit ↵</button>
|
||||
{/* </div> */}
|
||||
{/* <div className="text-muted small text-center mt-2">
|
||||
Type <kbd>Enter</kbd> to check
|
||||
|
|
Loading…
Reference in New Issue