a bit of refactoring
This commit is contained in:
parent
6c53b2a896
commit
68633089f9
|
@ -69,8 +69,8 @@ export function getRandomTense(type: "basic" | "modal" | "perfect", o?: T.Perfec
|
||||||
}
|
}
|
||||||
|
|
||||||
function TensePicker({ onChange, vps, mode, locked }: {
|
function TensePicker({ onChange, vps, mode, locked }: {
|
||||||
vps: T.VPSelectionState,
|
vps: T.VPSelection,
|
||||||
onChange: (p: T.VPSelectionState) => void,
|
onChange: (p: T.VPSelection) => void,
|
||||||
mode: "charts" | "phrases" | "quiz",
|
mode: "charts" | "phrases" | "quiz",
|
||||||
locked: boolean,
|
locked: boolean,
|
||||||
}) {
|
}) {
|
||||||
|
|
|
@ -18,6 +18,9 @@ import InlinePs from "../InlinePs";
|
||||||
import { psStringEquals } from "../../lib/p-text-helpers";
|
import { psStringEquals } from "../../lib/p-text-helpers";
|
||||||
import { randFromArray } from "../../lib/misc-helpers";
|
import { randFromArray } from "../../lib/misc-helpers";
|
||||||
import playAudio from "../../lib/play-audio";
|
import playAudio from "../../lib/play-audio";
|
||||||
|
import { isVPSelectionComplete } from "../../lib/type-predicates";
|
||||||
|
import { getKingAndServant } from "../../lib/phrase-building/render-vp";
|
||||||
|
import { isPastTense } from "../../lib/phrase-building/vp-tools";
|
||||||
// import { useReward } from 'react-rewards';
|
// import { useReward } from 'react-rewards';
|
||||||
|
|
||||||
const kingEmoji = "👑";
|
const kingEmoji = "👑";
|
||||||
|
@ -35,6 +38,9 @@ const answerFeedback: CSSProperties = {
|
||||||
"transform": "translate(-50%, -50%)",
|
"transform": "translate(-50%, -50%)",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: make answerFeedback emojis appear at random translate angles a little bit
|
||||||
|
// add energy drinks?
|
||||||
|
|
||||||
// TODO: Drill Down text display options
|
// TODO: Drill Down text display options
|
||||||
|
|
||||||
// TODO: SHOW KING AND SERVANT ONCE TENSE PICKED, EVEN IF NPs not selected
|
// TODO: SHOW KING AND SERVANT ONCE TENSE PICKED, EVEN IF NPs not selected
|
||||||
|
@ -72,33 +78,25 @@ export function VPExplorer(props: {
|
||||||
getNounByTs: (ts: number) => T.NounEntry | undefined,
|
getNounByTs: (ts: number) => T.NounEntry | undefined,
|
||||||
getVerbByTs: (ts: number) => T.VerbEntry | undefined,
|
getVerbByTs: (ts: number) => T.VerbEntry | undefined,
|
||||||
})) {
|
})) {
|
||||||
const [vps, setVps] = useStickyState<T.VPSelectionState>(
|
const [vps, setVps] = useStickyState<T.VPSelection>(
|
||||||
o => makeVPSelectionState(props.verb, o),
|
savedVps => makeVPSelectionState(props.verb, savedVps),
|
||||||
"vpsState1",
|
"vpsState1",
|
||||||
);
|
);
|
||||||
const [mode, setMode] = useStickyState<"charts" | "phrases" | "quiz">("phrases", "verbExplorerMode");
|
const [mode, setMode] = useStickyState<"charts" | "phrases" | "quiz">(
|
||||||
|
savedMode => {
|
||||||
|
if (!savedMode) return "charts";
|
||||||
|
if (savedMode === "quiz") return "phrases";
|
||||||
|
return savedMode;
|
||||||
|
},
|
||||||
|
"verbExplorerMode",
|
||||||
|
);
|
||||||
const [quizState, setQuizState] = useState<QuizState | undefined>(undefined);
|
const [quizState, setQuizState] = useState<QuizState | undefined>(undefined);
|
||||||
const [showCheck, setShowCheck] = useState<boolean>(false);
|
const [showCheck, setShowCheck] = useState<boolean>(false);
|
||||||
const [currentCorrectEmoji, setCurrentCorrectEmoji] = useState<string>(randFromArray(correctEmoji));
|
const [currentCorrectEmoji, setCurrentCorrectEmoji] = useState<string>(randFromArray(correctEmoji));
|
||||||
// const { reward } = useReward('rewardId', "emoji", {
|
|
||||||
// emoji: ['🤓', '😊', '🥳', "👏", "💯", "😎", "👍"],
|
|
||||||
// lifetime: 50,
|
|
||||||
// elementCount: 10,
|
|
||||||
// elementSize: 30,
|
|
||||||
// });
|
|
||||||
useEffect(() => {
|
|
||||||
if (mode === "quiz") {
|
|
||||||
handleResetQuiz();
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, []);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setVps(o => {
|
setVps(o => {
|
||||||
if (mode === "quiz") {
|
if (mode === "quiz") {
|
||||||
const newvps = makeVPSelectionState(props.verb, o);
|
setMode("phrases");
|
||||||
const { VPS, qs } = makeQuizState(newvps);
|
|
||||||
setQuizState(qs);
|
|
||||||
return VPS;
|
|
||||||
}
|
}
|
||||||
return makeVPSelectionState(props.verb, o);
|
return makeVPSelectionState(props.verb, o);
|
||||||
});
|
});
|
||||||
|
@ -148,7 +146,10 @@ export function VPExplorer(props: {
|
||||||
}
|
}
|
||||||
function quizLock<T>(f: T) {
|
function quizLock<T>(f: T) {
|
||||||
if (mode === "quiz") {
|
if (mode === "quiz") {
|
||||||
return () => null;
|
return () => {
|
||||||
|
alert("to adjust this, get out of quiz mode");
|
||||||
|
return null;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
@ -177,8 +178,6 @@ export function VPExplorer(props: {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const verbPhrase: T.VPSelectionComplete | undefined = completeVPSelection(vps);
|
|
||||||
const VPRendered = verbPhrase && renderVP(verbPhrase);
|
|
||||||
return <div className="mt-3" style={{ maxWidth: "950px"}}>
|
return <div className="mt-3" style={{ maxWidth: "950px"}}>
|
||||||
<VerbPicker
|
<VerbPicker
|
||||||
{..."getNounByTs" in props ? {
|
{..."getNounByTs" in props ? {
|
||||||
|
@ -188,7 +187,7 @@ export function VPExplorer(props: {
|
||||||
verbs: props.verbs,
|
verbs: props.verbs,
|
||||||
}}
|
}}
|
||||||
vps={vps}
|
vps={vps}
|
||||||
onChange={setVps}
|
onChange={quizLock(setVps)}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
/>
|
/>
|
||||||
<div className="mt-2 mb-3 text-center">
|
<div className="mt-2 mb-3 text-center">
|
||||||
|
@ -211,7 +210,7 @@ export function VPExplorer(props: {
|
||||||
<div className="d-flex flex-row justify-content-around flex-wrap" style={{ marginLeft: "-0.5rem", marginRight: "-0.5rem" }}>
|
<div className="d-flex flex-row justify-content-around flex-wrap" style={{ marginLeft: "-0.5rem", marginRight: "-0.5rem" }}>
|
||||||
{mode !== "charts" && <>
|
{mode !== "charts" && <>
|
||||||
<div className="my-2">
|
<div className="my-2">
|
||||||
<div className="h5 text-center">Subject {showRole(VPRendered, "subject")}</div>
|
<div className="h5 text-center">Subject {showRole(vps, "subject")}</div>
|
||||||
<NPPicker
|
<NPPicker
|
||||||
{..."getNounByTs" in props ? {
|
{..."getNounByTs" in props ? {
|
||||||
getNounByTs: props.getNounByTs,
|
getNounByTs: props.getNounByTs,
|
||||||
|
@ -230,7 +229,7 @@ export function VPExplorer(props: {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{vps.verb && (vps.verb.object !== "none") && <div className="my-2">
|
{vps.verb && (vps.verb.object !== "none") && <div className="my-2">
|
||||||
<div className="h5 text-center">Object {showRole(VPRendered, "object")}</div>
|
<div className="h5 text-center">Object {showRole(vps, "object")}</div>
|
||||||
{(typeof vps.verb.object === "number")
|
{(typeof vps.verb.object === "number")
|
||||||
? <div className="text-muted">Unspoken 3rd Pers. Masc. Plur.</div>
|
? <div className="text-muted">Unspoken 3rd Pers. Masc. Plur.</div>
|
||||||
: <NPPicker
|
: <NPPicker
|
||||||
|
@ -261,8 +260,8 @@ export function VPExplorer(props: {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{(verbPhrase && (mode === "phrases")) &&
|
{(isVPSelectionComplete(vps) && (mode === "phrases")) &&
|
||||||
<VPDisplay VP={verbPhrase} opts={props.opts} />
|
<VPDisplay VP={vps} opts={props.opts} />
|
||||||
}
|
}
|
||||||
{(vps.verb && (mode === "charts")) && <ChartDisplay VS={vps.verb} opts={props.opts} />}
|
{(vps.verb && (mode === "charts")) && <ChartDisplay VS={vps.verb} opts={props.opts} />}
|
||||||
{(mode === "quiz" && quizState) && <div className="text-center">
|
{(mode === "quiz" && quizState) && <div className="text-center">
|
||||||
|
@ -296,18 +295,6 @@ export function VPExplorer(props: {
|
||||||
|
|
||||||
export default VPExplorer;
|
export default VPExplorer;
|
||||||
|
|
||||||
function completeVPSelection(vps: T.VPSelectionState): T.VPSelectionComplete | undefined {
|
|
||||||
if (vps.subject === undefined) return undefined
|
|
||||||
if (vps.verb.object === undefined) return undefined;
|
|
||||||
const verb = vps.verb;
|
|
||||||
return {
|
|
||||||
type: "VPSelectionComplete",
|
|
||||||
subject: vps.subject,
|
|
||||||
object: vps.verb.object,
|
|
||||||
verb,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function hasPronounConflict(subject: T.NPSelection | undefined, object: undefined | T.VerbObject): boolean {
|
function hasPronounConflict(subject: T.NPSelection | undefined, object: undefined | T.VerbObject): boolean {
|
||||||
const subjPronoun = (subject && subject.type === "pronoun") ? subject : undefined;
|
const subjPronoun = (subject && subject.type === "pronoun") ? subject : undefined;
|
||||||
const objPronoun = (object && typeof object === "object" && object.type === "pronoun") ? object : undefined;
|
const objPronoun = (object && typeof object === "object" && object.type === "pronoun") ? object : undefined;
|
||||||
|
@ -315,15 +302,19 @@ function hasPronounConflict(subject: T.NPSelection | undefined, object: undefine
|
||||||
return isInvalidSubjObjCombo(subjPronoun.person, objPronoun.person);
|
return isInvalidSubjObjCombo(subjPronoun.person, objPronoun.person);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showRole(VP: T.VPRendered | undefined, member: "subject" | "object") {
|
function showRole(VP: T.VPSelection, member: "subject" | "object") {
|
||||||
|
const roles = getKingAndServant(
|
||||||
|
isPastTense(VP.verb.tense),
|
||||||
|
VP.verb.transitivity !== "intransitive",
|
||||||
|
);
|
||||||
return VP
|
return VP
|
||||||
? <span className="ml-2">
|
? <span className="ml-2">
|
||||||
{(VP.king === member ? kingEmoji : VP.servant === member ? servantEmoji : "")}
|
{(roles.king === member ? kingEmoji : roles.servant === member ? servantEmoji : "")}
|
||||||
</span>
|
</span>
|
||||||
: "";
|
: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function switchSubjObj({ subject, verb }: T.VPSelectionState): T.VPSelectionState {
|
function switchSubjObj({ subject, verb }: T.VPSelection): T.VPSelection {
|
||||||
if (!subject|| !verb || !verb.object || !(typeof verb.object === "object")) {
|
if (!subject|| !verb || !verb.object || !(typeof verb.object === "object")) {
|
||||||
return { subject, verb };
|
return { subject, verb };
|
||||||
}
|
}
|
||||||
|
@ -336,20 +327,16 @@ function switchSubjObj({ subject, verb }: T.VPSelectionState): T.VPSelectionStat
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeQuizState(oldVps: T.VPSelectionState): { VPS: T.VPSelectionState, qs: QuizState } {
|
function makeQuizState(oldVps: T.VPSelection): { VPS: T.VPSelectionComplete, qs: QuizState } {
|
||||||
function makeRes(x: T.VPSelectionState) {
|
function makeRes(x: T.VPSelectionComplete) {
|
||||||
const y = completeVPSelection(x);
|
return compileVP(renderVP(x), { removeKing: false, shrinkServant: false });
|
||||||
if (!y) {
|
|
||||||
throw new Error("trying to make a quiz out of an incomplete VPSelection")
|
|
||||||
}
|
|
||||||
return compileVP(renderVP(y), { removeKing: false, shrinkServant: false });
|
|
||||||
}
|
}
|
||||||
const vps = getRandomVPSelection("both")(oldVps);
|
const vps = getRandomVPSelection("both")(oldVps);
|
||||||
const wrongStates: T.VPSelectionState[] = [];
|
const wrongStates: T.VPSelectionComplete[] = [];
|
||||||
// don't do the SO switches every time
|
// don't do the SO switches every time
|
||||||
const wholeTimeSOSwitch = randFromArray([true, false]);
|
const wholeTimeSOSwitch = randFromArray([true, false]);
|
||||||
[1, 2, 3].forEach(() => {
|
[1, 2, 3].forEach(() => {
|
||||||
let v: T.VPSelectionState;
|
let v: T.VPSelectionComplete;
|
||||||
do {
|
do {
|
||||||
const SOSwitch = wholeTimeSOSwitch && randFromArray([true, false]);
|
const SOSwitch = wholeTimeSOSwitch && randFromArray([true, false]);
|
||||||
// TODO: if switich subj and obj, include the tense being correct maybe
|
// TODO: if switich subj and obj, include the tense being correct maybe
|
||||||
|
@ -399,13 +386,7 @@ function getOptionFromResult(r: {
|
||||||
|
|
||||||
function getRandomVPSelection(mix: MixType = "both") {
|
function getRandomVPSelection(mix: MixType = "both") {
|
||||||
// TODO: Type safety to make sure it's safe?
|
// TODO: Type safety to make sure it's safe?
|
||||||
return ({ subject, verb }: T.VPSelectionState): T.VPSelectionState => {
|
return ({ subject, verb }: T.VPSelection): T.VPSelectionComplete => {
|
||||||
if (mix === "tenses") {
|
|
||||||
return {
|
|
||||||
subject,
|
|
||||||
verb: randomizeTense(verb, true),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const oldSubj = (subject?.type === "pronoun")
|
const oldSubj = (subject?.type === "pronoun")
|
||||||
? subject.person
|
? subject.person
|
||||||
: undefined;
|
: undefined;
|
||||||
|
@ -432,7 +413,8 @@ function getRandomVPSelection(mix: MixType = "both") {
|
||||||
person: obj,
|
person: obj,
|
||||||
};
|
};
|
||||||
const s = randSubj;
|
const s = randSubj;
|
||||||
const v: T.VerbSelection = {
|
// ensure that the verb selection is complete
|
||||||
|
const v: T.VerbSelectionComplete = {
|
||||||
...verb,
|
...verb,
|
||||||
object: (
|
object: (
|
||||||
(typeof verb.object === "object" && !(verb.object.type === "noun" && verb.object.dynamicComplement))
|
(typeof verb.object === "object" && !(verb.object.type === "noun" && verb.object.dynamicComplement))
|
||||||
|
@ -442,6 +424,12 @@ function getRandomVPSelection(mix: MixType = "both") {
|
||||||
? randObj
|
? randObj
|
||||||
: verb.object,
|
: verb.object,
|
||||||
};
|
};
|
||||||
|
if (mix === "tenses") {
|
||||||
|
return {
|
||||||
|
subject: subject !== undefined ? subject : randSubj,
|
||||||
|
verb: randomizeTense(v, true),
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
subject: s,
|
subject: s,
|
||||||
verb: randomizeTense(v, true),
|
verb: randomizeTense(v, true),
|
||||||
|
@ -449,7 +437,7 @@ function getRandomVPSelection(mix: MixType = "both") {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
function randomizeTense(verb: T.VerbSelection, dontRepeatTense: boolean): T.VerbSelection {
|
function randomizeTense(verb: T.VerbSelectionComplete, dontRepeatTense: boolean): T.VerbSelectionComplete {
|
||||||
return {
|
return {
|
||||||
...verb,
|
...verb,
|
||||||
tense: getRandomTense(
|
tense: getRandomTense(
|
||||||
|
|
|
@ -9,8 +9,8 @@ import useStickyState from "../../lib/useStickyState";
|
||||||
// TODO: dark on past tense selecitons
|
// TODO: dark on past tense selecitons
|
||||||
|
|
||||||
function VerbPicker(props: {
|
function VerbPicker(props: {
|
||||||
vps: T.VPSelectionState,
|
vps: T.VPSelection,
|
||||||
onChange: (p: T.VPSelectionState) => void,
|
onChange: (p: T.VPSelection) => void,
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
}) {
|
}) {
|
||||||
const [showRootsAndStems, setShowRootsAndStems] = useStickyState<boolean>(false, "showRootsAndStems");
|
const [showRootsAndStems, setShowRootsAndStems] = useStickyState<boolean>(false, "showRootsAndStems");
|
||||||
|
@ -31,18 +31,13 @@ function VerbPicker(props: {
|
||||||
props.onChange({
|
props.onChange({
|
||||||
...props.vps,
|
...props.vps,
|
||||||
subject: props.vps.verb.object,
|
subject: props.vps.verb.object,
|
||||||
})
|
});
|
||||||
}
|
} else {
|
||||||
if (value === "active") {
|
|
||||||
props.onChange({
|
props.onChange({
|
||||||
...props.vps,
|
...props.vps,
|
||||||
subject: undefined,
|
verb: props.vps.verb.changeVoice(value, value === "active" ? props.vps.subject : undefined),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
props.onChange({
|
|
||||||
...props.vps,
|
|
||||||
verb: props.vps.verb.changeVoice(value, value === "active" ? props.vps.subject : undefined),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function notInstransitive(t: "transitive" | "intransitive" | "grammatically transitive"): "transitive" | "grammatically transitive" {
|
function notInstransitive(t: "transitive" | "intransitive" | "grammatically transitive"): "transitive" | "grammatically transitive" {
|
||||||
|
|
|
@ -7,8 +7,8 @@ import { isPerfectTense } from "../../lib/phrase-building/vp-tools";
|
||||||
|
|
||||||
export function makeVPSelectionState(
|
export function makeVPSelectionState(
|
||||||
verb: T.VerbEntry,
|
verb: T.VerbEntry,
|
||||||
os?: T.VPSelectionState,
|
os?: T.VPSelection,
|
||||||
): T.VPSelectionState {
|
): T.VPSelection {
|
||||||
const info = getVerbInfo(verb.entry, verb.complement);
|
const info = getVerbInfo(verb.entry, verb.complement);
|
||||||
const subject = (os?.verb.voice === "passive" && info.type === "dynamic compound")
|
const subject = (os?.verb.voice === "passive" && info.type === "dynamic compound")
|
||||||
? makeNounSelection(info.objComplement.entry as T.NounEntry, true)
|
? makeNounSelection(info.objComplement.entry as T.NounEntry, true)
|
||||||
|
|
|
@ -30,18 +30,20 @@ import { renderEnglishVPBase } from "./english-vp-rendering";
|
||||||
export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
|
export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
|
||||||
// Sentence Rules Logic
|
// Sentence Rules Logic
|
||||||
const isPast = isPastTense(VP.verb.tense);
|
const isPast = isPastTense(VP.verb.tense);
|
||||||
const isTransitive = VP.object !== "none";
|
const isTransitive = VP.verb.object !== "none";
|
||||||
const { king, servant } = getKingAndServant(isPast, isTransitive);
|
const { king, servant } = getKingAndServant(isPast, isTransitive);
|
||||||
const kingPerson = getPersonFromNP(VP[king]);
|
const kingPerson = getPersonFromNP(
|
||||||
|
king === "subject" ? VP.subject : VP.verb.object,
|
||||||
|
);
|
||||||
// TODO: more elegant way of handling this type safety
|
// TODO: more elegant way of handling this type safety
|
||||||
if (kingPerson === undefined) {
|
if (kingPerson === undefined) {
|
||||||
throw new Error("king of sentance does not exist");
|
throw new Error("king of sentance does not exist");
|
||||||
}
|
}
|
||||||
const subjectPerson = getPersonFromNP(VP.subject);
|
const subjectPerson = getPersonFromNP(VP.subject);
|
||||||
const objectPerson = getPersonFromNP(VP.object);
|
const objectPerson = getPersonFromNP(VP.verb.object);
|
||||||
// TODO: also don't inflect if it's a pattern one animate noun
|
// TODO: also don't inflect if it's a pattern one animate noun
|
||||||
const inflectSubject = isPast && isTransitive && !isMascSingAnimatePattern4(VP.subject);
|
const inflectSubject = isPast && isTransitive && !isMascSingAnimatePattern4(VP.subject);
|
||||||
const inflectObject = !isPast && isFirstOrSecondPersPronoun(VP.object);
|
const inflectObject = !isPast && isFirstOrSecondPersPronoun(VP.verb.object);
|
||||||
// Render Elements
|
// Render Elements
|
||||||
return {
|
return {
|
||||||
type: "VPRendered",
|
type: "VPRendered",
|
||||||
|
@ -51,11 +53,11 @@ export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
|
||||||
isTransitive,
|
isTransitive,
|
||||||
isCompound: VP.verb.isCompound,
|
isCompound: VP.verb.isCompound,
|
||||||
subject: renderNPSelection(VP.subject, inflectSubject, false, "subject"),
|
subject: renderNPSelection(VP.subject, inflectSubject, false, "subject"),
|
||||||
object: renderNPSelection(VP.object, inflectObject, true, "object"),
|
object: renderNPSelection(VP.verb.object, inflectObject, true, "object"),
|
||||||
verb: renderVerbSelection(VP.verb, kingPerson, objectPerson),
|
verb: renderVerbSelection(VP.verb, kingPerson, objectPerson),
|
||||||
englishBase: renderEnglishVPBase({
|
englishBase: renderEnglishVPBase({
|
||||||
subjectPerson,
|
subjectPerson,
|
||||||
object: VP.verb.isCompound === "dynamic" ? "none" : VP.object,
|
object: VP.verb.isCompound === "dynamic" ? "none" : VP.verb.object,
|
||||||
vs: VP.verb,
|
vs: VP.verb,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
@ -300,7 +302,7 @@ function getInf(infs: T.InflectorOutput, t: "plural" | "arabicPlural" | "inflect
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getKingAndServant(isPast: boolean, isTransitive: boolean):
|
export function getKingAndServant(isPast: boolean, isTransitive: boolean):
|
||||||
{ king: "subject", servant: "object" } |
|
{ king: "subject", servant: "object" } |
|
||||||
{ king: "object", servant: "subject" } |
|
{ king: "object", servant: "subject" } |
|
||||||
{ king: "subject", servant: undefined } {
|
{ king: "subject", servant: undefined } {
|
||||||
|
|
|
@ -159,3 +159,10 @@ export function isSingularEntry<U extends T.NounEntry>(e: U): e is T.SingularEnt
|
||||||
export function isArrayOneOrMore<U>(a: U[]): a is T.ArrayOneOrMore<U> {
|
export function isArrayOneOrMore<U>(a: U[]): a is T.ArrayOneOrMore<U> {
|
||||||
return a.length > 0;
|
return a.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isVPSelectionComplete(vps: T.VPSelection | T.VPSelectionComplete): vps is T.VPSelectionComplete {
|
||||||
|
if ((vps.subject !== undefined) && (vps.verb.object !== undefined)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -536,16 +536,18 @@ export type NounNumber = "singular" | "plural";
|
||||||
|
|
||||||
export type PerfectTense = `${EquativeTense} perfect`;
|
export type PerfectTense = `${EquativeTense} perfect`;
|
||||||
|
|
||||||
export type VPSelectionState = {
|
export type VPSelection = {
|
||||||
subject: NPSelection | undefined,
|
subject: NPSelection | undefined,
|
||||||
verb: VerbSelection,
|
verb: VerbSelection,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type VPSelectionComplete = {
|
export type VPSelectionComplete = {
|
||||||
type: "VPSelectionComplete",
|
|
||||||
subject: NPSelection,
|
subject: NPSelection,
|
||||||
|
verb: VerbSelectionComplete,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type VerbSelectionComplete = Exclude<VerbSelection, "object"> & {
|
||||||
object: Exclude<VerbObject, undefined>,
|
object: Exclude<VerbObject, undefined>,
|
||||||
verb: Exclude<VerbSelection, "object">,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type VerbSelection = {
|
export type VerbSelection = {
|
||||||
|
|
Loading…
Reference in New Issue