proper quizzin
This commit is contained in:
parent
a2a0200a38
commit
3f58fb6bef
|
@ -87,6 +87,10 @@ function App() {
|
||||||
if (transitivity === "grammatically transitive") {
|
if (transitivity === "grammatically transitive") {
|
||||||
setVerbTypeShowing("simple");
|
setVerbTypeShowing("simple");
|
||||||
}
|
}
|
||||||
|
if (transitivity === "intransitive" && verbTypeShowing === "dynamic compound") {
|
||||||
|
setTransitivityShowing("transitive");
|
||||||
|
return;
|
||||||
|
}
|
||||||
setTransitivityShowing(e.target.value as T.Transitivity);
|
setTransitivityShowing(e.target.value as T.Transitivity);
|
||||||
}
|
}
|
||||||
const isRegularVerb = (entry: T.DictionaryEntry): boolean => (
|
const isRegularVerb = (entry: T.DictionaryEntry): boolean => (
|
||||||
|
|
|
@ -6,7 +6,7 @@ import * as T from "../../types";
|
||||||
import ButtonSelect from "../ButtonSelect";
|
import ButtonSelect from "../ButtonSelect";
|
||||||
import { isPerfectTense } from "../../lib/phrase-building/vp-tools";
|
import { isPerfectTense } from "../../lib/phrase-building/vp-tools";
|
||||||
|
|
||||||
const tenseOptions: { label: string | JSX.Element, value: T.VerbTense }[] = [{
|
const verbTenseOptions: { label: string | JSX.Element, value: T.VerbTense }[] = [{
|
||||||
label: <div><i className="fas fa-video mr-2" />present</div>,
|
label: <div><i className="fas fa-video mr-2" />present</div>,
|
||||||
value: "presentVerb",
|
value: "presentVerb",
|
||||||
}, {
|
}, {
|
||||||
|
@ -55,34 +55,53 @@ const perfectTenseOptions: { label: string | JSX.Element, value: T.PerfectTense
|
||||||
value: "pastSubjunctive perfect",
|
value: "pastSubjunctive perfect",
|
||||||
}];
|
}];
|
||||||
|
|
||||||
function TensePicker({ onChange, verb, mode }: {
|
export function getRandomTense(type: "basic" | "modal", o?: T.VerbTense): T.VerbTense;
|
||||||
verb: T.VerbSelection,
|
export function getRandomTense(type: "perfect", o?: T.PerfectTense | T.VerbTense): T.PerfectTense;
|
||||||
onChange: (p: T.VerbSelection) => void,
|
export function getRandomTense(type: "basic" | "modal" | "perfect", o?: T.PerfectTense | T.VerbTense): T.PerfectTense | T.VerbTense {
|
||||||
|
let tns: T.PerfectTense | T.VerbTense;
|
||||||
|
const tenseOptions = type === "perfect" ? perfectTenseOptions : verbTenseOptions;
|
||||||
|
do {
|
||||||
|
tns = tenseOptions[
|
||||||
|
Math.floor(Math.random()*tenseOptions.length)
|
||||||
|
].value;
|
||||||
|
} while (o === tns);
|
||||||
|
return tns;
|
||||||
|
}
|
||||||
|
|
||||||
|
function TensePicker({ onChange, vps, mode }: {
|
||||||
|
vps: T.VPSelectionState,
|
||||||
|
onChange: (p: T.VPSelectionState) => void,
|
||||||
mode: "charts" | "phrases" | "quiz",
|
mode: "charts" | "phrases" | "quiz",
|
||||||
}) {
|
}) {
|
||||||
function onTenseSelect(o: { value: T.VerbTense | T.PerfectTense } | null) {
|
function onTenseSelect(o: { value: T.VerbTense | T.PerfectTense } | null) {
|
||||||
const value = o?.value ? o.value : undefined;
|
const value = o?.value ? o.value : undefined;
|
||||||
if (verb && value) {
|
if (vps.verb && value) {
|
||||||
if (isPerfectTense(value)) {
|
if (isPerfectTense(value)) {
|
||||||
onChange({
|
onChange({
|
||||||
...verb,
|
...vps,
|
||||||
tense: value,
|
verb: {
|
||||||
tenseCategory: "perfect",
|
...vps.verb,
|
||||||
|
tense: value,
|
||||||
|
tenseCategory: "perfect",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
onChange({
|
onChange({
|
||||||
...verb,
|
...vps,
|
||||||
tense: value,
|
verb: {
|
||||||
tenseCategory: verb.tenseCategory === "perfect" ? "basic" : verb.tenseCategory,
|
...vps.verb,
|
||||||
|
tense: value,
|
||||||
|
tenseCategory: vps.verb.tenseCategory === "perfect" ? "basic" : vps.verb.tenseCategory,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function moveTense(dir: "forward" | "back") {
|
function moveTense(dir: "forward" | "back") {
|
||||||
if (!verb) return;
|
if (!vps.verb) return;
|
||||||
return () => {
|
return () => {
|
||||||
const tenses = verb.tenseCategory === "perfect" ? perfectTenseOptions : tenseOptions;
|
const tenses = vps.verb.tenseCategory === "perfect" ? perfectTenseOptions : verbTenseOptions;
|
||||||
const currIndex = tenses.findIndex(tn => tn.value === verb.tense)
|
const currIndex = tenses.findIndex(tn => tn.value === vps.verb.tense)
|
||||||
if (currIndex === -1) {
|
if (currIndex === -1) {
|
||||||
console.error("error moving tense", dir);
|
console.error("error moving tense", dir);
|
||||||
return;
|
return;
|
||||||
|
@ -95,39 +114,48 @@ function TensePicker({ onChange, verb, mode }: {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function onPosNegSelect(value: string) {
|
function onPosNegSelect(value: string) {
|
||||||
if (verb) {
|
if (vps.verb) {
|
||||||
onChange({
|
onChange({
|
||||||
...verb,
|
...vps,
|
||||||
negative: value === "true",
|
verb: {
|
||||||
|
...vps.verb,
|
||||||
|
negative: value === "true",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function onTenseCategorySelect(value: "basic" | "modal" | "perfect") {
|
function onTenseCategorySelect(value: "basic" | "modal" | "perfect") {
|
||||||
if (verb) {
|
if (vps.verb) {
|
||||||
if (value === "perfect") {
|
if (value === "perfect") {
|
||||||
onChange({
|
onChange({
|
||||||
...verb,
|
...vps,
|
||||||
tenseCategory: value,
|
verb: {
|
||||||
tense: isPerfectTense(verb.tense) ? verb.tense : "present perfect",
|
...vps.verb,
|
||||||
|
tenseCategory: value,
|
||||||
|
tense: isPerfectTense(vps.verb.tense) ? vps.verb.tense : "present perfect",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
onChange({
|
onChange({
|
||||||
...verb,
|
...vps,
|
||||||
tenseCategory: value,
|
verb: {
|
||||||
tense: isPerfectTense(verb.tense) ? "presentVerb" : verb.tense,
|
...vps.verb,
|
||||||
|
tenseCategory: value,
|
||||||
|
tense: isPerfectTense(vps.verb.tense) ? "presentVerb" : vps.verb.tense,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const tOptions = (verb?.tenseCategory === "perfect") ? perfectTenseOptions : tenseOptions;
|
const tOptions = (vps.verb?.tenseCategory === "perfect") ? perfectTenseOptions : verbTenseOptions;
|
||||||
return <div>
|
return <div>
|
||||||
<div style={{ maxWidth: "300px", minWidth: "250px", margin: "0 auto" }}>
|
<div style={{ maxWidth: "300px", minWidth: "250px", margin: "0 auto" }}>
|
||||||
<div className="d-flex flex-row justify-content-between align-items-center">
|
<div className="d-flex flex-row justify-content-between align-items-center">
|
||||||
<div className="h5">Tense:</div>
|
<div className="h5">Tense:</div>
|
||||||
{verb && <div className="mb-2">
|
{vps.verb && <div className="mb-2">
|
||||||
<ButtonSelect
|
<ButtonSelect
|
||||||
small
|
small
|
||||||
value={verb.tenseCategory}
|
value={vps.verb.tenseCategory}
|
||||||
options={[{
|
options={[{
|
||||||
label: "Basic",
|
label: "Basic",
|
||||||
value: "basic",
|
value: "basic",
|
||||||
|
@ -145,19 +173,19 @@ function TensePicker({ onChange, verb, mode }: {
|
||||||
<Select
|
<Select
|
||||||
isSearchable={false}
|
isSearchable={false}
|
||||||
// for some reason can't use tOptions with find here;
|
// for some reason can't use tOptions with find here;
|
||||||
value={verb && ([...tenseOptions, ...perfectTenseOptions].find(o => o.value === verb.tense))}
|
value={vps.verb && ([...verbTenseOptions, ...perfectTenseOptions].find(o => o.value === vps.verb.tense))}
|
||||||
onChange={onTenseSelect}
|
onChange={onTenseSelect}
|
||||||
className="mb-2"
|
className="mb-2"
|
||||||
options={tOptions}
|
options={tOptions}
|
||||||
{...zIndexProps}
|
{...zIndexProps}
|
||||||
/>
|
/>
|
||||||
{verb && <div className="d-flex flex-row justify-content-between align-items-center mt-3 mb-1" style={{ width: "100%" }}>
|
{vps.verb && <div className="d-flex flex-row justify-content-between align-items-center mt-3 mb-1" style={{ width: "100%" }}>
|
||||||
<div className="btn btn-light clickable" onClick={moveTense("back")}>
|
<div className="btn btn-light clickable" onClick={moveTense("back")}>
|
||||||
<i className="fas fa-chevron-left" />
|
<i className="fas fa-chevron-left" />
|
||||||
</div>
|
</div>
|
||||||
{mode !== "charts" && <ButtonSelect
|
{mode !== "charts" && <ButtonSelect
|
||||||
small
|
small
|
||||||
value={verb.negative.toString()}
|
value={vps.verb.negative.toString()}
|
||||||
options={[{
|
options={[{
|
||||||
label: "Pos.",
|
label: "Pos.",
|
||||||
value: "false",
|
value: "false",
|
||||||
|
|
|
@ -5,7 +5,7 @@ import AbbreviationFormSelector from "./AbbreviationFormSelector";
|
||||||
import { isPastTense } from "../../lib/phrase-building/vp-tools";
|
import { isPastTense } from "../../lib/phrase-building/vp-tools";
|
||||||
import { useStickyState } from "../../library";
|
import { useStickyState } from "../../library";
|
||||||
|
|
||||||
function VPDisplay({ VP, opts }: { VP: T.VPSelection, opts: T.TextOptions }) {
|
function VPDisplay({ VP, opts }: { VP: T.VPSelectionComplete, opts: T.TextOptions }) {
|
||||||
const [form, setForm] = useStickyState<T.FormVersion>({ removeKing: false, shrinkServant: false }, "abbreviationForm");
|
const [form, setForm] = useStickyState<T.FormVersion>({ removeKing: false, shrinkServant: false }, "abbreviationForm");
|
||||||
const [OSV, setOSV] = useStickyState<boolean>(false, "includeOSV");
|
const [OSV, setOSV] = useStickyState<boolean>(false, "includeOSV");
|
||||||
const result = compileVP(renderVP(VP), { ...form, OSV });
|
const result = compileVP(renderVP(VP), { ...form, OSV });
|
||||||
|
@ -46,7 +46,7 @@ function VPDisplay({ VP, opts }: { VP: T.VPSelection, opts: T.TextOptions }) {
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
function whatsAdjustable(VP: T.VPSelection): "both" | "king" | "servant" {
|
function whatsAdjustable(VP: T.VPSelectionComplete): "both" | "king" | "servant" {
|
||||||
// TODO: intransitive dynamic compounds?
|
// TODO: intransitive dynamic compounds?
|
||||||
return (VP.verb.isCompound === "dynamic" && VP.verb.transitivity === "transitive")
|
return (VP.verb.isCompound === "dynamic" && VP.verb.transitivity === "transitive")
|
||||||
? (isPastTense(VP.verb.tense) ? "servant" : "king")
|
? (isPastTense(VP.verb.tense) ? "servant" : "king")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import NPPicker from "../np-picker/NPPicker";
|
import NPPicker from "../np-picker/NPPicker";
|
||||||
import VerbPicker from "./VerbPicker";
|
import VerbPicker from "./VerbPicker";
|
||||||
import TensePicker from "./TensePicker";
|
import TensePicker, { getRandomTense } from "./TensePicker";
|
||||||
import VPDisplay from "./VPDisplay";
|
import VPDisplay from "./VPDisplay";
|
||||||
import ButtonSelect from "../ButtonSelect";
|
import ButtonSelect from "../ButtonSelect";
|
||||||
import { renderVP } from "../../lib/phrase-building/index";
|
import { renderVP } from "../../lib/phrase-building/index";
|
||||||
|
@ -10,7 +10,7 @@ import {
|
||||||
import * as T from "../../types";
|
import * as T from "../../types";
|
||||||
import ChartDisplay from "./ChartDisplay";
|
import ChartDisplay from "./ChartDisplay";
|
||||||
import useStickyState from "../../lib/useStickyState";
|
import useStickyState from "../../lib/useStickyState";
|
||||||
import { makeVerbSelection } from "./verb-selection";
|
import { makeVPSelectionState } from "./verb-selection";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { randomSubjObj } from "../../library";
|
import { randomSubjObj } from "../../library";
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ const servantEmoji = "🙇♂️";
|
||||||
// TODO: option to show 3 modes Phrases - Charts - Quiz
|
// TODO: option to show 3 modes Phrases - Charts - Quiz
|
||||||
|
|
||||||
// TODO: error handling on error with rendering etc
|
// TODO: error handling on error with rendering etc
|
||||||
|
type MixState = "NPs" | "tenses" | "both";
|
||||||
|
|
||||||
export function VPExplorer(props: {
|
export function VPExplorer(props: {
|
||||||
verb: T.VerbEntry,
|
verb: T.VerbEntry,
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
|
@ -41,35 +43,22 @@ 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,
|
||||||
})) {
|
})) {
|
||||||
console.log("passedVerb", props.verb);
|
const [vps, setVps] = useStickyState<T.VPSelectionState>(
|
||||||
const [subject, setSubject] = useStickyState<T.NPSelection | undefined>(undefined, "subjectNPSelection");
|
o => makeVPSelectionState(props.verb, o),
|
||||||
// not quite working with stickyState
|
"vpsState1",
|
||||||
|
);
|
||||||
const [mode, setMode] = useStickyState<"charts" | "phrases" | "quiz">("phrases", "verbExplorerMode");
|
const [mode, setMode] = useStickyState<"charts" | "phrases" | "quiz">("phrases", "verbExplorerMode");
|
||||||
|
const [mix, setMix] = useStickyState<MixState>("NPs", "mixState1");
|
||||||
const [showAnswer, setShowAnswer] = useState<boolean>(false);
|
const [showAnswer, setShowAnswer] = useState<boolean>(false);
|
||||||
// this isn't quite working
|
|
||||||
// const [verb, setVerb] = useStickyState<T.VerbSelection | undefined>(
|
|
||||||
// passedVerb
|
|
||||||
// ? (old) => makeVerbSelection(passedVerb, setSubject, old)
|
|
||||||
// : undefined,
|
|
||||||
// "verbExplorerVerb",
|
|
||||||
// );
|
|
||||||
const [verb, setVerb] = useState<T.VerbSelection>(
|
|
||||||
makeVerbSelection(props.verb, setSubject)
|
|
||||||
)
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mode === "quiz") {
|
setVps(o => {
|
||||||
if (!verb) setMode("phrases");
|
if (mode === "quiz") {
|
||||||
handleResetQuiz();
|
return setRandomQuizState(mix)(
|
||||||
}
|
makeVPSelectionState(props.verb, o)
|
||||||
// TODO: better system with all this
|
);
|
||||||
// eslint-disable-next-line
|
}
|
||||||
}, []);
|
return makeVPSelectionState(props.verb, o);
|
||||||
useEffect(() => {
|
});
|
||||||
setVerb(o => makeVerbSelection(props.verb, setSubject, o));
|
|
||||||
if (mode === "quiz") {
|
|
||||||
// TODO: Better
|
|
||||||
setMode("charts");
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, [props.verb]);
|
}, [props.verb]);
|
||||||
function handleChangeMode(m: "charts" | "phrases" | "quiz") {
|
function handleChangeMode(m: "charts" | "phrases" | "quiz") {
|
||||||
|
@ -78,46 +67,42 @@ export function VPExplorer(props: {
|
||||||
}
|
}
|
||||||
setMode(m);
|
setMode(m);
|
||||||
}
|
}
|
||||||
function handleSetVerb(v: T.VerbSelection) {
|
|
||||||
if (v?.verb.entry.ts !== verb?.verb.entry.ts) {
|
|
||||||
handleResetQuiz();
|
|
||||||
}
|
|
||||||
setVerb(v);
|
|
||||||
}
|
|
||||||
function handleResetQuiz() {
|
function handleResetQuiz() {
|
||||||
if (!verb) {
|
if (!vps.verb) {
|
||||||
alert("Choose a verb to quiz");
|
alert("Choose a verb to quiz");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { S, V } = setRandomQuizState(subject, verb);
|
|
||||||
setShowAnswer(false);
|
setShowAnswer(false);
|
||||||
setSubject(S);
|
setVps(setRandomQuizState(mix));
|
||||||
setVerb(V);
|
|
||||||
}
|
}
|
||||||
function handleSubjectChange(subject: T.NPSelection | undefined, skipPronounConflictCheck?: boolean) {
|
function handleSubjectChange(subject: T.NPSelection | undefined, skipPronounConflictCheck?: boolean) {
|
||||||
if (!skipPronounConflictCheck && hasPronounConflict(subject, verb?.object)) {
|
if (!skipPronounConflictCheck && hasPronounConflict(subject, vps.verb?.object)) {
|
||||||
alert("That combination of pronouns is not allowed");
|
alert("That combination of pronouns is not allowed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setSubject(subject);
|
setVps(o => ({ ...o, subject }));
|
||||||
}
|
}
|
||||||
function handleObjectChange(object: T.NPSelection | undefined) {
|
function handleObjectChange(object: T.NPSelection | undefined) {
|
||||||
if (!verb) return;
|
if (!vps.verb) return;
|
||||||
if ((verb.object === "none") || (typeof verb.object === "number")) return;
|
if ((vps.verb.object === "none") || (typeof vps.verb.object === "number")) return;
|
||||||
// check for pronoun conflict
|
// check for pronoun conflict
|
||||||
if (hasPronounConflict(subject, object)) {
|
if (hasPronounConflict(vps.subject, object)) {
|
||||||
alert("That combination of pronouns is not allowed");
|
alert("That combination of pronouns is not allowed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setVerb({ ...verb, object });
|
setVps(o => ({
|
||||||
|
...o,
|
||||||
|
verb: {
|
||||||
|
...o.verb,
|
||||||
|
object,
|
||||||
|
},
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
function handleSubjObjSwap() {
|
function handleSubjObjSwap() {
|
||||||
if (verb?.isCompound === "dynamic") return;
|
if (vps.verb?.isCompound === "dynamic") return;
|
||||||
const output = switchSubjObj({ subject, verb });
|
setVps(switchSubjObj)
|
||||||
setSubject(output.subject);
|
|
||||||
setVerb(output.verb);
|
|
||||||
}
|
}
|
||||||
const verbPhrase: T.VPSelection | undefined = verbPhraseComplete({ subject, verb });
|
const verbPhrase: T.VPSelectionComplete | undefined = completeVPSelection(vps);
|
||||||
const VPRendered = verbPhrase && renderVP(verbPhrase);
|
const VPRendered = verbPhrase && renderVP(verbPhrase);
|
||||||
return <div className="mt-3" style={{ maxWidth: "950px"}}>
|
return <div className="mt-3" style={{ maxWidth: "950px"}}>
|
||||||
<VerbPicker
|
<VerbPicker
|
||||||
|
@ -127,11 +112,8 @@ export function VPExplorer(props: {
|
||||||
} : {
|
} : {
|
||||||
verbs: props.verbs,
|
verbs: props.verbs,
|
||||||
}}
|
}}
|
||||||
verbLocked={!!props.verb}
|
vps={vps}
|
||||||
verb={verb}
|
onChange={setVps}
|
||||||
subject={subject}
|
|
||||||
changeSubject={(s) => handleSubjectChange(s, true)}
|
|
||||||
onChange={handleSetVerb}
|
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
/>
|
/>
|
||||||
<div className="mt-2 mb-3 text-center">
|
<div className="mt-2 mb-3 text-center">
|
||||||
|
@ -145,7 +127,20 @@ export function VPExplorer(props: {
|
||||||
handleChange={handleChangeMode}
|
handleChange={handleChangeMode}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{(verb && (typeof verb.object === "object") && (verb.isCompound !== "dynamic") && (mode === "phrases")) &&
|
{mode === "quiz" && <div className="mt-2 mb-3 d-flex flex-row justify-content-center align-items-center">
|
||||||
|
<div className="mr-2">Mix:</div>
|
||||||
|
<ButtonSelect
|
||||||
|
small
|
||||||
|
value={mix}
|
||||||
|
options={[
|
||||||
|
{ label: "NPs", value: "NPs" },
|
||||||
|
{ label: "Tenses", value: "tenses" },
|
||||||
|
{ label: "Both", value: "both" },
|
||||||
|
]}
|
||||||
|
handleChange={setMix}
|
||||||
|
/>
|
||||||
|
</div>}
|
||||||
|
{(vps.verb && (typeof vps.verb.object === "object") && (vps.verb.isCompound !== "dynamic") && (mode === "phrases")) &&
|
||||||
<div className="text-center mt-4">
|
<div className="text-center mt-4">
|
||||||
<button onClick={handleSubjObjSwap} className="btn btn-sm btn-light">
|
<button onClick={handleSubjObjSwap} className="btn btn-sm btn-light">
|
||||||
<i className="fas fa-exchange-alt mr-2" /> subj/obj
|
<i className="fas fa-exchange-alt mr-2" /> subj/obj
|
||||||
|
@ -165,16 +160,16 @@ export function VPExplorer(props: {
|
||||||
nouns: props.nouns,
|
nouns: props.nouns,
|
||||||
verbs: props.verbs,
|
verbs: props.verbs,
|
||||||
}}
|
}}
|
||||||
np={subject}
|
np={vps.subject}
|
||||||
counterPart={verb ? verb.object : undefined}
|
counterPart={vps.verb ? vps.verb.object : undefined}
|
||||||
onChange={handleSubjectChange}
|
onChange={handleSubjectChange}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
cantClear={mode === "quiz"}
|
cantClear={mode === "quiz"}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{verb && (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(VPRendered, "object")}</div>
|
||||||
{(typeof 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
|
||||||
{..."getNounByTs" in props ? {
|
{..."getNounByTs" in props ? {
|
||||||
|
@ -187,8 +182,8 @@ export function VPExplorer(props: {
|
||||||
verbs: props.verbs,
|
verbs: props.verbs,
|
||||||
}}
|
}}
|
||||||
asObject
|
asObject
|
||||||
np={verb.object}
|
np={vps.verb.object}
|
||||||
counterPart={subject}
|
counterPart={vps.subject}
|
||||||
onChange={handleObjectChange}
|
onChange={handleObjectChange}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
cantClear={mode === "quiz"}
|
cantClear={mode === "quiz"}
|
||||||
|
@ -197,13 +192,13 @@ export function VPExplorer(props: {
|
||||||
</>}
|
</>}
|
||||||
<div className="my-2">
|
<div className="my-2">
|
||||||
<TensePicker
|
<TensePicker
|
||||||
verb={verb}
|
vps={vps}
|
||||||
onChange={handleSetVerb}
|
onChange={setVps}
|
||||||
mode={mode}
|
mode={mode}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{(verb && (mode === "quiz")) && <div className="text-center my-2">
|
{(vps.verb && (mode === "quiz")) && <div className="text-center my-2">
|
||||||
<button
|
<button
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
onClick={showAnswer ? handleResetQuiz : () => setShowAnswer(true)}
|
onClick={showAnswer ? handleResetQuiz : () => setShowAnswer(true)}
|
||||||
|
@ -216,14 +211,27 @@ export function VPExplorer(props: {
|
||||||
{(verbPhrase && ((mode === "phrases") || (mode === "quiz" && showAnswer))) &&
|
{(verbPhrase && ((mode === "phrases") || (mode === "quiz" && showAnswer))) &&
|
||||||
<VPDisplay VP={verbPhrase} opts={props.opts} />
|
<VPDisplay VP={verbPhrase} opts={props.opts} />
|
||||||
}
|
}
|
||||||
{(verb && (mode === "charts")) && <ChartDisplay VS={verb} opts={props.opts} />}
|
{(vps.verb && (mode === "charts")) && <ChartDisplay VS={vps.verb} opts={props.opts} />}
|
||||||
{mode === "quiz" && <div style={{ height: "300px" }}>
|
{mode === "quiz" && <div style={{ height: "300px" }}>
|
||||||
|
{/* spacer for blank space while quizzing */}
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -231,18 +239,6 @@ function hasPronounConflict(subject: T.NPSelection | undefined, object: undefine
|
||||||
return isInvalidSubjObjCombo(subjPronoun.person, objPronoun.person);
|
return isInvalidSubjObjCombo(subjPronoun.person, objPronoun.person);
|
||||||
}
|
}
|
||||||
|
|
||||||
function verbPhraseComplete({ subject, verb }: { subject: T.NPSelection | undefined, verb: T.VerbSelection }): T.VPSelection | undefined {
|
|
||||||
if (!subject) return undefined;
|
|
||||||
if (!verb) return undefined;
|
|
||||||
if (verb.object === undefined) return undefined;
|
|
||||||
return {
|
|
||||||
type: "VPSelection",
|
|
||||||
subject,
|
|
||||||
object: verb.object,
|
|
||||||
verb,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function showRole(VP: T.VPRendered | undefined, member: "subject" | "object") {
|
function showRole(VP: T.VPRendered | undefined, member: "subject" | "object") {
|
||||||
return VP
|
return VP
|
||||||
? <span className="ml-2">
|
? <span className="ml-2">
|
||||||
|
@ -251,8 +247,7 @@ function showRole(VP: T.VPRendered | undefined, member: "subject" | "object") {
|
||||||
: "";
|
: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
type SOClump = { subject: T.NPSelection | undefined, verb: T.VerbSelection };
|
function switchSubjObj({ subject, verb }: T.VPSelectionState): T.VPSelectionState {
|
||||||
function switchSubjObj({ subject, verb }: SOClump): SOClump {
|
|
||||||
if (!subject|| !verb || !verb.object || !(typeof verb.object === "object")) {
|
if (!subject|| !verb || !verb.object || !(typeof verb.object === "object")) {
|
||||||
return { subject, verb };
|
return { subject, verb };
|
||||||
}
|
}
|
||||||
|
@ -265,39 +260,41 @@ function switchSubjObj({ subject, verb }: SOClump): SOClump {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function setRandomQuizState(subject: T.NPSelection | undefined, verb: T.VerbSelection): {
|
function setRandomQuizState(mix: MixState) {
|
||||||
S: T.NPSelection,
|
return ({ subject, verb }: T.VPSelectionState): T.VPSelectionState => {
|
||||||
V: T.VerbSelection,
|
if (mix === "tenses") {
|
||||||
} {
|
return {
|
||||||
const oldSubj = (subject?.type === "pronoun")
|
subject,
|
||||||
? subject.person
|
verb: randomizeTense(verb, true),
|
||||||
: undefined;
|
}
|
||||||
const oldObj = (typeof verb?.object === "object" && verb.object.type === "pronoun")
|
}
|
||||||
? verb.object.person
|
const oldSubj = (subject?.type === "pronoun")
|
||||||
: undefined;
|
? subject.person
|
||||||
const { subj, obj } = randomSubjObj(
|
: undefined;
|
||||||
oldSubj !== undefined ? { subj: oldSubj, obj: oldObj } : undefined
|
const oldObj = (typeof verb?.object === "object" && verb.object.type === "pronoun")
|
||||||
);
|
? verb.object.person
|
||||||
const randSubj: T.PronounSelection = subject?.type === "pronoun" ? {
|
: undefined;
|
||||||
...subject,
|
const { subj, obj } = randomSubjObj(
|
||||||
person: subj,
|
oldSubj !== undefined ? { subj: oldSubj, obj: oldObj } : undefined
|
||||||
} : {
|
);
|
||||||
type: "pronoun",
|
const randSubj: T.PronounSelection = subject?.type === "pronoun" ? {
|
||||||
distance: "far",
|
...subject,
|
||||||
person: subj,
|
person: subj,
|
||||||
};
|
} : {
|
||||||
const randObj: T.PronounSelection = typeof verb?.object === "object" && verb.object.type === "pronoun" ? {
|
type: "pronoun",
|
||||||
...verb.object,
|
distance: "far",
|
||||||
person: obj,
|
person: subj,
|
||||||
} : {
|
};
|
||||||
type: "pronoun",
|
const randObj: T.PronounSelection = typeof verb?.object === "object" && verb.object.type === "pronoun" ? {
|
||||||
distance: "far",
|
...verb.object,
|
||||||
person: obj,
|
person: obj,
|
||||||
};
|
} : {
|
||||||
return {
|
type: "pronoun",
|
||||||
// TODO: Randomize the near/far ??
|
distance: "far",
|
||||||
S: randSubj,
|
person: obj,
|
||||||
V: {
|
};
|
||||||
|
const s = randSubj;
|
||||||
|
const v: T.VerbSelection = {
|
||||||
...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))
|
||||||
|
@ -306,6 +303,22 @@ function setRandomQuizState(subject: T.NPSelection | undefined, verb: T.VerbSele
|
||||||
)
|
)
|
||||||
? randObj
|
? randObj
|
||||||
: verb.object,
|
: verb.object,
|
||||||
},
|
};
|
||||||
}
|
return {
|
||||||
|
subject: s,
|
||||||
|
verb: mix === "both" ? randomizeTense(v, false) : v,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function randomizeTense(verb: T.VerbSelection, dontRepeatTense: boolean): T.VerbSelection {
|
||||||
|
return {
|
||||||
|
...verb,
|
||||||
|
tense: getRandomTense(
|
||||||
|
// TODO: WHY ISN'T THE OVERLOADING ON THIS
|
||||||
|
// @ts-ignore
|
||||||
|
verb.tenseCategory,
|
||||||
|
dontRepeatTense ? verb.tense : undefined,
|
||||||
|
),
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -3,93 +3,68 @@ import ButtonSelect from "../ButtonSelect";
|
||||||
import { RootsAndStems } from "../verb-info/VerbInfo";
|
import { RootsAndStems } from "../verb-info/VerbInfo";
|
||||||
import { getVerbInfo } from "../../lib/verb-info";
|
import { getVerbInfo } from "../../lib/verb-info";
|
||||||
import Hider from "../Hider";
|
import Hider from "../Hider";
|
||||||
import { makeVerbSelection } from "./verb-selection";
|
|
||||||
import EntrySelect from "../EntrySelect";
|
|
||||||
import useStickyState from "../../lib/useStickyState";
|
import useStickyState from "../../lib/useStickyState";
|
||||||
|
|
||||||
|
|
||||||
// TODO: dark on past tense selecitons
|
// TODO: dark on past tense selecitons
|
||||||
|
|
||||||
function VerbPicker(props: ({
|
function VerbPicker(props: {
|
||||||
verbs: T.VerbEntry[],
|
vps: T.VPSelectionState,
|
||||||
} | {
|
onChange: (p: T.VPSelectionState) => void,
|
||||||
verbs: (s: string) => T.VerbEntry[],
|
|
||||||
getVerbByTs: (ts: number) => T.VerbEntry | undefined;
|
|
||||||
}) & {
|
|
||||||
verb: T.VerbSelection,
|
|
||||||
subject: T.NPSelection | undefined,
|
|
||||||
onChange: (p: T.VerbSelection) => void,
|
|
||||||
changeSubject: (p: T.NPSelection | undefined) => void,
|
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
verbLocked: boolean,
|
|
||||||
}) {
|
}) {
|
||||||
const [showRootsAndStems, setShowRootsAndStems] = useStickyState<boolean>(false, "showRootsAndStems");
|
const [showRootsAndStems, setShowRootsAndStems] = useStickyState<boolean>(false, "showRootsAndStems");
|
||||||
const infoRaw = props.verb ? getVerbInfo(props.verb.verb.entry, props.verb.verb.complement) : undefined;
|
const infoRaw = props.vps.verb ? getVerbInfo(props.vps.verb.verb.entry, props.vps.verb.verb.complement) : undefined;
|
||||||
const info = (!infoRaw || !props.verb)
|
const info = (!infoRaw || !props.vps.verb)
|
||||||
? undefined
|
? undefined
|
||||||
: ("stative" in infoRaw)
|
: ("stative" in infoRaw)
|
||||||
? infoRaw[props.verb.isCompound === "stative" ? "stative" : "dynamic"]
|
? infoRaw[props.vps.verb.isCompound === "stative" ? "stative" : "dynamic"]
|
||||||
: ("transitive" in infoRaw)
|
: ("transitive" in infoRaw)
|
||||||
? infoRaw[props.verb.transitivity === "grammatically transitive" ? "grammaticallyTransitive" : "transitive"]
|
? infoRaw[props.vps.verb.transitivity === "grammatically transitive" ? "grammaticallyTransitive" : "transitive"]
|
||||||
: infoRaw;
|
: infoRaw;
|
||||||
if (info && ("stative" in info || "transitive" in info)) {
|
if (info && ("stative" in info || "transitive" in info)) {
|
||||||
return <div>ERROR: Verb version should be select first</div>;
|
return <div>ERROR: Verb version should be select first</div>;
|
||||||
}
|
}
|
||||||
// const [filters, useFilters] = useState<Filters>({
|
|
||||||
// stative: true,
|
|
||||||
// dynamic: true,
|
|
||||||
// transitive: true,
|
|
||||||
// intransitive: true,
|
|
||||||
// grammaticallyTransitive: true,
|
|
||||||
// });
|
|
||||||
function onVerbSelect(v: T.VerbEntry | undefined) {
|
|
||||||
// TODO: what to do when clearing
|
|
||||||
if (!v) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
props.onChange(makeVerbSelection(v, props.changeSubject, props.verb));
|
|
||||||
}
|
|
||||||
function onVoiceSelect(value: "active" | "passive") {
|
function onVoiceSelect(value: "active" | "passive") {
|
||||||
if (props.verb && props.verb.changeVoice) {
|
if (props.vps.verb && props.vps.verb.changeVoice) {
|
||||||
if (value === "passive" && (typeof props.verb.object === "object")) {
|
if (value === "passive" && (typeof props.vps.verb.object === "object")) {
|
||||||
props.changeSubject(props.verb.object);
|
props.onChange({
|
||||||
|
...props.vps,
|
||||||
|
subject: props.vps.verb.object,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if (value === "active") {
|
if (value === "active") {
|
||||||
props.changeSubject(undefined);
|
props.onChange({
|
||||||
|
...props.vps,
|
||||||
|
subject: undefined,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
props.onChange(props.verb.changeVoice(value, value === "active" ? props.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" {
|
||||||
return t === "intransitive" ? "transitive" : t;
|
return t === "intransitive" ? "transitive" : t;
|
||||||
}
|
}
|
||||||
function handleChangeTransitivity(t: "transitive" | "grammatically transitive") {
|
function handleChangeTransitivity(t: "transitive" | "grammatically transitive") {
|
||||||
if (props.verb && props.verb.changeTransitivity) {
|
if (props.vps.verb && props.vps.verb.changeTransitivity) {
|
||||||
props.onChange(props.verb.changeTransitivity(t));
|
props.onChange({
|
||||||
|
...props.vps,
|
||||||
|
verb: props.vps.verb.changeTransitivity(t),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function handleChangeStatDyn(c: "stative" | "dynamic") {
|
function handleChangeStatDyn(c: "stative" | "dynamic") {
|
||||||
if (props.verb && props.verb.changeStatDyn) {
|
if (props.vps.verb && props.vps.verb.changeStatDyn) {
|
||||||
props.onChange(props.verb.changeStatDyn(c));
|
props.onChange({
|
||||||
|
...props.vps,
|
||||||
|
verb: props.vps.verb.changeStatDyn(c),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return <div className="mb-3">
|
return <div className="mb-3">
|
||||||
{!props.verbLocked && <div style={{ maxWidth: "300px", margin: "0 auto" }}>
|
|
||||||
<div className="h5">Verb:</div>
|
|
||||||
<EntrySelect
|
|
||||||
{..."getVerbByTs" in props ? {
|
|
||||||
searchF: props.verbs,
|
|
||||||
getByTs: props.getVerbByTs,
|
|
||||||
} : {
|
|
||||||
entries: props.verbs,
|
|
||||||
}}
|
|
||||||
value={props.verb?.verb}
|
|
||||||
onChange={onVerbSelect}
|
|
||||||
name="Verb"
|
|
||||||
isVerbSelect
|
|
||||||
opts={props.opts}
|
|
||||||
/>
|
|
||||||
</div>}
|
|
||||||
{info && <div className="mt-3 mb-1 text-center">
|
{info && <div className="mt-3 mb-1 text-center">
|
||||||
<Hider
|
<Hider
|
||||||
showing={showRootsAndStems}
|
showing={showRootsAndStems}
|
||||||
|
@ -104,7 +79,7 @@ function VerbPicker(props: ({
|
||||||
</Hider>
|
</Hider>
|
||||||
</div>}
|
</div>}
|
||||||
<div className="d-flex flex-row justify-content-around flex-wrap" style={{ maxWidth: "400px", margin: "0 auto" }}>
|
<div className="d-flex flex-row justify-content-around flex-wrap" style={{ maxWidth: "400px", margin: "0 auto" }}>
|
||||||
{props.verb && props.verb.changeTransitivity && <div className="text-center my-2">
|
{props.vps.verb && props.vps.verb.changeTransitivity && <div className="text-center my-2">
|
||||||
<ButtonSelect
|
<ButtonSelect
|
||||||
small
|
small
|
||||||
options={[{
|
options={[{
|
||||||
|
@ -114,14 +89,14 @@ function VerbPicker(props: ({
|
||||||
label: "trans.",
|
label: "trans.",
|
||||||
value: "transitive",
|
value: "transitive",
|
||||||
}]}
|
}]}
|
||||||
value={notInstransitive(props.verb.transitivity)}
|
value={notInstransitive(props.vps.verb.transitivity)}
|
||||||
handleChange={handleChangeTransitivity}
|
handleChange={handleChangeTransitivity}
|
||||||
/>
|
/>
|
||||||
</div>}
|
</div>}
|
||||||
{props.verb && props.verb.changeVoice && <div className="text-center my-2">
|
{props.vps.verb && props.vps.verb.changeVoice && <div className="text-center my-2">
|
||||||
<ButtonSelect
|
<ButtonSelect
|
||||||
small
|
small
|
||||||
value={props.verb.voice}
|
value={props.vps.verb.voice}
|
||||||
options={[{
|
options={[{
|
||||||
label: "Active",
|
label: "Active",
|
||||||
value: "active",
|
value: "active",
|
||||||
|
@ -132,7 +107,7 @@ function VerbPicker(props: ({
|
||||||
handleChange={onVoiceSelect}
|
handleChange={onVoiceSelect}
|
||||||
/>
|
/>
|
||||||
</div>}
|
</div>}
|
||||||
{props.verb && props.verb.changeStatDyn && <div className="text-center my-2">
|
{props.vps.verb && props.vps.verb.changeStatDyn && <div className="text-center my-2">
|
||||||
<ButtonSelect
|
<ButtonSelect
|
||||||
small
|
small
|
||||||
options={[{
|
options={[{
|
||||||
|
@ -142,7 +117,7 @@ function VerbPicker(props: ({
|
||||||
label: "dynamic",
|
label: "dynamic",
|
||||||
value: "dynamic",
|
value: "dynamic",
|
||||||
}]}
|
}]}
|
||||||
value={props.verb.isCompound ? props.verb.isCompound : "stative"}
|
value={props.vps.verb.isCompound ? props.vps.verb.isCompound : "stative"}
|
||||||
handleChange={handleChangeStatDyn}
|
handleChange={handleChangeStatDyn}
|
||||||
/>
|
/>
|
||||||
</div>}
|
</div>}
|
||||||
|
|
|
@ -5,31 +5,34 @@ import * as T from "../../types";
|
||||||
import { getVerbInfo } from "../../lib/verb-info";
|
import { getVerbInfo } from "../../lib/verb-info";
|
||||||
import { isPerfectTense } from "../../lib/phrase-building/vp-tools";
|
import { isPerfectTense } from "../../lib/phrase-building/vp-tools";
|
||||||
|
|
||||||
export function makeVerbSelection(verb: T.VerbEntry, changeSubject: (s: T.NPSelection | undefined) => void, oldVerbSelection?: T.VerbSelection): T.VerbSelection {
|
export function makeVPSelectionState(
|
||||||
|
verb: T.VerbEntry,
|
||||||
|
os?: T.VPSelectionState,
|
||||||
|
): T.VPSelectionState {
|
||||||
const info = getVerbInfo(verb.entry, verb.complement);
|
const info = getVerbInfo(verb.entry, verb.complement);
|
||||||
function getTransObjFromOldVerbSelection() {
|
const subject = (os?.verb.voice === "passive" && info.type === "dynamic compound")
|
||||||
|
? makeNounSelection(info.objComplement.entry as T.NounEntry, true)
|
||||||
|
: (os?.subject || undefined);
|
||||||
|
function getTransObjFromos() {
|
||||||
if (
|
if (
|
||||||
!oldVerbSelection ||
|
!os ||
|
||||||
oldVerbSelection.object === "none" ||
|
os.verb.object === "none" ||
|
||||||
typeof oldVerbSelection.object === "number" ||
|
typeof os.verb.object === "number" ||
|
||||||
oldVerbSelection.isCompound === "dynamic" ||
|
os.verb.isCompound === "dynamic" ||
|
||||||
(oldVerbSelection.object?.type === "noun" && oldVerbSelection.object.dynamicComplement)
|
(os.verb.object?.type === "noun" && os.verb.object.dynamicComplement)
|
||||||
) return undefined;
|
) return undefined;
|
||||||
return oldVerbSelection.object;
|
return os.verb.object;
|
||||||
}
|
}
|
||||||
const transitivity: T.Transitivity = "grammaticallyTransitive" in info
|
const transitivity: T.Transitivity = "grammaticallyTransitive" in info
|
||||||
? "transitive"
|
? "transitive"
|
||||||
: info.transitivity;
|
: info.transitivity;
|
||||||
const object = (transitivity === "grammatically transitive")
|
const object = (transitivity === "grammatically transitive")
|
||||||
? T.Person.ThirdPlurMale
|
? T.Person.ThirdPlurMale
|
||||||
: (info.type === "dynamic compound" && oldVerbSelection?.voice !== "passive")
|
: (info.type === "dynamic compound" && os?.verb.voice !== "passive")
|
||||||
? makeNounSelection(info.objComplement.entry as T.NounEntry, true)
|
? makeNounSelection(info.objComplement.entry as T.NounEntry, true)
|
||||||
: (transitivity === "transitive" && oldVerbSelection?.voice !== "passive")
|
: (transitivity === "transitive" && os?.verb.voice !== "passive")
|
||||||
? getTransObjFromOldVerbSelection()
|
? getTransObjFromos()
|
||||||
: "none";
|
: "none";
|
||||||
if (oldVerbSelection?.voice === "passive" && info.type === "dynamic compound") {
|
|
||||||
changeSubject(makeNounSelection(info.objComplement.entry as T.NounEntry, true));
|
|
||||||
}
|
|
||||||
const isCompound = ("stative" in info || info.type === "stative compound")
|
const isCompound = ("stative" in info || info.type === "stative compound")
|
||||||
? "stative"
|
? "stative"
|
||||||
: info.type === "dynamic compound"
|
: info.type === "dynamic compound"
|
||||||
|
@ -47,60 +50,63 @@ export function makeVerbSelection(verb: T.VerbEntry, changeSubject: (s: T.NPSele
|
||||||
tenseCategory: "basic" | "modal",
|
tenseCategory: "basic" | "modal",
|
||||||
tense: T.VerbTense,
|
tense: T.VerbTense,
|
||||||
} => {
|
} => {
|
||||||
if (!oldVerbSelection) {
|
if (!os) {
|
||||||
return { tense: "presentVerb", tenseCategory: "basic" };
|
return { tense: "presentVerb", tenseCategory: "basic" };
|
||||||
}
|
}
|
||||||
if (oldVerbSelection.tenseCategory === "modal") {
|
if (os.verb.tenseCategory === "modal") {
|
||||||
return { tenseCategory: "modal", tense: isPerfectTense(oldVerbSelection.tense) ? "presentVerb" : oldVerbSelection.tense };
|
return { tenseCategory: "modal", tense: isPerfectTense(os.verb.tense) ? "presentVerb" : os.verb.tense };
|
||||||
}
|
}
|
||||||
if (oldVerbSelection.tenseCategory === "basic") {
|
if (os.verb.tenseCategory === "basic") {
|
||||||
return { tenseCategory: "basic", tense: isPerfectTense(oldVerbSelection.tense) ? "presentVerb" : oldVerbSelection.tense };
|
return { tenseCategory: "basic", tense: isPerfectTense(os.verb.tense) ? "presentVerb" : os.verb.tense };
|
||||||
}
|
}
|
||||||
return { tenseCategory: "perfect", tense: isPerfectTense(oldVerbSelection.tense) ? oldVerbSelection.tense : "present perfect" };
|
return { tenseCategory: "perfect", tense: isPerfectTense(os.verb.tense) ? os.verb.tense : "present perfect" };
|
||||||
})();
|
})();
|
||||||
return {
|
return {
|
||||||
type: "verb",
|
subject,
|
||||||
verb: verb,
|
verb: {
|
||||||
dynAuxVerb,
|
type: "verb",
|
||||||
...tenseSelection,
|
verb: verb,
|
||||||
object,
|
dynAuxVerb,
|
||||||
transitivity,
|
...tenseSelection,
|
||||||
isCompound,
|
object,
|
||||||
voice: transitivity === "transitive"
|
transitivity,
|
||||||
? (oldVerbSelection?.voice || "active")
|
isCompound,
|
||||||
: "active",
|
voice: transitivity === "transitive"
|
||||||
negative: oldVerbSelection ? oldVerbSelection.negative : false,
|
? (os?.verb.voice || "active")
|
||||||
...("grammaticallyTransitive" in info) ? {
|
: "active",
|
||||||
changeTransitivity: function(t) {
|
negative: os ? os.verb.negative : false,
|
||||||
return {
|
...("grammaticallyTransitive" in info) ? {
|
||||||
...this,
|
changeTransitivity: function(t) {
|
||||||
transitivity: t,
|
return {
|
||||||
object: t === "grammatically transitive" ? T.Person.ThirdPlurMale : undefined,
|
...this,
|
||||||
};
|
transitivity: t,
|
||||||
},
|
object: t === "grammatically transitive" ? T.Person.ThirdPlurMale : undefined,
|
||||||
} : {},
|
};
|
||||||
...("stative" in info) ? {
|
},
|
||||||
changeStatDyn: function(c) {
|
} : {},
|
||||||
return {
|
...("stative" in info) ? {
|
||||||
...this,
|
changeStatDyn: function(c) {
|
||||||
isCompound: c,
|
return {
|
||||||
object: c === "dynamic"
|
...this,
|
||||||
? makeNounSelection(info.dynamic.objComplement.entry as T.NounEntry, true)
|
isCompound: c,
|
||||||
: undefined,
|
object: c === "dynamic"
|
||||||
dynAuxVerb: c === "dynamic"
|
? makeNounSelection(info.dynamic.objComplement.entry as T.NounEntry, true)
|
||||||
? { entry: info.dynamic.auxVerb } as T.VerbEntry
|
: undefined,
|
||||||
: undefined,
|
dynAuxVerb: c === "dynamic"
|
||||||
};
|
? { entry: info.dynamic.auxVerb } as T.VerbEntry
|
||||||
}
|
: undefined,
|
||||||
} : {},
|
};
|
||||||
...(transitivity === "transitive") ? {
|
}
|
||||||
changeVoice: function(v, s) {
|
} : {},
|
||||||
return {
|
...(transitivity === "transitive") ? {
|
||||||
...this,
|
changeVoice: function(v, s) {
|
||||||
voice: v,
|
return {
|
||||||
object: v === "active" ? s : "none",
|
...this,
|
||||||
};
|
voice: v,
|
||||||
},
|
object: v === "active" ? s : "none",
|
||||||
} : {},
|
};
|
||||||
|
},
|
||||||
|
} : {},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { renderEnglishVPBase } from "./english-vp-rendering";
|
||||||
|
|
||||||
// TODO: ISSUE GETTING SPLIT HEAD NOT MATCHING WITH FUTURE VERBS
|
// TODO: ISSUE GETTING SPLIT HEAD NOT MATCHING WITH FUTURE VERBS
|
||||||
|
|
||||||
export function renderVP(VP: T.VPSelection): 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.object !== "none";
|
||||||
|
|
|
@ -15,7 +15,6 @@ import {
|
||||||
import {
|
import {
|
||||||
getVerbInfo,
|
getVerbInfo,
|
||||||
} from "./lib/verb-info";
|
} from "./lib/verb-info";
|
||||||
import { makeVerbSelection } from "./components/vp-explorer/verb-selection";
|
|
||||||
import ConjugationViewer from "./components/ConjugationViewer";
|
import ConjugationViewer from "./components/ConjugationViewer";
|
||||||
import InflectionsTable from "./components/InflectionsTable";
|
import InflectionsTable from "./components/InflectionsTable";
|
||||||
import Pashto from "./components/Pashto";
|
import Pashto from "./components/Pashto";
|
||||||
|
@ -164,7 +163,6 @@ export {
|
||||||
capitalizeFirstLetter,
|
capitalizeFirstLetter,
|
||||||
psStringFromEntry,
|
psStringFromEntry,
|
||||||
getLong,
|
getLong,
|
||||||
makeVerbSelection,
|
|
||||||
useStickyState,
|
useStickyState,
|
||||||
randomPerson,
|
randomPerson,
|
||||||
isInvalidSubjObjCombo,
|
isInvalidSubjObjCombo,
|
||||||
|
|
19
src/types.ts
19
src/types.ts
|
@ -508,13 +508,6 @@ export type Words = {
|
||||||
adverbs: AdverbEntry[],
|
adverbs: AdverbEntry[],
|
||||||
}
|
}
|
||||||
|
|
||||||
export type VPSelection = {
|
|
||||||
type: "VPSelection",
|
|
||||||
subject: NPSelection,
|
|
||||||
object: Exclude<VerbObject, undefined>,
|
|
||||||
verb: Exclude<VerbSelection, "object">,
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: make this Rendered<VPSelection> with recursive Rendered<>
|
// TODO: make this Rendered<VPSelection> with recursive Rendered<>
|
||||||
export type VPRendered = {
|
export type VPRendered = {
|
||||||
type: "VPRendered",
|
type: "VPRendered",
|
||||||
|
@ -543,6 +536,18 @@ export type NounNumber = "singular" | "plural";
|
||||||
|
|
||||||
export type PerfectTense = `${EquativeTense} perfect`;
|
export type PerfectTense = `${EquativeTense} perfect`;
|
||||||
|
|
||||||
|
export type VPSelectionState = {
|
||||||
|
subject: NPSelection | undefined,
|
||||||
|
verb: VerbSelection,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type VPSelectionComplete = {
|
||||||
|
type: "VPSelectionComplete",
|
||||||
|
subject: NPSelection,
|
||||||
|
object: Exclude<VerbObject, undefined>,
|
||||||
|
verb: Exclude<VerbSelection, "object">,
|
||||||
|
};
|
||||||
|
|
||||||
export type VerbSelection = {
|
export type VerbSelection = {
|
||||||
type: "verb",
|
type: "verb",
|
||||||
verb: VerbEntry,
|
verb: VerbEntry,
|
||||||
|
|
Loading…
Reference in New Issue