proper verb showcases - but now the sandwich english is broken

This commit is contained in:
lingdocs 2022-06-21 17:29:54 -05:00
parent 8ec6f0f2ec
commit 17f62439b5
11 changed files with 248 additions and 120 deletions

View File

@ -6,7 +6,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": "^2.9.8", "@lingdocs/pashto-inflector": "^3.0.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

@ -0,0 +1,211 @@
import {
Types as T,
RootsAndStems,
conjugateVerb,
VerbTable,
renderVP,
compileVP,
ButtonSelect,
getEnglishVerb,
InlinePs,
removeFVarients,
} from "@lingdocs/pashto-inflector";
import { isImperativeTense } from "@lingdocs/pashto-inflector/dist/lib/type-predicates";
import { useState } from "react";
import Carousel from "./Carousel";
import { basicVerbs } from "../content/verbs/basic-present-verbs";
function BasicVerbShowCase({ opts, tense }: {
opts: T.TextOptions,
tense: T.VerbTense | T.ImperativeTense,
}) {
return <Carousel stickyTitle items={basicVerbs} render={(item) => {
return {
title: <InlinePs opts={opts}>{{
...removeFVarients(item.entry),
e: undefined,
}}</InlinePs>,
body: <BasicVerbChart
verb={item}
opts={opts}
tense={tense}
/>,
};
}}/>
}
export default BasicVerbShowCase;
function BasicVerbChart({ verb, opts, tense }: {
verb: T.VerbEntry,
opts: T.TextOptions,
tense: T.VerbTense | T.ImperativeTense,
}) {
const [negative, setNegative] = useState<boolean>(false);
const c = conjugateVerb(verb.entry, verb.complement);
const conjugations = "stative" in c
? c.stative
: "grammaticallyTransitive" in c
? c.grammaticallyTransitive
: c;
const phrasesForTable = makeExamplePhrases(verb, tense, negative)
return <div>
<div>
{getEnglishVerb(verb.entry)}
</div>
<RootsAndStems
textOptions={opts}
info={conjugations.info}
hidePastParticiple={true}
highlighted={[tenseToStem(tense)]}
/>
<div className="my-3">
<ButtonSelect
handleChange={(value) => setNegative(value === "true")}
value={String(negative)}
small
options={[
{ value: "true", label: "Neg." },
{ value: "false", label: "Pos." },
]}
/>
</div>
<div className="text-left">
<VerbTable
textOptions={opts}
block={phrasesForTable.ps}
english={phrasesForTable.e}
/>
</div>
</div>
}
function makeExamplePhrases(verb: T.VerbEntry, tense: T.VerbTense | T.ImperativeTense, negative: boolean): { ps: T.VerbBlock | T.ImperativeBlock, e: T.EnglishBlock } {
function makeSelection(person: T.Person): T.VPSelectionComplete{
return {
"blocks": [
{"key":Math.random(),"block":{"type":"subjectSelection","selection":{"type":"NP","selection":{"type":"pronoun","person": person,"distance":"far"}}}},
{
key: Math.random(),
// @ts-ignore
block: verb.entry.c?.includes("intrans.")
? {"type":"objectSelection","selection":"none"}
: {"type":"objectSelection", "selection":{"type":"NP","selection":{"type":"noun","entry":{"ts":1527812817,"i":10011,"p":"کتاب","f":"kitáab","g":"kitaab","e":"book","c":"n. m."},"gender":"masc","genderCanChange":false,"number":"singular","numberCanChange":true,"adjectives":[]}}},
},
],
"verb":{
"type":"verb",
verb,
tense,
"transitivity":"intransitive",
"isCompound":false,
"voice":"active",
negative,
"canChangeTransitivity":false,
"canChangeVoice":false,
"canChangeStatDyn":false,
},
"form":{"removeKing":false,"shrinkServant":false},
};
}
function makePhrase(person: T.Person): { ps: T.ArrayOneOrMore<T.PsString>, e: string } {
const selection = makeSelection(person);
const rendered = renderVP(selection);
const compiled = compileVP(rendered, rendered.form, true);
return {
ps: [modifyP(compiled.ps[0])],
e: compiled.e ? modifyEnglish(compiled.e.join(" • ")) : "",
};
}
return createVerbTable(makePhrase, isImperativeTense(tense) ? "imperative" : "nonImperative");
}
function modifyP(ps: T.PsString): T.PsString {
return {
p: ps.p.replace(" کتاب ", ""),
f: ps.f.replace(" kitáab ", ""),
};
}
function modifyEnglish(e: string): string {
// "kitaab" used as a dummy object
return e
.replace(/\(a\/the\) +book/ig, "")
.replace(/he\/it/ig, "he/she/it")
.replace(/We \(m\. pl\.\)/ig, "We ")
.replace(/They \(m\. pl\.\)/ig, "They ")
.replace(/\(m\. pl\.\)/ig, "(pl.)")
.replace(/\(m\.\)/ig, "");
}
function tenseToStem(t: T.VerbTense | T.ImperativeTense): "imperfective stem" | "perfective stem" | "imperfective root" | "perfective root" {
return t === "presentVerb"
? "imperfective stem"
: t === "subjunctiveVerb"
? "perfective stem"
: t === "imperfectiveFuture"
? "imperfective stem"
: t === "perfectiveFuture"
? "perfective stem"
: t === "imperfectivePast"
? "imperfective root"
: t === "perfectivePast"
? "perfective root"
: t === "habitualImperfectivePast"
? "imperfective root"
: t === "habitualPerfectivePast"
? "perfective root"
: t === "imperfectiveImperative"
? "imperfective root"
: "perfective root";
}
function createVerbTable(f: (person: T.Person) => { ps: T.ArrayOneOrMore<T.PsString>, e: string }, type: "imperative" | "nonImperative"): { ps: T.VerbBlock | T.ImperativeBlock, e: T.EnglishBlock } {
if (type === "imperative") {
const b = [
[f(2), f(8)],
[f(3), f(9)],
];
return {
ps: [
[b[0][0].ps, b[0][1].ps],
[b[1][0].ps, b[1][1].ps],
],
e: [
[b[0][0].e, b[0][1].e],
[b[1][0].e, b[1][1].e],
[b[0][0].e, b[0][1].e],
[b[1][0].e, b[1][1].e],
[b[0][0].e, b[0][1].e],
[b[1][0].e, b[1][1].e],
],
};
}
const b = [
[f(0), f(6)],
[f(1), f(7)],
[f(2), f(8)],
[f(3), f(9)],
[f(4), f(10)],
[f(5), f(11)],
];
return {
ps: [
[b[0][0].ps, b[0][1].ps],
[b[1][0].ps, b[1][1].ps],
[b[2][0].ps, b[2][1].ps],
[b[3][0].ps, b[3][1].ps],
[b[4][0].ps, b[4][1].ps],
[b[5][0].ps, b[5][1].ps],
],
e: [
[b[0][0].e, b[0][1].e],
[b[1][0].e, b[1][1].e],
[b[2][0].e, b[2][1].e],
[b[3][0].e, b[3][1].e],
[b[4][0].e, b[4][1].e],
[b[5][0].e, b[5][1].e],
],
};
}

