pashto-inflector/src/lib/misc-helpers.ts

215 lines
7.1 KiB
TypeScript

/**
* Copyright (c) 2021 lingdocs.com
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import * as T from "../types";
// just for type safety
export function noPersInfs(s: T.OptionalPersonInflections<T.LengthOptions<T.PsString>>): T.LengthOptions<T.PsString>;
export function noPersInfs(s: T.FullForm<T.PsString>): T.SingleOrLengthOpts<T.PsString>;
export function noPersInfs(s:
T.OptionalPersonInflections<T.LengthOptions<T.PsString>> | T.FullForm<T.PsString>
): T.SingleOrLengthOpts<T.PsString> | T.LengthOptions<T.PsString> {
if ("mascSing" in s) {
// this path shouldn't be used, just for type safety
return s.mascSing;
}
return s;
}
export function pickPersInf<T>(s: T.OptionalPersonInflections<T>, persInf: T.PersonInflectionsField): T {
if ("mascSing" in s) {
return s[persInf];
}
return s;
}
// export function pickPersInf(
// s: T.OptionalPersonInflections<T.LengthOptions<T.PsString>>,
// persInf: T.PersonInflectionsField,
// ): T.LengthOptions<T.PsString>;
// export function pickPersInf(
// s: T.FullForm<T.PsString>,
// persInf: T.PersonInflectionsField,
// ): T.SingleOrLengthOpts<T.PsString>;
// export function pickPersInf(
// s: T.FullForm<T.VerbBlock>,
// persInf: T.PersonInflectionsField,
// ): T.SingleOrLengthOpts<T.VerbBlock>;
// export function pickPersInf(
// s: T.SplitInfo,
// persInf: T.PersonInflectionsField,
// ): T.SingleOrLengthOpts<[T.PsString, T.PsString]>;
// export function pickPersInf(
// s: T.OptionalPersonInflections<T.LengthOptions<T.PsString>> | T.FullForm<T.PsString> | T.FullForm<T.VerbBlock> | T.SplitInfo,
// persInf: T.PersonInflectionsField,
// ): T.SingleOrLengthOpts<T.PsString> | T.LengthOptions<T.PsString> | T.SingleOrLengthOpts<T.VerbBlock> | T.SingleOrLengthOpts<[T.PsString, T.PsString]> {
// if ("mascSing" in s) {
// return s[persInf];
// }
// return s;
// }
export function hasPersInfs(info: T.NonComboVerbInfo): boolean {
return (
"mascSing" in info.root.perfective ||
"mascSing" in info.stem.perfective ||
"mascSing" in info.participle.present ||
"mascSing" in info.participle.past
);
}
export function chooseParticipleInflection(
pPartInfs: T.SingleOrLengthOpts<T.UnisexInflections> | T.SingleOrLengthOpts<T.PsString>,
person: T.Person,
): T.SingleOrLengthOpts<T.PsString> {
if ("long" in pPartInfs) {
return {
short: chooseParticipleInflection(pPartInfs.short, person) as T.PsString,
long: chooseParticipleInflection(pPartInfs.long, person) as T.PsString,
};
}
if ("masc" in pPartInfs) {
const gender = personGender(person);
const infNum = personIsPlural(person) ? 1 : 0;
return pPartInfs[gender][infNum][0];
}
return pPartInfs; // already just one thing
}
export function getPersonNumber(gender: "masc" | "fem", number: "singular" | "plural"): T.Person {
const base = gender === "masc" ? 4 : 5;
return base + (number === "singular" ? 0 : 6);
}
export function getPersonInflectionsKey(person: T.Person): T.PersonInflectionsField {
return `${personGender(person)}${personIsPlural(person) ? "Plur" : "Sing"}` as T.PersonInflectionsField;
}
export function spaceInForm(form: T.FullForm<T.PsString>): boolean {
if ("mascSing" in form) {
return spaceInForm(form.mascSing);
}
if ("long" in form) {
return spaceInForm(form.long);
}
return form.p.includes(" ");
}
export function getPersonFromVerbForm(form: T.SingleOrLengthOpts<T.VerbBlock>, person: T.Person): T.SentenceForm {
if ("long" in form) {
return {
long: getPersonFromVerbForm(form.long, person) as T.ArrayOneOrMore<T.PsString>,
short: getPersonFromVerbForm(form.short, person) as T.ArrayOneOrMore<T.PsString>,
...form.mini ? {
mini: getPersonFromVerbForm(form.mini, person) as T.ArrayOneOrMore<T.PsString>,
} : {},
};
}
const [row, col] = getBlockRowCol(person);
return form[row][col];
}
export function getBlockRowCol(person: T.Person): [0 | 1 | 2 | 3 | 4 | 5, 0 | 1] {
const plural = personIsPlural(person)
const row = (plural ? (person - 6) : person) as 0 | 1 | 2 | 3 | 4 | 5;
const col = plural ? 1 : 0;
return [row, col];
}
export function getAuxTransitivity(trans: T.Transitivity): "transitive" | "intransitive" {
return trans === "intransitive" ? "intransitive" : "transitive";
}
export function personGender(person: T.Person): "masc" | "fem" {
return person % 2 === 0 ? "masc" : "fem";
}
export function personIsPlural(person: T.Person): boolean {
return person > 5;
}
export function getEnglishPersonInfo(person: T.Person): string {
const p = [0,1,6,7].includes(person)
? "1st pers"
: [2,3,8,9].includes(person)
? "2nd pers"
: "3rd pers";
const a = personIsPlural(person) ? "plur" : "sing";
const g = personGender(person);
return `${p}. ${a}. ${g}.`;
}
export function randomNumber(minInclusive: number, maxExclusive: number): number {
return Math.floor(Math.random() * (maxExclusive - minInclusive) + minInclusive);
}
/**
* Sees if a possiblePerson (for subject/object) is possible, given the other person
*
* @param possiblePerson
* @param existingPerson
*/
export function personIsAllowed(possiblePerson: T.Person, existingPerson: T.Person): boolean {
const isFirstPerson = (p: T.Person) => [0, 1, 6, 7].includes(p);
const isSecondPerson = (p: T.Person) => [2, 3, 8, 9].includes(p);
// can't have both subject and object be 1st person
if (isFirstPerson(possiblePerson) && isFirstPerson(existingPerson)) {
return false;
}
// can't have both subject and object be 2nd person
if (isSecondPerson(possiblePerson) && isSecondPerson(existingPerson)) {
return false;
}
// otherwise it's ok
return true;
}
/**
* Picks a random person while assuring that the other person is not in conflict
*
* @param other
*/
export function randomPerson(other: T.Person): T.Person {
let newPerson: T.Person;
do {
newPerson = randomNumber(0, 12);
} while(!personIsAllowed(newPerson, other));
return newPerson;
}
export function incrementPerson(p: T.Person): T.Person {
return (p + 1) % 12;
}
export function isSentenceForm(f: any): boolean {
if ("long" in f) {
return isSentenceForm(f.long);
}
return Array.isArray(f) && "p" in f[0];
}
export function isNounAdjOrVerb(entry: T.DictionaryEntry): "nounAdj" | "verb" | false {
if (!entry.c) {
return false;
}
if (entry.c.includes("adj.") || entry.c.includes("n. m.") || entry.c.includes("n. f.")) {
return "nounAdj";
}
if (entry.c.slice(0, 3) === "v. ") {
return "verb";
}
return false;
}
// not being used
// export function isImperativeBlock(f: any): boolean {
// function isPersonLine(g: any): boolean {
// return Array.isArray(g) && Array.isArray(g[0]) && "p" in g[0][0];
// }
// return Array.isArray(f) && f.length === 2 && isPersonLine(f[0]);
// }