passive and better UI

This commit is contained in:
lingdocs 2022-04-02 21:07:10 +05:00
parent 7449e8d4ad
commit 516b60523e
7 changed files with 192 additions and 47 deletions

View File

@ -5,7 +5,7 @@
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^5.15.4", "@fortawesome/fontawesome-free": "^5.15.4",
"@lingdocs/lingdocs-main": "^0.2.0", "@lingdocs/lingdocs-main": "^0.2.0",
"@lingdocs/pashto-inflector": "^1.6.3", "@lingdocs/pashto-inflector": "^1.6.7",
"@testing-library/jest-dom": "^5.11.4", "@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0", "@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10", "@testing-library/user-event": "^12.1.10",

View File

@ -54,7 +54,7 @@ const perfectTenseOptions: { label: string | JSX.Element, value: PerfectTense }[
label: "Past Perfect", label: "Past Perfect",
value: "past perfect", value: "past perfect",
}, { }, {
label: "Would Be Perfect", label: `"Would Be" Perfect`,
value: "wouldBe perfect", value: "wouldBe perfect",
}, { }, {
label: "Past Subjunctive Perfect", label: "Past Subjunctive Perfect",
@ -86,7 +86,7 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
} }
onChange(makeVerbSelection(v, verb)); onChange(makeVerbSelection(v, verb));
} }
function onTenseSelect({ value }: { label: string, value: VerbTense | PerfectTense }) { function onTenseSelect({ value }: { label: string | JSX.Element, value: VerbTense | PerfectTense }) {
if (verb) { if (verb) {
if (isPerfectTense(value)) { if (isPerfectTense(value)) {
onChange({ onChange({
@ -103,6 +103,22 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
} }
} }
} }
function moveTense(dir: "forward" | "back") {
if (!verb) return;
return () => {
const tenses = verb.tenseCategory === "perfect" ? perfectTenseOptions : tenseOptions;
const currIndex = tenses.findIndex(tn => tn.value === verb.tense)
if (currIndex === -1) {
console.error("error moving tense", dir);
return;
}
const newIndex = dir === "forward"
? ((currIndex + 1) % tenses.length)
: (currIndex === 0 ? (tenses.length - 1) : (currIndex - 1))
const newTense = tenses[newIndex];
onTenseSelect(newTense);
};
}
function onPosNegSelect(value: string) { function onPosNegSelect(value: string) {
if (verb) { if (verb) {
onChange({ onChange({
@ -128,6 +144,11 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
} }
} }
} }
function onVoiceSelect(value: "active" | "passive") {
if (verb && verb.changeVoice) {
onChange(verb.changeVoice(value));
}
}
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;
} }
@ -155,6 +176,20 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
placeholder={verb ? options.find(o => o.value === (verb.verb.entry).ts.toString())?.label : "Select Verb..."} placeholder={verb ? options.find(o => o.value === (verb.verb.entry).ts.toString())?.label : "Select Verb..."}
{...zIndexProps} {...zIndexProps}
/> />
{verb && verb.changeTransitivity && <div className="text-center mt-3">
<ButtonSelect
small
options={[{
label: "gramm. trans.",
value: "grammatically transitive",
}, {
label: "trans.",
value: "transitive",
}]}
value={notInstransitive(verb.transitivity)}
handleChange={handleChangeTransitivity}
/>
</div>}
{verb && <div className="text-center my-3"> {verb && <div className="text-center my-3">
<ButtonSelect <ButtonSelect
small small
@ -162,16 +197,30 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
options={[{ options={[{
label: "Basic", label: "Basic",
value: "basic", value: "basic",
}, {
label: "Modal",
value: "modal",
}, { }, {
label: "Perfect", label: "Perfect",
value: "perfect", value: "perfect",
}, {
label: "Modal",
value: "modal",
}]} }]}
handleChange={onTenseCategorySelect} handleChange={onTenseCategorySelect}
/> />
</div>} </div>}
{verb && verb.changeTransitivity && <div className="text-center my-3">
<ButtonSelect
small
value={verb.voice}
options={[{
label: "Active",
value: "active",
}, {
label: "Passive",
value: "passive",
}]}
handleChange={onVoiceSelect}
/>
</div>}
<div>Tense:</div> <div>Tense:</div>
<Select <Select
isSearchable={false} isSearchable={false}
@ -189,34 +238,6 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
})() : undefined} })() : undefined}
{...zIndexProps} {...zIndexProps}
/> />
{verb && <div className="text-center my-3">
<ButtonSelect
small
value={verb.negative.toString()}
options={[{
label: "Pos.",
value: "false",
}, {
label: "Neg.",
value: "true",
}]}
handleChange={onPosNegSelect}
/>
</div>}
{verb && verb.changeTransitivity && <div className="text-center">
<ButtonSelect
small
options={[{
label: "gramm. trans.",
value: "grammatically transitive",
}, {
label: "trans.",
value: "transitive",
}]}
value={notInstransitive(verb.transitivity)}
handleChange={handleChangeTransitivity}
/>
</div>}
{verb && verb.changeStatDyn && <div className="text-center"> {verb && verb.changeStatDyn && <div className="text-center">
<ButtonSelect <ButtonSelect
small small
@ -231,6 +252,26 @@ function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbS
handleChange={handleChangeStatDyn} handleChange={handleChangeStatDyn}
/> />
</div>} </div>}
{verb && <div className="d-flex flex-row justify-content-between align-items-center my-3" style={{ width: "100%" }}>
<div onClick={moveTense("back")} className="clickable">
<i className="fas fa-chevron-left" />
</div>
<ButtonSelect
small
value={verb.negative.toString()}
options={[{
label: "Pos.",
value: "false",
}, {
label: "Neg.",
value: "true",
}]}
handleChange={onPosNegSelect}
/>
<div onClick={moveTense("forward")} className="clickable">
<i className="fas fa-chevron-right" />
</div>
</div>}
</div>; </div>;
} }
@ -253,7 +294,7 @@ function makeVerbSelection(verb: VerbEntry, oldVerbSelection?: VerbSelection): V
? T.Person.ThirdPlurMale ? T.Person.ThirdPlurMale
: info.type === "dynamic compound" : info.type === "dynamic compound"
? makeNounSelection(info.objComplement.entry as NounEntry, true) ? makeNounSelection(info.objComplement.entry as NounEntry, true)
: (transitivity === "transitive") : (transitivity === "transitive" && oldVerbSelection?.voice !== "passive")
? getTransObjFromOldVerbSelection() ? getTransObjFromOldVerbSelection()
: "none"; : "none";
const isCompound = ("stative" in info || info.type === "stative compound") const isCompound = ("stative" in info || info.type === "stative compound")
@ -292,9 +333,12 @@ function makeVerbSelection(verb: VerbEntry, oldVerbSelection?: VerbSelection): V
object, object,
transitivity, transitivity,
isCompound, isCompound,
voice: transitivity === "transitive"
? (oldVerbSelection?.voice || "active")
: "active",
negative: oldVerbSelection ? oldVerbSelection.negative : false, negative: oldVerbSelection ? oldVerbSelection.negative : false,
...("grammaticallyTransitive" in info) ? { ...("grammaticallyTransitive" in info) ? {
changeTransitivity: function (t) { changeTransitivity: function(t) {
return { return {
...this, ...this,
transitivity: t, transitivity: t,
@ -303,7 +347,7 @@ function makeVerbSelection(verb: VerbEntry, oldVerbSelection?: VerbSelection): V
}, },
} : {}, } : {},
...("stative" in info) ? { ...("stative" in info) ? {
changeStatDyn: function (c) { changeStatDyn: function(c) {
return { return {
...this, ...this,
isCompound: c, isCompound: c,
@ -316,6 +360,15 @@ function makeVerbSelection(verb: VerbEntry, oldVerbSelection?: VerbSelection): V
}; };
} }
} : {}, } : {},
...(transitivity === "transitive") ? {
changeVoice: function(v) {
return {
...this,
voice: v,
object: v === "passive" ? "none" : undefined,
};
},
} : {},
}; };
} }