View File

@ -23,7 +23,7 @@ const Chapter = ({ children: chapter }) => {
}); });
} }
return <> return <>
<main className="col bg-faded py-3 d-flex flex-column"> <main className="col bg-faded py-3 d-flex flex-column" style={{ maxWidth: !chapter.frontMatter.fullWidth ? "850px" : undefined }}>
<div className="flex-shrink-0"> <div className="flex-shrink-0">
<div className="mb-2" style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}> <div className="mb-2" style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
<h1>{chapter.frontMatter.title}</h1> <h1>{chapter.frontMatter.title}</h1>

View File

@ -17,8 +17,8 @@ function BlockDiagram({ opts, children }: {
return <div className="mb-3"> return <div className="mb-3">
<div className="d-flex flex-row justify-content-center" style={{ maxWidth: "100%" }}> <div className="d-flex flex-row justify-content-center" style={{ maxWidth: "100%" }}>
{rendered.type === "NP" {rendered.type === "NP"
? <NPBlock opts={opts} english={rendered.selection.e}>{rendered}</NPBlock> ? <NPBlock script="f" opts={opts} english={rendered.selection.e}>{rendered}</NPBlock>
: <APBlock opts={opts} english={rendered.selection.e}>{rendered}</APBlock>} : <APBlock script="f" opts={opts} english={rendered.selection.e}>{rendered}</APBlock>}
</div> </div>
</div>; </div>;
} catch(e) { } catch(e) {

View File

@ -0,0 +1,15 @@
import {
Types as T,
} from "@lingdocs/pashto-inflector";
// @ts-ignore
export const basicVerbs: T.VerbEntry[] = [
{"ts":1527812856,"i":11630,"p":"لیکل","f":"leekul","g":"leekul","e":"to write, draw","c":"v. trans./gramm. trans.","ec":"write,writes,writing,wrote,written"},
{"ts":1527815399,"i":14480,"p":"وهل","f":"wahul","g":"wahul","e":"to hit","c":"v. trans.","tppp":"واهه","tppf":"waahu","ec":"hit,hits,hitting,hit,hit"},
{"ts":1527817750,"i":7843,"p":"سکل","f":"skul","g":"skul","e":"to drink","c":"v. trans.","ec":"drink,drinks,drinking,drank,drank"},
{"ts":1527812752,"i":10625,"p":"کول","f":"kawul","g":"kawul","e":"to do (an action or activity)","c":"v. trans. irreg.","ssp":"وکړ","ssf":"óokR","prp":"وکړل","prf":"óokRul","pprtp":"کړی","pprtf":"kúRey","diacExcept":true,"ec":"do,does,doing,did,done"},
{"ts":1527812275,"i":11608,"p":"لیدل","f":"leedul","g":"leedul","e":"to see","c":"v. trans./gramm. trans.","psp":"وین","psf":"ween","tppp":"لید","tppf":"leed","ec":"see,sees,seeing,saw,seen"},
{"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":5795,"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":1527815216,"i":6630,"p":"راتلل","f":"raatlúl","g":"raatlul","e":"to come","c":"v. intrans. irreg.","psp":"راځ","psf":"raadz","ssp":"راش","ssf":"ráash","prp":"راغلل","prf":"ráaghlul","pprtp":"راغلی","pprtf":"raaghúley","tppp":"راغی","tppf":"ráaghey","noOo":true,"separationAtP":2,"separationAtF":3,"ec":"come,comes,coming,came,come"},
].map(entry => ({ entry }));

View File

@ -6,20 +6,14 @@ import {
defaultTextOptions as opts, defaultTextOptions as opts,
Examples, Examples,
InlinePs, InlinePs,
removeFVarients,
ConjugationViewer,
} from "@lingdocs/pashto-inflector"; } from "@lingdocs/pashto-inflector";
import cousins from "./cousins.png"; import cousins from "./cousins.png";
import psmd from "../../lib/psmd"; import psmd from "../../lib/psmd";
import Carousel from "../../components/Carousel";
import Link from "../../components/Link"; import Link from "../../components/Link";
import Formula from "../../components/formula/Formula"; import Formula from "../../components/formula/Formula";
import { verbs } from "../../words/words";
import shuffleArray from "../../lib/shuffle-array";
import imperfectiveFuture from "./imperfective-future-graph.svg"; import imperfectiveFuture from "./imperfective-future-graph.svg";
import perfectiveFuture from "./perfective-future-graph.svg"; import perfectiveFuture from "./perfective-future-graph.svg";
import BasicVerbShowCase from "../../components/BasicVerbShowCase";
export const basicVerbs = verbs.filter((v) => !v.entry.c?.includes("gramm. trans."));
There are two kinds of future forms in Pashto: There are two kinds of future forms in Pashto:
@ -39,24 +33,9 @@ This is used to talk about something happening in the future, while thinking of
<Link to="/verbs/present-verbs/">Present</Link> <Link to="/verbs/present-verbs/">Present</Link>
</Formula> </Formula>
<Carousel stickyTitle items={shuffleArray(basicVerbs)} render={(item) => { <BasicVerbShowCase opts={opts} tense="imperfectiveFuture" />
return {
title: <InlinePs opts={opts} ps={{ Notice that the <InlinePs opts={opts} ps={{ p: "به", f: "ba" }} /> goes in the <Link to="/phrase-structure/kids-section/">kid's section</Link>.
...removeFVarients(item.entry),
e: item.def,
}} />,
body: <div style={{ textAlign: "left" }}>
<ConjugationViewer
entry={item.entry}
textOptions={opts}
highlightInRootsAndStems={["imperfective stem"]}
showOnly={["Present", "Imperfective Future"]}
hidePastParticiple
sentenceLevel="easy"
/>
</div>,
};
}}/>
## Perfective Future ## Perfective Future
@ -71,21 +50,4 @@ This is used to talk about something happening in the future, while thinking of
<Link to="/verbs/subjunctive-verbs/">Subjunctive</Link> <Link to="/verbs/subjunctive-verbs/">Subjunctive</Link>
</Formula> </Formula>
<Carousel stickyTitle items={shuffleArray(basicVerbs)} render={(item) => { <BasicVerbShowCase opts={opts} tense="perfectiveFuture" />
return {
title: <InlinePs opts={opts} ps={{
...removeFVarients(item.entry),
e: item.def,
}} />,
body: <div style={{ textAlign: "left" }}>
<ConjugationViewer
entry={item.entry}
textOptions={opts}
highlightInRootsAndStems={["Perfective stem"]}
showOnly={["Subjunctive", "Perfective Future"]}
hidePastParticiple
sentenceLevel="easy"
/>
</div>,
};
}}/>

View File

@ -7,7 +7,6 @@ import {
Examples, Examples,
InlinePs, InlinePs,
removeFVarients, removeFVarients,
ConjugationViewer,
} from "@lingdocs/pashto-inflector"; } from "@lingdocs/pashto-inflector";
import psmd from "../../lib/psmd"; import psmd from "../../lib/psmd";
import Carousel from "../../components/Carousel"; import Carousel from "../../components/Carousel";
@ -17,6 +16,7 @@ import { verbs } from "../../words/words";
import shuffleArray from "../../lib/shuffle-array"; 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";
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).
@ -39,6 +39,8 @@ The <i className="fas fa-video" /> **imperfective imperative** is used when you
<img src={imperfectiveImperative} alt="" className="img-fluid" /> <img src={imperfectiveImperative} alt="" className="img-fluid" />
</div> </div>
<BasicVerbShowCase opts={opts} tense="imperfectiveImperative" />
## Perfective Imperative ## Perfective Imperative
<Formula name="Perfective Imperative"> <Formula name="Perfective Imperative">
@ -51,24 +53,7 @@ The <i className="fas fa-camera" /> **perfective imperative** is used when you w
<img src={perfectiveImperative} alt="" className="img-fluid" /> <img src={perfectiveImperative} alt="" className="img-fluid" />
</div> </div>
<Carousel stickyTitle items={shuffleArray(basicVerbs)} render={(item) => { <BasicVerbShowCase opts={opts} tense="perfectiveImperative" />
return {
title: <InlinePs opts={opts} ps={{
...removeFVarients(item.entry),
e: item.def,
}} />,
body: <div className="text-left">
<ConjugationViewer
entry={item.entry}
textOptions={opts}
highlightInRootsAndStems={["imperfective stem", "perfective stem"]}
showOnly={["Perfective Imperative", "Imperfective Imperative"]}
hidePastParticiple
sentenceLevel="easy"
/>
</div>,
};
}}/>
## Using Imperatives ## Using Imperatives

