Refactor for use of keys in the blocks so that we can autoAnimate the blocks diagrams, but it still doesn't work because we need a way to persist the keys in the blocks on re-renders - could be tricky

This commit is contained in:
lingdocs 2022-06-24 14:29:33 -05:00
parent 7275fbd73c
commit 4062cedd48
9 changed files with 280 additions and 228 deletions

View File

@ -1,4 +1,5 @@
import { useState } from "react";
// import autoAnimate from "@formkit/auto-animate";
import { filterForVisibleBlocksEP, filterForVisibleBlocksVP } from "../lib/phrase-building/compile";
import * as T from "../types";
import Block from "./blocks/Block";
@ -11,6 +12,11 @@ function RenderedBlocksDisplay({ opts, rendered, justify, script }: {
justify?: "left" | "right" | "center",
}) {
const [variation, setVariation] = useState<number>(0);
// not using autoAnimate here because we need a way to persist the keys in the blocks first
// const parent = useRef(null);
// useEffect(() => {
// parent.current && autoAnimate(parent.current)
// }, [parent]);
const blocksWVars = ("omitSubject" in rendered)
? filterForVisibleBlocksEP(rendered.blocks, rendered.omitSubject)
: filterForVisibleBlocksVP(rendered.blocks, rendered.form, rendered.king);
@ -19,14 +25,14 @@ function RenderedBlocksDisplay({ opts, rendered, justify, script }: {
function handleVariationChange() {
setVariation(ov => ((ov + 1) % blocksWVars.length));
}
return <div className={`d-flex flex-row justify-content-${justify ? justify : "center"}`} style={{}}>
return <div className={`d-flex flex-row justify-content-${justify ? justify : "center"}`}>
<div className={`d-flex flex-row${script === "p" ? "-reverse" : ""} justify-content-left align-items-end mt-3 pb-2`} style={{ overflowX: "auto" }}>
<div key={Math.random()} className="mr-2">
<div key={blocks[0].key} className="mr-2">
<Block opts={opts} block={blocks[0]} king={king} script={script} />
</div>
<KidsSection opts={opts} kids={rendered.kids} script={script} />
<KidsSection key="kidsSection" opts={opts} kids={rendered.kids} script={script} />
{blocks.slice(1).map((block) => (
<div key={Math.random()} className="mr-2">
<div key={block.key} className="mr-2">
<Block opts={opts} block={block} king={king} script={script} />
</div>
))}
@ -42,10 +48,15 @@ function KidsSection({ opts, kids, script }: {
kids: T.Kid[],
script: "p" | "f",
}) {
// not using autoAnimate here because we need a way to persist the keys in the blocks first
// const parent = useRef(null);
// useEffect(() => {
// parent.current && autoAnimate(parent.current)
// }, [parent]);
return kids.length > 0 ? <div className="text-center mx-1 mr-3" style={{ paddingBottom: "1rem"}}>
<div className={`d-flex flex-row${script === "p" ? "-reverse" : ""} mb-3 justify-content-center`}>
{kids.map(kid => (
<KidDisplay key={Math.random()} opts={opts} kid={kid} script={script} />
<KidDisplay key={kid.key} opts={opts} kid={kid} script={script} />
))}
</div>
<div><strong>kids</strong></div>

View File

@ -15,53 +15,53 @@ function Block({ opts, block, king, script }: {
king?: "subject" | "object" | undefined,
script: "p" | "f";
}) {
if ("equative" in block) {
return <EquativeBlock opts={opts} eq={block.equative} script={script} />;
if ("equative" in block.block) {
return <EquativeBlock opts={opts} eq={block.block.equative} script={script} />;
}
if (block.type === "AP") {
const english = getEnglishFromRendered(block);
return <APBlock opts={opts} english={english} script={script}>{block}</APBlock>
if (block.block.type === "AP") {
const english = getEnglishFromRendered(block.block);
return <APBlock opts={opts} english={english} script={script}>{block.block}</APBlock>
}
if (block.type === "subjectSelection") {
if (block.block.type === "subjectSelection") {
const role = king === "subject" ? "king" : king === "object" ? "servant" : undefined;
return <SubjectBlock opts={opts} np={block.selection} role={role} script={script} />
return <SubjectBlock opts={opts} np={block.block.selection} role={role} script={script} />
}
if (block.type === "predicateSelection") {
const english = getEnglishFromRendered(block.selection);
if (block.block.type === "predicateSelection") {
const english = getEnglishFromRendered(block.block.selection);
return <div className="text-center">
<div><strong>Predicate</strong></div>
{block.selection.type === "EQComp"
? <EqCompBlock opts={opts} comp={block.selection.selection} script={script} />
: <NPBlock opts={opts} english={english} script={script}>{block.selection}</NPBlock>}
{block.block.selection.type === "EQComp"
? <EqCompBlock opts={opts} comp={block.block.selection.selection} script={script} />
: <NPBlock opts={opts} english={english} script={script}>{block.block.selection}</NPBlock>}
</div>
}
if (block.type === "negative") {
return <NegBlock opts={opts} imperative={block.imperative} script={script} />
if (block.block.type === "negative") {
return <NegBlock opts={opts} imperative={block.block.imperative} script={script} />
}
if (block.type === "perfectiveHead") {
return <PerfHeadBlock opts={opts} ps={block.ps} script={script} />
if (block.block.type === "perfectiveHead") {
return <PerfHeadBlock opts={opts} ps={block.block.ps} script={script} />
}
if (block.type === "verbComplement") {
return <VCompBlock opts={opts} comp={block.complement} script={script} />;
if (block.block.type === "verbComplement") {
return <VCompBlock opts={opts} comp={block.block.complement} script={script} />;
}
if (block.type === "verb") {
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.type === "objectSelection") {
const role = king === "object" ? "king" : king === "subject" ? "servant" : undefined;
return <ObjectBlock opts={opts} obj={block.selection} role={role} script={script} />;
if (block.block.type === "perfectEquativeBlock") {
return <EquativeBlock opts={opts} eq={block.block} script={script} />;
}
if (block.type === "perfectParticipleBlock") {
return <VerbSBlock opts={opts} v={block} script={script} />;
if (block.block.type === "modalVerbBlock") {
return <ModalVerbBlock opts={opts} v={block.block} script={script} />;
}
if (block.type === "perfectEquativeBlock") {
return <EquativeBlock opts={opts} eq={block} script={script} />;
}
if (block.type === "modalVerbBlock") {
return <ModalVerbBlock opts={opts} v={block} script={script} />;
}
if (block.type === "modalVerbKedulPart") {
return <ModalAuxBlock opts={opts} aux={block} script={script} />
if (block.block.type === "modalVerbKedulPart") {
return <ModalAuxBlock opts={opts} aux={block.block} script={script} />
}
return null;
}

View File

@ -8,10 +8,10 @@ function KidDisplay({ opts, kid, script }: {
kid: T.Kid,
script: "p" | "f",
}) {
const ps = kid.type === "ba"
const ps = kid.kid.type === "ba"
? baParticle
: kid.ps;
return <div className="mx-1">
: kid.kid.ps;
return <div className="mx-1" key={kid.key}>
{script === "p"
? <Pashto opts={opts}>{ps}</Pashto>
: <Phonetics opts={opts}>{ps}</Phonetics>}

View File

@ -1,6 +1,20 @@
import * as T from "../../types";
import { getLength } from "../p-text-helpers";
export function makeBlock(block: T.Block["block"], key?: number): T.Block {
return {
key: key === undefined ? Math.random() : key,
block,
};
}
export function makeKid(kid: T.Kid["kid"], key?: number): T.Kid {
return {
key: key === undefined ? Math.random() : key,
kid,
};
}
export function getSubjectSelection(blocks: T.EPSBlockComplete[] | T.VPSBlockComplete[]): T.SubjectSelectionComplete;
export function getSubjectSelection(blocks: T.EPSBlock[] | T.VPSBlock[]): T.SubjectSelection;
export function getSubjectSelection(blocks: T.EPSBlock[] | T.EPSBlockComplete[] | T.VPSBlockComplete[] | T.VPSBlock[]): T.SubjectSelection | T.SubjectSelectionComplete {
@ -12,31 +26,31 @@ export function getSubjectSelection(blocks: T.EPSBlock[] | T.EPSBlockComplete[]
}
export function getSubjectSelectionFromBlocks(blocks: T.Block[][]): T.Rendered<T.SubjectSelectionComplete> {
const b = blocks[0].find(f => f.type === "subjectSelection");
if (!b || b.type !== "subjectSelection") {
const b = blocks[0].find(f => f.block.type === "subjectSelection");
if (!b || b.block.type !== "subjectSelection") {
throw new Error("subjectSelection not found in blocks");
}
return b;
return b.block;
}
export function getObjectSelectionFromBlocks(blocks: T.Block[][]): T.Rendered<T.ObjectSelectionComplete> {
const b = blocks[0].find(f => f.type === "objectSelection");
if (!b || b.type !== "objectSelection") {
const b = blocks[0].find(f => f.block.type === "objectSelection");
if (!b || b.block.type !== "objectSelection") {
throw new Error("objectSelection not found in blocks");
}
return b;
return b.block;
}
export function getVerbFromBlocks(blocks: T.Block[][]): T.VerbRenderedBlock {
const b = blocks[0].find(f => f.type === "verb");
const p = blocks[0].find(f => f.type === "perfectParticipleBlock");
const m = blocks[0].find(f => f.type === "modalVerbBlock");
const v = (b && b.type === "verb")
? b
: (p && p.type === "perfectParticipleBlock")
? p.verb
: (m && m.type === "modalVerbBlock")
? m.verb
const b = blocks[0].find(f => f.block.type === "verb");
const p = blocks[0].find(f => f.block.type === "perfectParticipleBlock");
const m = blocks[0].find(f => f.block.type === "modalVerbBlock");
const v = (b && b.block.type === "verb")
? b.block
: (p && p.block.type === "perfectParticipleBlock")
? p.block.verb
: (m && m.block.type === "modalVerbBlock")
? m.block.verb
: undefined;
if (!v) {
throw new Error("verbSelection not found in blocks");
@ -46,8 +60,8 @@ export function getVerbFromBlocks(blocks: T.Block[][]): T.VerbRenderedBlock {
export function getVerbAndHeadFromBlocks(blocks: T.Block[][]): { verb: T.VerbRenderedBlock, perfectiveHead: T.PerfectiveHeadBlock | undefined } {
const verb = getVerbFromBlocks(blocks);
const perfectiveHead = blocks[0].find(f => f.type === "perfectiveHead");
if (!perfectiveHead || perfectiveHead.type !== "perfectiveHead") {
const perfectiveHead = blocks[0].find(f => f.block.type === "perfectiveHead");
if (!perfectiveHead || perfectiveHead.block.type !== "perfectiveHead") {
return {
verb,
perfectiveHead: undefined,
@ -55,27 +69,27 @@ export function getVerbAndHeadFromBlocks(blocks: T.Block[][]): { verb: T.VerbRen
}
return {
verb,
perfectiveHead,
perfectiveHead: perfectiveHead.block,
};
}
export function includesShrunkenServant(kids?: T.Kid[]): boolean {
if (!kids) return false;
return kids.some(k => (
k.type === "mini-pronoun" && k.source === "servant"
k.kid.type === "mini-pronoun" && k.kid.source === "servant"
));
}
export function getPredicateSelectionFromBlocks(blocks: T.Block[][]): T.Rendered<T.PredicateSelectionComplete> {
const b = blocks[0].find(f => f.type === "predicateSelection");
if (!b || b.type !== "predicateSelection") {
const b = blocks[0].find(f => f.block.type === "predicateSelection");
if (!b || b.block.type !== "predicateSelection") {
throw new Error("predicateSelection not found in blocks");
}
return b;
return b.block;
}
export function getAPsFromBlocks(blocks: T.Block[][]): T.Rendered<T.APSelection>[] {
return blocks[0].filter(b => b.type === "AP") as T.Rendered<T.APSelection>[];
return blocks[0].filter(b => b.block.type === "AP").map(b => b.block) as T.Rendered<T.APSelection>[];
}
export function getObjectSelection(blocks: T.VPSBlockComplete[]): T.ObjectSelectionComplete;
@ -238,16 +252,19 @@ export function isNoObject(b: T.VPSBlock["block"] | T.EPSBlock["block"]): b is {
export function specifyEquativeLength(blocksWVars: T.Block[][], length: "long" | "short"): T.Block[][] {
function specify(blocks: T.Block[]): T.Block[] {
const i = blocks.findIndex(b => b.type === "equative");
const i = blocks.findIndex(b => b.block.type === "equative");
if (i === -1) throw new Error("equative block not found in EPRendered");
const eq = blocks[i];
if (eq.type !== "equative") throw new Error("error searching for equative block");
if (eq.block.type !== "equative") throw new Error("error searching for equative block");
const adjusted = [...blocks];
adjusted[i] = {
...eq,
equative: {
...eq.equative,
ps: getLength(eq.equative.ps, length),
block: {
...eq.block,
equative: {
...eq.block.equative,
ps: getLength(eq.block.equative.ps, length),
},
},
};
return adjusted;
@ -257,28 +274,37 @@ export function specifyEquativeLength(blocksWVars: T.Block[][], length: "long" |
export function specifyVerbLength(blocksWVars: T.Block[][], length: "long" | "short" | "mini"): T.Block[][] {
function specify(blocks: T.Block[]): T.Block[] {
return blocks.map((block) => {
if (block.type === "verb") {
const v: T.VerbRenderedBlock = {
return blocks.map((block): T.Block => {
if (block.block.type === "verb") {
const v: T.Block = {
...block,
block: {
...block.block,
block: {
...block.block.block,
ps: getLength(block.block.block.ps, length),
},
},
};
return v;
}
if (block.block.type === "perfectParticipleBlock") {
const p: T.Block = {
...block,
block: {
...block.block,
ps: getLength(block.block.ps, length),
},
};
return v;
}
if (block.type === "perfectParticipleBlock") {
const p: T.PerfectParticipleBlock = {
...block,
ps: getLength(block.ps, length),
};
return p;
}
if (block.type === "modalVerbBlock") {
const m: T.ModalVerbBlock = {
if (block.block.type === "modalVerbBlock") {
const m: T.Block = {
...block,
ps: getLength(block.ps, length),
block: {
...block.block,
ps: getLength(block.block.ps, length),
},
};
return m;
}
@ -289,21 +315,21 @@ export function specifyVerbLength(blocksWVars: T.Block[][], length: "long" | "sh
}
export function hasEquativeWithLengths(blocks: T.Block[][]): boolean {
const equative = blocks[0].find(x => x.type === "equative");
const equative = blocks[0].find(x => x.block.type === "equative");
if (!equative) throw new Error("equative not found in blocks");
if (equative.type !== "equative") throw new Error("error finding equative in blocks");
return "long" in equative.equative.ps;
if (equative.block.type !== "equative") throw new Error("error finding equative in blocks");
return "long" in equative.block.equative.ps;
}
export function hasVerbWithLengths(blocks: T.Block[][]): boolean {
// TODO: handle length options with perfect verb equative as well?
const verb = blocks[0].find(x => (x.type === "verb" || x.type === "perfectParticipleBlock" || x.type === "modalVerbBlock"));
const verb = blocks[0].find(x => (x.block.type === "verb" || x.block.type === "perfectParticipleBlock" || x.block.type === "modalVerbBlock"));
if (!verb) throw new Error("verb not found in blocks");
if (verb.type !== "verb" && verb.type !== "perfectParticipleBlock" && verb.type !== "modalVerbBlock") throw new Error("error finding verb in blocks");
if (verb.block.type !== "verb" && verb.block.type !== "perfectParticipleBlock" && verb.block.type !== "modalVerbBlock") throw new Error("error finding verb in blocks");
return (
(verb.type === "verb" && "long" in verb.block.ps)
|| (verb.type === "perfectParticipleBlock" && "long" in verb.ps)
|| (verb.type === "modalVerbBlock" && "long" in verb.ps)
(verb.block.type === "verb" && "long" in verb.block.block.ps)
|| (verb.block.type === "perfectParticipleBlock" && "long" in verb.block.ps)
|| (verb.block.type === "modalVerbBlock" && "long" in verb.block.ps)
);
}

View File

@ -107,7 +107,7 @@ function compileEPPs(blocks: T.Block[][], kids: T.Kid[], omitSubject: boolean, b
const subjectPerson = getSubjectSelectionFromBlocks(blocks)
.selection.selection.person;
const blocksWKids = putKidsInKidsSection(
omitSubject ? blocks.map(blks => blks.filter(b => b.type !== "subjectSelection")) : blocks,
omitSubject ? blocks.map(blks => blks.filter(b => b.block.type !== "subjectSelection")) : blocks,
kids,
!!blankOut?.kidsSection
);
@ -119,19 +119,19 @@ export function filterForVisibleBlocksVP(blocks: T.Block[][], form: T.FormVersio
return blocks.map(blks => blks.filter((block) => {
if (form.removeKing) {
if (
(king === "subject" && block.type === "subjectSelection")
(king === "subject" && block.block.type === "subjectSelection")
||
(king === "object" && block.type === "objectSelection")
(king === "object" && block.block.type === "objectSelection")
) return false;
}
if (form.shrinkServant) {
if (
(servant === "subject" && block.type === "subjectSelection")
(servant === "subject" && block.block.type === "subjectSelection")
||
(servant === "object" && block.type === "objectSelection")
(servant === "object" && block.block.type === "objectSelection")
) return false;
}
if (block.type === "objectSelection" && typeof block.selection !== "object") {
if (block.block.type === "objectSelection" && typeof block.block.selection !== "object") {
return false;
}
return true;
@ -140,7 +140,7 @@ export function filterForVisibleBlocksVP(blocks: T.Block[][], form: T.FormVersio
export function filterForVisibleBlocksEP(blocks: T.Block[][], omitSubject: boolean): T.Block[][] {
if (!omitSubject) return blocks;
return blocks.map(blks => blks.filter((block) => {
return blocks.map(blks => blks.filter(({ block }) => {
if (block.type === "subjectSelection") {
return false;
}
@ -155,9 +155,9 @@ function combineIntoText(piecesWVars: (T.Block | T.Kid | T.PsString)[][], subjec
const rest = pieces.slice(1);
const firstPs = ("p" in first)
? [first]
: (blankOut?.equative && first.type === "equative")
: (blankOut?.equative && "block" in first && first.block.type === "equative")
? [blank]
: ((blankOut?.ba) && first.type === "ba")
: ((blankOut?.ba) && "kid" in first && first.kid.type === "ba")
? [kidsBlank]
: getPsFromPiece(first, subjectPerson);
if (!rest.length) {
@ -166,8 +166,8 @@ function combineIntoText(piecesWVars: (T.Block | T.Kid | T.PsString)[][], subjec
return combine(rest).flatMap(r => (
firstPs.map(fPs => concatPsString(
fPs,
(!("p" in first) && first.type === "perfectiveHead" && !("p" in next) && (next.type === "verb" || next.type === "negative" || next.type === "mini-pronoun"))
? ((next.type === "negative" || next.type === "mini-pronoun") ? { p: "", f: "-" } : "")
(!("p" in first) && "block" in first && first.block.type === "perfectiveHead" && !("p" in next) && (("block" in next && (next.block.type === "verb" || next.block.type === "negative")) || ("kid" in next && next.kid.type === "mini-pronoun")))
? ((("block" in next && next.block.type === "negative") || ("kid" in next && next.kid.type === "mini-pronoun")) ? { p: "", f: "-" } : "")
: " ",
r,
))
@ -178,59 +178,64 @@ function combineIntoText(piecesWVars: (T.Block | T.Kid | T.PsString)[][], subjec
}
function getPsFromPiece(piece: T.Block | T.Kid, subjectPerson: T.Person): T.PsString[] {
if (piece.type === "ba") {
return [grammarUnits.baParticle];
}
if (piece.type === "mini-pronoun") {
return [piece.ps];
}
if (piece.type === "negative") {
return [
negativeParticle[piece.imperative ? "imperative" : "nonImperative"],
];
}
if (piece.type === "equative") {
// length will already be specified in compileEPPs - this is just for type safety
return getLong(piece.equative.ps);
}
if (piece.type === "subjectSelection" || piece.type === "predicateSelection") {
return getPashtoFromRendered(piece.selection, subjectPerson);
}
if (piece.type === "AP") {
return getPashtoFromRendered(piece, subjectPerson);
}
if (piece.type === "perfectiveHead") {
return [piece.ps];
}
if (piece.type === "verbComplement") {
return [{ p: "---", f: "---"}]; //getPashtoFromRendered(piece.complement);
}
if (piece.type === "objectSelection") {
if (typeof piece.selection !== "object") {
return [{ p: "", f: "" }];
if ("block" in piece) {
if (piece.block.type === "negative") {
return [
negativeParticle[piece.block.imperative ? "imperative" : "nonImperative"],
];
}
if (piece.block.type === "equative") {
// length will already be specified in compileEPPs - this is just for type safety
return getLong(piece.block.equative.ps);
}
if (piece.block.type === "subjectSelection" || piece.block.type === "predicateSelection") {
return getPashtoFromRendered(piece.block.selection, subjectPerson);
}
if (piece.block.type === "AP") {
return getPashtoFromRendered(piece.block, subjectPerson);
}
if (piece.block.type === "perfectiveHead") {
return [piece.block.ps];
}
if (piece.block.type === "verbComplement") {
return [{ p: "---", f: "---"}]; //getPashtoFromRendered(piece.block.complement);
}
if (piece.block.type === "objectSelection") {
if (typeof piece.block.selection !== "object") {
return [{ p: "", f: "" }];
}
return getPashtoFromRendered(piece.block.selection, subjectPerson);
}
if (piece.block.type === "verb") {
// getLong is just for type safety - we will have split up the length options earlier in compileVPPs
return getLong(piece.block.block.ps);
}
if (piece.block.type === "perfectParticipleBlock") {
// getLong is just for type safety - we will have split up the length options earlier in compileVPPs
return getLong(piece.block.ps);
}
if (piece.block.type === "perfectEquativeBlock") {
// just using the short one for now - it will only be short anyways
return getShort(piece.block.ps);
}
if (piece.block.type === "modalVerbBlock") {
// getLong is just for type safety - we will have split up the length options earlier in compileVPPs
return getLong(piece.block.ps);
}
if (piece.block.type === "modalVerbKedulPart") {
// just using the short one for now - it will only be short anyways
return getShort(piece.block.ps);
}
return getPashtoFromRendered(piece.selection, subjectPerson);
}
if (piece.type === "verb") {
// getLong is just for type safety - we will have split up the length options earlier in compileVPPs
return getLong(piece.block.ps);
}
if (piece.type === "perfectParticipleBlock") {
// getLong is just for type safety - we will have split up the length options earlier in compileVPPs
return getLong(piece.ps);
}
if (piece.type === "perfectEquativeBlock") {
// just using the short one for now - it will only be short anyways
return getShort(piece.ps);
}
if (piece.type === "modalVerbBlock") {
// getLong is just for type safety - we will have split up the length options earlier in compileVPPs
return getLong(piece.ps);
}
if (piece.type === "modalVerbKedulPart") {
// just using the short one for now - it will only be short anyways
return getShort(piece.ps);
if ("kid" in piece) {
if (piece.kid.type === "ba") {
return [grammarUnits.baParticle];
}
if (piece.kid.type === "mini-pronoun") {
return [piece.kid.ps];
}
}
throw new Error("unrecognized piece type");
}
@ -317,7 +322,7 @@ export function checkForMiniPronounsError(s: T.EPSelectionState | T.VPSelectionS
return renderVP(VPS).kids;
})();
if (!kids) return undefined;
const miniPronouns = kids.filter(x => x.type === "mini-pronoun") as T.MiniPronoun[];
const miniPronouns = kids.filter(x => x.kid.type === "mini-pronoun").map(m => m.kid) as T.MiniPronoun[];
if (miniPronouns.length > 2) {
return "can't add another mini-pronoun, there are alread two";
}

View File

@ -88,11 +88,11 @@ export function getMiniPronounPs(person: T.Person): T.PsString {
export function orderKids(kids: T.Kid[]): T.Kid[] {
const sorted = [...kids].sort((a, b) => {
// ba first
if (a.type === "ba") return -1;
if (a.kid.type === "ba") return -1;
// kinds lined up 1st 2nd 3rd person
if (a.type === "mini-pronoun" && b.type === "mini-pronoun") {
const aPers = getFirstSecThird(a.person);
const bPers = getFirstSecThird(b.person);
if (a.kid.type === "mini-pronoun" && b.kid.type === "mini-pronoun") {
const aPers = getFirstSecThird(a.kid.person);
const bPers = getFirstSecThird(b.kid.person);
if (aPers < bPers) {
return -1;
}

View File

@ -11,7 +11,7 @@ import { psStringFromEntry } from "../p-text-helpers";
import { isLocativeAdverbEntry } from "../type-predicates";
import { renderAdjectiveSelection } from "./render-adj";
import { renderSandwich } from "./render-sandwich";
import { EPSBlocksAreComplete, getSubjectSelection } from "./blocks-utils";
import { EPSBlocksAreComplete, getSubjectSelection, makeBlock, makeKid } from "./blocks-utils";
import { removeAccentsWLength } from "../accent-helpers";
import { findPossesivesToShrink, orderKids } from "./render-common";
@ -41,18 +41,18 @@ function getEPSBlocksAndKids(EP: T.EPSelectionComplete): { kids: T.Kid[], blocks
const equative: T.EquativeBlock = { type: "equative", equative: renderEquative(EP.equative, commandingPerson) };
const blocks: T.Block[][] = insertNegative([
...renderEPSBlocks(EP.blocks),
{
makeBlock({
type: "predicateSelection",
selection: EP.predicate.selection.type === "NP"
? renderNPSelection(EP.predicate.selection, false, false, "subject", "king")
: renderEqCompSelection(EP.predicate.selection, commandingPerson),
},
equative,
selection: EP.predicate.selection.type === "NP"
? renderNPSelection(EP.predicate.selection, false, false, "subject", "king")
: renderEqCompSelection(EP.predicate.selection, commandingPerson),
}),
makeBlock(equative),
], EP.equative.negative);
const miniPronouns = findPossesivesToShrink(removeOrKeepSubject([...EP.blocks, EP.predicate], EP.omitSubject));
const kids: T.Kid[] = orderKids([
...equative.equative.hasBa ? [{ type: "ba" } as T.Kid] : [],
...miniPronouns,
...equative.equative.hasBa ? [makeKid({ type: "ba" })] : [],
...miniPronouns.map(makeKid),
]);
return {
blocks,
@ -69,12 +69,12 @@ function insertNegative(blocks: T.Block[], negative: boolean): T.Block[][] {
return [
[
...blocksA.slice(0, blocks.length - 1),
{ type: "negative", imperative: false },
makeBlock({ type: "negative", imperative: false }),
...blocksA.slice(-1), // last (equative)
],
[
...blocksA.slice(0, blocks.length - 2),
{ type: "negative", imperative: false },
makeBlock({ type: "negative", imperative: false }),
...blocksA.slice(-1), // last (equative)
...blocksA.slice(-2, -1), // second last (predicate)
],
@ -100,25 +100,25 @@ export function getEquativeForm(tense: T.EquativeTense): { hasBa: boolean, form:
}
function renderEPSBlocks(blocks: T.EPSBlockComplete[]): T.Block[] {
return blocks.map(({ block }): (T.Rendered<T.SubjectSelectionComplete> | T.Rendered<T.APSelection>) => {
return blocks.map(({ block }): T.Block => {
if (block.type === "AP") {
if (block.selection.type === "adverb") {
return {
return makeBlock({
type: "AP",
selection: renderAdverbSelection(block.selection),
};
});
}
// if (block.selection.type === "sandwich") {
return {
return makeBlock({
type: "AP",
selection: renderSandwich(block.selection),
};
});
// }
}
return {
return makeBlock({
type: "subjectSelection",
selection: renderNPSelection(block.selection, false, false, "subject", "none")
};
selection: renderNPSelection(block.selection, false, false, "subject", "none"),
});
});
}
@ -279,15 +279,17 @@ export function completeEPSelection(eps: T.EPSelectionState): T.EPSelectionCompl
function removeAccentsFromEq(blocks: T.Block[]): T.Block[] {
return blocks.map((block) => {
if (block.type === "equative") {
const e: T.EquativeBlock = {
if (block.block.type === "equative") {
return {
...block,
equative: {
...block.equative,
ps: removeAccentsWLength(block.equative.ps),
},
};
return e;
block: {
...block.block,
equative: {
...block.block.equative,
ps: removeAccentsWLength(block.block.equative.ps),
}
}
}
}
return block;
});

View File

@ -26,7 +26,7 @@ import {
import { renderEnglishVPBase } from "./english-vp-rendering";
import { personGender } from "../../lib/misc-helpers";
import { renderNPSelection } from "./render-np";
import { getObjectSelection, getSubjectSelection } from "./blocks-utils";
import { getObjectSelection, getSubjectSelection, makeBlock, makeKid } from "./blocks-utils";
import { renderAPSelection } from "./render-ap";
import { findPossesivesToShrink, orderKids, getMiniPronounPs } from "./render-common";
@ -67,7 +67,7 @@ export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
isCompound: VP.verb.isCompound,
blocks: insertNegative([
...firstBlocks,
...verbBlocks,
...verbBlocks.map(makeBlock),
], VP.verb.negative, isImperativeTense(VP.verb.tense)),
kids: getVPKids(hasBa, VP.blocks, VP.form, king),
englishBase: renderEnglishVPBase({
@ -200,11 +200,11 @@ function getVPKids(hasBa: boolean, blocks: T.VPSBlockComplete[], form: T.FormVer
const object = typeof objectS === "object" ? objectS : undefined;
const servantNP = king === "subject" ? object : subject;
const shrunkenServant = (form.shrinkServant && servantNP)
? shrinkServant(servantNP)
? makeKid(shrinkServant(servantNP))
: undefined;
const shrunkenPossesives = findPossesivesToShrink(removeAbbreviated(blocks, form, king));
const shrunkenPossesives = findPossesivesToShrink(removeAbbreviated(blocks, form, king)).map(makeKid);
return orderKids([
...hasBa ? [{ type: "ba" } as T.Kid] : [],
...hasBa ? [makeKid({ type: "ba" })] : [],
...shrunkenServant ? [shrunkenServant] : [],
...shrunkenPossesives ? shrunkenPossesives : [],
]);
@ -231,10 +231,10 @@ function insertNegative(blocks: T.Block[], negative: boolean, imperative: boolea
const blocksA = removeVerbAccent(blocks);
const basic: T.Block[] = [
...blocksA.slice(0, blocks.length - 1),
{
makeBlock({
type: "negative",
imperative,
},
}),
...blocksA.slice(-1),
];
if (hasNonStandardPerfectiveSplit(blocks)) {
@ -242,7 +242,7 @@ function insertNegative(blocks: T.Block[], negative: boolean, imperative: boolea
basic,
[
...blocksA.slice(0, blocks.length - 2),
{ type: "negative", imperative },
makeBlock({ type: "negative", imperative }),
...blocksA.slice(-2, -1), // second last (perfective split)
...blocksA.slice(-1), // last (verb)
],
@ -252,7 +252,7 @@ function insertNegative(blocks: T.Block[], negative: boolean, imperative: boolea
return [
[
...blocksA.slice(0, blocks.length - 2),
{ type: "negative", imperative },
makeBlock({ type: "negative", imperative }),
...blocksA.slice(-1), // last
...blocksA.slice(-2, -1), // second last
],
@ -263,31 +263,34 @@ function insertNegative(blocks: T.Block[], negative: boolean, imperative: boolea
}
function hasLeapFroggable(blocks: T.Block[]): boolean {
return blocks.some(b => b.type === "perfectEquativeBlock" || b.type === "modalVerbBlock");
return blocks.some(b => b.block.type === "perfectEquativeBlock" || b.block.type === "modalVerbBlock");
}
function hasNonStandardPerfectiveSplit(blocks: T.Block[]): boolean {
const perfS = blocks.find(b => b.type === "perfectiveHead");
if (!perfS || perfS.type !== "perfectiveHead") {
const perfS = blocks.find(b => b.block.type === "perfectiveHead");
if (!perfS || perfS.block.type !== "perfectiveHead") {
return false;
}
return !["و", "وا"].includes(perfS.ps.p);
return !["و", "وا"].includes(perfS.block.ps.p);
}
function removeVerbAccent(blocks: T.Block[]): T.Block[] {
return blocks.map((block) => {
if (block.type === "perfectiveHead") {
return {
...block,
ps: removeAccents(block.ps),
};
}
if (block.type === "verb") {
if (block.block.type === "perfectiveHead") {
return {
...block,
block: {
...block.block,
ps: removeAccentsWLength(block.block.ps),
ps: removeAccents(block.block.ps),
},
};
}
if (block.block.type === "verb") {
return {
...block,
block: {
...block.block,
ps: removeAccentsWLength(block.block.block.ps),
},
};
}
@ -315,10 +318,10 @@ function renderVPBlocks(blocks: T.VPSBlockComplete[], config: {
if (block.type === "subjectSelection") {
return [
...blocks,
{
makeBlock({
type: "subjectSelection",
selection: renderNPSelection(block.selection, config.inflectSubject, false, "subject", config.king === "subject" ? "king" : "servant"),
},
}),
];
}
if (block.type === "objectSelection") {
@ -326,24 +329,24 @@ function renderVPBlocks(blocks: T.VPSBlockComplete[], config: {
if (typeof object !== "object") {
return [
...blocks,
{
makeBlock({
type: "objectSelection",
selection: object,
},
}),
];
}
const selection = renderNPSelection(object, config.inflectObject, true, "object", config.king === "object" ? "king" : "servant");
return [
...blocks,
{
makeBlock({
type: "objectSelection",
selection,
},
}),
];
}
return [
...blocks,
renderAPSelection(block),
makeBlock(renderAPSelection(block)),
];
}, [] as T.Block[]);
}
@ -362,7 +365,8 @@ function whatsAdjustable(VP: T.VPSelectionComplete): "both" | "king" | "servant"
: "king";
}
type VerbBlocks = | [T.PerfectiveHeadBlock, T.VerbRenderedBlock] // verb w perfective split
type VerbBlocks =
| [T.PerfectiveHeadBlock, T.VerbRenderedBlock] // verb w perfective split
| [T.VerbRenderedBlock] // verb w/out perfective split
| [T.PerfectParticipleBlock, T.PerfectEquativeBlock] // perfect verb
| [T.ModalVerbBlock, T.ModalVerbKedulPart] // modal verb

View File

@ -900,24 +900,28 @@ export type VerbRenderedBlock = {
},
};
export type Block =
| Rendered<SubjectSelectionComplete>
| Rendered<ObjectSelectionComplete>
| Rendered<APSelection>
| Rendered<PredicateSelectionComplete>
| PerfectParticipleBlock
| PerfectEquativeBlock
| ModalVerbBlock
| ModalVerbKedulPart
| { type: "negative", imperative: boolean }
| PerfectiveHeadBlock
| VerbRenderedBlock
| VerbComplementBlock
| EquativeBlock;
export type Block = {
key: number,
block: | Rendered<SubjectSelectionComplete>
| Rendered<ObjectSelectionComplete>
| Rendered<APSelection>
| Rendered<PredicateSelectionComplete>
| PerfectParticipleBlock
| PerfectEquativeBlock
| ModalVerbBlock
| ModalVerbKedulPart
| { type: "negative", imperative: boolean }
| PerfectiveHeadBlock
| VerbRenderedBlock
| VerbComplementBlock
| EquativeBlock;
}
export type Kid =
| { type: "ba" }
| MiniPronoun;
export type Kid = {
key: number,
kid: | { type: "ba" }
| MiniPronoun,
}
export type MiniPronoun = {
type: "mini-pronoun",