more games

This commit is contained in:
lingdocs 2022-05-10 16:48:13 -05:00
parent b1c654b929
commit 10915e3728
5 changed files with 194 additions and 44 deletions

View File

@ -149,7 +149,7 @@ function GameCore<T>({ questions, Display, timeLimit, Instructions, studyLink, i
/> />
<button onClick={handleQuit} className="btn btn-outline-secondary btn-sm mr-2">Quit</button> <button onClick={handleQuit} className="btn btn-outline-secondary btn-sm mr-2">Quit</button>
</div>} </div>}
<Reward ref={rewardRef} config={{ lifetime: 130, spread: 90, elementCount: 150, zIndex: 500 }} type="confetti"> <Reward ref={rewardRef} config={{ lifetime: 130, spread: 90, elementCount: 150, zIndex: 999999999 }} type="confetti">
<div className="py-3"> <div className="py-3">
{finish === undefined && {finish === undefined &&
(current (current
@ -176,7 +176,9 @@ function GameCore<T>({ questions, Display, timeLimit, Instructions, studyLink, i
<h4 className="mt-4">{failMessage(current?.progress, finish)}</h4> <h4 className="mt-4">{failMessage(current?.progress, finish)}</h4>
{typeof finish === "object" && <div> {typeof finish === "object" && <div>
<div>The correct answer was:</div> <div>The correct answer was:</div>
{finish?.answer} <div className="my-2">
{finish?.answer}
</div>
</div>} </div>}
<div className="mt-3"> <div className="mt-3">
<button className="btn btn-success mr-2" onClick={handleRestart}>Try Again</button> <button className="btn btn-success mr-2" onClick={handleRestart}>Try Again</button>

View File

@ -91,6 +91,13 @@ export const equativeGameAllIdentify = makeGameRecord(
(id, link) => () => <EquativeGame id={id} link={link} level="allIdentify" />, (id, link) => () => <EquativeGame id={id} link={link} level="allIdentify" />,
); );
export const equativeGameSituations = makeGameRecord(
"Choose the right equative for the situation",
"equative-past-situations",
"/equatives/other-equatives",
(id, link) => () => <EquativeGame id={id} link={link} level="situations" />,
);
export const equativeGameAllProduce = makeGameRecord( export const equativeGameAllProduce = makeGameRecord(
"Write the equative (all tenses)", "Write the equative (all tenses)",
"equative-past-summary-produce", "equative-past-summary-produce",
@ -117,6 +124,7 @@ const games: { chapter: string, items: GameRecord[] }[] = [
equativeGamePast, equativeGamePast,
equativeGameWouldBe, equativeGameWouldBe,
equativeGamePastSubjunctive, equativeGamePastSubjunctive,
equativeGameSituations,
equativeGameAllIdentify, equativeGameAllIdentify,
equativeGameAllProduce, equativeGameAllProduce,
], ],

View File

@ -57,13 +57,126 @@ const tenses: T.EquativeTense[] = [
"present", "habitual", "subjunctive", "future", "past", "wouldBe", "pastSubjunctive", "present", "habitual", "subjunctive", "future", "past", "wouldBe", "pastSubjunctive",
]; ];
const amount = 16; type Situation = {
const timeLimit = 75; description: string | JSX.Element,
tense: T.EquativeTense[],
};
const situations: Situation[] = [
{
description: <>A is B, for sure, right now</>,
tense: ["present"],
},
{
description: <>A is <em>probably</em> B, right now</>,
tense: ["future"],
},
{
description: <>A will be B in the future</>,
tense: ["future"],
},
{
description: <>We can assume that A is most likely B</>,
tense: ["future"],
},
{
description: <>You <em>know</em> A is B, currently</>,
tense: ["present"],
},
{
description: <>A tends to be B</>,
tense: ["habitual"],
},
{
description: <>A is usually B</>,
tense: ["habitual"],
},
{
description: <>A is generally B</>,
tense: ["habitual"],
},
{
description: <>A is B, right now</>,
tense: ["present"],
},
{
description: <>A is always B, as a matter of habit</>,
tense: ["present"],
},
{
description: "It's a good thing for A to be B",
tense: ["subjunctive"],
},
{
description: "A needs to be B (out of obligation/necessity)",
tense: ["subjunctive"],
},
{
description: "You hope that A is B",
tense: ["subjunctive"],
},
{
description: "You desire A to be B",
tense: ["subjunctive"],
},
{
description: "If A is B ...",
tense: ["subjunctive"],
},
{
description: "...so that A will be B (a purpose)",
tense: ["subjunctive"],
},
{
description: "A was definately B",
tense: ["past"],
},
{
description: "A was B",
tense: ["past"],
},
{
description: "A was probably B in the past",
tense: ["wouldBe"],
},
{
description: "A used to be B (habitually, repeatedly)",
tense: ["wouldBe"],
},
{
description: "assume that A would have probably been B",
tense: ["wouldBe"],
},
{
description: "under different circumstances, A would have been B",
tense: ["wouldBe", "pastSubjunctive"],
},
{
description: "You wish A were B (but it's not)",
tense: ["pastSubjunctive"],
},
{
description: "If A were B (but it's not)",
tense: ["pastSubjunctive"],
},
{
description: "Aaagh! If only A were B!",
tense: ["pastSubjunctive"],
},
{
description: "A should have been B!",
tense: ["pastSubjunctive", "wouldBe"],
},
];
const amount = 20;
const timeLimit = 90;
type Question = { type Question = {
EPS: T.EPSelectionComplete, EPS: T.EPSelectionComplete,
phrase: { ps: T.PsString[], e?: string[] }, phrase: { ps: T.PsString[], e?: string[] },
equative: T.EquativeRendered, equative: T.EquativeRendered,
} | {
situation: Situation,
}; };
const pronounTypes = [ const pronounTypes = [
@ -76,12 +189,12 @@ const pronounTypes = [
[T.Person.ThirdPlurMale, T.Person.ThirdPlurFemale], [T.Person.ThirdPlurMale, T.Person.ThirdPlurFemale],
]; ];
export default function EquativeGame({ id, link, level }: { id: string, link: string, level: T.EquativeTense | "allProduce" | "allIdentify" }) { export default function EquativeGame({ id, link, level }: { id: string, link: string, level: T.EquativeTense | "allProduce" | "allIdentify" | "situations" }) {
function* questions (): Generator<Current<Question>> { function* questions (): Generator<Current<Question>> {
let pool = [...pronounTypes]; let pool = [...pronounTypes];
let situationPool = [...situations];
function makeRandPronoun(): T.PronounSelection { function makeRandPronoun(): T.PronounSelection {
let person: T.Person; let person: T.Person;
console.log(pool);
do { do {
person = randomPerson(); person = randomPerson();
// eslint-disable-next-line // eslint-disable-next-line
@ -104,7 +217,7 @@ export default function EquativeGame({ id, link, level }: { id: string, link: st
number: n.numberCanChange ? randFromArray(["singular", "plural"]) : n.number, number: n.numberCanChange ? randFromArray(["singular", "plural"]) : n.number,
}; };
} }
function makeRandomEPS(): T.EPSelectionComplete { function makeRandomEPS(l: T.EquativeTense | "allIdentify" | "allProduce"): T.EPSelectionComplete {
const subj = randFromArray([ const subj = randFromArray([
makeRandPronoun, makeRandPronoun,
makeRandPronoun, makeRandPronoun,
@ -112,31 +225,43 @@ export default function EquativeGame({ id, link, level }: { id: string, link: st
makeRandPronoun, makeRandPronoun,
])(); ])();
const pred = randFromArray([...adjectives, ...locAdverbs]); const pred = randFromArray([...adjectives, ...locAdverbs]);
const tense = (level === "allIdentify" || level === "allProduce") const tense = (l === "allIdentify" || l === "allProduce")
? randFromArray(tenses) ? randFromArray(tenses)
: level; : l;
return makeEPS(subj, pred, tense); return makeEPS(subj, pred, tense);
} }
for (let i = 0; i < amount; i++) { for (let i = 0; i < amount; i++) {
const EPS = makeRandomEPS(); if (level === "situations") {
const EP = renderEP(EPS); const picked = randFromArray(situationPool);
const compiled = compileEP( situationPool = situationPool.filter(x => picked.description !== x.description);
EP, if (situationPool.length === 0) situationPool = [...situations];
true, yield {
level === "allIdentify" ? undefined : { equative: true, kidsSection: true }, progress: makeProgress(i, amount),
); question: {
const phrase = { situation: picked,
ps: compiled.ps, },
e: level === "allIdentify" ? undefined : compiled.e, };
}; } else {
yield { const EPS = makeRandomEPS(level);
progress: makeProgress(i, amount), const EP = renderEP(EPS);
question: { const compiled = compileEP(
EPS, EP,
phrase, true,
equative: EP.equative, level === "allIdentify" ? undefined : { equative: true, kidsSection: true },
}, );
}; const phrase = {
ps: compiled.ps,
e: level === "allIdentify" ? undefined : compiled.e,
};
yield {
progress: makeProgress(i, amount),
question: {
EPS,
phrase,
equative: EP.equative,
},
};
}
}; };
} }
@ -148,6 +273,9 @@ export default function EquativeGame({ id, link, level }: { id: string, link: st
setAnswer(value); setAnswer(value);
} }
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => { const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
if ("situation" in question) {
return;
}
e.preventDefault(); e.preventDefault();
const given = standardizePashto(answer.trim()); const given = standardizePashto(answer.trim());
const correct = checkAnswer(given, question.equative.ps) const correct = checkAnswer(given, question.equative.ps)
@ -158,6 +286,15 @@ export default function EquativeGame({ id, link, level }: { id: string, link: st
callback(!correct ? makeCorrectAnswer(question) : true); callback(!correct ? makeCorrectAnswer(question) : true);
} }
const handleTenseIdentify = (tense: T.EquativeTense) => { const handleTenseIdentify = (tense: T.EquativeTense) => {
if ("situation" in question) {
const wasCorrect = question.situation.tense.includes(tense);
if (wasCorrect) {
callback(true);
} else {
callback(makeCorrectAnswer(question));
}
return;
}
const renderedWAnswer = renderEP({ const renderedWAnswer = renderEP({
...question.EPS, ...question.EPS,
equative: { equative: {
@ -186,7 +323,7 @@ export default function EquativeGame({ id, link, level }: { id: string, link: st
)); ));
}); });
callback(<div className="lead"> callback(<div className="lead">
{makeCorrectTenseAnswer(possibleCorrect)} {possibleCorrect.map(humanReadableTense).join(" or ")}
</div>) </div>)
} }
} }
@ -195,13 +332,15 @@ export default function EquativeGame({ id, link, level }: { id: string, link: st
}, [question]); }, [question]);
return <div> return <div>
{level === "allIdentify" ? {(level === "allIdentify" || level === "situations") ?
<div className="pt-2 pb-1 mb-2" style={{ maxWidth: "300px", margin: "0 auto" }}> <div className="pt-2 pb-1 mb-2" style={{ maxWidth: "300px", margin: "0 auto" }}>
<Examples opts={opts}> {"situation" in question ? <p className="lead">
{question.situation.description}
</p> : <Examples opts={opts}>
{randFromArray(question.phrase.ps)} {randFromArray(question.phrase.ps)}
</Examples> </Examples>}
</div> </div>
: <div className="pt-2 pb-1 mb-2" style={{ maxWidth: "300px", margin: "0 auto" }}> : !("situation" in question) && <div className="pt-2 pb-1 mb-2" style={{ maxWidth: "300px", margin: "0 auto" }}>
<Examples opts={opts}> <Examples opts={opts}>
{/* @ts-ignore TODO: REMOVE AS P_INFLE */} {/* @ts-ignore TODO: REMOVE AS P_INFLE */}
{modExs(question.phrase.ps, withBa)[0]} {modExs(question.phrase.ps, withBa)[0]}
@ -212,9 +351,9 @@ export default function EquativeGame({ id, link, level }: { id: string, link: st
<div className="lead text-muted">{humanReadableTense(question.EPS.equative.tense)} equative</div> <div className="lead text-muted">{humanReadableTense(question.EPS.equative.tense)} equative</div>
</div> </div>
} }
{level === "allIdentify" ? <div className="text-center"> {level === "allIdentify" || "situation" in question ? <div className="text-center">
<div className="row"> <div className="row">
{tenses.map(t => <div className="col" key={t+question.phrase.ps}> {tenses.map(t => <div className="col" key={Math.random()}>
<button <button
style={{ width: "8rem" }} style={{ width: "8rem" }}
className="btn btn-outline-secondary mb-3" className="btn btn-outline-secondary mb-3"
@ -265,6 +404,8 @@ export default function EquativeGame({ id, link, level }: { id: string, link: st
return <div> return <div>
{level === "allProduce" {level === "allProduce"
? <p className="lead">Fill in the blank with the correct <strong>{humanReadableTense(level)} equative</strong> <strong>in Pashto script</strong></p> ? <p className="lead">Fill in the blank with the correct <strong>{humanReadableTense(level)} equative</strong> <strong>in Pashto script</strong></p>
: level === "situations"
? <p className="lead">Choose the right type of equative for each given situation</p>
: <p className="lead">Identify a correct tense for each equative phrase you see</p>} : <p className="lead">Identify a correct tense for each equative phrase you see</p>}
{level === "allProduce" && <div> All tenses included...</div>} {level === "allProduce" && <div> All tenses included...</div>}
</div> </div>
@ -280,15 +421,14 @@ export default function EquativeGame({ id, link, level }: { id: string, link: st
/> />
}; };
function makeCorrectTenseAnswer(tenses: T.EquativeTense[]): string {
return tenses.reduce((accum, curr, i) => (
`${accum}${(i > 0 ? " or " : " ")}'${humanReadableTense(curr)}'`
), "");
}
function makeCorrectAnswer(question: Question): JSX.Element { function makeCorrectAnswer(question: Question): JSX.Element {
if ("situation" in question) {
return <div>
{question.situation.tense.map(humanReadableTense).join(" or ")}
</div>;
}
return <div> return <div>
<div className="my-2"> <div>
{flattenLengths(question.equative.ps).reduce(((accum, curr, i): JSX.Element[] => ( {flattenLengths(question.equative.ps).reduce(((accum, curr, i): JSX.Element[] => (
[ [
...accum, ...accum,

View File

@ -114,7 +114,7 @@ export default function GenderGame({level, id, link }: { level: 1 | 2, id: strin
const nounGender: T.Gender = nounNotIn(mascNouns)(question) ? "fem" : "masc"; const nounGender: T.Gender = nounNotIn(mascNouns)(question) ? "fem" : "masc";
const correct = gender === nounGender; const correct = gender === nounGender;
callback(!correct callback(!correct
? <div className="my-4 text-center"> ? <div className="my-2 text-center">
<button style={{ background: genderColors[nounGender === "masc" ? "m" : "f"], color: "black" }} className="btn btn-lg" disabled> <button style={{ background: genderColors[nounGender === "masc" ? "m" : "f"], color: "black" }} className="btn btn-lg" disabled>
{nounGender === "masc" ? "Masculine" : "Feminine"} {nounGender === "masc" ? "Masculine" : "Feminine"}
</button> </button>

View File

@ -36,7 +36,7 @@ function UserProvider({ children }: any) {
}).catch(console.error); }).catch(console.error);
} }
const checkUserCronJob = new CronJob("1/30 * * * * *", () => { const checkUserCronJob = new CronJob("10 * * * *", () => {
pullUser(); pullUser();
if (value) { if (value) {
postSavedResults(value.userId); postSavedResults(value.userId);