View File

@ -6,19 +6,13 @@ import {
defaultTextOptions as opts, defaultTextOptions as opts,
Examples, Examples,
InlinePs, InlinePs,
removeFVarients,
ConjugationViewer,
} from "@lingdocs/pashto-inflector"; } from "@lingdocs/pashto-inflector";
import psmd from "../../lib/psmd"; import psmd from "../../lib/psmd";
import Carousel from "../../components/Carousel";
import Link from "../../components/Link"; import Link from "../../components/Link";
import Formula from "../../components/formula/Formula"; import Formula from "../../components/formula/Formula";
import { verbs } from "../../words/words";
import shuffleArray from "../../lib/shuffle-array";
import realityGraph from "./reality-graph.svg"; import realityGraph from "./reality-graph.svg";
import presentTime from "./present-time.svg"; import presentTime from "./present-time.svg";
import BasicVerbShowCase from "./../../components/BasicVerbShowCase";
export const basicVerbs = verbs.filter((v) => !v.entry.c?.includes("gramm. trans."));
The first verb form we'll learn is the **present**. This will be the first tool in our toolbox of verb forms. 🧰 With each verb form we'll learn two things: The first verb form we'll learn is the **present**. This will be the first tool in our toolbox of verb forms. 🧰 With each verb form we'll learn two things:
@ -35,24 +29,7 @@ As with all verb forms, the **present form** is made by following a very simple
The <Link to="/verbs/verb-endings/">present ending</Link> will change according to what the subject is. Have a look through the verbs below and see how the present form follows the same formula for all of them. 👇 The <Link to="/verbs/verb-endings/">present ending</Link> will change according to what the subject is. Have a look through the verbs below and see how the present form follows the same formula for all of them. 👇
<Carousel stickyTitle items={shuffleArray(basicVerbs)} render={(item) => { <BasicVerbShowCase opts={opts} tense="presentVerb" />
return {
title: <InlinePs opts={opts} ps={{
...removeFVarients(item.entry),
e: item.def,
}} />,
body: <div className="text-left">
<ConjugationViewer
entry={item.entry}
textOptions={opts}
highlightInRootsAndStems={["imperfective stem"]}
showOnly="Present"
hidePastParticiple
sentenceLevel="easy"
/>
</div>,
};
}}/>
**Notes:** **Notes:**

