This commit is contained in:
parent
b4a84645ea
commit
e6a13c61f7
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import {
|
||||||
VerbFormDisplay,
|
VerbFormDisplay,
|
||||||
ButtonSelect,
|
ButtonSelect,
|
||||||
|
@ -10,9 +10,10 @@ function EquativeFormChoice({forms, opts}) {
|
||||||
<div>
|
<div>
|
||||||
<div className="text-center my-3">
|
<div className="text-center my-3">
|
||||||
<ButtonSelect
|
<ButtonSelect
|
||||||
|
small
|
||||||
options={[
|
options={[
|
||||||
{ label: "Equative", value: "pure" },
|
{ label: "Equative", value: "pure" },
|
||||||
{ label: "w/ Sentences", value: "sentence" },
|
{ label: "w/ Pronouns", value: "sentence" },
|
||||||
]}
|
]}
|
||||||
value={choice}
|
value={choice}
|
||||||
handleChange={(p) => setChoice(p)}
|
handleChange={(p) => setChoice(p)}
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
import {
|
|
||||||
Types as T,
|
|
||||||
grammarUnits,
|
|
||||||
getVerbBlockPosFromPerson,
|
|
||||||
getPersonFromVerbForm,
|
|
||||||
concatPsString,
|
|
||||||
removeAccents,
|
|
||||||
typePredicates as tp,
|
|
||||||
} from "@lingdocs/pashto-inflector";
|
|
||||||
import {
|
|
||||||
personFromNP,
|
|
||||||
evaluateNP,
|
|
||||||
} from "./np-tools";
|
|
||||||
import {
|
|
||||||
evaluateCompliment,
|
|
||||||
} from "./compliment-tools";
|
|
||||||
|
|
||||||
// Equative Rules
|
|
||||||
// - An equative equates a SUBJECT: Noun Phrase and a PREDICATE: Noun Phrase | Compliment
|
|
||||||
// - In Pashto, the equative agrees with the predicate when the predicate is a Noun Phrase,
|
|
||||||
// otherwise it agrees with the subject
|
|
||||||
// - If the subject is a pronoun, always agree with the subject
|
|
||||||
// - In English, the equative agrees with the subject
|
|
||||||
|
|
||||||
export function equativeMachine(e: EquativeClause): EquativeClauseOutput {
|
|
||||||
const ba = (e.tense === "future" || e.tense === "wouldBe");
|
|
||||||
const subject = evaluateNP(e.subject);
|
|
||||||
const predicate = ("type" in e.predicate && e.predicate.type === "compliment")
|
|
||||||
? evaluateCompliment(e.predicate, personFromNP(e.subject))
|
|
||||||
: evaluateNP(e.predicate);
|
|
||||||
const equative = makeEquative(e);
|
|
||||||
const negative = !!e?.negative;
|
|
||||||
return {
|
|
||||||
ba,
|
|
||||||
subject,
|
|
||||||
predicate,
|
|
||||||
equative,
|
|
||||||
negative,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function assembleEquativeOutput(o: EquativeClauseOutput): T.SingleOrLengthOpts<T.ArrayOneOrMore<T.PsString>> {
|
|
||||||
if ("long" in o.equative.ps) {
|
|
||||||
return {
|
|
||||||
long: assembleEquativeOutput({ ...o, equative: { ...o.equative, ps: o.equative.ps.long }}) as T.ArrayOneOrMore<T.PsString>,
|
|
||||||
short: assembleEquativeOutput({ ...o, equative: { ...o.equative, ps:o.equative.ps.short }}) as T.ArrayOneOrMore<T.PsString>,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// get all possible combinations of subject, predicate, and equative
|
|
||||||
// soooo cool how this works 🤓
|
|
||||||
const equatives = o.equative.ps;
|
|
||||||
const predicates = o.predicate.ps;
|
|
||||||
const ba = o.ba ? { p: " به", f: " ba" } : "";
|
|
||||||
const neg = o.negative ? { p: "نه ", f: "nú " } : "";
|
|
||||||
const ps = o.subject.ps.flatMap(subj => (
|
|
||||||
predicates.flatMap(pred => (
|
|
||||||
equatives.map(eq => (
|
|
||||||
concatPsString(
|
|
||||||
subj,
|
|
||||||
ba,
|
|
||||||
" ",
|
|
||||||
pred,
|
|
||||||
" ",
|
|
||||||
neg,
|
|
||||||
o.negative ? removeAccents(eq) : eq,
|
|
||||||
))
|
|
||||||
)
|
|
||||||
))
|
|
||||||
));
|
|
||||||
const e = `${o.subject.e} ${o.equative.e[0]} ${o.predicate.e}`;
|
|
||||||
return ps.map(x => ({ ...x, e })) as T.ArrayOneOrMore<T.PsString>;
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeEquative(e: EquativeClause) {
|
|
||||||
function getEngEq(row: number, col: number): string[] {
|
|
||||||
const t = grammarUnits.englishEquative[(e.tense === "subjunctive" || e.tense === "habitual") ? "present" : e.tense];
|
|
||||||
return typeof t === "string"
|
|
||||||
? [t]
|
|
||||||
: [t[row][col]];
|
|
||||||
}
|
|
||||||
const baseTense = (e.tense === "future")
|
|
||||||
? "habitual"
|
|
||||||
: e.tense === "wouldBe"
|
|
||||||
? "past"
|
|
||||||
: e.tense;
|
|
||||||
const subjP = personFromNP(e.subject);
|
|
||||||
const englishPerson = (e.subject.type === "participle" || (e.subject.type === "noun" && tp.isPluralNounEntry(e.subject.entry)))
|
|
||||||
? T.Person.ThirdSingMale
|
|
||||||
: subjP
|
|
||||||
const pashtoPerson = (e.subject.type === "pronoun")
|
|
||||||
? e.subject.person
|
|
||||||
: ("type" in e.predicate && e.predicate.type === "compliment")
|
|
||||||
? subjP
|
|
||||||
: personFromNP(e.predicate);
|
|
||||||
return {
|
|
||||||
ps: getPersonFromVerbForm(
|
|
||||||
grammarUnits.equativeEndings[baseTense],
|
|
||||||
pashtoPerson,
|
|
||||||
),
|
|
||||||
e: getEngEq(...getVerbBlockPosFromPerson(englishPerson)),
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,215 +0,0 @@
|
||||||
import {
|
|
||||||
Types as T,
|
|
||||||
getEnglishWord,
|
|
||||||
parseEc,
|
|
||||||
getVerbBlockPosFromPerson,
|
|
||||||
grammarUnits,
|
|
||||||
inflectWord,
|
|
||||||
psStringFromEntry,
|
|
||||||
typePredicates as tp,
|
|
||||||
} from "@lingdocs/pashto-inflector";
|
|
||||||
|
|
||||||
function getRandPers(): T.Person {
|
|
||||||
return Math.floor(Math.random() * 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function randomPerson(a?: { prev?: T.Person, counterPart?: T.VerbObject | T.NPSelection }) {
|
|
||||||
// no restrictions, just get any person
|
|
||||||
if (!a) {
|
|
||||||
return getRandPers();
|
|
||||||
}
|
|
||||||
if (a.counterPart !== undefined && typeof a.counterPart === "object" && a.counterPart.type === "pronoun") {
|
|
||||||
// with counterpart pronoun
|
|
||||||
let newP = 0;
|
|
||||||
do {
|
|
||||||
newP = getRandPers();
|
|
||||||
} while (
|
|
||||||
isInvalidSubjObjCombo(a.counterPart.person, newP)
|
|
||||||
||
|
|
||||||
(newP === a.prev)
|
|
||||||
);
|
|
||||||
return newP;
|
|
||||||
}
|
|
||||||
// without counterpart pronoun, just previous
|
|
||||||
let newP = 0;
|
|
||||||
do {
|
|
||||||
newP = getRandPers();
|
|
||||||
} while (newP === a.prev);
|
|
||||||
return newP;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isInvalidSubjObjCombo(subj: T.Person, obj: T.Person): boolean {
|
|
||||||
const firstPeople = [
|
|
||||||
T.Person.FirstSingMale,
|
|
||||||
T.Person.FirstSingFemale,
|
|
||||||
T.Person.FirstPlurMale,
|
|
||||||
T.Person.FirstPlurFemale,
|
|
||||||
];
|
|
||||||
const secondPeople = [
|
|
||||||
T.Person.SecondSingMale,
|
|
||||||
T.Person.SecondSingFemale,
|
|
||||||
T.Person.SecondPlurMale,
|
|
||||||
T.Person.SecondPlurFemale,
|
|
||||||
];
|
|
||||||
return (
|
|
||||||
(firstPeople.includes(subj) && firstPeople.includes(obj))
|
|
||||||
||
|
|
||||||
(secondPeople.includes(subj) && secondPeople.includes(obj))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function randomSubjObj(old?: { subj: T.Person, obj: T.Person }): { subj: T.Person, obj: T.Person } {
|
|
||||||
let subj = 0;
|
|
||||||
let obj = 0;
|
|
||||||
do {
|
|
||||||
subj = getRandPers();
|
|
||||||
obj = getRandPers();
|
|
||||||
} while (
|
|
||||||
(old && ((old.subj === subj) || (old.obj === obj)))
|
|
||||||
||
|
|
||||||
isInvalidSubjObjCombo(subj, obj)
|
|
||||||
);
|
|
||||||
return { subj, obj };
|
|
||||||
}
|
|
||||||
|
|
||||||
export function personFromNP(np: NounPhrase): T.Person {
|
|
||||||
if (np.type === "participle") {
|
|
||||||
return T.Person.ThirdPlurMale;
|
|
||||||
}
|
|
||||||
if (np.type === "pronoun") {
|
|
||||||
return np.person;
|
|
||||||
}
|
|
||||||
const gender = nounGender(np);
|
|
||||||
const number = nounNumber(np);
|
|
||||||
return number === "plural"
|
|
||||||
? (gender === "masc" ? T.Person.ThirdPlurMale : T.Person.ThirdPlurFemale)
|
|
||||||
: (gender === "masc" ? T.Person.ThirdSingMale : T.Person.ThirdSingFemale);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function evaluateNP(np: NounPhrase): { ps: T.PsString[], e: string } {
|
|
||||||
if (np.type === "participle") {
|
|
||||||
return evaluateParticiple(np);
|
|
||||||
}
|
|
||||||
if (np.type === "pronoun") {
|
|
||||||
return evaluatePronoun(np);
|
|
||||||
}
|
|
||||||
return evaluateNoun(np);
|
|
||||||
}
|
|
||||||
|
|
||||||
function nounGender(n: Noun): T.Gender {
|
|
||||||
const nGender = tp.isUnisexNounEntry(n.entry)
|
|
||||||
? "unisex"
|
|
||||||
: tp.isMascNounEntry(n.entry)
|
|
||||||
? "masc"
|
|
||||||
: "fem";
|
|
||||||
return (nGender === "unisex" && n.gender)
|
|
||||||
? n.gender
|
|
||||||
: (nGender === "unisex")
|
|
||||||
? "masc"
|
|
||||||
: nGender;
|
|
||||||
}
|
|
||||||
|
|
||||||
function nounNumber(n: Noun): NounNumber {
|
|
||||||
const nNumber = tp.isPluralNounEntry(n.entry)
|
|
||||||
? "plural"
|
|
||||||
: "singular";
|
|
||||||
return nNumber === "plural"
|
|
||||||
? "plural"
|
|
||||||
: n.number
|
|
||||||
? n.number
|
|
||||||
: nNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
function evaluatePronoun(p: Pronoun): { ps: T.PsString[], e: string } {
|
|
||||||
// TODO: Will need to handle inflecting and inflecting english pronouns etc.
|
|
||||||
const [row, col] = getVerbBlockPosFromPerson(p.person);
|
|
||||||
return {
|
|
||||||
ps: grammarUnits.pronouns[p.pronounType].plain[row][col],
|
|
||||||
e: grammarUnits.persons[p.person].label.subject,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function evaluateNoun(n: Noun): { ps: T.PsString[], e: string } {
|
|
||||||
const number = nounNumber(n);
|
|
||||||
const english = getEnglishFromNoun(n.entry, number);
|
|
||||||
const pashto = ((): T.PsString[] => {
|
|
||||||
const infs = inflectWord(n.entry);
|
|
||||||
const gender = nounGender(n);
|
|
||||||
const ps = number === "singular"
|
|
||||||
? getInf(infs, "inflections", gender, false)
|
|
||||||
: [
|
|
||||||
...getInf(infs, "plural", gender, true),
|
|
||||||
...getInf(infs, "arabicPlural", gender, true),
|
|
||||||
...getInf(infs, "inflections", gender, true),
|
|
||||||
];
|
|
||||||
return ps.length > 0
|
|
||||||
? ps
|
|
||||||
: [psStringFromEntry(n.entry)];
|
|
||||||
})();
|
|
||||||
return { ps: pashto, e: english };
|
|
||||||
}
|
|
||||||
|
|
||||||
function getInf(infs: T.InflectorOutput, t: "plural" | "arabicPlural" | "inflections", gender: T.Gender, plural: 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;
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getEnglishVerb(entry: T.DictionaryEntry): string {
|
|
||||||
if (!entry.ec) {
|
|
||||||
console.log("errored verb");
|
|
||||||
console.log(entry);
|
|
||||||
throw new Error("no english information for verb");
|
|
||||||
}
|
|
||||||
if (entry.ep) {
|
|
||||||
const ec = entry.ec.includes(",") ? parseEc(entry.ec)[0] : entry.ec;
|
|
||||||
return `to ${ec} ${entry.ep}`;
|
|
||||||
}
|
|
||||||
const ec = parseEc(entry.ec);
|
|
||||||
return `to ${ec[0]}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getEnglishParticiple(entry: T.DictionaryEntry): string {
|
|
||||||
if (!entry.ec) {
|
|
||||||
console.log("errored participle");
|
|
||||||
console.log(entry);
|
|
||||||
throw new Error("no english information for participle");
|
|
||||||
}
|
|
||||||
const ec = parseEc(entry.ec);
|
|
||||||
const participle = ec[2];
|
|
||||||
return (entry.ep)
|
|
||||||
? `${participle} ${entry.ep}`
|
|
||||||
: participle;
|
|
||||||
}
|
|
||||||
|
|
||||||
function evaluateParticiple({ entry: { entry }}: Participle): { ps: T.PsString[], e: string } {
|
|
||||||
return {
|
|
||||||
ps: [psStringFromEntry(entry)],
|
|
||||||
e: getEnglishParticiple(entry),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEnglishFromNoun(entry: T.DictionaryEntry, number: NounNumber): string {
|
|
||||||
const articles = {
|
|
||||||
singular: "(a/the)",
|
|
||||||
plural: "(the)",
|
|
||||||
};
|
|
||||||
const article = articles[number];
|
|
||||||
function addArticle(s: string) {
|
|
||||||
return `${article} ${s}`;
|
|
||||||
}
|
|
||||||
const e = getEnglishWord(entry);
|
|
||||||
if (!e) throw new Error(`unable to get english from subject ${entry.f} - ${entry.ts}`);
|
|
||||||
|
|
||||||
if (typeof e === "string") return ` ${e}`;
|
|
||||||
if (number === "plural") return addArticle(e.plural);
|
|
||||||
if (!e.singular || e.singular === undefined) {
|
|
||||||
throw new Error(`unable to get english from subject ${entry.f} - ${entry.ts}`);
|
|
||||||
}
|
|
||||||
return addArticle(e.singular);
|
|
||||||
}
|
|
Loading…
Reference in New Issue