a lot more working

This commit is contained in:
adueck 2023-06-27 16:59:06 +04:00
parent bce8bf8365
commit 4deff6110b
15 changed files with 319 additions and 300 deletions

View File

@ -3,7 +3,7 @@ import classNames from "classnames";
import {
getEnglishFromRendered,
} from "../../../lib/src/phrase-building/np-tools";
import { getEnglishPersonInfo, getEnglishParticipleInflection } from "../../../lib/src/misc-helpers";
import { getEnglishPersonInfo, getEnglishParticipleInflection, getEnglishGenNumInfo } from "../../../lib/src/misc-helpers";
import { useState } from "react";
import { getLength } from "../../../lib/src/p-text-helpers";
import { roleIcon } from "../vp-explorer/VPExplorerExplanationModal";
@ -26,6 +26,10 @@ function Block({ opts, block, king, script }: {
const role = king === "subject" ? "king" : king === "object" ? "servant" : undefined;
return <SubjectBlock opts={opts} np={block.block.selection} role={role} script={script} />
}
if (block.block.type === "objectSelection") {
const role = king === "object" ? "king" : king === "subject" ? "servant" : undefined;
return <ObjectBlock opts={opts} obj={block.block.selection} role={role} script={script} />;
}
if (block.block.type === "predicateSelection") {
const english = getEnglishFromRendered(block.block.selection);
return <div className="text-center">
@ -38,33 +42,19 @@ function Block({ opts, block, king, script }: {
if (block.block.type === "negative") {
return <NegBlock opts={opts} imperative={block.block.imperative} script={script} />
}
return <div>TODO</div>
// if (block.block.type === "perfectiveHead") {
// return <PerfHeadBlock opts={opts} ps={block.block.ps} script={script} />
// }
// if (block.block.type === "verb") {
// return <VerbSBlock opts={opts} v={block.block.block} script={script} />;
// }
// if (block.block.type === "objectSelection") {
// const role = king === "object" ? "king" : king === "subject" ? "servant" : undefined;
// return <ObjectBlock opts={opts} obj={block.block.selection} role={role} script={script} />;
// }
// if (block.block.type === "perfectParticipleBlock") {
// return <VerbSBlock opts={opts} v={block.block} script={script} />;
// }
// if (block.block.type === "perfectEquativeBlock") {
// return <EquativeBlock opts={opts} eq={block.block} script={script} />;
// }
// if (block.block.type === "modalVerbBlock") {
// return <ModalVerbBlock opts={opts} v={block.block} script={script} />;
// }
// if (block.block.type === "modalVerbKedulPart") {
// return <ModalAuxBlock opts={opts} aux={block.block} script={script} />
// }
// if (block.block.type === "complement") {
// return <ComplementBlock opts={opts} comp={block.block.selection} script={script} />;
// }
return null;
if (block.block.type === "PH") {
return <PerfHeadBlock opts={opts} ps={block.block.ps} script={script} />;
}
if (block.block.type === "VB") {
return <VBBlock opts={opts} block={block.block} script={script} />;
}
if (block.block.type === "complement") {
return <ComplementBlock opts={opts} comp={block.block.selection} script={script} />
}
if (block.block.type === "NComp") {
return <NCompBlock opts={opts} comp={block.block.comp} script={script} />
}
return <WeldedBlock opts={opts} welded={block.block} script={script} />
}
export default Block;
@ -75,12 +65,72 @@ function Border({ children, extraClassName, padding }: { children: JSX.Element |
style={{
padding: padding ? padding : "1rem",
textAlign: "center",
gap: "0.5rem",
}}
>
<>{children}</>
</div>
}
function VBBlock({ opts, block, script }: {
opts: T.TextOptions,
script: "p" | "f",
block: T.VBBasic | T.VBGenNum | (T.VBBasic & {
person: T.Person;
}),
}) {
const [length, setLength] = useState<T.Length>("long");
const [version, setVersion] = useState<number>(0);
const ps = getLength(block.ps, length);
function changeVersion() {
setVersion(o => (o + 1) % ps.length);
}
function changeLength() {
setLength(o => (
o === "long"
? "short"
: o === "short" && "mini" in block.ps
? "mini"
: "long"
));
}
const infInfo = "gender" in block
? getEnglishGenNumInfo(block.gender, block.number)
: "person" in block
? getEnglishPersonInfo(block.person, "short")
: "";
return <div className="text-center">
<div className="d-flex flex-row justify-content-around">
{"long" in block.ps && <div className="clickable small mb-1" onClick={changeLength}>{length}</div>}
{ps.length > 1 && <div className="clickable small mb-1" onClick={changeVersion}>v. {version + 1}</div>}
</div>
<Border>
<>
{ps[version][script]}
</>
</Border>
<div>VBlock</div>
<SubText>{infInfo}</SubText>
</div>
}
function WeldedBlock({ opts, welded, script }: {
opts: T.TextOptions,
script: "p" | "f",
welded: T.Welded,
}) {
return <div className="text-center">
<Border padding="0.5rem" extraClassName={script === "p" ? "flex-row-reverse" : ""}>
{welded.left.type === "NComp"
? <NCompBlock opts={opts} comp={welded.left.comp} script={script} />
: welded.left.type === "VB"
? <VBBlock opts={opts} block={welded.left} script={script} />
: <WeldedBlock opts={opts} welded={welded.left} script={script} />}
<VBBlock opts={opts} block={welded.right} script={script} />
</Border>
</div>
}
// function VerbSBlock({ opts, v, script }: {
// opts: T.TextOptions,
// script: "p" | "f",
@ -142,20 +192,20 @@ function Border({ children, extraClassName, padding }: { children: JSX.Element |
// </div>
// }
// function PerfHeadBlock({ opts, ps, script }: {
// opts: T.TextOptions,
// ps: T.PsString,
// script: "p" | "f",
function PerfHeadBlock({ opts, ps, script }: {
opts: T.TextOptions,
ps: T.PsString,
script: "p" | "f",
// }) {
// return <div className="text-center">
// <Border>
// {ps[script]}
// </Border>
// <div>perf. head</div>
// <EnglishBelow>{'\u00A0'}</EnglishBelow>
// </div>;
// }
}) {
return <div className="text-center">
<Border>
{ps[script]}
</Border>
<div>perf. head</div>
<SubText>{'\u00A0'}</SubText>
</div>;
}
// function ModalAuxBlock({ opts, aux, script }: {
// opts: T.TextOptions,
@ -182,7 +232,7 @@ function NegBlock({ opts, imperative, script }: {
{negativeParticle[imperative ? "imperative" : "nonImperative"][script]}
</Border>
<div>Neg.</div>
<EnglishBelow>{imperative ? "don't" : "not"}</EnglishBelow>
<SubText>{imperative ? "don't" : "not"}</SubText>
</div>;
}
@ -207,7 +257,7 @@ function EquativeBlock({ opts, eq, script }: {
{getLength(eq.ps, length)[0][script]}
</Border>
<div>Equative</div>
<EnglishBelow>{getEnglishPersonInfo(eq.person, "short")}</EnglishBelow>
<SubText>{getEnglishPersonInfo(eq.person, "short")}</SubText>
</div>;
}
@ -240,6 +290,25 @@ function ObjectBlock({ opts, obj, role, script }: {
</div>;
}
function NCompBlock({ opts, comp, script }: {
script: "p" | "f",
opts: T.TextOptions,
comp: T.Comp,
}) {
return <div className="text-center">
<Border>
{comp.ps[script]}
</Border>
{comp.type === "AdjComp"
? <div>adj. <span className="text-muted small">{getEnglishGenNumInfo(comp.gender, comp.number)}</span></div>
: <div>TODO</div>}
<SubText>
todo
{/* {adj.e} */}
</SubText>
</div>;
}
function ComplementBlock({ opts, comp, script, inside }: {
script: "p" | "f",
opts: T.TextOptions,
@ -255,7 +324,7 @@ function ComplementBlock({ opts, comp, script, inside }: {
{adj.ps[0][script]}
</Border>
<div>Adj. <span className="text-muted small">({getEnglishParticipleInflection(adj.person, "short")})</span></div>
<EnglishBelow>{adj.e}</EnglishBelow>
<SubText>{adj.e}</SubText>
</div>;
}
@ -268,7 +337,7 @@ function ComplementBlock({ opts, comp, script, inside }: {
{adv.ps[0][script]}
</Border>
<div>Loc. Adv.</div>
<EnglishBelow>{adv.e}</EnglishBelow>
<SubText>{adv.e}</SubText>
</div>;
}
return <div className="text-center">
@ -286,13 +355,13 @@ function ComplementBlock({ opts, comp, script, inside }: {
</Border>
{!inside && <>
<div>&nbsp;</div>
<EnglishBelow>{comp.e}</EnglishBelow>
<SubText>{comp.e}</SubText>
</>}
</div>
: <div>
<Sandwich opts={opts} sandwich={comp} script={script} />
<div>Sandwich</div>
<EnglishBelow>{comp.e}</EnglishBelow>
<SubText>{comp.e}</SubText>
</div>}
</div>;
}
@ -310,13 +379,13 @@ export function APBlock({ opts, children, english, script }: {
{ap.selection.ps[0][script]}
</Border>
<div>AP</div>
<EnglishBelow>{english}</EnglishBelow>
<SubText>{english}</SubText>
</div>;
}
return <div>
<Sandwich opts={opts} sandwich={ap.selection} script={script} />
<div>AP</div>
<EnglishBelow>{english}</EnglishBelow>
<SubText>{english}</SubText>
</div>;
}
@ -355,7 +424,7 @@ function CompNounBlock({ opts, noun, script }: {
<div>
Comp. Noun
</div>
<EnglishBelow>{noun.e}</EnglishBelow>
<SubText>{noun.e}</SubText>
</div>
}
@ -388,7 +457,7 @@ export function NPBlock({ opts, children, inside, english, script }: {
<span className="text-muted small">({getEnglishPersonInfo(np.selection.person, "short")})</span>
</> : <></>}
</div>
{!inside && <EnglishBelow>{english}</EnglishBelow>}
{!inside && <SubText>{english}</SubText>}
</div>
}
@ -438,7 +507,7 @@ function Adjectives({ opts, children, script }: {
</em>
}
function EnglishBelow({ children: e }: { children: string | undefined }) {
function SubText({ children: e }: { children: string | undefined }) {
return <div className="small text-muted text-center" style={{
margin: "0 auto",
maxWidth: "300px",

View File

@ -15,8 +15,6 @@ import playAudio from "../play-audio";
import TensePicker from "./TensePicker";
import Keyframes from "../Keyframes";
import energyDrink from "./energy-drink.jpg";
import { flattenLengths } from "../../../lib/src/phrase-building/compile";
import { concatPsString } from "../../../lib/src/p-text-helpers";
import { isImperativeTense } from "../../../lib/src/type-predicates";
import {
adjustObjectSelection,

View File

@ -12,7 +12,6 @@ import {
randomNumber,
} from "../lib/src/misc-helpers";
import { entryFeeder } from "./entryFeeder";
import NPPronounPicker from "../components/src/np-picker/NPPronounPicker";
const transitivities: T.Transitivity[] = [
"transitive",
@ -32,49 +31,12 @@ const verbTypes: VerbType[] = [
"dynamic compound",
];
const testVerbTenses: T.VerbTense[] = [
"presentVerb",
"subjunctiveVerb",
"imperfectiveFuture",
"perfectiveFuture",
"imperfectivePast",
"perfectivePast",
"habitualImperfectivePast",
"habitualPerfectivePast",
];
const testPerfectTenses: T.PerfectTense[] = [
"presentPerfect",
"futurePerfect",
"habitualPerfect",
"pastPerfect",
"subjunctivePerfect",
"wouldBePerfect",
"wouldHaveBeenPerfect",
"pastSubjunctivePerfect",
];
const testAbilityTenses: T.AbilityTense[] = testVerbTenses.map<T.AbilityTense>(t => `${t}Modal`);
const testTenses = [
...testVerbTenses,
...testPerfectTenses,
...testAbilityTenses,
];
function VPBuilderDemo({ opts }: {
opts: T.TextOptions,
}) {
const [verbTs, setVerbTs] = useStickyState<number>(0, "verbTs1");
const [verbTypeShowing, setVerbTypeShowing] = useStickyState<VerbType>("simple", "vTypeShowing");
const [transitivityShowing, setTransitivityShowing] = useStickyState<T.Transitivity>("intransitive", "transitivityShowing1");
const [testPerson, setTestPerson] = useStickyState<T.PronounSelection>({
type: "pronoun",
distance: "far",
person: 0,
}, "testPronoun");
const [testVoice, setTestVoice] = useStickyState<T.Voice>("active", "testVoice");
const [testTense, setTestTense] = useStickyState<T.VerbTense | T.PerfectTense | T.AbilityTense>("presentVerb", "testTense");
// const onlyGrammTrans = (arr: Transitivity[]) => (
// arr.length === 1 && arr[0] === "grammatically transitive"
// );
@ -227,20 +189,6 @@ function VPBuilderDemo({ opts }: {
</div>
</div>
</div>
<button onClick={() => setTestVoice(v => v === "active" ? "passive" : "active")}>
{testVoice}
</button>
<select value={testTense} onChange={e => setTestTense(e.target.value as any)}>
{testTenses.map(t => (
<option key={t} value={t}>{t}</option>
))}
</select>
<NPPronounPicker
onChange={setTestPerson}
pronoun={testPerson}
role="subject"
opts={opts}
/>
{v?.verb.entry && <div style={{ paddingBottom: "20px" }}>
<PhraseBuilder
handleLinkClick="none"

View File

@ -8,7 +8,6 @@
import * as T from "../../types";
import { makePsString, removeFVarients } from "./accent-and-ps-utils";
import { applyToSingOrLengthOpts } from "./misc-helpers";
/**
* Returns a Pashto string (or string with Length options) ensuring that
@ -156,16 +155,6 @@ export function removeAccents(s: T.PsString | string | T.PsString[]): T.PsString
});
}
export function removeAccentsFromInflections(inf: T.UnisexInflections): T.UnisexInflections {
function removeFromSide(inf: T.InflectionSet): T.InflectionSet {
return inf.map(removeAccents) as T.ArrayFixed<T.ArrayOneOrMore<T.PsString>, 3>;
}
return {
masc: removeFromSide(inf.masc),
fem: removeFromSide(inf.fem),
};
}
/**
* Determines if a string has any accents on it
*
@ -175,60 +164,3 @@ export function hasAccents(s: string | T.PsString): boolean {
if (typeof s !== "string") return hasAccents(s.f);
return accentReplacer.some((x) => s.includes(x.accented));
}
export function removeVerbAccent([a, b]: T.VerbRenderedOutput): T.VerbRenderedOutput {
return [
removeVHeadAccent(a),
removeVAccent(b),
];
}
function removeVHeadAccent([v]: [T.VHead] | []): [T.VHead] | [] {
if (v === undefined) {
return [];
}
if (v.type === "PH") {
return [{
...v,
ps: removeAccents(v.ps),
}];
}
return [{
...v,
comp: removeCompAccent(v.comp),
}];
}
function removeCompAccent(comp: T.Comp): T.Comp {
return {
...comp,
ps: removeAccents(comp.ps),
}
}
function removeVAccent(v: [T.VB, T.VBE] | [T.VBE]): [T.VB, T.VBE]| [T.VBE] {
return v.map(removeVBAccent) as [T.VB, T.VBE]| [T.VBE];
}
function removeVBAccent<V extends T.VB | T.VBE>(v: V): V {
if (v.type === "welded") {
return {
...v,
left: removeWeldedLeftAccent(v.left),
}
}
return {
...v,
ps: applyToSingOrLengthOpts(removeAccents, v.ps),
};
}
function removeWeldedLeftAccent(v: T.NComp | T.VBBasic | T.Welded) {
if (v.type === "NComp") {
return {
...v,
comp: removeCompAccent(v.comp),
};
}
return removeVBAccent(v);
}

85
src/lib/src/fmaps.ts Normal file
View File

@ -0,0 +1,85 @@
import * as T from "../../types";
export function fmapSingleOrLengthOpts<A extends object, B extends object>(f: (x: A) => B, x: T.SingleOrLengthOpts<A>): T.SingleOrLengthOpts<B> {
if ("long" in x) {
return {
long: f(x.long),
short: f(x.short),
..."mini" in x && x.mini ? {
mini: f(x.mini),
} : {},
};
} else {
return f(x);
}
}
export function mapInflections(f: (x: T.PsString) => T.PsString, inf: T.UnisexInflections): T.UnisexInflections {
function handleSide(inf: T.InflectionSet): T.InflectionSet {
return inf.map(x => x.map(f)) as T.ArrayFixed<T.ArrayOneOrMore<T.PsString>, 3>;
}
return {
masc: handleSide(inf.masc),
fem: handleSide(inf.fem),
};
}
export function mapVerbRenderedOutput(f: (a: T.PsString) => T.PsString, [a, b]: T.VerbRenderedOutput): T.VerbRenderedOutput {
return [
fmapVHead(a),
fmapV(b),
];
function fmapVHead([v]: [T.VHead] | []): [T.VHead] | [] {
if (v === undefined) {
return [];
}
if (v.type === "PH") {
return [{
...v,
ps: f(v.ps),
}];
}
return [{
...v,
comp: fmapComp(v.comp),
}];
}
function fmapComp(comp: T.Comp): T.Comp {
return {
...comp,
ps: f(comp.ps),
};
}
function fmapV(v: [T.VB, T.VBE] | [T.VBE]): [T.VB, T.VBE]| [T.VBE] {
return v.map(fmapVB) as [T.VB, T.VBE]| [T.VBE];
}
function fmapVB<V extends T.VB | T.VBE>(v: V): V {
if (v.type === "welded") {
return {
...v,
left: fmapWeldedLeft(v.left),
right: fmapVB(v.right),
};
}
return {
...v,
ps: fmapSingleOrLengthOpts((x) => x.map(f), v.ps),
};
}
function fmapWeldedLeft(v: T.NComp | T.VBBasic | T.Welded) {
if (v.type === "NComp") {
return {
...v,
comp: fmapComp(v.comp),
};
}
return fmapVB(v);
}
}

View File

@ -7,20 +7,7 @@
*/
import * as T from "../../types";
export function applyToSingOrLengthOpts<X extends object>(f: (x: X) => X, x: T.SingleOrLengthOpts<X>): T.SingleOrLengthOpts<X> {
if ("long" in x) {
return {
long: f(x.long),
short: f(x.short),
..."mini" in x && x.mini ? {
mini: f(x.mini),
} : {},
};
} else {
return f(x);
}
}
import { fmapSingleOrLengthOpts } from "./fmaps";
export const blank: T.PsString = {
p: "_____",
@ -110,19 +97,6 @@ export function hasPersInfs(info: T.NonComboVerbInfo | T.PassiveRootsAndStems |
);
}
export function functionOnOptLengths<U extends object, F extends object>(x: T.SingleOrLengthOpts<U>, f: (y: U) => F): T.SingleOrLengthOpts<F> {
if ("long" in x) {
return {
long: f(x.long),
short: f(x.short),
...("mini" in x && x.mini) ? {
mini: f(x.mini),
} : {},
};
}
return f(x);
}
// TODO: deprecated using new verb rendering thing
export function chooseParticipleInflection(
pPartInfs: T.SingleOrLengthOpts<T.UnisexInflections> | T.SingleOrLengthOpts<T.PsString>,
@ -166,17 +140,10 @@ export function spaceInForm(form: T.FullForm<T.PsString>): boolean {
}
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] = getVerbBlockPosFromPerson(person);
return form[row][col];
return fmapSingleOrLengthOpts(x => {
const [row, col] = getVerbBlockPosFromPerson(person);
return x[row][col];
}, form);
}
export function getVerbBlockPosFromPerson(person: T.Person): [0 | 1 | 2 | 3 | 4 | 5, 0 | 1] {
@ -207,7 +174,7 @@ export function getEnglishPersonInfo(person: T.Person, version?: "short" | "long
? "1st"
: [2,3,8,9].includes(person)
? "2nd"
: "3rd") + (version !== "short" ? " pers." : "");
: "3rd") + " pers.";
const number = personIsPlural(person) ? "plur" : "sing";
const n = version === "short"
? (number === "plur" ? "pl" : "sg") : number;
@ -218,6 +185,10 @@ export function getEnglishPersonInfo(person: T.Person, version?: "short" | "long
return `${p} ${n}. ${g}.`;
}
export function getEnglishGenNumInfo(gender: T.Gender, number: T.NounNumber): string {
return `${gender === "masc" ? "masc" : "fem"} ${number === "plural" ? "plur." : "sing."}`;
}
export function getEnglishParticipleInflection(person: T.Person, version?: "short" | "long"): string {
const number = personIsPlural(person) ? "plural" : "singular";
const n = version === "short"

View File

@ -52,6 +52,7 @@ test("basic tenses", () => {
verb: wahul,
tense: "presentVerb",
person: T.Person.FirstSingMale,
complementPerson: T.Person.FirstSingMale,
voice: "active",
negative: false,
})).toEqual({
@ -68,6 +69,7 @@ test("basic tenses", () => {
verb: wahul,
tense: "subjunctiveVerb",
person: T.Person.SecondSingMale,
complementPerson: T.Person.SecondSingMale,
voice: "active",
negative: false,
})).toEqual({
@ -83,6 +85,7 @@ test("basic tenses", () => {
verb: wahul,
tense: "habitualPerfectivePast",
person: T.Person.ThirdSingFemale,
complementPerson: T.Person.ThirdSingFemale,
voice: "active",
negative: false,
})).toEqual({
@ -108,7 +111,7 @@ test("basic tenses with inflecting roots/stems", () => {
verb: bandawul,
tense: "subjunctiveVerb",
person: T.Person.FirstSingMale,
presObj: T.Person.ThirdSingFemale,
complementPerson: T.Person.ThirdSingFemale,
voice: "active",
negative: false,
})).toEqual({
@ -521,6 +524,7 @@ test("special endings", () => {
verb: x.verb,
tense: x.tense,
person: T.Person.ThirdSingMale,
complementPerson: T.Person.ThirdSingMale,
voice: "active",
negative: false,
})).toEqual({ hasBa: false, vbs: x.result });
@ -530,6 +534,7 @@ test("special endings", () => {
verb: kedulStat,
tense: "perfectivePast",
person: T.Person.FirstPlurMale,
complementPerson: T.Person.FirstPlurMale,
voice: "active",
negative: false,
})).toEqual({
@ -552,6 +557,7 @@ test("special endings", () => {
verb: tlul,
tense: "imperfectivePast",
person: T.Person.FirstSingMale,
complementPerson: T.Person.FirstSingMale,
voice: "active",
negative: false,
})).toEqual({
@ -575,6 +581,7 @@ test("special endings", () => {
verb: tlul,
tense: "imperfectivePast",
person: T.Person.ThirdSingFemale,
complementPerson: T.Person.ThirdSingFemale,
voice: "active",
negative: false,
})).toEqual({
@ -599,6 +606,7 @@ test("special endings", () => {
verb: khorul,
tense: "imperfectivePast",
person: T.Person.ThirdPlurMale,
complementPerson: T.Person.ThirdPlurMale,
voice: "active",
negative: false,
})).toEqual({
@ -621,6 +629,7 @@ test("special endings", () => {
verb: khorul,
tense: "perfectivePast",
person: T.Person.ThirdPlurMale,
complementPerson: T.Person.ThirdPlurMale,
voice: "active",
negative: false,
})).toEqual({
@ -646,6 +655,7 @@ test("imperative tenses", () => {
verb: wahul,
tense: "imperfectiveImperative",
person: T.Person.SecondSingMale,
complementPerson: T.Person.SecondSingMale,
voice: "active",
negative: false,
})).toEqual({
@ -661,6 +671,7 @@ test("imperative tenses", () => {
verb: wahul,
tense: "perfectiveImperative",
person: T.Person.SecondSingFemale,
complementPerson: T.Person.SecondSingFemale,
voice: "active",
negative: false,
})).toEqual({
@ -676,6 +687,7 @@ test("imperative tenses", () => {
verb: wahul,
tense: "imperfectiveImperative",
person: T.Person.SecondPlurMale,
complementPerson: T.Person.SecondPlurMale,
voice: "active",
negative: false,
})).toEqual({
@ -691,6 +703,7 @@ test("imperative tenses", () => {
verb: wahul,
tense: "perfectiveImperative",
person: T.Person.SecondPlurFemale,
complementPerson: T.Person.SecondPlurFemale,
voice: "active",
negative: false,
})).toEqual({
@ -709,6 +722,7 @@ test("ability tenses", () => {
verb: wahul,
tense: "presentVerbModal",
person: T.Person.FirstSingMale,
complementPerson: T.Person.FirstSingMale,
voice: "active",
negative: false,
})).toEqual({
@ -744,6 +758,7 @@ test("basic tenses", () => {
verb: wahul,
tense: "presentVerb",
person: T.Person.FirstSingMale,
complementPerson: T.Person.FirstSingMale,
voice: "active",
negative: false,
})).toEqual({
@ -760,6 +775,7 @@ test("basic tenses", () => {
verb: wahul,
tense: "subjunctiveVerb",
person: T.Person.SecondSingMale,
complementPerson: T.Person.SecondSingMale,
voice: "active",
negative: false,
})).toEqual({
@ -775,6 +791,7 @@ test("basic tenses", () => {
verb: wahul,
tense: "habitualPerfectivePast",
person: T.Person.ThirdSingFemale,
complementPerson: T.Person.ThirdSingFemale,
voice: "active",
negative: false,
})).toEqual({
@ -800,6 +817,7 @@ test("perfect tenses", () => {
verb: wahul,
tense: "presentPerfect",
person: T.Person.FirstSingMale,
complementPerson: T.Person.FirstSingMale,
voice: "active",
negative: false,
})).toEqual({
@ -816,6 +834,7 @@ test("perfect tenses", () => {
verb: wahul,
tense: "subjunctivePerfect",
person: T.Person.FirstSingMale,
complementPerson: T.Person.FirstSingMale,
voice: "active",
negative: false,
})).toEqual({
@ -832,6 +851,7 @@ test("perfect tenses", () => {
verb: wahul,
tense: "habitualPerfect",
person: T.Person.FirstSingMale,
complementPerson: T.Person.FirstSingMale,
voice: "active",
negative: false,
})).toEqual({
@ -848,6 +868,7 @@ test("perfect tenses", () => {
verb: wahul,
tense: "habitualPerfect",
person: T.Person.ThirdPlurMale,
complementPerson: T.Person.ThirdPlurMale,
voice: "active",
negative: false,
})).toEqual({
@ -864,6 +885,7 @@ test("perfect tenses", () => {
verb: wahul,
tense: "futurePerfect",
person: T.Person.FirstSingMale,
complementPerson: T.Person.FirstSingMale,
voice: "active",
negative: false,
})).toEqual({
@ -880,6 +902,7 @@ test("perfect tenses", () => {
verb: wahul,
tense: "pastPerfect",
person: T.Person.SecondSingFemale,
complementPerson: T.Person.SecondSingFemale,
voice: "active",
negative: false,
})).toEqual({
@ -903,6 +926,7 @@ test("perfect tenses", () => {
verb: wahul,
tense: "wouldBePerfect",
person: T.Person.SecondSingFemale,
complementPerson: T.Person.SecondSingFemale,
voice: "active",
negative: false,
})).toEqual({
@ -926,6 +950,7 @@ test("perfect tenses", () => {
verb: wahul,
tense: "pastSubjunctivePerfect",
person: T.Person.SecondSingFemale,
complementPerson: T.Person.SecondSingFemale,
voice: "active",
negative: false,
})).toEqual({
@ -946,6 +971,7 @@ test("perfect tenses", () => {
verb: wahul,
tense: "wouldHaveBeenPerfect",
person: T.Person.SecondSingFemale,
complementPerson: T.Person.SecondSingFemale,
voice: "active",
negative: false,
})).toEqual({
@ -970,7 +996,7 @@ test("ending on complex verbs", () => {
tense: "presentVerbModal",
person: T.Person.SecondSingMale,
voice: "active",
presObj: T.Person.ThirdSingFemale,
complementPerson: T.Person.ThirdSingFemale,
negative: false,
})).toEqual({
hasBa: false,
@ -1015,7 +1041,7 @@ test("ending on complex verbs", () => {
tense: "presentVerb",
person: T.Person.SecondSingMale,
voice: "active",
presObj: T.Person.ThirdSingFemale,
complementPerson: T.Person.ThirdSingFemale,
negative: false,
})).toEqual({
hasBa: false,

View File

@ -5,6 +5,9 @@ import {
personGender,
personNumber,
} from "../misc-helpers";
import {
fmapSingleOrLengthOpts,
} from "../fmaps";
import {
concatPsString,
getLength,
@ -24,13 +27,13 @@ import { getAspect, isKedul, perfectTenseToEquative, verbEndingConcat } from "./
import { accentOnNFromEnd, accentPsSyllable, removeAccents } from "../accent-helpers";
// TODO: problem with laaR - no perfective split
export function renderVerb({ verb, tense, person, voice, presObj, negative }: {
export function renderVerb({ verb, tense, person, voice, negative, complementPerson }: {
verb: T.VerbEntry,
negative: boolean,
tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense, // TODO: make T.Tense
person: T.Person,
complementPerson: T.Person,
voice: T.Voice,
presObj?: T.Person,
}): {
hasBa: boolean,
vbs: T.VerbRenderedOutput,
@ -39,13 +42,7 @@ export function renderVerb({ verb, tense, person, voice, presObj, negative }: {
return renderPerfectVerb({ verb, tense, voice, person });
}
const isPast = isPastTense(tense);
const rootPerson = isPast ? person : (presObj ?? person);
const hasBa = tenseHasBa(tense);
const genderNumber = {
gender: personGender(rootPerson),
number: personNumber(rootPerson),
};
const aspect = getAspect(tense, negative);
const isImperative = isImperativeTense(tense);
const type = isAbilityTense(tense) ? "ability" : "basic";
@ -57,7 +54,10 @@ export function renderVerb({ verb, tense, person, voice, presObj, negative }: {
aspect,
voice,
type,
genderNumber,
genderNumber: {
gender: personGender(complementPerson),
number: personNumber(complementPerson),
},
});
// #2 add the verb ending to it
const ending = getEnding(person, isPast, isImperative, aspect);
@ -98,10 +98,7 @@ function renderPerfectVerb({ tense, verb, voice, person }: {
const equativeBlock: T.VBE = {
type: "VB",
person,
ps: "long" in equative ? {
long: equative.long[row][col],
short: equative.short[row][col],
} : equative[row][col],
ps: fmapSingleOrLengthOpts(x => x[row][col], equative),
};
return {
hasBa,

View File

@ -15,6 +15,7 @@ import { accentOnNFromEnd, countSyllables, removeAccents } from "../accent-helpe
import { isKawulVerb, isTlulVerb } from "../type-predicates";
import { vEntry, addAbilityEnding, weld, removeL, addTrailingAccent, tlulPerfectiveStem, getLongVB, possiblePPartLengths, isStatComp, statCompImperfectiveSpace, makeComplement, vTransitivity, isKedul } from "./rs-helpers";
import { inflectPattern3 } from "./new-inflectors";
import { fmapSingleOrLengthOpts } from "../fmaps";
const statVerb = {
intransitive: vEntry({"ts":1581086654898,"i":11100,"p":"کېدل","f":"kedul","g":"kedul","e":"to become _____","r":2,"c":"v. intrans.","ssp":"ش","ssf":"sh","prp":"شول","prf":"shwul","pprtp":"شوی","pprtf":"shúwey","noOo":true,"ec":"become"}),
@ -116,14 +117,10 @@ export function getPastParticiple(verb: T.VerbEntry, voice: T.Voice, { gender, n
};
function addTail(ps: T.SingleOrLengthOpts<T.PsString[]>): T.SingleOrLengthOpts<T.PsString[]> {
if ("long" in ps) {
return {
long: addTail(ps.long) as T.PsString[],
short: addTail(ps.short) as T.PsString[],
};
}
const withTail = concatPsString(ps[0], { p: "ی", f: "ey"});
return inflectPattern3(withTail, { gender, number });
return fmapSingleOrLengthOpts((x) => {
const withTail = concatPsString(x[0], { p: "ی", f: "ey"});
return inflectPattern3(withTail, { gender, number });
}, ps);
}
}

View File

@ -30,6 +30,7 @@ import {
splitUpSyllables,
} from "./accent-helpers";
import * as T from "../../types";
import { fmapSingleOrLengthOpts } from "./fmaps";
const endingInSingleARegex = /[^a]'??[aá]'??$/;
const endingInHeyOrAynRegex = /[^ا][هع]$/;
@ -661,11 +662,5 @@ function makePlural(w: T.DictionaryEntryNoFVars): { plural: T.PluralInflections,
}
export function inflectYey(ps: T.SingleOrLengthOpts<T.PsString>): T.SingleOrLengthOpts<T.UnisexInflections> {
if ("long" in ps) {
return {
long: inflectYey(ps.long) as T.UnisexInflections,
short: inflectYey(ps.short) as T.UnisexInflections,
}
}
return inflectRegularYeyUnisex(ps.p, ps.f);
return fmapSingleOrLengthOpts((x) => inflectRegularYeyUnisex(x.p, x.f), ps);
}

View File

@ -25,6 +25,11 @@ export function getSubjectSelection(blocks: T.EPSBlock[] | T.EPSBlockComplete[]
return b.block;
}
export function getComplementFromBlocks(blocks: T.Block[][]): T.Rendered<T.ComplementSelection> | T.UnselectedComplementSelection | undefined {
const b = blocks[0].find(f => f.block.type === "complement");
return b?.block as T.Rendered<T.ComplementSelection> | T.UnselectedComplementSelection | undefined;
}
export function getSubjectSelectionFromBlocks(blocks: T.Block[][]): T.Rendered<T.SubjectSelectionComplete> {
const b = blocks[0].find(f => f.block.type === "subjectSelection");
if (!b || b.block.type !== "subjectSelection") {

View File

@ -1,7 +1,7 @@
import * as T from "../../../types";
import {
capitalizeFirstLetter,
concatPsString, getLong, getShort,
concatPsString, getLong,
} from "../p-text-helpers";
import { negativeParticle } from "../grammar-units";
import * as grammarUnits from "../grammar-units";
@ -14,6 +14,7 @@ import { completeVPSelection } from "./vp-tools";
import { renderVP } from "./render-vp";
import {
getAPsFromBlocks,
getComplementFromBlocks,
getObjectSelectionFromBlocks,
getPredicateSelectionFromBlocks,
getSubjectSelectionFromBlocks,
@ -249,7 +250,13 @@ function getPsFromWelded(v: T.Welded): T.PsString[] {
}
return getPsFromWelded(v);
}
return [...getPsFromSide(v.left), ...getPsFromSide(v.right)];
const left = getPsFromSide(v.left);
const right = getPsFromSide(v.right);
return left.flatMap(leftVar => (
right.flatMap(rightVar => (
concatPsString(leftVar, " ", rightVar)
))
));
}
function getEngAPs(blocks: T.Block[][]): string {
@ -261,16 +268,17 @@ function getEngAPs(blocks: T.Block[][]): string {
}
function getEngComplement(blocks: T.Block[][]): string | undefined {
return "TODO";
// const comp = getComplementFromBlocks(blocks);
// if (!comp) return undefined;
// if (comp.selection.type === "unselected") {
// return "____";
// }
// if (comp.selection.type === "sandwich") {
// return getEnglishFromRendered({ type: "AP", selection: comp.selection });
// }
// return comp.selection.e;
console.log("getting comp");
const comp = getComplementFromBlocks(blocks);
console.log({ blocks, comp });
if (!comp) return undefined;
if (comp.selection.type === "unselected") {
return "____";
}
if (comp.selection.type === "sandwich") {
return getEnglishFromRendered({ type: "AP", selection: comp.selection });
}
return comp.selection.e;
}
function putKidsInKidsSection(blocksWVars: T.Block[][], kids: T.Kid[], enforceKidsSectionBlankout: boolean): (T.Block | T.Kid | T.PsString)[][] {

View File

@ -1,42 +1,23 @@
import * as T from "../../../types";
import {
applyToSingOrLengthOpts,
getVerbBlockPosFromPerson,
} from "../misc-helpers";
import { conjugateVerb } from "../verb-conjugation";
import {
hasBaParticle,
getLong,
isImperativeBlock,
splitOffLeapfrogWordFull,
getShort,
} from "../p-text-helpers";
import { removeAccents, removeAccentsWLength, removeVerbAccent } from "../accent-helpers";
mapVerbRenderedOutput,
} from "../fmaps";
import { removeAccents } from "../accent-helpers";
import {
getPersonFromNP,
removeBa,
isPastTense,
getTenseVerbForm,
} from "./vp-tools";
import {
isAdjectiveEntry,
isImperativeTense,
isLocativeAdverbEntry,
isAbilityTense,
isNounEntry,
isPattern4Entry,
isPerfectTense,
isTlulVerb,
} from "../type-predicates";
import { renderVerb } from "../new-verb-engine/render-verb";
import { renderEnglishVPBase } from "./english-vp-rendering";
import { personGender } from "../misc-helpers";
import { renderNPSelection } from "./render-np";
import { getObjectSelection, getSubjectSelection, makeBlock, makeKid } from "./blocks-utils";
import { renderAPSelection } from "./render-ap";
import { findPossesivesToShrink, orderKids, getMiniPronounPs } from "./render-common";
import { renderComplementSelection } from "./render-complement";
import { makeNounSelection } from "./make-selections";
export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
const subject = getSubjectSelection(VP.blocks).selection;
@ -58,7 +39,7 @@ export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
const inflectSubject = isPast && isTransitive && !isMascSingAnimatePattern4(subject);
const inflectObject = !isPast && isFirstOrSecondPersPronoun(object);
// Render Elements
const firstBlocks = renderVPBlocks(VP.blocks, {
const firstBlocks = renderVPBlocks(VP.blocks, VP.externalComplement, {
inflectSubject,
inflectObject,
king,
@ -68,6 +49,7 @@ export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
verb: VP.verb.verb,
tense: VP.verb.tense,
person: kingPerson,
complementPerson: objectPerson || kingPerson,
voice: VP.verb.voice,
negative: VP.verb.negative,
});
@ -119,14 +101,15 @@ function removeAbbreviated(blocks: T.VPSBlockComplete[], form: T.FormVersion, ki
if (form.removeKing && king === "object") return false;
}
return true;
})
});
}
function insertNegative(blocks: T.VerbRenderedOutput, negative: boolean, imperative: boolean): T.Block[][] {
if (!negative) {
return [blocks.flat().map(makeBlock)];
};
const blocksA = removeVerbAccent(blocks).flat().map(makeBlock);
const blocksA = blocks.flat().map(makeBlock);
const blocksNoAccentA = mapVerbRenderedOutput(removeAccents, blocks).flat().map(makeBlock);
const neg = makeBlock({ type: "negative", imperative });
const nonStandPerfectiveSplit = hasNonStandardPerfectiveSplit(blocks);
if (blocks[1].length === 2) {
@ -135,21 +118,21 @@ function insertNegative(blocks: T.VerbRenderedOutput, negative: boolean, imperat
return [
insertFromEnd(swapEndingBlocks(blocksA), neg, 2),
insertFromEnd(swapEndingBlocks(blocksA, 2), neg, 3),
insertFromEnd(blocksA, neg, 1),
insertFromEnd(blocksNoAccentA, neg, 1),
]
}
return [
insertFromEnd(swapEndingBlocks(blocksA), neg, 2),
insertFromEnd(blocksA, neg, 1),
insertFromEnd(blocksNoAccentA, neg, 1),
];
}
if (nonStandPerfectiveSplit) {
return [
insertFromEnd(blocksA, neg, 1),
insertFromEnd(blocksA, neg, 2),
insertFromEnd(blocksNoAccentA, neg, 1),
insertFromEnd(blocksNoAccentA, neg, 2),
];
} else {
return [insertFromEnd(blocksA, neg, 1)];
return [insertFromEnd(blocksNoAccentA, neg, 1)];
}
}
@ -172,8 +155,6 @@ function insertFromEnd<X>(arr: X[], x: X, n: number): X[] {
];
}
function hasNonStandardPerfectiveSplit([[ph]]: T.VerbRenderedOutput): boolean {
if (!ph) {
return false;
@ -196,7 +177,7 @@ function shrinkServant(np: T.NPSelection): T.MiniPronoun {
}
function renderVPBlocks(blocks: T.VPSBlockComplete[], config: {
function renderVPBlocks(blocks: T.VPSBlockComplete[], externalComplement: T.VPSelectionComplete["externalComplement"], config: {
inflectSubject: boolean,
inflectObject: boolean,
king: "subject" | "object",
@ -207,7 +188,8 @@ function renderVPBlocks(blocks: T.VPSBlockComplete[], config: {
const adverbPerson = typeof object.selection === "object"
? getPersonFromNP(object.selection)
: getPersonFromNP(subject.selection);
return blocks.reduce((blocks, { block }): T.Block[] => {
const b = externalComplement ? [...blocks, { block: externalComplement }] : blocks
return b.reduce((blocks, { block }): T.Block[] => {
if (block.type === "subjectSelection") {
return [
...blocks,

View File

@ -32,8 +32,11 @@ import {
inflectYey,
} from "./pashto-inflector";
import {
accentOnNFromEnd, removeAccents, removeAccentsFromInflections,
accentOnNFromEnd, removeAccents,
} from "./accent-helpers";
import {
mapInflections,
} from "./fmaps";
import { pashtoConsonants } from "./pashto-consonants";
import {
checkForIrregularConjugation,
@ -289,7 +292,7 @@ function makeJoinedModalContent(info: T.NonComboVerbInfo, aspectIn: T.Aspect): T
function makeStativeCompoundSeperatedAspectContent(info: T.StativeCompoundVerbInfo, aspect: T.Aspect): T.AspectContent {
const transitivity = getTransitivity(info);
const complement: T.UnisexInflections = aspect === "imperfective"
? removeAccentsFromInflections(info.complement)
? mapInflections(removeAccents, info.complement)
: info.complement;
const presentComplement = (transitivity === "transitive" && complementInflects(complement))
? unisexInfToObjectMatrix(complement) // transitive verb requires an object matrix for the complex
@ -406,7 +409,7 @@ function makePerfectContent(info: T.NonComboVerbInfo): T.PerfectContent {
const pastPart: (" " | T.SingleOrLengthOpts<T.UnisexInflections> | T.SingleOrLengthOpts<T.PsString>)[] =
(info.type === "stative compound")
// for stative compounds
? [removeAccentsFromInflections(info.complement), " ", stativeAux[transitivity].participle.past]
? [mapInflections(removeAccents, info.complement), " ", stativeAux[transitivity].participle.past]
// for regular compounds
: [inflectYey(noPersInfs(info.participle.past))]

View File

@ -6,9 +6,9 @@
*
*/
type Prettify<T> = {
[K in keyof T]: T[K];
} & {};
// type prettify<t> = {
// [k in keyof t]: t[k];
// } & {};
export type PsStringField = "p" | "f";
export type PsString = {
@ -1105,13 +1105,16 @@ export type NComp = {
// - locative adv
// - sandwich (TODO)
// - noun
/** complement block */
export type Comp = {
export type Comp = AdjComp | OtherComp
export type AdjComp = {
type: "AdjComp",
ps: PsString,
gender: Gender,
number: NounNumber,
} | {
gender: Gender,
};
export type OtherComp = {
type: "Comp",
ps: PsString,
};