View File

@ -7,19 +7,14 @@ import {
Examples, Examples,
InlinePs, InlinePs,
removeFVarients, removeFVarients,
ConjugationViewer,
} from "@lingdocs/pashto-inflector"; } from "@lingdocs/pashto-inflector";
import cousins from "./cousins.png"; import cousins from "./cousins.png";
import psmd from "../../lib/psmd"; import psmd from "../../lib/psmd";
import Carousel from "../../components/Carousel";
import Link from "../../components/Link"; import Link from "../../components/Link";
import Formula from "../../components/formula/Formula"; import Formula from "../../components/formula/Formula";
import { verbs } from "../../words/words";
import shuffleArray from "../../lib/shuffle-array";
import presentInReality from "./present-in-reality.svg"; import presentInReality from "./present-in-reality.svg";
import subjunctiveAboveReality from "./subjunctive-above-reality.svg"; import subjunctiveAboveReality from "./subjunctive-above-reality.svg";
import BasicVerbShowCase from "../../components/BasicVerbShowCase";
export const basicVerbs = verbs.filter((v) => !v.entry.c?.includes("gramm. trans."));
The **subjunctive** is a very important verb form in Pashto, but it's often ignored by English-speaking learners because we don't really have anything like it in English. So, we need to understand what it is, and then train our brains to reach for it and use it in the right situations! The **subjunctive** is a very important verb form in Pashto, but it's often ignored by English-speaking learners because we don't really have anything like it in English. So, we need to understand what it is, and then train our brains to reach for it and use it in the right situations!
@ -55,24 +50,7 @@ The subjunctive is made the same way as its cousin the <Link to="/verbs/present-
Perfective Stem + <Link to="/verbs/verb-endings/">Present Ending</Link> Perfective Stem + <Link to="/verbs/verb-endings/">Present Ending</Link>
</Formula> </Formula>
<Carousel stickyTitle items={shuffleArray(basicVerbs)} render={(item) => { <BasicVerbShowCase opts={opts} tense="subjunctiveVerb" />
return {
title: <InlinePs opts={opts} ps={{
...removeFVarients(item.entry),
e: item.def,
}} />,
body: <div className="text-left">
<ConjugationViewer
entry={item.entry}
textOptions={opts}
highlightInRootsAndStems={["perfective stem"]}
showOnly="Subjunctive"
hidePastParticiple
sentenceLevel="easy"
/>
</div>,
};
}}/>
## Examples ## Examples

