This commit is contained in:
parent
83654a8276
commit
40089f76a2
|
@ -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.4",
|
"@lingdocs/pashto-inflector": "^3.8.7",
|
||||||
"@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",
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {
|
||||||
import { isImperativeTense, isPerfectTense } from "@lingdocs/pashto-inflector/dist/lib/type-predicates";
|
import { isImperativeTense, isPerfectTense } from "@lingdocs/pashto-inflector/dist/lib/type-predicates";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Carousel from "./Carousel";
|
import Carousel from "./Carousel";
|
||||||
import { basicVerbs, intransitivePast } from "../content/verbs/basic-present-verbs";
|
import { basicVerbs, intransitivePastVerbs } from "../content/verbs/basic-present-verbs";
|
||||||
import { getLength } from "@lingdocs/pashto-inflector/dist/lib/p-text-helpers";
|
import { getLength } from "@lingdocs/pashto-inflector/dist/lib/p-text-helpers";
|
||||||
import { isThirdPerson } from "@lingdocs/pashto-inflector/dist/lib/phrase-building/vp-tools";
|
import { isThirdPerson } from "@lingdocs/pashto-inflector/dist/lib/phrase-building/vp-tools";
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ function BasicVerbShowCase({ opts, tense, passive, ability }: {
|
||||||
ability?: boolean,
|
ability?: boolean,
|
||||||
}) {
|
}) {
|
||||||
const items = isPastTense(tense)
|
const items = isPastTense(tense)
|
||||||
? intransitivePast
|
? intransitivePastVerbs
|
||||||
: (passive ? basicVerbs.filter(v => v.entry.p !== "کول") : basicVerbs);
|
: (passive ? basicVerbs.filter(v => v.entry.p !== "کول") : basicVerbs);
|
||||||
return <Carousel stickyTitle items={items} render={(item) => {
|
return <Carousel stickyTitle items={items} render={(item) => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -14,7 +14,7 @@ export const basicVerbs: T.VerbEntry[] = [
|
||||||
].map(entry => ({ entry }));
|
].map(entry => ({ entry }));
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export const intransitivePast: T.VerbEntry[] = [
|
export const intransitivePastVerbs: T.VerbEntry[] = [
|
||||||
{"ts":1527813573,"i":6809,"p":"رسېدل","f":"rasedul","g":"rasedul","e":"arrive, reached; (fig.) understand, attain to; mature, ripen","c":"v. intrans.","shortIntrans":true,"ec":"arrive"},
|
{"ts":1527813573,"i":6809,"p":"رسېدل","f":"rasedul","g":"rasedul","e":"arrive, reached; (fig.) understand, attain to; mature, ripen","c":"v. intrans.","shortIntrans":true,"ec":"arrive"},
|
||||||
{"ts":1527812645,"i":10822,"p":"ګرځېدل","f":"gurdzedul","g":"gurdzedul","e":"to walk, wander, turn about; to become, to be","c":"v. intrans.","shortIntrans":true,"ec":"walk"},
|
{"ts":1527812645,"i":10822,"p":"ګرځېدل","f":"gurdzedul","g":"gurdzedul","e":"to walk, wander, turn about; to become, to be","c":"v. intrans.","shortIntrans":true,"ec":"walk"},
|
||||||
{"ts":1527816495,"i":3470,"p":"تښتېدل","f":"tuxtedul","g":"tuxtedul","e":"to run off, escape, flee","c":"v. intrans.","shortIntrans":true,"ec":"escape"},
|
{"ts":1527816495,"i":3470,"p":"تښتېدل","f":"tuxtedul","g":"tuxtedul","e":"to run off, escape, flee","c":"v. intrans.","shortIntrans":true,"ec":"escape"},
|
||||||
|
|
|
@ -54,13 +54,13 @@ function ChapterDisplay({ chapter, user, handleClick, expanded }: {
|
||||||
return <div key={id}>
|
return <div key={id}>
|
||||||
<div className="d-flex flex-row justify-content-between align-items-center">
|
<div className="d-flex flex-row justify-content-between align-items-center">
|
||||||
<div>
|
<div>
|
||||||
<h4 className="my-4 clickable" onClick={() => handleTitleClick(id)}>
|
<h5 className="my-3 clickable" onClick={() => handleTitleClick(id)}>
|
||||||
<i className={`fas fa-caret-${open ? "down" : "right"}`}></i> {title}
|
<i className={`fas fa-caret-${open ? "down" : "right"}`}></i> {title}
|
||||||
{` `}
|
{` `}
|
||||||
</h4>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4>
|
<h4 className={done ? "clickable" : ""}>
|
||||||
{done ? "✅"
|
{done ? "✅"
|
||||||
:
|
:
|
||||||
<Link to={studyLink}>{"📚"}</Link>
|
<Link to={studyLink}>{"📚"}</Link>
|
||||||
|
|
|
@ -41,6 +41,18 @@ export const imperativeVerbGame = makeGameRecord(
|
||||||
"/verbs/imperative-verbs/",
|
"/verbs/imperative-verbs/",
|
||||||
(id, link) => () => <VerbGame id={id} level="imperative" link={link} />
|
(id, link) => () => <VerbGame id={id} level="imperative" link={link} />
|
||||||
);
|
);
|
||||||
|
export const intransitivePerfectivePastVerbGame = makeGameRecord(
|
||||||
|
"Write the intransitive simple past verb",
|
||||||
|
"intransitive-perfective-past-verbs-write",
|
||||||
|
"/verbs/past-verbs/#past-tense-with-transitive-verbs-",
|
||||||
|
(id, link) => () => <VerbGame id={id} level="intransitivePerfectivePast" link={link} />
|
||||||
|
);
|
||||||
|
export const intransitiveImperfectivePastVerbGame = makeGameRecord(
|
||||||
|
"Write the intransitive continuous past verb",
|
||||||
|
"transitive-imperfective-past-verbs-write",
|
||||||
|
"/verbs/past-verbs/#past-tense-with-transitive-verbs-",
|
||||||
|
(id, link) => () => <VerbGame id={id} level="intransitiveImperfectivePast" link={link} />
|
||||||
|
);
|
||||||
|
|
||||||
export const nounGenderGame1 = makeGameRecord(
|
export const nounGenderGame1 = makeGameRecord(
|
||||||
"Identify Noun Genders - Level 1",
|
"Identify Noun Genders - Level 1",
|
||||||
|
@ -170,6 +182,8 @@ const games: { chapter: string, items: GameRecord[] }[] = [
|
||||||
subjunctiveVerbGame,
|
subjunctiveVerbGame,
|
||||||
futureVerbGame,
|
futureVerbGame,
|
||||||
imperativeVerbGame,
|
imperativeVerbGame,
|
||||||
|
intransitiveImperfectivePastVerbGame,
|
||||||
|
intransitivePerfectivePastVerbGame,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
@ -34,6 +34,8 @@ import { isThirdPerson } from "@lingdocs/pashto-inflector/dist/lib/phrase-buildi
|
||||||
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";
|
import { baParticle } from "@lingdocs/pashto-inflector/dist/lib/grammar-units";
|
||||||
|
import { intransitivePastVerbs } from "../../content/verbs/basic-present-verbs";
|
||||||
|
import { makePool } from "../../lib/pool";
|
||||||
|
|
||||||
const kidsColor = "#017BFE";
|
const kidsColor = "#017BFE";
|
||||||
|
|
||||||
|
@ -66,45 +68,47 @@ const nouns: T.NounEntry[] = [
|
||||||
{"ts":1527812661,"i":13938,"p":"هلک","f":"halík, halúk","g":"halik,haluk","e":"boy, young lad","c":"n. m. anim."},
|
{"ts":1527812661,"i":13938,"p":"هلک","f":"halík, halúk","g":"halik,haluk","e":"boy, young lad","c":"n. m. anim."},
|
||||||
].filter(tp.isNounEntry);
|
].filter(tp.isNounEntry);
|
||||||
|
|
||||||
const pronounTypes = [
|
const persons = [
|
||||||
[T.Person.FirstSingMale, T.Person.FirstSingFemale],
|
T.Person.FirstSingMale,
|
||||||
[T.Person.SecondSingMale, T.Person.SecondSingFemale],
|
T.Person.FirstSingFemale,
|
||||||
[T.Person.ThirdSingMale],
|
T.Person.SecondSingMale,
|
||||||
[T.Person.ThirdSingFemale],
|
T.Person.SecondSingFemale,
|
||||||
[T.Person.FirstPlurMale, T.Person.FirstPlurFemale],
|
T.Person.ThirdSingMale,
|
||||||
[T.Person.SecondPlurMale, T.Person.SecondPlurFemale],
|
T.Person.ThirdSingFemale,
|
||||||
[T.Person.ThirdPlurMale, T.Person.ThirdPlurFemale],
|
T.Person.FirstPlurMale,
|
||||||
|
T.Person.FirstPlurFemale,
|
||||||
|
T.Person.SecondPlurMale,
|
||||||
|
T.Person.SecondPlurFemale,
|
||||||
|
T.Person.ThirdPlurMale,
|
||||||
|
T.Person.ThirdPlurFemale,
|
||||||
];
|
];
|
||||||
|
|
||||||
const secondPersonPronounTypes = [
|
const secondPersons = [
|
||||||
[T.Person.SecondSingMale, T.Person.SecondSingFemale],
|
T.Person.SecondSingMale,
|
||||||
[T.Person.SecondPlurMale, T.Person.SecondPlurFemale],
|
T.Person.SecondSingFemale,
|
||||||
|
T.Person.SecondPlurMale,
|
||||||
|
T.Person.SecondPlurFemale,
|
||||||
];
|
];
|
||||||
|
|
||||||
type VerbGameLevel = "presentVerb" | "subjunctiveVerb" | "futureVerb" | "imperative";
|
type VerbGameLevel = "presentVerb" | "subjunctiveVerb"
|
||||||
|
| "futureVerb" | "imperative" | "intransitivePerfectivePast" | "intransitiveImperfectivePast";
|
||||||
|
|
||||||
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;
|
|
||||||
function* questions (): Generator<Current<Question>> {
|
function* questions (): Generator<Current<Question>> {
|
||||||
let pool = [...poolBase];
|
const personPool = makePool(level === "imperative"
|
||||||
function getRandPersFromPool(): T.Person {
|
? secondPersons
|
||||||
let person: T.Person;
|
: persons
|
||||||
do {
|
);
|
||||||
person = randomPerson();
|
const verbPool = makePool(
|
||||||
// eslint-disable-next-line
|
level.includes("intransitive")
|
||||||
} while (!pool.some(p => p.includes(person)));
|
? intransitivePastVerbs
|
||||||
pool = pool.filter(p => !p.includes(person));
|
: verbs,
|
||||||
if (pool.length === 0) {
|
30,
|
||||||
pool = poolBase;
|
);
|
||||||
}
|
|
||||||
return person;
|
|
||||||
}
|
|
||||||
function makeRandomNoun(): T.NounSelection {
|
function makeRandomNoun(): T.NounSelection {
|
||||||
const n = makeNounSelection(randFromArray(nouns), undefined);
|
const n = makeNounSelection(randFromArray(nouns), undefined);
|
||||||
return {
|
return {
|
||||||
|
@ -137,8 +141,8 @@ export default function VerbGame({ id, link, level }: {
|
||||||
distance: randFromArray(["far", "near", "far"]),
|
distance: randFromArray(["far", "near", "far"]),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const verb = randFromArray(verbs);
|
const verb = verbPool();
|
||||||
const subj = getRandPersFromPool();
|
const subj = personPool();
|
||||||
let obj: T.Person;
|
let obj: T.Person;
|
||||||
do {
|
do {
|
||||||
obj = randomPerson();
|
obj = randomPerson();
|
||||||
|
@ -184,9 +188,6 @@ export default function VerbGame({ id, link, level }: {
|
||||||
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 correct = comparePs(answer, getVerbPs(question.rendered))
|
const correct = comparePs(answer, getVerbPs(question.rendered))
|
||||||
&& (withBa === verbHasBa(question.rendered));
|
&& (withBa === verbHasBa(question.rendered));
|
||||||
|
@ -347,6 +348,10 @@ function levelToDescription(level: VerbGameLevel): string {
|
||||||
? "subjunctive"
|
? "subjunctive"
|
||||||
: level === "futureVerb"
|
: level === "futureVerb"
|
||||||
? "imperfective future or perfective future"
|
? "imperfective future or perfective future"
|
||||||
|
: level === "intransitivePerfectivePast"
|
||||||
|
? "simple past intransitive"
|
||||||
|
: level === "intransitiveImperfectivePast"
|
||||||
|
? "continuous past intransitive"
|
||||||
: "imperfective imperative or perfective imperative";
|
: "imperfective imperative or perfective imperative";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,8 +362,12 @@ function levelToTense(level: VerbGameLevel): T.VerbTense | T.ImperativeTense {
|
||||||
? level
|
? level
|
||||||
: level === "futureVerb"
|
: level === "futureVerb"
|
||||||
? randFromArray(["perfectiveFuture", "imperfectiveFuture"])
|
? randFromArray(["perfectiveFuture", "imperfectiveFuture"])
|
||||||
// : level === "imperative"
|
: level === "imperative"
|
||||||
: randFromArray(["perfectiveImperative", "imperfectiveImperative"]);
|
? randFromArray(["perfectiveImperative", "imperfectiveImperative"])
|
||||||
|
: level.includes("ImperfectivePast")
|
||||||
|
? "imperfectivePast"
|
||||||
|
// : level.includes("perfectivePast")
|
||||||
|
: "perfectivePast";
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeVPS({ verb, subject, object, tense }: {
|
function makeVPS({ verb, subject, object, tense }: {
|
||||||
|
@ -371,6 +380,7 @@ function makeVPS({ verb, subject, object, tense }: {
|
||||||
const transitivity = (vps.verb.transitivity === "transitive" && vps.verb.canChangeTransitivity)
|
const transitivity = (vps.verb.transitivity === "transitive" && vps.verb.canChangeTransitivity)
|
||||||
? "grammatically transitive"
|
? "grammatically transitive"
|
||||||
: vps.verb.transitivity;
|
: vps.verb.transitivity;
|
||||||
|
console.log({ transitivity });
|
||||||
return {
|
return {
|
||||||
...vps,
|
...vps,
|
||||||
verb: {
|
verb: {
|
||||||
|
|
|
@ -53,6 +53,8 @@ export function comparePs(input: string, answer: T.SingleOrLengthOpts<T.PsString
|
||||||
if (Array.isArray(answer)) {
|
if (Array.isArray(answer)) {
|
||||||
return answer.some(a => comparePs(input, a));
|
return answer.some(a => comparePs(input, a));
|
||||||
}
|
}
|
||||||
const stand = standardizePhonetics(standardizePashto(input)).trim();
|
const stand = standardizePhonetics(
|
||||||
|
standardizePashto(input)
|
||||||
|
).trim();
|
||||||
return stand === answer.p || compareF(stand, answer.f);
|
return stand === answer.p || compareF(stand, answer.f);
|
||||||
}
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { randFromArray } from "@lingdocs/pashto-inflector";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param poolBase an array of things you want to use as the pool to pick from
|
||||||
|
* @param removalLaxity If set, thery will be a n% chance that the pick will NOT
|
||||||
|
* be removed after use. Defaults to 0, meaning that every time an item is picked
|
||||||
|
* it is removed from the. 100 means that items will never be removed from the pool.
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function makePool<P>(poolBase: P[], removalLaxity = 0): () => P {
|
||||||
|
let pool = [...poolBase];
|
||||||
|
function shouldStillKeepIt() {
|
||||||
|
return Math.random() < (removalLaxity / 100);
|
||||||
|
}
|
||||||
|
function pickRandomFromPool(): P {
|
||||||
|
// Pick an item from the pool;
|
||||||
|
const pick = randFromArray(pool);
|
||||||
|
// Remove the (first occurance of) the item from the pool
|
||||||
|
// This step might be skipped if the removal laxity is set
|
||||||
|
if (removalLaxity && !shouldStillKeepIt()) {
|
||||||
|
const index = pool.findIndex(v => matches(v, pick))
|
||||||
|
if (index === -1) throw new Error("could not find pick from pool");
|
||||||
|
pool.splice(index, 1);
|
||||||
|
// If the pool is empty, reset it
|
||||||
|
if (pool.length === 0) {
|
||||||
|
pool = [...poolBase];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pick;
|
||||||
|
}
|
||||||
|
return pickRandomFromPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
function matches(a: unknown, b: unknown): boolean {
|
||||||
|
return JSON.stringify(a) === JSON.stringify(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.4":
|
"@lingdocs/pashto-inflector@^3.8.7":
|
||||||
version "3.8.4"
|
version "3.8.7"
|
||||||
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-3.8.4.tgz#2a29b04c541f3d12842ae2dabc3bc1e71a1b77ad"
|
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-3.8.7.tgz#9f9a28718f82620a74c4d7732232bd716cf0fd85"
|
||||||
integrity sha512-YVH+LFX4UslcQnNfYbmE9vX+bsq/LFylnxk3lEMLDLRW/abRmWlcPcElJr2wXYm3VR5uoLCK463ulS7IhQoUeQ==
|
integrity sha512-rVjQole0oQpsGBZOqQ7btO80mbL04JhHC6z21G0vLYAswOe4OFdnQyBfKztMclYKiJV2vdtWLXpjjdIPt+Ypbg==
|
||||||
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"
|
||||||
|
|
Loading…
Reference in New Issue