From 5d632f095e77d311d51c6727118106ea4d521242 Mon Sep 17 00:00:00 2001
From: lingdocs <71590811+lingdocs@users.noreply.github.com>
Date: Tue, 15 Mar 2022 19:09:29 +0400
Subject: [PATCH] fix not-allowed pronoun combos
---
src/components/VerbPicker.tsx | 12 +-
src/content/practice-tools/phrase-builder.mdx | 2 +-
src/content/practice-tools/pronoun-picker.mdx | 30 ++++-
src/lib/eval-vp.ts | 114 ++++++++++++++----
src/lib/np-tools.ts | 2 +-
src/types/gen-g.d.ts | 4 +-
6 files changed, 131 insertions(+), 33 deletions(-)
diff --git a/src/components/VerbPicker.tsx b/src/components/VerbPicker.tsx
index 989da49..cd3ed65 100644
--- a/src/components/VerbPicker.tsx
+++ b/src/components/VerbPicker.tsx
@@ -7,12 +7,18 @@ import {
Types as T,
} from "@lingdocs/pashto-inflector";
-const tenseOptions = [{
+const tenseOptions: { label: string, value: VerbTense }[] = [{
label: "present",
value: "present",
}, {
label: "subjunctive",
value: "subjunctive",
+}, {
+ label: "simple past",
+ value: "perfectivePast",
+}, {
+ label: "continuous past",
+ value: "imperfectivePast",
}];
function makeVerbSelection(verb: VerbEntry, oldVerbSelection?: VerbSelection): VerbSelection {
@@ -49,7 +55,7 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
}
onChange(makeVerbSelection(v, verb));
}
- function onTenseSelect({ value }: { label: string, value: "present" | "subjunctive" }) {
+ function onTenseSelect({ value }: { label: string, value: VerbTense }) {
if (verb) {
onChange({
...verb,
@@ -80,7 +86,7 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
// @ts-ignore
options={tenseOptions}
isSearchable
- placeholder={verb ? tenseOptions.find(o => o.value === verb.tense)?.value : "Select Tense..."}
+ placeholder={verb ? tenseOptions.find(o => o.value === verb.tense)?.label : "Select Tense..."}
{...zIndexProps}
/>
;
diff --git a/src/content/practice-tools/phrase-builder.mdx b/src/content/practice-tools/phrase-builder.mdx
index d4c482e..467e248 100644
--- a/src/content/practice-tools/phrase-builder.mdx
+++ b/src/content/practice-tools/phrase-builder.mdx
@@ -4,6 +4,6 @@ title: Phrase Builder
import PhraseBuilder from "../../components/phrase-builder/PhraseBuilder";
-This is under construction... It's not quite working yet. 👷🚧
+##### This is under construction... It's not fully working yet. 👷🚧
\ No newline at end of file
diff --git a/src/content/practice-tools/pronoun-picker.mdx b/src/content/practice-tools/pronoun-picker.mdx
index 9c5c3a1..7914841 100644
--- a/src/content/practice-tools/pronoun-picker.mdx
+++ b/src/content/practice-tools/pronoun-picker.mdx
@@ -12,13 +12,39 @@ import { useState } from "react";
import {
randomPerson,
randomSubjObj,
+ isInvalidSubjObjCombo,
} from "../../lib/np-tools";
export function RPicker() {
+ // TODO: Pull this into a type safe file
const startSubjObj = randomSubjObj();
const [subject, setSubject] = useState({ type: "pronoun", pronounType: "far", person: startSubjObj.subj });
const [object, setObject] = useState({ type: "pronoun", pronounType: "far", person: startSubjObj.obj });
const [mode, setMode] = useState("single");
+ function handleSetSubject(incoming) {
+ if (mode !== "single" && isInvalidSubjObjCombo(incoming.person, object.person)) {
+ alert("That combination of pronouns is not allowed");
+ return;
+ // let newP = 0;
+ // do {
+ // newP = randomPerson();
+ // } while (isInvalidSubjObjCombo(newP, object.person));
+ // return setSubject({ ...incoming, person: newP });
+ }
+ return setSubject(incoming);
+ }
+ function handleSetObject(incoming) {
+ if (isInvalidSubjObjCombo(subject.person, incoming.person)) {
+ alert("That combination of pronouns is not allowed");
+ return;
+ // let newP = 0;
+ // do {
+ // newP = randomPerson();
+ // } while (isInvalidSubjObjCombo(newP, subject.person));
+ // return setObject({ ...incoming, person: newP });
+ }
+ return setObject(incoming);
+ }
function setRandomSubjObj() {
const { subj, obj } = randomSubjObj();
setSubject(s => ({
@@ -64,12 +90,12 @@ export function RPicker() {
{mode === "subjObj" &&
Subject
}
-
+
{mode === "subjObj" &&
}
diff --git a/src/lib/eval-vp.ts b/src/lib/eval-vp.ts
index 3e84ce8..f5ab69e 100644
--- a/src/lib/eval-vp.ts
+++ b/src/lib/eval-vp.ts
@@ -14,22 +14,25 @@ import {
export function renderVP(VP: VPSelection): VPRendered {
// TODO: Will be based on past tense etc
- const king = "subject";
- // const servant = VP.object ? "object" : undefined;
+ const isPast = isPastTense(VP.verb.tense);
+ const isTransitive = VP.object !== "none";
+ const { king, /* servant */ } = getKingAndServant(isPast, isTransitive);
+ console.log({ king, isPast, isTransitive });
const verbPerson = getPersonFromNP(VP[king]);
const subjectPerson = getPersonFromNP(VP.subject);
+ // TODO: also don't inflect if it's a pattern one animate noun
+ const inflectSubject = isPast && isTransitive;
+ console.log({ inflectSubject });
const subject: Rendered = {
...VP.subject,
- inflected: false,
- // TODO: possibility for inflecting
- ...textOfNP(VP.subject, false, false),
+ inflected: inflectSubject,
+ ...textOfNP(VP.subject, inflectSubject, false),
};
- const inflectObject = isFirstOrSecondPersPronoun(VP.object);
+ const inflectObject = !isPast && isFirstOrSecondPersPronoun(VP.object);
const object: "none" | Rendered | T.Person.ThirdPlurMale = typeof VP.object === "object"
? {
...VP.subject,
inflected: inflectObject,
- // TODO: possibility for inflecting
...textOfNP(VP.object, inflectObject, true),
} : VP.object;
// TODO: error handle this?
@@ -64,11 +67,20 @@ export function compileVP(VP: VPRendered | VPSelection): { ps: T.SingleOrLengthO
if (VP.type === "VPSelection") {
return compileVP(renderVP(VP));
}
+ function insertEWords(e: string, { subject, object }: { subject: string, object?: string }): string {
+ return e.replace("$SUBJ", subject).replace("$OBJ", object || "");
+ }
+ // TODO: display of short and long options etc.
const vPs = "long" in VP.verb.ps ? VP.verb.ps.long : VP.verb.ps;
- // const vE = VP.verb.e;
+ const engSubj = VP.subject.e || undefined;
+ const engObj = (typeof VP.object === "object" && VP.object.e) ? VP.object.e : undefined;
+ // require all English parts for making the English phrase
+ const e = (VP.verb.e && engSubj && engObj) ? VP.verb.e.map(e => insertEWords(e, {
+ subject: engSubj,
+ object: engObj,
+ })) : undefined;
const obj = typeof VP.object === "object" ? VP.object : undefined;
const ps = VP.subject.ps.flatMap(s => (
- // TODO: fix double space thing
obj ? obj.ps.flatMap(o => (
vPs.flatMap(v => (
concatPsString(s, " ", o, " ", v)
@@ -77,7 +89,27 @@ export function compileVP(VP: VPRendered | VPSelection): { ps: T.SingleOrLengthO
concatPsString(s, " ", v)
))
));
- return { ps };
+ return { ps, e };
+}
+
+function isPastTense(tense: VerbTense): boolean {
+ return tense.toLowerCase().includes("past");
+}
+
+function getKingAndServant(isPast: boolean, isTransitive: boolean):
+ { king: "subject", servant: "object" } |
+ { king: "object", servant: "subject" } |
+ { king: "subject", servant: undefined } {
+ if (!isTransitive) {
+ return { king: "subject", servant: undefined };
+ }
+ return isPast ? {
+ king: "object",
+ servant: "subject",
+ } : {
+ king: "subject",
+ servant: "object",
+ };
}
function isFirstOrSecondPersPronoun(o: "none" | NPSelection | T.Person.ThirdPlurMale): boolean {
@@ -86,8 +118,8 @@ function isFirstOrSecondPersPronoun(o: "none" | NPSelection | T.Person.ThirdPlur
return [0,1,2,3,6,7,8,9].includes(o.person);
}
-function getPsVerbConjugation(conj: T.VerbConjugation, tense: "present" | "subjunctive", person: T.Person): T.SingleOrLengthOpts {
- const f = conj[tense === "present" ? "imperfective" : "perfective"].nonImperative;
+function getPsVerbConjugation(conj: T.VerbConjugation, tense: VerbTense, person: T.Person): T.SingleOrLengthOpts {
+ const f = getTenseVerbForm(conj, tense);
// TODO: ability to grab the correct part of matrix
const block = "mascSing" in f
? f.mascSing
@@ -108,12 +140,28 @@ function getPsVerbConjugation(conj: T.VerbConjugation, tense: "present" | "subju
return grabFromBlock(block, pos);
}
+function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense): T.VerbForm {
+ if (tense === "present") {
+ return conj.imperfective.nonImperative;
+ }
+ if (tense === "subjunctive") {
+ return conj.perfective.nonImperative;
+ }
+ if (tense === "imperfectivePast") {
+ return conj.imperfective.past;
+ }
+ if (tense === "perfectivePast") {
+ return conj.perfective.past;
+ }
+ throw new Error("unknown tense");
+}
+
function getEnglishVerbConjugation({ subjectPerson, object, ep, v, tense, n }: {
subjectPerson: T.Person,
object: "none" | NPSelection | T.Person.ThirdPlurMale,
v: T.EnglishVerbConjugationEc,
ep: string | undefined,
- tense: "present" | "subjunctive",
+ tense: VerbTense,
n: boolean,
}): string[] {
function engEquative(tense: "past" | "present", s: T.Person): string {
@@ -133,7 +181,7 @@ function getEnglishVerbConjugation({ subjectPerson, object, ep, v, tense, n }: {
return (v[2] === "being");
}
const builders: Record<
- string,
+ VerbTense,
(s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[]
> = {
present: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
@@ -146,12 +194,28 @@ function getEnglishVerbConjugation({ subjectPerson, object, ep, v, tense, n }: {
`that $SUBJ ${n ? " won't" : " will"} ${isToBe(v) ? "be" : v[0]}`,
`should $SUBJ ${n ? " not" : ""} ${isToBe(v) ? "be" : v[0]}`,
]),
+ imperfectivePast: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
+ // - subj pastEquative (N && "not") v.2 obj
+ `$SUBJ ${engEquative("past", s)}${n ? " not" : ""} ${v[2]}`,
+ // - subj "would" (N && "not") v.0 obj
+ `$SUBJ would${n ? " not" : ""} ${isToBe(v) ? "be" : v[0]}`,
+ // - subj pastEquative (N && "not") going to" v.0 obj
+ `$SUBJ ${engEquative("past", s)}${n ? " not" : ""} going to ${isToBe(v) ? "be" : v[0]}`,
+ ]),
+ perfectivePast: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
+ `$SUBJ${isToBe(v)
+ ? ` ${engEquative("past", s)}${n ? " not" : ""}`
+ : `${n ? " did not" : ""} ${v[3]}`}`,
+ ]),
};
const base = builders[tense](subjectPerson, v, n);
return base.map(b => `${b}${typeof object === "object" ? " $OBJ" : ""}${ep ? ` ${ep}` : ""}`);
}
-function getPersonFromNP(np: NPSelection | T.Person.ThirdPlurMale): T.Person {
+function getPersonFromNP(np: NPSelection | T.Person.ThirdPlurMale | "none"): T.Person {
+ if (np === "none") {
+ throw new Error("empty entity");
+ }
if (typeof np === "number") return np;
if (np.type === "participle") {
return T.Person.ThirdPlurMale;
@@ -166,20 +230,19 @@ function getPersonFromNP(np: NPSelection | T.Person.ThirdPlurMale): T.Person {
function textOfNP(np: NPSelection, inflected: boolean, englishInflected: boolean): { ps: T.PsString[], e: string } {
if (np.type === "participle") {
- // TODO: Implement ability to inflect participles
return textOfParticiple(np, inflected);
}
if (np.type === "pronoun") {
return textOfPronoun(np, inflected, englishInflected);
}
- // TODO: Implement ability to inflect nouns
return textOfNoun(np, inflected);
}
function textOfParticiple({ verb: { entry }}: ParticipleSelection, inflected: boolean): { ps: T.PsString[], e: string } {
// TODO: ability to inflect participles
return {
- ps: [psStringFromEntry(entry)],
+ // TODO: More robust inflection of inflecting pariticiples - get from the conjugation engine
+ ps: [psStringFromEntry(entry)].map(ps => inflected ? concatPsString(ps, { p: "Ùˆ", f: "o" }) : ps),
e: getEnglishParticiple(entry),
};
}
@@ -218,11 +281,11 @@ function textOfNoun(n: NounSelection, inflected: boolean): { ps: T.PsString[], e
const pashto = ((): T.PsString[] => {
const infs = inflectWord(n.entry);
const ps = n.number === "singular"
- ? getInf(infs, "inflections", n.gender, false)
+ ? getInf(infs, "inflections", n.gender, false, inflected)
: [
- ...getInf(infs, "plural", n.gender, true),
- ...getInf(infs, "arabicPlural", n.gender, true),
- ...getInf(infs, "inflections", n.gender, true),
+ ...getInf(infs, "plural", n.gender, true, inflected),
+ ...getInf(infs, "arabicPlural", n.gender, true, inflected),
+ ...getInf(infs, "inflections", n.gender, true, inflected),
];
return ps.length > 0
? ps
@@ -231,13 +294,14 @@ function textOfNoun(n: NounSelection, inflected: boolean): { ps: T.PsString[], e
return { ps: pashto, e: english };
}
-function getInf(infs: T.InflectorOutput, t: "plural" | "arabicPlural" | "inflections", gender: T.Gender, plural: boolean): T.PsString[] {
+function getInf(infs: T.InflectorOutput, t: "plural" | "arabicPlural" | "inflections", gender: T.Gender, plural: boolean, inflected: boolean): T.PsString[] {
// @ts-ignore
if (infs && t in infs && infs[t] !== undefined && gender in infs[t] && infs[t][gender] !== undefined) {
// @ts-ignore
const iset = infs[t][gender] as T.InflectionSet;
- const ipick = iset[(t === "inflections" && plural) ? 1 : 0];
- return ipick;
+ const inflectionNumber = (inflected ? 1 : 0) + ((t === "inflections" && plural) ? 1 : 0);
+ console.log({ t, plural, inflectionNumber });
+ return iset[inflectionNumber];
}
return [];
}
diff --git a/src/lib/np-tools.ts b/src/lib/np-tools.ts
index 424fe4a..e80a66a 100644
--- a/src/lib/np-tools.ts
+++ b/src/lib/np-tools.ts
@@ -23,7 +23,7 @@ export function randomPerson(p?: T.Person) {
return newP;
}
-function isInvalidSubjObjCombo(subj: T.Person, obj: T.Person): boolean {
+export function isInvalidSubjObjCombo(subj: T.Person, obj: T.Person): boolean {
const firstPeople = [
T.Person.FirstSingMale,
T.Person.FirstSingFemale,
diff --git a/src/types/gen-g.d.ts b/src/types/gen-g.d.ts
index 5ad94cf..fef3ad7 100644
--- a/src/types/gen-g.d.ts
+++ b/src/types/gen-g.d.ts
@@ -20,10 +20,12 @@ type VPRendered = {
verb: VerbRendered,
}
+type VerbTense = "present" | "subjunctive" | "perfectivePast" | "imperfectivePast";
+
type VerbSelection = {
type: "verb",
verb: VerbEntry,
- tense: "present" | "subjunctive",
+ tense: VerbTense,
object: VerbObject,
};