View File

@ -503,7 +503,7 @@ function makeEPS(subject: T.NPSelection, predicate: T.AdjectiveEntry | T.Locativ
} }
function getEqFromRendered(e: T.EPRendered): T.EquativeRendered { function getEqFromRendered(e: T.EPRendered): T.EquativeRendered {
const eblock = e.blocks.find(x => x.type === "equative"); const eblock = e.blocks[0].find(x => x.type === "equative");
if (!eblock || eblock.type !== "equative") throw new Error("Error getting equative block"); if (!eblock || eblock.type !== "equative") throw new Error("Error getting equative block");
return eblock.equative; return eblock.equative;
} }

View File

@ -1695,10 +1695,10 @@
rambda "^6.7.0" rambda "^6.7.0"
react-select "^5.2.2" react-select "^5.2.2"
"@lingdocs/pashto-inflector@^2.9.7": "@lingdocs/pashto-inflector@^3.0.4":
version "2.9.7" version "3.0.4"
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-2.9.7.tgz#bd27694db0cd528c784847161392e115f2a00139" resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-3.0.4.tgz#6ea750f66509e9e88c8d6fa01298a4e9fb07a807"
integrity sha512-TNIlv9Ktv+aSZEu+BJtl0ZMBZSpD1wcBtMibhT/JEDqd7g7KzbrNW0kkbgnIZm3nvZB1UavrgVzQgATJdvdG/g== integrity sha512-fUVTuQBeJ0YrtbBbj0JUlCEgrnKLadD0dL6Ig6eawDA0Fayrfp/yeuz1MsFRcYosdtNx5juY5JQyioh9AgC4YQ==
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"