diff --git a/src/components/EquativeFormChoice.js b/src/components/EquativeFormChoice.js index acff660..84b3669 100644 --- a/src/components/EquativeFormChoice.js +++ b/src/components/EquativeFormChoice.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import { useState } from "react"; import { VerbFormDisplay, ButtonSelect, @@ -10,9 +10,10 @@ function EquativeFormChoice({forms, opts}) {
setChoice(p)} diff --git a/src/lib/equative-machine.ts b/src/lib/equative-machine.ts deleted file mode 100644 index 9e1a080..0000000 --- a/src/lib/equative-machine.ts +++ /dev/null @@ -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> { - if ("long" in o.equative.ps) { - return { - long: assembleEquativeOutput({ ...o, equative: { ...o.equative, ps: o.equative.ps.long }}) as T.ArrayOneOrMore, - short: assembleEquativeOutput({ ...o, equative: { ...o.equative, ps:o.equative.ps.short }}) as T.ArrayOneOrMore, - } - } - // 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; -} - -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)), - }; -} diff --git a/src/lib/np-tools.ts b/src/lib/np-tools.ts deleted file mode 100644 index 5290e44..0000000 --- a/src/lib/np-tools.ts +++ /dev/null @@ -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); -}