View File

@ -141,11 +141,100 @@ export function renderEnglishVPBase({ subjectPerson, object, vs }: {
`$SUBJ should${n ? " not" : ""} have ${v[4]}`, `$SUBJ should${n ? " not" : ""} have ${v[4]}`,
]), ]),
} }
const passiveBasicBuilders: Record<
VerbTense,
(s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[]
> = {
presentVerb: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ ${engEquative("present", s)}${n ? " not" : ""} being ${v[4]}`,
`$SUBJ ${engEquative("present", s)}${n ? " not" : ""} ${v[4]}`,
]),
subjunctiveVerb: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`that $SUBJ will${n ? " not" : ""} be ${v[4]}`,
]),
imperfectiveFuture: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ will${n ? " not" : ""} be ${v[4]}`,
]),
perfectiveFuture: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ will${n ? " not" : ""} be ${v[4]}`,
]),
imperfectivePast: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ ${engEquative("past", s)}${n ? " not" : ""} being ${v[4]}`,
`$SUBJ would${n ? " not" : ""} be ${v[4]}`,
]),
perfectivePast: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ ${engEquative("past", s)}${n ? " not" : ""} ${v[4]}`,
]),
habitualPerfectivePast: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ would${n ? " not" : ""} be ${v[4]}`,
]),
habitualImperfectivePast: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ would${n ? " not" : ""} be ${v[4]}`,
]),
};
const passivePerfectBuilders: Record<
PerfectTense,
(s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[]
> = {
"present perfect": (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ ${engHave(s)}${n ? " not" : ""} been ${v[4]}`,
]),
"past perfect": (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ had${n ? " not" : ""} been ${v[4]}`,
]),
"habitual perfect": (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ ${engHave(s)}${n ? " not" : ""} been ${v[4]}`,
]),
"subjunctive perfect": (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`that $SUBJ will${n ? " not" : ""} have been ${v[4]}`,
]),
"future perfect": (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ will${n ? " not" : ""} have been ${v[4]}`,
]),
"wouldBe perfect": (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ will${n ? " not" : ""} have been ${v[4]}`,
]),
"pastSubjunctive perfect": (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ would${n ? " not" : ""} have been ${v[4]}`,
]),
}
const passiveModalBuilders: Record<
VerbTense,
(s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[]
> = {
presentVerb: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ can${n ? " not" : ""} be ${v[4]}`,
`$SUBJ ${engEquative("present", s)}${n ? " not" : ""} able to be ${v[4]}`,
]),
subjunctiveVerb: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`that $SUBJ will${n ? " not" : ""} be able to be ${v[4]}`,
`that $SUBJ ${n ? " not" : ""} be able to be ${v[4]}`,
]),
imperfectiveFuture: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ will${n ? " not" : ""} be able to be ${v[4]}`,
]),
perfectiveFuture: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ will${n ? " not" : ""} be able to be ${v[4]}`,
]),
imperfectivePast: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ would${n ? " not" : ""} be able to be ${v[4]}`,
`$SUBJ ${engEquative("past", s)}${n ? " not" : ""} being able to be ${v[4]}`,
]),
perfectivePast: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ ${engEquative("past", s)}${n ? " not" : ""} able to be ${v[4]}`,
]),
habitualPerfectivePast: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ would${n ? " not" : ""} be able to be ${v[4]}`,
]),
habitualImperfectivePast: (s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => ([
`$SUBJ would${n ? " not" : ""} be able to be ${v[4]}`,
]),
};
const base = ( const base = (
(vs.tenseCategory === "perfect") (vs.tenseCategory === "perfect")
? perfectBuilders[vs.tense] ? (vs.voice === "active" ? perfectBuilders : passivePerfectBuilders)[vs.tense]
: vs.tenseCategory === "basic" : vs.tenseCategory === "basic"
? basicBuilders[vs.tense] ? (vs.voice === "active" ? basicBuilders : passiveBasicBuilders)[vs.tense]
: modalBuilders[vs.tense])(subjectPerson, ec, vs.negative); : (vs.voice === "active" ? modalBuilders : passiveModalBuilders)[vs.tense])(subjectPerson, ec, vs.negative);
return base.map(b => `${b}${typeof object === "object" ? " $OBJ" : ""}${ep ? ` ${ep}` : ""}`); return base.map(b => `${b}${typeof object === "object" ? " $OBJ" : ""}${ep ? ` ${ep}` : ""}`);
} }

View File

@ -152,7 +152,7 @@ function getPsVerbConjugation(conj: T.VerbConjugation, vs: VerbSelection, person
}, },
hasBa: boolean, hasBa: boolean,
} { } {
const f = getTenseVerbForm(conj, vs.tense, vs.tenseCategory); const f = getTenseVerbForm(conj, vs.tense, vs.tenseCategory, vs.voice);
const block = getMatrixBlock(f, objectPerson, person); const block = getMatrixBlock(f, objectPerson, person);
const perfective = isPerfective(vs.tense); const perfective = isPerfective(vs.tense);
const verbForm = getVerbFromBlock(block, person); const verbForm = getVerbFromBlock(block, person);
@ -254,7 +254,8 @@ function getMatrixBlock<U>(f: {
return f[personToLabel(person)]; return f[personToLabel(person)];
} }
function getTenseVerbForm(conj: T.VerbConjugation, tense: VerbTense | PerfectTense, tenseCategory: "basic" | "modal" | "perfect"): T.VerbForm { function getTenseVerbForm(conjR: T.VerbConjugation, tense: VerbTense | PerfectTense, tenseCategory: "basic" | "modal" | "perfect", voice: "active" | "passive"): T.VerbForm {
const conj = (voice === "passive" && conjR.passive) ? conjR.passive : conjR;
if (tenseCategory === "basic") { if (tenseCategory === "basic") {
if (tense === "presentVerb") { if (tense === "presentVerb") {
return conj.imperfective.nonImperative; return conj.imperfective.nonImperative;

View File

@ -44,8 +44,10 @@ type VerbSelection = {
object: VerbObject, // TODO: should have a locked in (but number changeable noun) here for dynamic compounds object: VerbObject, // TODO: should have a locked in (but number changeable noun) here for dynamic compounds
transitivity: import("@lingdocs/pashto-inflector").Types.Transitivity, transitivity: import("@lingdocs/pashto-inflector").Types.Transitivity,
isCompound: "stative" | "dynamic" | false, isCompound: "stative" | "dynamic" | false,
voice: "active" | "passive",
changeTransitivity?: (t: "transitive" | "grammatically transitive") => VerbSelection, changeTransitivity?: (t: "transitive" | "grammatically transitive") => VerbSelection,
changeStatDyn?: (t: "stative" | "dynamic") => VerbSelection, changeStatDyn?: (t: "stative" | "dynamic") => VerbSelection,
changeVoice?: (v: "active" | "passive") => VerbSelection,
// TODO: changeStativeDynamic // TODO: changeStativeDynamic
// TODO: add in aspect element here?? // TODO: add in aspect element here??
negative: boolean, negative: boolean,

File diff suppressed because one or more lines are too long

View File

@ -1684,10 +1684,10 @@
pbf "^3.2.1" pbf "^3.2.1"
rambda "^6.7.0" rambda "^6.7.0"
"@lingdocs/pashto-inflector@^1.6.2": "@lingdocs/pashto-inflector@^1.6.7":
version "1.6.2" version "1.6.7"
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-1.6.2.tgz#956fa4c27af9d0d6e2643cfbd8a3ff1c76edffc5" resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-1.6.7.tgz#958d7cf8a27db44f960d0a76a9b8f04a9537b5a3"
integrity sha512-sCjuzznCmqLkd8U7xr6JMNu7OMgNyAbInC2Szx7JROSOAByv2le3ldeidt/ZuzQN8Plq+oMkIti+VoJ9R7Tg1w== integrity sha512-DnhSL2Uiphm+z2Y0eTVsYCtq73JG+eqf00Txo1fDx0928w7dRQuaaTquuiuk2W+HSR/HuGTTDi+yHjRTMDj13w==
dependencies: dependencies:
classnames "^2.2.6" classnames "^2.2.6"
pbf "^3.2.1" pbf "^3.2.1"