working - quiz is broken
This commit is contained in:
parent
4e5075ca19
commit
0f720e3be1
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@lingdocs/pashto-inflector",
|
"name": "@lingdocs/pashto-inflector",
|
||||||
"version": "2.8.0",
|
"version": "2.8.1",
|
||||||
"author": "lingdocs.com",
|
"author": "lingdocs.com",
|
||||||
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
|
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
|
||||||
"homepage": "https://verbs.lingdocs.com",
|
"homepage": "https://verbs.lingdocs.com",
|
||||||
|
|
|
@ -0,0 +1,306 @@
|
||||||
|
import * as T from "../../types";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import {
|
||||||
|
getEnglishFromRendered,
|
||||||
|
} from "../../lib/phrase-building/np-tools";
|
||||||
|
|
||||||
|
function Block({ opts, block }: {
|
||||||
|
opts: T.TextOptions,
|
||||||
|
block: T.Block,
|
||||||
|
}) {
|
||||||
|
if ("equative" in block) {
|
||||||
|
return <EquativeBlock opts={opts} eq={block.equative} />;
|
||||||
|
}
|
||||||
|
if (block.type === "AP") {
|
||||||
|
const english = getEnglishFromRendered(block);
|
||||||
|
return <AP opts={opts} english={english}>{block}</AP>
|
||||||
|
}
|
||||||
|
if (block.type === "subjectSelection") {
|
||||||
|
return <SubjectBlock opts={opts} np={block.selection} />
|
||||||
|
}
|
||||||
|
if (block.type === "predicateSelection") {
|
||||||
|
const english = getEnglishFromRendered(block.selection);
|
||||||
|
return <div className="text-center">
|
||||||
|
<div>Pred</div>
|
||||||
|
{block.selection.type === "EQComp"
|
||||||
|
? <EqCompBlock opts={opts} comp={block.selection.selection} />
|
||||||
|
: <NP opts={opts} english={english}>{block.selection}</NP>}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
if (block.type === "nu") {
|
||||||
|
return <NUBlock opts={opts} />
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Block;
|
||||||
|
|
||||||
|
function NUBlock({ opts }: {
|
||||||
|
opts: T.TextOptions,
|
||||||
|
}) {
|
||||||
|
return <div>
|
||||||
|
<div
|
||||||
|
className={classNames("d-flex flex-row justify-content-center align-items-center")}
|
||||||
|
style={{
|
||||||
|
border: "2px solid black",
|
||||||
|
padding: "1rem",
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
nu
|
||||||
|
</div>
|
||||||
|
<div className="small text-muted text-center" style={{
|
||||||
|
// TODO: find a better way to keep this limited to the width of the div above
|
||||||
|
// don't let this make the div above expand
|
||||||
|
margin: "0 auto",
|
||||||
|
maxWidth: "300px",
|
||||||
|
}}>not</div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function EquativeBlock({ opts, eq }: {
|
||||||
|
opts: T.TextOptions,
|
||||||
|
eq: T.EquativeRendered,
|
||||||
|
}) {
|
||||||
|
return <div>
|
||||||
|
<div
|
||||||
|
className={classNames("d-flex flex-row justify-content-center align-items-center")}
|
||||||
|
style={{
|
||||||
|
border: "2px solid black",
|
||||||
|
padding: "1rem",
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{"short" in eq.ps ? eq.ps.short[0].f : eq.ps[0].f}
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function SubjectBlock({ opts, np }: {
|
||||||
|
opts: T.TextOptions,
|
||||||
|
np: T.Rendered<T.NPSelection>,
|
||||||
|
}) {
|
||||||
|
const english = getEnglishFromRendered(np);
|
||||||
|
return <div className="text-center">
|
||||||
|
<div>Subject</div>
|
||||||
|
<NP opts={opts} english={english}>{np}</NP>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function EqCompBlock({ opts, comp }: {
|
||||||
|
opts: T.TextOptions,
|
||||||
|
comp: T.Rendered<T.EqCompSelection["selection"]>,
|
||||||
|
}) {
|
||||||
|
function AdjectiveBlock({ opts, adj }: {
|
||||||
|
opts: T.TextOptions,
|
||||||
|
adj: T.Rendered<T.AdjectiveSelection>,
|
||||||
|
}) {
|
||||||
|
return <div>
|
||||||
|
<div
|
||||||
|
className={classNames("d-flex flex-row justify-content-center align-items-center")}
|
||||||
|
style={{
|
||||||
|
border: "2px solid black",
|
||||||
|
padding: "1rem",
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{adj.ps[0].f}
|
||||||
|
</div>
|
||||||
|
<div>Adj.</div>
|
||||||
|
{adj.e && <div className="small text-muted text-center" style={{
|
||||||
|
// TODO: find a better way to keep this limited to the width of the div above
|
||||||
|
// don't let this make the div above expand
|
||||||
|
margin: "0 auto",
|
||||||
|
maxWidth: "300px",
|
||||||
|
}}>{adj.e}</div>}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function LocAdvBlock({ opts, adv }: {
|
||||||
|
opts: T.TextOptions,
|
||||||
|
adv: T.Rendered<T.LocativeAdverbSelection>,
|
||||||
|
}) {
|
||||||
|
return <div>
|
||||||
|
<div
|
||||||
|
className={classNames("d-flex flex-row justify-content-center align-items-center")}
|
||||||
|
style={{
|
||||||
|
border: "2px solid black",
|
||||||
|
padding: "1rem",
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{adv.ps[0].f}
|
||||||
|
</div>
|
||||||
|
<div>Loc. Adv.</div>
|
||||||
|
{adv.e && <div className="small text-muted text-center" style={{
|
||||||
|
// TODO: find a better way to keep this limited to the width of the div above
|
||||||
|
// don't let this make the div above expand
|
||||||
|
margin: "0 auto",
|
||||||
|
maxWidth: "300px",
|
||||||
|
}}>{adv.e}</div>}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="text-center mb-2">
|
||||||
|
<div>Comp.</div>
|
||||||
|
{comp.type === "adjective"
|
||||||
|
? <AdjectiveBlock opts={opts} adj={comp} />
|
||||||
|
: comp.type === "loc. adv."
|
||||||
|
? <LocAdvBlock opts={opts} adv={comp} />
|
||||||
|
: <div>
|
||||||
|
<Sandwich opts={opts} sandwich={comp} />
|
||||||
|
<div>Sandwich</div>
|
||||||
|
</div>}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function AP({ opts, children, english }: {
|
||||||
|
opts: T.TextOptions,
|
||||||
|
children: T.Rendered<T.APSelection>,
|
||||||
|
english?: string,
|
||||||
|
}) {
|
||||||
|
const ap = children;
|
||||||
|
if (ap.selection.type === "adverb") {
|
||||||
|
return <div>
|
||||||
|
<div
|
||||||
|
className={classNames("d-flex flex-row justify-content-center align-items-center")}
|
||||||
|
style={{
|
||||||
|
border: "2px solid black",
|
||||||
|
padding: "1rem",
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{ap.selection.ps[0].f}
|
||||||
|
</div>
|
||||||
|
<div>AP</div>
|
||||||
|
{english && <div className="small text-muted text-center" style={{
|
||||||
|
// TODO: find a better way to keep this limited to the width of the div above
|
||||||
|
// don't let this make the div above expand
|
||||||
|
margin: "0 auto",
|
||||||
|
maxWidth: "300px",
|
||||||
|
}}>{english}</div>}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
return <div>
|
||||||
|
<Sandwich opts={opts} sandwich={ap.selection} />
|
||||||
|
<div>AP</div>
|
||||||
|
{english && <div className="small text-muted text-center" style={{
|
||||||
|
// TODO: find a better way to keep this limited to the width of the div above
|
||||||
|
// don't let this make the div above expand
|
||||||
|
margin: "0 auto",
|
||||||
|
maxWidth: "300px",
|
||||||
|
}}>{english}</div>}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Sandwich({ opts, sandwich }: {
|
||||||
|
opts: T.TextOptions,
|
||||||
|
sandwich: T.Rendered<T.SandwichSelection<T.Sandwich>>,
|
||||||
|
}) {
|
||||||
|
return <div>
|
||||||
|
<div className="text-center">Sandwich 🥪</div>
|
||||||
|
<div
|
||||||
|
className={classNames("d-flex flex-row justify-content-center align-items-center")}
|
||||||
|
style={{
|
||||||
|
border: "2px solid black",
|
||||||
|
padding: "0.75rem 0.5rem 0.25rem 0.5rem",
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="d-flex flex-row justify-content-between align-items-end">
|
||||||
|
<Possesors opts={opts}>{sandwich.inside.selection.type !== "pronoun" ? sandwich.inside.selection.possesor : undefined}</Possesors>
|
||||||
|
<div className="mr-2 ml-1 mb-1"><strong>{sandwich.before ? sandwich.before.f : ""}</strong></div>
|
||||||
|
<div>
|
||||||
|
<NP opts={opts} inside>{sandwich.inside}</NP>
|
||||||
|
</div>
|
||||||
|
<div className="ml-2 mr-1 mb-1"><strong>{sandwich.after ? sandwich.after.f : ""}</strong></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function NP({ opts, children, inside, english }: {
|
||||||
|
opts: T.TextOptions,
|
||||||
|
children: T.Rendered<T.NPSelection>,
|
||||||
|
inside?: boolean,
|
||||||
|
english?: string,
|
||||||
|
}) {
|
||||||
|
const np = children;
|
||||||
|
const hasPossesor = !!(np.selection.type !== "pronoun" && np.selection.possesor);
|
||||||
|
return <div>
|
||||||
|
<div
|
||||||
|
className={classNames("d-flex flex-row justify-content-center align-items-center", { "pt-2": !inside && hasPossesor })}
|
||||||
|
style={{
|
||||||
|
border: "2px solid black",
|
||||||
|
padding: inside ? "0.3rem" : hasPossesor ? "0.5rem 1rem 0.25rem 1rem" : "1rem",
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{!inside && <Possesors opts={opts}>{np.selection.type !== "pronoun" ? np.selection.possesor : undefined}</Possesors>}
|
||||||
|
<Adjectives opts={opts}>{np.selection.adjectives}</Adjectives>
|
||||||
|
<div> {np.selection.ps[0].f}</div>
|
||||||
|
</div>
|
||||||
|
<div className={inside ? "small" : ""}>NP</div>
|
||||||
|
{english && <div className="small text-muted text-center" style={{
|
||||||
|
// TODO: find a better way to keep this limited to the width of the div above
|
||||||
|
// don't let this make the div above expand
|
||||||
|
margin: "0 auto",
|
||||||
|
maxWidth: "300px",
|
||||||
|
}}>{english}</div>}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
function Possesors({ opts, children }: {
|
||||||
|
opts: T.TextOptions,
|
||||||
|
children: { shrunken: boolean, np: T.Rendered<T.NPSelection> } | undefined,
|
||||||
|
}) {
|
||||||
|
if (!children) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const contraction = checkForContraction(children.np);
|
||||||
|
return <div className="d-flex flex-row mr-1 align-items-end" style={{
|
||||||
|
marginBottom: "0.5rem",
|
||||||
|
borderBottom: "1px solid grey",
|
||||||
|
}}>
|
||||||
|
{children.np.selection.type !== "pronoun" && <Possesors opts={opts}>{children.np.selection.possesor}</Possesors>}
|
||||||
|
<div>
|
||||||
|
{contraction && <div className="mb-1">({contraction})</div>}
|
||||||
|
<div className={classNames("d-flex", "flex-row", "align-items-center", { "text-muted": contraction })}>
|
||||||
|
<div className="mr-1 pb-2">du</div>
|
||||||
|
<div>
|
||||||
|
<NP opts={opts} inside>{children.np}</NP>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkForContraction(np: T.Rendered<T.NPSelection>): string | undefined {
|
||||||
|
if (np.selection.type !== "pronoun") return undefined;
|
||||||
|
if (np.selection.person === T.Person.FirstSingMale || np.selection.person === T.Person.FirstSingFemale) {
|
||||||
|
return "zmaa"
|
||||||
|
}
|
||||||
|
if (np.selection.person === T.Person.SecondSingMale || np.selection.person === T.Person.SecondSingFemale) {
|
||||||
|
return "staa"
|
||||||
|
}
|
||||||
|
if (np.selection.person === T.Person.FirstPlurMale || np.selection.person === T.Person.FirstPlurFemale) {
|
||||||
|
return "zmoonG"
|
||||||
|
}
|
||||||
|
if (np.selection.person === T.Person.SecondPlurMale || np.selection.person === T.Person.SecondPlurFemale) {
|
||||||
|
return "staaso"
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Adjectives({ opts, children }: {
|
||||||
|
opts: T.TextOptions,
|
||||||
|
children: T.Rendered<T.AdjectiveSelection>[] | undefined,
|
||||||
|
}) {
|
||||||
|
if (!children) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return <em className="mr-1">
|
||||||
|
{children.map(a => a.ps[0].f).join(" ")}{` `}
|
||||||
|
</em>
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
import * as T from "../../types";
|
||||||
|
import Block from "../blocks/Block";
|
||||||
|
|
||||||
|
function EPBlocksDisplay({ opts, rendered }: { opts: T.TextOptions, rendered: T.EPRendered }) {
|
||||||
|
const blocks = rendered.omitSubject
|
||||||
|
? rendered.blocks.filter(b => b.type !== "subjectSelection")
|
||||||
|
: rendered.blocks;
|
||||||
|
|
||||||
|
return <div className="d-flex flex-row justify-content-center align-items-end mt-3">
|
||||||
|
{blocks.map((block, i) => (
|
||||||
|
<div key={Math.random()} className="mr-2">
|
||||||
|
<Block opts={opts} block={block} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EPBlocksDisplay;
|
|
@ -1,17 +1,22 @@
|
||||||
import * as T from "../../types";
|
import * as T from "../../types";
|
||||||
import { completeEPSelection, renderEP } from "../../lib/phrase-building/render-ep";
|
import { completeEPSelection, renderEP } from "../../lib/phrase-building/render-ep";
|
||||||
import { compileEP } from "../../lib/phrase-building/compile";
|
import { compileEP } from "../../lib/phrase-building/compile";
|
||||||
import Examples from "../Examples";
|
|
||||||
import ButtonSelect from "../ButtonSelect";
|
import ButtonSelect from "../ButtonSelect";
|
||||||
import { getRenderedSubjectSelection, getSubjectSelection } from "../../lib/phrase-building/blocks-utils";
|
import { getPredicateSelectionFromBlocks, getSubjectSelection, getSubjectSelectionFromBlocks } from "../../lib/phrase-building/blocks-utils";
|
||||||
|
import { useState } from "react";
|
||||||
|
import EPTextDisplay from "./EPTextDisplay";
|
||||||
|
import EPBlocksDisplay from "./EPBlocksDisplay";
|
||||||
|
type Mode = "text" | "blocks";
|
||||||
|
|
||||||
function EPDisplay({ eps, opts, setOmitSubject }: {
|
function EPDisplay({ eps, opts, setOmitSubject }: {
|
||||||
eps: T.EPSelectionState,
|
eps: T.EPSelectionState,
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
setOmitSubject: (value: "true" | "false") => void,
|
setOmitSubject: (value: "true" | "false") => void,
|
||||||
}) {
|
}) {
|
||||||
|
const [mode] = useState<Mode>("text");
|
||||||
const EP = completeEPSelection(eps);
|
const EP = completeEPSelection(eps);
|
||||||
const subject = getSubjectSelection(eps.blocks);
|
const subject = getSubjectSelection(eps.blocks);
|
||||||
|
|
||||||
if (!EP) {
|
if (!EP) {
|
||||||
return <div className="lead text-center my-4">
|
return <div className="lead text-center my-4">
|
||||||
{(!subject && !eps.predicate[eps.predicate.type])
|
{(!subject && !eps.predicate[eps.predicate.type])
|
||||||
|
@ -25,9 +30,11 @@ function EPDisplay({ eps, opts, setOmitSubject }: {
|
||||||
}
|
}
|
||||||
const rendered = renderEP(EP);
|
const rendered = renderEP(EP);
|
||||||
const result = compileEP(rendered);
|
const result = compileEP(rendered);
|
||||||
const renderedSubject = getRenderedSubjectSelection(rendered.blocks).selection;
|
const renderedSubject = getSubjectSelectionFromBlocks(rendered.blocks).selection;
|
||||||
|
const renderedPredicate = getPredicateSelectionFromBlocks(rendered.blocks).selection;
|
||||||
return <div className="text-center pt-3">
|
return <div className="text-center pt-3">
|
||||||
<div className="mb-2">
|
<div className="mb-2 d-flex flex-row justify-content-between align-items-center">
|
||||||
|
{/* <ModeSelect value={mode} onChange={setMode} /> */}
|
||||||
<ButtonSelect
|
<ButtonSelect
|
||||||
small
|
small
|
||||||
value={(eps.omitSubject ? "true" : "false") as "true" | "false"}
|
value={(eps.omitSubject ? "true" : "false") as "true" | "false"}
|
||||||
|
@ -37,31 +44,28 @@ function EPDisplay({ eps, opts, setOmitSubject }: {
|
||||||
]}
|
]}
|
||||||
handleChange={setOmitSubject}
|
handleChange={setOmitSubject}
|
||||||
/>
|
/>
|
||||||
|
<div />
|
||||||
</div>
|
</div>
|
||||||
{"long" in result.ps ?
|
{mode === "text"
|
||||||
<div>
|
? <EPTextDisplay opts={opts} compiled={result} />
|
||||||
<VariationLayer vs={result.ps.long} opts={opts} />
|
: <EPBlocksDisplay opts={opts} rendered={rendered} />}
|
||||||
<VariationLayer vs={result.ps.short} opts={opts} />
|
|
||||||
{result.ps.mini && <VariationLayer vs={result.ps.mini} opts={opts} />}
|
|
||||||
</div>
|
|
||||||
: <VariationLayer vs={result.ps} opts={opts} />
|
|
||||||
}
|
|
||||||
{result.e && <div className="text-muted mt-3">
|
|
||||||
{result.e.map((e, i) => <div key={i}>{e}</div>)}
|
|
||||||
</div>}
|
|
||||||
{EP.predicate.selection.selection.type === "participle" && <div style={{ maxWidth: "6 00px", margin: "0 auto" }} className="alert alert-warning mt-3 pt-4">
|
{EP.predicate.selection.selection.type === "participle" && <div style={{ maxWidth: "6 00px", margin: "0 auto" }} className="alert alert-warning mt-3 pt-4">
|
||||||
<p>⚠️ NOTE: This means that the subject {renderedSubject.selection.e ? `(${renderedSubject.selection.e})` : ""} is <strong>the action/idea</strong> of
|
<p>⚠️ NOTE: This means that the subject {renderedSubject.selection.e ? `(${renderedSubject.selection.e})` : ""} is <strong>the action/idea</strong> of
|
||||||
{` `}
|
{` `}
|
||||||
"{rendered.predicate.selection.e ? rendered.predicate.selection.e : "the particple"}".</p>
|
"{renderedPredicate.selection.e ? renderedPredicate.selection.e : "the particple"}".</p>
|
||||||
<p>It <strong>does not</strong> mean that the subject is doing the action, which is what the transaltion sounds like in English.</p>
|
<p>It <strong>does not</strong> mean that the subject is doing the action, which is what the transaltion sounds like in English.</p>
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
function VariationLayer({ vs, opts }: { vs: T.PsString[], opts: T.TextOptions }) {
|
// function ModeSelect({ value, onChange }: { value: Mode, onChange: (m: Mode) => void }) {
|
||||||
return <div className="mb-2">
|
// return <div style={{ fontSize: "larger" }}>
|
||||||
<Examples opts={opts} lineHeight={0}>{vs}</Examples>
|
// {value === "text" ? <div className="clickable" onClick={() => onChange("blocks")}>
|
||||||
</div>;
|
// <i className="fas fa-cubes" />
|
||||||
}
|
// </div> : <div className="clickable" onClick={() => onChange("text")}>
|
||||||
|
// <i className="fas fa-align-left" />
|
||||||
|
// </div>}
|
||||||
|
// </div>;
|
||||||
|
// }
|
||||||
|
|
||||||
export default EPDisplay;
|
export default EPDisplay;
|
|
@ -38,7 +38,7 @@ function EPExplorer(props: {
|
||||||
entryFeeder: T.EntryFeeder,
|
entryFeeder: T.EntryFeeder,
|
||||||
}) {
|
}) {
|
||||||
const [mode, setMode] = useStickyState<"charts" | "phrases">("charts", "EPExplorerMode");
|
const [mode, setMode] = useStickyState<"charts" | "phrases">("charts", "EPExplorerMode");
|
||||||
const [eps, adjustEps] = useStickyReducer(epsReducer, blankEps, "EPState5", flashMessage);
|
const [eps, adjustEps] = useStickyReducer(epsReducer, blankEps, "EPState6", flashMessage);
|
||||||
const [alert, setAlert] = useState<string | undefined>(undefined);
|
const [alert, setAlert] = useState<string | undefined>(undefined);
|
||||||
const [showClipped, setShowClipped] = useState<string>("");
|
const [showClipped, setShowClipped] = useState<string>("");
|
||||||
const parent = useRef<HTMLDivElement>(null);
|
const parent = useRef<HTMLDivElement>(null);
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import * as T from "../../types";
|
||||||
|
import Examples from "../Examples";
|
||||||
|
|
||||||
|
function EPTextDisplay({ compiled, opts }: { compiled: {
|
||||||
|
ps: T.SingleOrLengthOpts<T.PsString[]>;
|
||||||
|
e?: string[] | undefined;
|
||||||
|
}, opts: T.TextOptions }) {
|
||||||
|
function VariationLayer({ vs }: { vs: T.PsString[] }) {
|
||||||
|
return <div className="mb-2">
|
||||||
|
<Examples opts={opts} lineHeight={0}>{vs}</Examples>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
return <div>
|
||||||
|
{"long" in compiled.ps ?
|
||||||
|
<div>
|
||||||
|
<VariationLayer vs={compiled.ps.long} />
|
||||||
|
<VariationLayer vs={compiled.ps.short} />
|
||||||
|
{compiled.ps.mini && <VariationLayer vs={compiled.ps.mini} />}
|
||||||
|
</div>
|
||||||
|
: <VariationLayer vs={compiled.ps} />
|
||||||
|
}
|
||||||
|
{compiled.e && <div className="text-muted mt-3">
|
||||||
|
{compiled.e.map((e, i) => <div key={i}>{e}</div>)}
|
||||||
|
</div>}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EPTextDisplay;
|
|
@ -4,7 +4,7 @@ import {
|
||||||
personNumber,
|
personNumber,
|
||||||
} from "../../lib/misc-helpers";
|
} from "../../lib/misc-helpers";
|
||||||
import { isUnisexNounEntry } from "../../lib/type-predicates";
|
import { isUnisexNounEntry } from "../../lib/type-predicates";
|
||||||
import { checkForMiniPronounsError } from "../../lib/phrase-building/compile";
|
import { checkEPForMiniPronounsError } from "../../lib/phrase-building/compile";
|
||||||
import { adjustSubjectSelection, getSubjectSelection, insertNewAP, removeAP, setAP, shiftBlock } from "../../lib/phrase-building/blocks-utils";
|
import { adjustSubjectSelection, getSubjectSelection, insertNewAP, removeAP, setAP, shiftBlock } from "../../lib/phrase-building/blocks-utils";
|
||||||
|
|
||||||
type EpsReducerAction = {
|
type EpsReducerAction = {
|
||||||
|
@ -189,7 +189,7 @@ export default function epsReducer(eps: T.EPSelectionState, action: EpsReducerAc
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureMiniPronounsOk(old: T.EPSelectionState, eps: T.EPSelectionState, sendAlert?: (msg: string) => void): T.EPSelectionState {
|
function ensureMiniPronounsOk(old: T.EPSelectionState, eps: T.EPSelectionState, sendAlert?: (msg: string) => void): T.EPSelectionState {
|
||||||
const error = checkForMiniPronounsError(eps);
|
const error = checkEPForMiniPronounsError(eps);
|
||||||
if (error) {
|
if (error) {
|
||||||
if (sendAlert) sendAlert(error);
|
if (sendAlert) sendAlert(error);
|
||||||
return old;
|
return old;
|
||||||
|
|
|
@ -106,6 +106,12 @@ function VPExplorerQuiz(props: {
|
||||||
setAnswerBlank("");
|
setAnswerBlank("");
|
||||||
setQuizState(tickQuizState(quizState.vps));
|
setQuizState(tickQuizState(quizState.vps));
|
||||||
}
|
}
|
||||||
|
if (1 < 3) {
|
||||||
|
return <div className="text-center my-4">
|
||||||
|
<h3>The quiz is broken 😭</h3>
|
||||||
|
<p>It will be fixed in like a week or two... hopefully.</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
return <div className="mt-4">
|
return <div className="mt-4">
|
||||||
<ProgressBar quizState={quizState} />
|
<ProgressBar quizState={quizState} />
|
||||||
<div className="d-flex flex-row justify-content-around flex-wrap">
|
<div className="d-flex flex-row justify-content-around flex-wrap">
|
||||||
|
@ -322,6 +328,7 @@ function tickQuizState(startingWith: T.VPSelectionComplete | QuizState): QuizSta
|
||||||
}
|
}
|
||||||
const answer = makeRes(newVps);
|
const answer = makeRes(newVps);
|
||||||
const wrongAnswers = wrongVpsS.map(makeRes);
|
const wrongAnswers = wrongVpsS.map(makeRes);
|
||||||
|
console.log({ newVps, answer, wrongAnswers });
|
||||||
const allAnswers = shuffleArray([...wrongAnswers, answer]);
|
const allAnswers = shuffleArray([...wrongAnswers, answer]);
|
||||||
const options = allAnswers.map(getOptionFromResult);
|
const options = allAnswers.map(getOptionFromResult);
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -108,6 +108,20 @@ function accentSyllable(s: string): string {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function removeAccentsWLength(s: T.SingleOrLengthOpts<T.PsString[]>): T.SingleOrLengthOpts<T.PsString[]> {
|
||||||
|
if ("long" in s) {
|
||||||
|
return {
|
||||||
|
long: removeAccentsWLength(s.long) as T.PsString[],
|
||||||
|
short: removeAccentsWLength(s.short) as T.PsString[],
|
||||||
|
...s.mini ? {
|
||||||
|
mini: removeAccentsWLength(s.mini) as T.PsString[],
|
||||||
|
} : {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return removeAccents(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function removeAccents(s: T.PsString): T.PsString;
|
export function removeAccents(s: T.PsString): T.PsString;
|
||||||
export function removeAccents(s: string): string;
|
export function removeAccents(s: string): string;
|
||||||
export function removeAccents(s: T.PsString[]): T.PsString[];
|
export function removeAccents(s: T.PsString[]): T.PsString[];
|
||||||
|
|
|
@ -28,6 +28,12 @@ export function pickPersInf<T>(s: T.OptionalPersonInflections<T>, persInf: T.Per
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getFirstSecThird(p: T.Person): 1 | 2 | 3 {
|
||||||
|
if ([0, 1, 6, 7].includes(p)) return 1;
|
||||||
|
if ([2, 3, 8, 9].includes(p)) return 2;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
// export function pickPersInf(
|
// export function pickPersInf(
|
||||||
// s: T.OptionalPersonInflections<T.LengthOptions<T.PsString>>,
|
// s: T.OptionalPersonInflections<T.LengthOptions<T.PsString>>,
|
||||||
// persInf: T.PersonInflectionsField,
|
// persInf: T.PersonInflectionsField,
|
||||||
|
|
|
@ -984,6 +984,10 @@ export function psStringFromEntry(entry: T.PsString): T.PsString {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getLength<U>(x: T.SingleOrLengthOpts<U>, length: "long" | "short"): U {
|
||||||
|
return ("long" in x) ? x[length] : x;
|
||||||
|
}
|
||||||
|
|
||||||
export function getLong<U>(x: T.SingleOrLengthOpts<U>): U {
|
export function getLong<U>(x: T.SingleOrLengthOpts<U>): U {
|
||||||
if ("long" in x) {
|
if ("long" in x) {
|
||||||
return x.long;
|
return x.long;
|
||||||
|
@ -991,6 +995,13 @@ export function getLong<U>(x: T.SingleOrLengthOpts<U>): U {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getShort<U>(a: T.SingleOrLengthOpts<U>): U {
|
||||||
|
if ("long" in a) {
|
||||||
|
return a.short;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
export function capitalizeFirstLetter(string: string) {
|
export function capitalizeFirstLetter(string: string) {
|
||||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import * as T from "../../types";
|
import * as T from "../../types";
|
||||||
|
import { getLength } from "../p-text-helpers";
|
||||||
|
|
||||||
export function getSubjectSelection(blocks: T.EPSBlockComplete[] | T.VPSBlockComplete[]): T.SubjectSelectionComplete;
|
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.VPSBlock[]): T.SubjectSelection;
|
||||||
|
@ -10,6 +11,26 @@ export function getSubjectSelection(blocks: T.EPSBlock[] | T.EPSBlockComplete[]
|
||||||
return b.block;
|
return b.block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getSubjectSelectionFromBlocks(blocks: T.Block[]): T.Rendered<T.SubjectSelectionComplete> {
|
||||||
|
const b = blocks.find(f => f.type === "subjectSelection");
|
||||||
|
if (!b || b.type !== "subjectSelection") {
|
||||||
|
throw new Error("subjectSelection not found in blocks");
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPredicateSelectionFromBlocks(blocks: T.Block[]): T.Rendered<T.PredicateSelectionComplete> {
|
||||||
|
const b = blocks.find(f => f.type === "predicateSelection");
|
||||||
|
if (!b || b.type !== "predicateSelection") {
|
||||||
|
throw new Error("predicateSelection not found in blocks");
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAPsFromBlocks(blocks: T.Block[]): T.Rendered<T.APSelection>[] {
|
||||||
|
return blocks.filter(b => b.type === "AP") as T.Rendered<T.APSelection>[];
|
||||||
|
}
|
||||||
|
|
||||||
export function getObjectSelection(blocks: T.VPSBlockComplete[]): T.ObjectSelectionComplete;
|
export function getObjectSelection(blocks: T.VPSBlockComplete[]): T.ObjectSelectionComplete;
|
||||||
export function getObjectSelection(blocks: T.VPSBlock[]): T.ObjectSelection;
|
export function getObjectSelection(blocks: T.VPSBlock[]): T.ObjectSelection;
|
||||||
export function getObjectSelection(blocks: T.VPSBlock[] | T.VPSBlockComplete[]): T.ObjectSelection | T.ObjectSelectionComplete {
|
export function getObjectSelection(blocks: T.VPSBlock[] | T.VPSBlockComplete[]): T.ObjectSelection | T.ObjectSelectionComplete {
|
||||||
|
@ -185,6 +206,29 @@ export function isNoObject(b: T.VPSBlock["block"] | T.EPSBlock["block"]): b is {
|
||||||
return !!(b && b.type === "objectSelection" && b.selection === "none");
|
return !!(b && b.type === "objectSelection" && b.selection === "none");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function specifyEquativeLength(blocks: T.Block[], length: "long" | "short"): T.Block[] {
|
||||||
|
const i = blocks.findIndex(b => b.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");
|
||||||
|
const adjusted = [...blocks];
|
||||||
|
adjusted[i] = {
|
||||||
|
...eq,
|
||||||
|
equative: {
|
||||||
|
...eq.equative,
|
||||||
|
ps: getLength(eq.equative.ps, length),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return adjusted;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hasEquativeWithLengths(blocks: T.Block[]): boolean {
|
||||||
|
const equative = blocks.find(x => x.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;
|
||||||
|
}
|
||||||
|
|
||||||
function arrayMove<X>(ar: X[], old_index: number, new_index: number): X[] {
|
function arrayMove<X>(ar: X[], old_index: number, new_index: number): X[] {
|
||||||
const arr = [...ar];
|
const arr = [...ar];
|
||||||
const new_i = (new_index >= arr.length)
|
const new_i = (new_index >= arr.length)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as T from "../../types";
|
import * as T from "../../types";
|
||||||
import {
|
import {
|
||||||
concatPsString,
|
concatPsString, getLong,
|
||||||
} from "../p-text-helpers";
|
} from "../p-text-helpers";
|
||||||
import {
|
import {
|
||||||
Segment,
|
Segment,
|
||||||
|
@ -8,7 +8,7 @@ import {
|
||||||
flattenLengths,
|
flattenLengths,
|
||||||
combineSegments,
|
combineSegments,
|
||||||
splitOffLeapfrogWord,
|
splitOffLeapfrogWord,
|
||||||
putKidsInKidsSection,
|
putKidsInKidsSection as oldPutKidsInKidsSection,
|
||||||
} from "./segment";
|
} from "./segment";
|
||||||
import {
|
import {
|
||||||
removeAccents,
|
removeAccents,
|
||||||
|
@ -25,15 +25,17 @@ import { pronouns } from "../grammar-units";
|
||||||
import { completeEPSelection, renderEP } from "./render-ep";
|
import { completeEPSelection, renderEP } from "./render-ep";
|
||||||
import { completeVPSelection } from "./vp-tools";
|
import { completeVPSelection } from "./vp-tools";
|
||||||
import { renderVP } from "./render-vp";
|
import { renderVP } from "./render-vp";
|
||||||
import { getRenderedObjectSelection, getRenderedSubjectSelection } from "./blocks-utils";
|
import { getAPsFromBlocks, getPredicateSelectionFromBlocks, getRenderedObjectSelection, getRenderedSubjectSelection, getSubjectSelectionFromBlocks, hasEquativeWithLengths, specifyEquativeLength } from "./blocks-utils";
|
||||||
|
|
||||||
const blank: T.PsString = {
|
// TODO: GET BLANKING WORKING!
|
||||||
p: "______",
|
|
||||||
f: "______",
|
// const blank: T.PsString = {
|
||||||
};
|
// p: "______",
|
||||||
|
// f: "______",
|
||||||
|
// };
|
||||||
type BlankoutOptions = { equative?: boolean, ba?: boolean, kidsSection?: boolean };
|
type BlankoutOptions = { equative?: boolean, ba?: boolean, kidsSection?: boolean };
|
||||||
|
|
||||||
const kidsBlank = makeSegment({ p: "___", f: "___" }, ["isKid"]);
|
// const kidsBlank = makeSegment({ p: "___", f: "___" }, ["isKid"]);
|
||||||
|
|
||||||
export function compileVP(VP: T.VPRendered, form: T.FormVersion): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string [] };
|
export function compileVP(VP: T.VPRendered, form: T.FormVersion): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string [] };
|
||||||
export function compileVP(VP: T.VPRendered, form: T.FormVersion, combineLengths: true): { ps: T.PsString[], e?: string [] };
|
export function compileVP(VP: T.VPRendered, form: T.FormVersion, combineLengths: true): { ps: T.PsString[], e?: string [] };
|
||||||
|
@ -80,7 +82,7 @@ function compilePs({ blocks, kids, verb: { head, rest }, VP }: CompilePsInput):
|
||||||
return removeDuplicates(verbWNegativeVersions.flatMap((verbSegments) => {
|
return removeDuplicates(verbWNegativeVersions.flatMap((verbSegments) => {
|
||||||
// for each permutation of the possible ordering of NPs and Verb + nu
|
// for each permutation of the possible ordering of NPs and Verb + nu
|
||||||
// 1. put in kids in the kids section
|
// 1. put in kids in the kids section
|
||||||
const segments = putKidsInKidsSection([...blocks, ...verbSegments], kids);
|
const segments = oldPutKidsInKidsSection([...blocks, ...verbSegments], kids);
|
||||||
// 2. space out the words properly
|
// 2. space out the words properly
|
||||||
const withProperSpaces = addSpacesBetweenSegments(segments);
|
const withProperSpaces = addSpacesBetweenSegments(segments);
|
||||||
// 3. throw it all together into a PsString for each permutation
|
// 3. throw it all together into a PsString for each permutation
|
||||||
|
@ -145,37 +147,6 @@ export function getVPSegmentsAndKids(VP: T.VPRendered, form?: T.FormVersion): {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEPSegmentsAndKids(EP: T.EPRendered, blankOut?: BlankoutOptions): { kids: Segment[], blocks: Segment[] } {
|
|
||||||
const possToShrink = findPossesivesToShrinkInEP(EP);
|
|
||||||
const blocks = EP.blocks.reduce((accum, block) => {
|
|
||||||
if (block.type === "subjectSelection") {
|
|
||||||
if (EP.omitSubject) return accum;
|
|
||||||
return [
|
|
||||||
...accum,
|
|
||||||
makeSegment(getPashtoFromRendered(block.selection, false)),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
...accum,
|
|
||||||
makeSegment(getPashtoFromRendered(block, false)),
|
|
||||||
];
|
|
||||||
}, [] as Segment[]);
|
|
||||||
const predicate = makeSegment(getPashtoFromRendered(EP.predicate, false));
|
|
||||||
return {
|
|
||||||
kids: blankOut?.kidsSection ? [kidsBlank] : orderKidsSection([
|
|
||||||
...EP.equative.hasBa
|
|
||||||
? (
|
|
||||||
blankOut?.ba ? [kidsBlank] : [makeSegment(grammarUnits.baParticle, ["isBa", "isKid"])])
|
|
||||||
: [],
|
|
||||||
...possToShrink.map(a => shrinkNP(a.np)),
|
|
||||||
]),
|
|
||||||
blocks: [
|
|
||||||
...blocks,
|
|
||||||
predicate
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function arrangeVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[], V: T.VerbRendered): Segment[][] {
|
function arrangeVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[], V: T.VerbRendered): Segment[][] {
|
||||||
const hasLeapfrog = isPerfectTense(V.tense) || isModalTense(V.tense);
|
const hasLeapfrog = isPerfectTense(V.tense) || isModalTense(V.tense);
|
||||||
const rest = (() => {
|
const rest = (() => {
|
||||||
|
@ -292,42 +263,67 @@ function arrangeVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[
|
||||||
export function compileEP(EP: T.EPRendered): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string[] };
|
export function compileEP(EP: T.EPRendered): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string[] };
|
||||||
export function compileEP(EP: T.EPRendered, combineLengths: true, blankOut?: BlankoutOptions): { ps: T.PsString[], e?: string[] };
|
export function compileEP(EP: T.EPRendered, combineLengths: true, blankOut?: BlankoutOptions): { ps: T.PsString[], e?: string[] };
|
||||||
export function compileEP(EP: T.EPRendered, combineLengths?: boolean, blankOut?: BlankoutOptions): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string[] } {
|
export function compileEP(EP: T.EPRendered, combineLengths?: boolean, blankOut?: BlankoutOptions): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string[] } {
|
||||||
const { kids, blocks } = getEPSegmentsAndKids(EP, blankOut);
|
const psResult = compileEPPs(EP.blocks, EP.kids, blankOut);
|
||||||
const equative = EP.equative.ps;
|
|
||||||
const psResult = compileEPPs({
|
|
||||||
blocks,
|
|
||||||
kids,
|
|
||||||
equative: blankOut?.equative ? [blank] : equative,
|
|
||||||
negative: EP.equative.negative,
|
|
||||||
});
|
|
||||||
return {
|
return {
|
||||||
ps: combineLengths ? flattenLengths(psResult) : psResult,
|
ps: combineLengths ? flattenLengths(psResult) : psResult,
|
||||||
e: compileEnglishEP(EP),
|
e: compileEnglishEP(EP),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function compileEPPs({ blocks, kids, equative, negative }: {
|
function compileEPPs(blocks: T.Block[], kids: T.Kid[], blankOut?: BlankoutOptions): T.SingleOrLengthOpts<T.PsString[]> {
|
||||||
blocks: Segment[],
|
if (hasEquativeWithLengths(blocks)) {
|
||||||
kids: Segment[],
|
|
||||||
equative: T.SingleOrLengthOpts<T.PsString[]>,
|
|
||||||
negative: boolean,
|
|
||||||
}): T.SingleOrLengthOpts<T.PsString[]> {
|
|
||||||
if ("long" in equative) {
|
|
||||||
return {
|
return {
|
||||||
long: compileEPPs({ blocks, kids, equative: equative.long, negative }) as T.PsString[],
|
long: compileEPPs(specifyEquativeLength(blocks, "long"), kids, blankOut) as T.PsString[],
|
||||||
short: compileEPPs({ blocks, kids, equative: equative.short, negative }) as T.PsString[],
|
short: compileEPPs(specifyEquativeLength(blocks, "short"), kids, blankOut) as T.PsString[],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const allSegments = putKidsInKidsSection([
|
const subjectPerson = getSubjectSelectionFromBlocks(blocks)
|
||||||
...blocks,
|
.selection.selection.person;
|
||||||
...negative ? [
|
const blocksWKids = putKidsInKidsSection(blocks, kids);
|
||||||
makeSegment({ p: "نه", f: "nú" }),
|
return removeDuplicates(combineIntoText(blocksWKids, subjectPerson));
|
||||||
makeSegment(removeAccents(equative))
|
}
|
||||||
] : [
|
|
||||||
makeSegment(equative),
|
function combineIntoText(pieces: (T.Block | T.Kid)[], subjectPerson: T.Person): T.PsString[] {
|
||||||
],
|
const first = pieces[0];
|
||||||
], kids);
|
const rest = pieces.slice(1);
|
||||||
return removeDuplicates(combineSegments(allSegments, "spaces"));
|
const firstPs = getPsFromPiece(first, subjectPerson);
|
||||||
|
if (!rest.length) {
|
||||||
|
return firstPs;
|
||||||
|
}
|
||||||
|
return combineIntoText(rest, subjectPerson).flatMap(r => (
|
||||||
|
firstPs.map(fPs => concatPsString(fPs, " ", r))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 === "nu") {
|
||||||
|
return [{ p: "نه", f: "nú" }];
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEngAPs(blocks: T.Block[]): string {
|
||||||
|
return getAPsFromBlocks(blocks).reduce((accum, curr) => {
|
||||||
|
const e = getEnglishFromRendered(curr);
|
||||||
|
if (!e) return accum;
|
||||||
|
return `${accum} ${e}`;
|
||||||
|
}, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEnglishAPs(blocks: (T.Rendered<T.SubjectSelectionComplete> | T.Rendered<T.APSelection> | T.RenderedVPSBlock)[]) {
|
function getEnglishAPs(blocks: (T.Rendered<T.SubjectSelectionComplete> | T.Rendered<T.APSelection> | T.RenderedVPSBlock)[]) {
|
||||||
|
@ -339,6 +335,16 @@ function getEnglishAPs(blocks: (T.Rendered<T.SubjectSelectionComplete> | T.Rende
|
||||||
}, "");
|
}, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function putKidsInKidsSection(blocks: T.Block[], kids: T.Kid[]): (T.Block | T.Kid)[] {
|
||||||
|
const first = blocks[0];
|
||||||
|
const rest = blocks.slice(1);
|
||||||
|
return [
|
||||||
|
first,
|
||||||
|
...kids,
|
||||||
|
...rest,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function mergeSegments(s1: Segment, s2: Segment, noSpace?: "no space"): Segment {
|
function mergeSegments(s1: Segment, s2: Segment, noSpace?: "no space"): Segment {
|
||||||
if (noSpace) {
|
if (noSpace) {
|
||||||
|
@ -405,10 +411,11 @@ function compileEnglishEP(EP: T.EPRendered): string[] | undefined {
|
||||||
function insertEWords(e: string, { subject, predicate, APs }: { subject: string, predicate: string, APs: string }): string {
|
function insertEWords(e: string, { subject, predicate, APs }: { subject: string, predicate: string, APs: string }): string {
|
||||||
return e.replace("$SUBJ", subject).replace("$PRED", predicate || "") + APs;
|
return e.replace("$SUBJ", subject).replace("$PRED", predicate || "") + APs;
|
||||||
}
|
}
|
||||||
const engSubjR = getRenderedSubjectSelection(EP.blocks).selection;
|
const engSubjR = getSubjectSelectionFromBlocks(EP.blocks).selection;
|
||||||
|
const engPredR = getPredicateSelectionFromBlocks(EP.blocks).selection;
|
||||||
const engSubj = getEnglishFromRendered(engSubjR);
|
const engSubj = getEnglishFromRendered(engSubjR);
|
||||||
const engPred = getEnglishFromRendered(EP.predicate);
|
const engPred = getEnglishFromRendered(engPredR);
|
||||||
const engAPs = getEnglishAPs(EP.blocks);
|
const engAPs = getEngAPs(EP.blocks);
|
||||||
// require all English parts for making the English phrase
|
// require all English parts for making the English phrase
|
||||||
const b = (EP.englishBase && engSubj && engPred)
|
const b = (EP.englishBase && engSubj && engPred)
|
||||||
? EP.englishBase.map(e => insertEWords(e, {
|
? EP.englishBase.map(e => insertEWords(e, {
|
||||||
|
@ -440,7 +447,33 @@ export function orderKidsSection(kids: Segment[]): Segment[] {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function checkForMiniPronounsError(s: T.EPSelectionState | T.VPSelectionState): undefined | string {
|
export function checkEPForMiniPronounsError(s: T.EPSelectionState): undefined | string {
|
||||||
|
function findDuplicateMiniP(mp: T.MiniPronoun[]): T.MiniPronoun | undefined {
|
||||||
|
const duplicates = mp.filter((item, index) => (
|
||||||
|
mp.findIndex(m => item.ps.p === m.ps.p) !== index
|
||||||
|
));
|
||||||
|
if (duplicates.length === 0) return undefined;
|
||||||
|
return duplicates[0];
|
||||||
|
}
|
||||||
|
const kids = (() => {
|
||||||
|
const EPS = completeEPSelection(s);
|
||||||
|
if (!EPS) return undefined;
|
||||||
|
const { kids } = renderEP(EPS);
|
||||||
|
return kids;
|
||||||
|
})();
|
||||||
|
if (!kids) return undefined;
|
||||||
|
const miniPronouns = kids.filter(x => x.type === "mini-pronoun") as T.MiniPronoun[];
|
||||||
|
if (miniPronouns.length > 2) {
|
||||||
|
return "can't add another mini-pronoun, there are alread two";
|
||||||
|
}
|
||||||
|
const duplicateMiniPronoun = findDuplicateMiniP(miniPronouns);
|
||||||
|
if (duplicateMiniPronoun) {
|
||||||
|
return `there's already a ${duplicateMiniPronoun.ps.p} - ${duplicateMiniPronoun.ps.f} mini-pronoun in use, can't have two of those`;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function checkForMiniPronounsError(s: T.VPSelectionState): undefined | string {
|
||||||
function findDuplicateMiniPronoun(mp: Segment[]): Segment | undefined {
|
function findDuplicateMiniPronoun(mp: Segment[]): Segment | undefined {
|
||||||
const duplicates = mp.filter((item, index) => (
|
const duplicates = mp.filter((item, index) => (
|
||||||
mp.findIndex(m => item.ps[0].p === m.ps[0].p) !== index
|
mp.findIndex(m => item.ps[0].p === m.ps[0].p) !== index
|
||||||
|
@ -449,12 +482,6 @@ export function checkForMiniPronounsError(s: T.EPSelectionState | T.VPSelectionS
|
||||||
return duplicates[0];
|
return duplicates[0];
|
||||||
}
|
}
|
||||||
const kids = (() => {
|
const kids = (() => {
|
||||||
if ("predicate" in s) {
|
|
||||||
const EPS = completeEPSelection(s);
|
|
||||||
if (!EPS) return undefined;
|
|
||||||
const { kids } = getEPSegmentsAndKids(renderEP(EPS));
|
|
||||||
return kids;
|
|
||||||
}
|
|
||||||
const VPS = completeVPSelection(s);
|
const VPS = completeVPSelection(s);
|
||||||
if (!VPS) return undefined;
|
if (!VPS) return undefined;
|
||||||
const { kids } = getVPSegmentsAndKids(renderVP(VPS));
|
const { kids } = getVPSegmentsAndKids(renderVP(VPS));
|
||||||
|
@ -536,44 +563,6 @@ function findPossesivesInAdjective(a: T.Rendered<T.AdjectiveSelection>): T.Rende
|
||||||
return findPossesivesInNP(a.sandwich.inside);
|
return findPossesivesInNP(a.sandwich.inside);
|
||||||
}
|
}
|
||||||
|
|
||||||
type FoundNP = {
|
|
||||||
np: T.Rendered<T.NPSelection>,
|
|
||||||
from: "subject" | "predicate" | "AP",
|
|
||||||
};
|
|
||||||
|
|
||||||
export function findPossesivesToShrinkInEP(EP: T.EPRendered): FoundNP[] {
|
|
||||||
const inBlocks: FoundNP[] = EP.blocks.reduce((accum, block): FoundNP[] => {
|
|
||||||
if (block.type === "subjectSelection") {
|
|
||||||
if (EP.omitSubject) return accum;
|
|
||||||
const found: FoundNP[] = findPossesivesInNP(block.selection).map(np => ({ np, from: "subject" }));
|
|
||||||
return [
|
|
||||||
...accum,
|
|
||||||
...found,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
if (block.selection.type === "sandwich") {
|
|
||||||
const found: FoundNP[] = findPossesivesInNP(block.selection.inside).map(np => ({ np, from: "AP" }));
|
|
||||||
return [
|
|
||||||
...accum,
|
|
||||||
...found,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return accum;
|
|
||||||
}, [] as FoundNP[]);
|
|
||||||
const inPredicate: FoundNP[] = ((EP.predicate.selection.type === "loc. adv.")
|
|
||||||
? []
|
|
||||||
: (EP.predicate.selection.type === "adjective")
|
|
||||||
? findPossesivesInAdjective(EP.predicate.selection)
|
|
||||||
: EP.predicate.selection.type === "sandwich"
|
|
||||||
? findPossesivesInNP(EP.predicate.selection.inside)
|
|
||||||
: EP.predicate.selection.type === "pronoun"
|
|
||||||
? []
|
|
||||||
: findPossesivesInNP({ type: "NP", selection: EP.predicate.selection })).map(np => ({ np, from: "predicate" }));
|
|
||||||
return [
|
|
||||||
...inBlocks,
|
|
||||||
...inPredicate,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// export function findPossesiveToShrinkInVP(VP: T.VPRendered): T.Rendered<T.NPSelection>[] {
|
// export function findPossesiveToShrinkInVP(VP: T.VPRendered): T.Rendered<T.NPSelection>[] {
|
||||||
// const obj: T.Rendered<T.NPSelection> | undefined = ("object" in VP && typeof VP.object === "object")
|
// const obj: T.Rendered<T.NPSelection> | undefined = ("object" in VP && typeof VP.object === "object")
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
getPersonFromNP,
|
getPersonFromNP,
|
||||||
} from "./vp-tools";
|
} from "./vp-tools";
|
||||||
import { renderNPSelection } from "./render-np";
|
import { renderNPSelection } from "./render-np";
|
||||||
import { getPersonFromVerbForm } from "../../lib/misc-helpers";
|
import { getFirstSecThird, getPersonFromVerbForm } from "../../lib/misc-helpers";
|
||||||
import { getVerbBlockPosFromPerson } from "../misc-helpers";
|
import { getVerbBlockPosFromPerson } from "../misc-helpers";
|
||||||
import { getEnglishWord } from "../get-english-word";
|
import { getEnglishWord } from "../get-english-word";
|
||||||
import { psStringFromEntry } from "../p-text-helpers";
|
import { psStringFromEntry } from "../p-text-helpers";
|
||||||
|
@ -12,39 +12,143 @@ import { isLocativeAdverbEntry } from "../type-predicates";
|
||||||
import { renderAdjectiveSelection } from "./render-adj";
|
import { renderAdjectiveSelection } from "./render-adj";
|
||||||
import { renderSandwich } from "./render-sandwich";
|
import { renderSandwich } from "./render-sandwich";
|
||||||
import { EPSBlocksAreComplete, getSubjectSelection } from "./blocks-utils";
|
import { EPSBlocksAreComplete, getSubjectSelection } from "./blocks-utils";
|
||||||
|
import { removeAccentsWLength } from "../accent-helpers";
|
||||||
|
import { pronouns } from "../grammar-units";
|
||||||
|
|
||||||
export function renderEP(EP: T.EPSelectionComplete): T.EPRendered {
|
export function renderEP(EP: T.EPSelectionComplete): T.EPRendered {
|
||||||
const subject = getSubjectSelection(EP.blocks).selection;
|
const { kids, blocks, englishEquativePerson } = getEPSBlocksAndKids(EP);
|
||||||
const king = (subject.selection.type === "pronoun")
|
|
||||||
? "subject"
|
|
||||||
: EP.predicate.type === "NP"
|
|
||||||
? "predicate"
|
|
||||||
: "subject";
|
|
||||||
// TODO: less repetative logic
|
|
||||||
const kingPerson = king === "subject"
|
|
||||||
? getPersonFromNP(subject)
|
|
||||||
: EP.predicate.type === "NP"
|
|
||||||
? getPersonFromNP(EP.predicate.selection)
|
|
||||||
: getPersonFromNP(subject);
|
|
||||||
const kingIsParticiple = king === "subject"
|
|
||||||
? (subject.selection.type === "participle")
|
|
||||||
: (EP.predicate.type === "NP" && EP.predicate.selection.selection.type === "participle");
|
|
||||||
return {
|
return {
|
||||||
type: "EPRendered",
|
type: "EPRendered",
|
||||||
king: EP.predicate.type === "Complement" ? "subject" : "predicate",
|
blocks,
|
||||||
blocks: renderEPSBlocks(EP.blocks, king),
|
kids,
|
||||||
predicate: EP.predicate.type === "NP"
|
|
||||||
? renderNPSelection(EP.predicate.selection, false, true, "subject", "king")
|
|
||||||
: renderEqCompSelection(EP.predicate.selection, kingPerson),
|
|
||||||
equative: renderEquative(EP.equative, kingPerson),
|
|
||||||
englishBase: equativeBuilders[EP.equative.tense](
|
englishBase: equativeBuilders[EP.equative.tense](
|
||||||
kingIsParticiple ? T.Person.ThirdSingMale : kingPerson,
|
englishEquativePerson,
|
||||||
EP.equative.negative,
|
EP.equative.negative,
|
||||||
),
|
),
|
||||||
omitSubject: EP.omitSubject,
|
omitSubject: EP.omitSubject,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getEPSBlocksAndKids(EP: T.EPSelectionComplete): { kids: T.Kid[], blocks: T.Block[], englishEquativePerson: T.Person } {
|
||||||
|
const subject = getSubjectSelection(EP.blocks).selection;
|
||||||
|
const commandingNP: T.NPSelection = subject.selection.type === "pronoun"
|
||||||
|
? subject
|
||||||
|
: EP.predicate.selection.type === "NP"
|
||||||
|
? EP.predicate.selection
|
||||||
|
: subject;
|
||||||
|
const commandingPerson = getPersonFromNP(commandingNP);
|
||||||
|
const equative: T.EquativeBlock = { type: "equative", equative: renderEquative(EP.equative, commandingPerson) };
|
||||||
|
const blocks: T.Block[] = [
|
||||||
|
...renderEPSBlocks(EP.omitSubject ? EP.blocks.filter(b => b.block.type !== "subjectSelection") : EP.blocks),
|
||||||
|
{
|
||||||
|
type: "predicateSelection",
|
||||||
|
selection: EP.predicate.selection.type === "NP"
|
||||||
|
? renderNPSelection(EP.predicate.selection, false, false, "subject", "king")
|
||||||
|
: renderEqCompSelection(EP.predicate.selection, commandingPerson),
|
||||||
|
},
|
||||||
|
...EP.equative.negative ? [{ type: "nu" } as T.Block] : [],
|
||||||
|
EP.equative.negative ? removeAccontsFromEq(equative) : equative,
|
||||||
|
];
|
||||||
|
const miniPronouns = findPossesivesToShrink([...EP.blocks, EP.predicate], EP.omitSubject);
|
||||||
|
const kids: T.Kid[] = orderKids([
|
||||||
|
...equative.equative.hasBa ? [{ type: "ba" } as T.Kid] : [],
|
||||||
|
...miniPronouns,
|
||||||
|
]);
|
||||||
|
return {
|
||||||
|
blocks,
|
||||||
|
kids,
|
||||||
|
englishEquativePerson: commandingNP.selection.type === "participle" ? T.Person.ThirdSingMale : commandingPerson,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function orderKids(kids: T.Kid[]): T.Kid[] {
|
||||||
|
const sorted = [...kids].sort((a, b) => {
|
||||||
|
// ba first
|
||||||
|
if (a.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 (aPers < bPers) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (aPers > bPers) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// TODO: is this enough?
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findPossesivesToShrink(blocks: (T.EPSBlockComplete | T.SubjectSelectionComplete | T.PredicateSelectionComplete | T.APSelection)[], omitSubject: boolean): T.MiniPronoun[] {
|
||||||
|
return blocks.reduce((kids, item) => {
|
||||||
|
const block = "block" in item ? item.block : item;
|
||||||
|
if (block.type === "subjectSelection") {
|
||||||
|
if (omitSubject) return kids;
|
||||||
|
return [
|
||||||
|
...kids,
|
||||||
|
...findShrunkenPossInNP(block.selection),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if (block.type === "AP") {
|
||||||
|
if (block.selection.type === "adverb") return kids;
|
||||||
|
return [
|
||||||
|
...kids,
|
||||||
|
...findShrunkenPossInNP(block.selection.inside),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if (block.type === "predicateSelection") {
|
||||||
|
if (block.selection.type === "EQComp") {
|
||||||
|
if (block.selection.selection.type === "sandwich") {
|
||||||
|
return [
|
||||||
|
...kids,
|
||||||
|
...findShrunkenPossInNP(block.selection.selection.inside),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return kids;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
...kids,
|
||||||
|
...findShrunkenPossInNP(block.selection),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return kids;
|
||||||
|
}, [] as T.MiniPronoun[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findShrunkenPossInNP(NP: T.NPSelection): T.MiniPronoun[] {
|
||||||
|
if (NP.selection.type === "pronoun") return [];
|
||||||
|
if (!NP.selection.possesor) return [];
|
||||||
|
if (NP.selection.type === "noun") {
|
||||||
|
if (NP.selection.adjectives) {
|
||||||
|
const { adjectives, ...rest } = NP.selection;
|
||||||
|
return [
|
||||||
|
// TODO: ability to find possesives shrinkage in sandwiches in adjectives
|
||||||
|
// ...findShrunkenPossInAdjectives(adjectives),
|
||||||
|
...findShrunkenPossInNP({ type: "NP", selection: {
|
||||||
|
...rest,
|
||||||
|
adjectives: [],
|
||||||
|
}}),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NP.selection.possesor.shrunken) {
|
||||||
|
const person = getPersonFromNP(NP.selection.possesor.np);
|
||||||
|
const miniP: T.MiniPronoun = {
|
||||||
|
type: "mini-pronoun",
|
||||||
|
person,
|
||||||
|
ps: getMiniPronounPs(person),
|
||||||
|
source: "possesive",
|
||||||
|
np: NP.selection.possesor.np,
|
||||||
|
};
|
||||||
|
return [miniP];
|
||||||
|
}
|
||||||
|
return findShrunkenPossInNP(NP.selection.possesor.np);
|
||||||
|
}
|
||||||
|
|
||||||
export function getEquativeForm(tense: T.EquativeTense): { hasBa: boolean, form: T.SingleOrLengthOpts<T.VerbBlock> } {
|
export function getEquativeForm(tense: T.EquativeTense): { hasBa: boolean, form: T.SingleOrLengthOpts<T.VerbBlock> } {
|
||||||
const hasBa = (tense === "future" || tense === "wouldBe");
|
const hasBa = (tense === "future" || tense === "wouldBe");
|
||||||
const baseTense = (tense === "future")
|
const baseTense = (tense === "future")
|
||||||
|
@ -58,7 +162,7 @@ export function getEquativeForm(tense: T.EquativeTense): { hasBa: boolean, form:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderEPSBlocks(blocks: T.EPSBlockComplete[], king: "subject" | "predicate"): (T.Rendered<T.SubjectSelectionComplete> | T.Rendered<T.APSelection>)[] {
|
function renderEPSBlocks(blocks: T.EPSBlockComplete[]): T.Block[] {
|
||||||
return blocks.map(({ block }): (T.Rendered<T.SubjectSelectionComplete> | T.Rendered<T.APSelection>) => {
|
return blocks.map(({ block }): (T.Rendered<T.SubjectSelectionComplete> | T.Rendered<T.APSelection>) => {
|
||||||
if (block.type === "AP") {
|
if (block.type === "AP") {
|
||||||
if (block.selection.type === "adverb") {
|
if (block.selection.type === "adverb") {
|
||||||
|
@ -76,7 +180,7 @@ function renderEPSBlocks(blocks: T.EPSBlockComplete[], king: "subject" | "predic
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: "subjectSelection",
|
type: "subjectSelection",
|
||||||
selection: renderNPSelection(block.selection, false, false, "subject", king === "subject" ? "king" : "none")
|
selection: renderNPSelection(block.selection, false, false, "subject", "none")
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -218,7 +322,7 @@ export function completeEPSelection(eps: T.EPSelectionState): T.EPSelectionCompl
|
||||||
...eps,
|
...eps,
|
||||||
blocks: eps.blocks,
|
blocks: eps.blocks,
|
||||||
predicate: {
|
predicate: {
|
||||||
type: "Complement",
|
type: "predicateSelection",
|
||||||
selection,
|
selection,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -230,8 +334,23 @@ export function completeEPSelection(eps: T.EPSelectionState): T.EPSelectionCompl
|
||||||
...eps,
|
...eps,
|
||||||
blocks: eps.blocks,
|
blocks: eps.blocks,
|
||||||
predicate: {
|
predicate: {
|
||||||
type: "NP",
|
type: "predicateSelection",
|
||||||
selection,
|
selection,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getMiniPronounPs(person: T.Person): T.PsString {
|
||||||
|
const [row, col] = getVerbBlockPosFromPerson(person);
|
||||||
|
return pronouns.mini[row][col][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeAccontsFromEq(equ: T.EquativeBlock): T.EquativeBlock {
|
||||||
|
return {
|
||||||
|
...equ,
|
||||||
|
equative: {
|
||||||
|
...equ.equative,
|
||||||
|
ps: removeAccentsWLength(equ.equative.ps),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
|
@ -5,8 +5,6 @@ import {
|
||||||
import {
|
import {
|
||||||
concatPsString,
|
concatPsString,
|
||||||
} from "../p-text-helpers";
|
} from "../p-text-helpers";
|
||||||
// SEGMENT TOOLS
|
|
||||||
// TODO: PULL OUT FOR SHARING ACROSS COMPILE EP ETC?
|
|
||||||
|
|
||||||
type SegmentDescriptions = {
|
type SegmentDescriptions = {
|
||||||
isVerbHead?: boolean,
|
isVerbHead?: boolean,
|
||||||
|
|
47
src/types.ts
47
src/types.ts
|
@ -552,6 +552,11 @@ export type SubjectSelectionComplete = {
|
||||||
selection: NPSelection,
|
selection: NPSelection,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type PredicateSelectionComplete = {
|
||||||
|
type: "predicateSelection",
|
||||||
|
selection: EqCompSelection | NPSelection,
|
||||||
|
};
|
||||||
|
|
||||||
export type ObjectSelectionComplete = {
|
export type ObjectSelectionComplete = {
|
||||||
type: "objectSelection",
|
type: "objectSelection",
|
||||||
selection: NPSelection | ObjectNP,
|
selection: NPSelection | ObjectNP,
|
||||||
|
@ -695,6 +700,7 @@ export type Rendered<
|
||||||
| EqCompSelection["selection"]
|
| EqCompSelection["selection"]
|
||||||
| SubjectSelectionComplete
|
| SubjectSelectionComplete
|
||||||
| ObjectSelectionComplete
|
| ObjectSelectionComplete
|
||||||
|
| PredicateSelectionComplete
|
||||||
| AdjectiveSelection
|
| AdjectiveSelection
|
||||||
| SandwichSelection<Sandwich>
|
| SandwichSelection<Sandwich>
|
||||||
> =
|
> =
|
||||||
|
@ -744,7 +750,11 @@ export type Rendered<
|
||||||
type: "objectSelection",
|
type: "objectSelection",
|
||||||
selection: Rendered<NPSelection> | Person.ThirdPlurMale | "none",
|
selection: Rendered<NPSelection> | Person.ThirdPlurMale | "none",
|
||||||
}
|
}
|
||||||
: ReplaceKey<
|
: T extends PredicateSelectionComplete
|
||||||
|
? {
|
||||||
|
type: "predicateSelection",
|
||||||
|
selection: Rendered<EqCompSelection> | Rendered<NPSelection>,
|
||||||
|
} : ReplaceKey<
|
||||||
Omit<T, "changeGender" | "changeNumber" | "changeDistance" | "adjectives" | "possesor">,
|
Omit<T, "changeGender" | "changeNumber" | "changeDistance" | "adjectives" | "possesor">,
|
||||||
"e",
|
"e",
|
||||||
string
|
string
|
||||||
|
@ -794,13 +804,7 @@ export type VPSBlockComplete = {
|
||||||
|
|
||||||
export type EPSelectionComplete = Omit<EPSelectionState, "predicate" | "blocks"> & {
|
export type EPSelectionComplete = Omit<EPSelectionState, "predicate" | "blocks"> & {
|
||||||
blocks: EPSBlockComplete[],
|
blocks: EPSBlockComplete[],
|
||||||
predicate: {
|
predicate: PredicateSelectionComplete,
|
||||||
type: "NP",
|
|
||||||
selection: NPSelection,
|
|
||||||
} | {
|
|
||||||
type: "Complement",
|
|
||||||
selection: EqCompSelection,
|
|
||||||
},
|
|
||||||
omitSubject: boolean,
|
omitSubject: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -834,10 +838,8 @@ export type EquativeRendered = EquativeSelection & {
|
||||||
|
|
||||||
export type EPRendered = {
|
export type EPRendered = {
|
||||||
type: "EPRendered",
|
type: "EPRendered",
|
||||||
king: "subject" | "predicate",
|
blocks: Block[],
|
||||||
blocks: (Rendered<SubjectSelectionComplete> | Rendered<APSelection>)[],
|
kids: Kid[],
|
||||||
predicate: Rendered<NPSelection> | Rendered<EqCompSelection>,
|
|
||||||
equative: EquativeRendered,
|
|
||||||
englishBase?: string[],
|
englishBase?: string[],
|
||||||
omitSubject: boolean,
|
omitSubject: boolean,
|
||||||
}
|
}
|
||||||
|
@ -863,3 +865,24 @@ export type EntryLookupPortal<X extends VerbEntry | DictionaryEntry> = {
|
||||||
getByTs: (ts: number) => (X | undefined),
|
getByTs: (ts: number) => (X | undefined),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type EquativeBlock = { type: "equative", equative: EquativeRendered };
|
||||||
|
|
||||||
|
export type Block =
|
||||||
|
| Rendered<SubjectSelectionComplete>
|
||||||
|
| Rendered<APSelection>
|
||||||
|
| Rendered<PredicateSelectionComplete>
|
||||||
|
| { type: "nu" }
|
||||||
|
| EquativeBlock;
|
||||||
|
|
||||||
|
export type Kid =
|
||||||
|
| { type: "ba" }
|
||||||
|
| MiniPronoun;
|
||||||
|
|
||||||
|
export type MiniPronoun = {
|
||||||
|
type: "mini-pronoun",
|
||||||
|
person: Person,
|
||||||
|
ps: PsString,
|
||||||
|
source: "servant" | "possesive",
|
||||||
|
np: NPSelection,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue