This commit is contained in:
lingdocs 2022-08-30 19:08:17 +04:00
parent 83654a8276
commit 40089f76a2
9 changed files with 112 additions and 47 deletions

View File

@ -7,7 +7,7 @@
"@formkit/auto-animate": "^1.0.0-beta.1",
"@fortawesome/fontawesome-free": "^5.15.4",
"@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/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",

View File

@ -16,7 +16,7 @@ import {
import { isImperativeTense, isPerfectTense } from "@lingdocs/pashto-inflector/dist/lib/type-predicates";
import { useState } from "react";
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 { isThirdPerson } from "@lingdocs/pashto-inflector/dist/lib/phrase-building/vp-tools";
@ -27,7 +27,7 @@ function BasicVerbShowCase({ opts, tense, passive, ability }: {
ability?: boolean,
}) {
const items = isPastTense(tense)
? intransitivePast
? intransitivePastVerbs
: (passive ? basicVerbs.filter(v => v.entry.p !== "کول") : basicVerbs);
return <Carousel stickyTitle items={items} render={(item) => {
return {

View File

@ -14,7 +14,7 @@ export const basicVerbs: T.VerbEntry[] = [
].map(entry => ({ entry }));
// @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":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"},

View File

@ -54,13 +54,13 @@ function ChapterDisplay({ chapter, user, handleClick, expanded }: {
return <div key={id}>
<div className="d-flex flex-row justify-content-between align-items-center">
<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}
{` `}
</h4>
</h5>
</div>
<div>
<h4>
<h4 className={done ? "clickable" : ""}>
{done ? "✅"
:
<Link to={studyLink}>{"📚"}</Link>

View File

@ -41,6 +41,18 @@ export const imperativeVerbGame = makeGameRecord(
"/verbs/imperative-verbs/",
(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(
"Identify Noun Genders - Level 1",
@ -170,6 +182,8 @@ const games: { chapter: string, items: GameRecord[] }[] = [
subjunctiveVerbGame,
futureVerbGame,
imperativeVerbGame,
intransitiveImperfectivePastVerbGame,
intransitivePerfectivePastVerbGame,
],
}
];

View File

@ -34,6 +34,8 @@ import { isThirdPerson } from "@lingdocs/pashto-inflector/dist/lib/phrase-buildi
import { maybeShuffleArray } from "../../lib/shuffle-array";
import { getVerbFromBlocks } from "@lingdocs/pashto-inflector/dist/lib/phrase-building/blocks-utils";
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";
@ -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."},
].filter(tp.isNounEntry);
const pronounTypes = [
[T.Person.FirstSingMale, T.Person.FirstSingFemale],
[T.Person.SecondSingMale, T.Person.SecondSingFemale],
[T.Person.ThirdSingMale],
[T.Person.ThirdSingFemale],
[T.Person.FirstPlurMale, T.Person.FirstPlurFemale],
[T.Person.SecondPlurMale, T.Person.SecondPlurFemale],
[T.Person.ThirdPlurMale, T.Person.ThirdPlurFemale],
const persons = [
T.Person.FirstSingMale,
T.Person.FirstSingFemale,
T.Person.SecondSingMale,
T.Person.SecondSingFemale,
T.Person.ThirdSingMale,
T.Person.ThirdSingFemale,
T.Person.FirstPlurMale,
T.Person.FirstPlurFemale,
T.Person.SecondPlurMale,
T.Person.SecondPlurFemale,
T.Person.ThirdPlurMale,
T.Person.ThirdPlurFemale,
];
const secondPersonPronounTypes = [
[T.Person.SecondSingMale, T.Person.SecondSingFemale],
[T.Person.SecondPlurMale, T.Person.SecondPlurFemale],
const secondPersons = [
T.Person.SecondSingMale,
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 }: {
id: string,
link: string,
level: VerbGameLevel,
}) {
const poolBase = level === "imperative"
? secondPersonPronounTypes
: pronounTypes;
function* questions (): Generator<Current<Question>> {
let pool = [...poolBase];
function getRandPersFromPool(): T.Person {
let person: T.Person;
do {
person = randomPerson();
// eslint-disable-next-line
} while (!pool.some(p => p.includes(person)));
pool = pool.filter(p => !p.includes(person));
if (pool.length === 0) {
pool = poolBase;
}
return person;
}
const personPool = makePool(level === "imperative"
? secondPersons
: persons
);
const verbPool = makePool(
level.includes("intransitive")
? intransitivePastVerbs
: verbs,
30,
);
function makeRandomNoun(): T.NounSelection {
const n = makeNounSelection(randFromArray(nouns), undefined);
return {
@ -137,8 +141,8 @@ export default function VerbGame({ id, link, level }: {
distance: randFromArray(["far", "near", "far"]),
};
}
const verb = randFromArray(verbs);
const subj = getRandPersFromPool();
const verb = verbPool();
const subj = personPool();
let obj: T.Person;
do {
obj = randomPerson();
@ -184,9 +188,6 @@ export default function VerbGame({ id, link, level }: {
setAnswer(value);
}
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
if ("situation" in question) {
return;
}
e.preventDefault();
const correct = comparePs(answer, getVerbPs(question.rendered))
&& (withBa === verbHasBa(question.rendered));
@ -347,6 +348,10 @@ function levelToDescription(level: VerbGameLevel): string {
? "subjunctive"
: level === "futureVerb"
? "imperfective future or perfective future"
: level === "intransitivePerfectivePast"
? "simple past intransitive"
: level === "intransitiveImperfectivePast"
? "continuous past intransitive"
: "imperfective imperative or perfective imperative";
}
@ -357,8 +362,12 @@ function levelToTense(level: VerbGameLevel): T.VerbTense | T.ImperativeTense {
? level
: level === "futureVerb"
? randFromArray(["perfectiveFuture", "imperfectiveFuture"])
// : level === "imperative"
: randFromArray(["perfectiveImperative", "imperfectiveImperative"]);
: level === "imperative"
? randFromArray(["perfectiveImperative", "imperfectiveImperative"])
: level.includes("ImperfectivePast")
? "imperfectivePast"
// : level.includes("perfectivePast")
: "perfectivePast";
}
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)
? "grammatically transitive"
: vps.verb.transitivity;
console.log({ transitivity });
return {
...vps,
verb: {

View File

@ -53,6 +53,8 @@ export function comparePs(input: string, answer: T.SingleOrLengthOpts<T.PsString
if (Array.isArray(answer)) {
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);
}

39
src/lib/pool.ts Normal file
View File

@ -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);
}

View File

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