towards refactor

This commit is contained in:
lingdocs 2021-10-23 22:54:55 -04:00
parent 2d17daf81f
commit 8843a7f106
5 changed files with 176 additions and 81 deletions

View File

@ -15,42 +15,121 @@ import {
equativeMachine, equativeMachine,
assembleEquativeOutput, assembleEquativeOutput,
SubjectInput, SubjectInput,
PredicateInput,
isParticipleInput,
ParticipleInput,
} from "../../lib/equative-machine"; } from "../../lib/equative-machine";
import { isNoun, isPluralEntry, isUnisexNoun } from "../../lib/type-predicates"; import { isPluralEntry, isUnisexNoun, isAdjective, isSingularEntry } from "../../lib/type-predicates";
export function chooseLength<O>(o: T.SingleOrLengthOpts<O>, length: "short" | "long"): O { export function chooseLength<O>(o: T.SingleOrLengthOpts<O>, length: "short" | "long"): O {
return ("long" in o) ? o[length] : o; return ("long" in o) ? o[length] : o;
} }
function SingleItemDisplay({ state }: { state: ExplorerState }) { function SingleItemDisplay({ state }: { state: ExplorerState }) {
if (state.subjectType === "pronouns") { if (state.subject.type === "pronouns") {
return <div>ERROR: Wrong display being used</div>; return <div>ERROR: Wrong display being used</div>;
} }
const entry = state.subjectsSelected[state.subjectType]; try {
// @ts-ignore - TODO: safer and for use with unisex nouns const subjInput = makeSubjectInput(state.subject[state.subject.type], state);
const subjInput: SubjectInput = isNoun(entry) ? { const predInput = makePredicateInput(state.predicate[state.predicate.type], state);
entry,
plural: isPluralEntry(entry) ? true : state.subjectsSelected.info.plural,
...isUnisexNoun(entry) ? {
gender: state.subjectsSelected.info.gender,
} : {},
} : entry;
const block = assembleEquativeOutput( const block = assembleEquativeOutput(
equativeMachine(subjInput, state.predicatesSelected[state.predicateType], state.tense) equativeMachine(subjInput, predInput, state.tense)
); );
return <div> return <div>
<VerbTable textOptions={opts} block={chooseLength(block, state.length)} /> <VerbTable textOptions={opts} block={chooseLength(block, state.length)} />
</div>; </div>;
} catch (e) {
console.error(e);
return <div>Error making equative sentence</div>
}
}
function makeSubjectInput(entry: Noun | ParticipleInput | UnisexNoun, state: ExplorerState): SubjectInput {
if (isParticipleInput(entry)) {
return entry;
}
const isUnisex = isUnisexNoun(entry);
if (isUnisex && isSingularEntry(entry)) {
return {
...state.subject.info,
entry,
};
}
if (isUnisex && isPluralEntry(entry)) {
return {
...state.subject.info,
plural: true,
entry,
};
}
if (isUnisex) {
throw new Error("improper unisex noun");
}
if (isPluralEntry(entry)) {
return {
plural: true,
entry,
}
}
if (isSingularEntry(entry)) {
return {
entry,
plural: state.subject.info.plural,
};
}
throw new Error("unable to make subject input from entry");
}
function makePredicateInput(entry: Noun | ParticipleInput | UnisexNoun | Adjective, state: ExplorerState): PredicateInput {
if (isParticipleInput(entry) || isAdjective(entry)) {
return entry;
}
const isUnisex = isUnisexNoun(entry);
if (isUnisex && state.subject.type === "pronouns") {
return entry;
}
if (isUnisex && isSingularEntry(entry)) {
return {
...state.predicate.info,
entry,
};
}
if (isUnisex && isPluralEntry(entry)) {
return {
...state.predicate.info,
plural: true,
entry,
};
}
if (isUnisex) {
throw new Error("improper unisex noun");
}
if (isPluralEntry(entry)) {
return {
plural: true,
entry,
}
}
if (isSingularEntry(entry)) {
return {
entry,
plural: state.predicate.info.plural,
};
}
throw new Error("unable to make predicate input from entry");
} }
function PronounBlockDisplay({ state }: { state: ExplorerState }) { function PronounBlockDisplay({ state }: { state: ExplorerState }) {
const block = makeBlockWPronouns(state.predicatesSelected[state.predicateType], state.tense); const pred = state.predicate[state.predicate.type];
if (!isParticipleInput(pred) && (isAdjective(pred) || isUnisexNoun(pred))) {
const block = makeBlockWPronouns(pred, state.tense);
return <VerbTable return <VerbTable
textOptions={opts} textOptions={opts}
block={chooseLength(block, state.length)} block={chooseLength(block, state.length)}
/>; />;
} }
return <div>Invalid combination</div>
}
function EquativeDisplay({ state, dispatch }: { state: ExplorerState, dispatch: (action: ExplorerReducerAction) => void }) { function EquativeDisplay({ state, dispatch }: { state: ExplorerState, dispatch: (action: ExplorerReducerAction) => void }) {
return <> return <>
@ -65,7 +144,7 @@ function EquativeDisplay({ state, dispatch }: { state: ExplorerState, dispatch:
handleChange={(p) => dispatch({ type: "setLength", payload: p as "long" | "short" })} handleChange={(p) => dispatch({ type: "setLength", payload: p as "long" | "short" })}
/> />
</div>} </div>}
{state.subjectType === "pronouns" {state.subject.type === "pronouns"
? <PronounBlockDisplay state={state} /> ? <PronounBlockDisplay state={state} />
: <SingleItemDisplay state={state} /> : <SingleItemDisplay state={state} />
} }

View File

@ -22,11 +22,19 @@ import EquativeDisplay from "./EquativeDisplay";
const defaultState: ExplorerState = { const defaultState: ExplorerState = {
tense: "present", tense: "present",
length: "short", length: "short",
predicatesSelected: { predicate: {
type: "adjective",
adjective: defaultAdjective, adjective: defaultAdjective,
unisexNoun: defaultUnisexNoun, unisexNoun: defaultUnisexNoun,
participle: defaultParticiple,
noun: defaultNoun,
info: {
plural: false,
gender: "masc",
}, },
subjectsSelected: { },
subject: {
type: "pronouns",
noun: defaultNoun, noun: defaultNoun,
participle: defaultParticiple, participle: defaultParticiple,
unisexNoun: defaultUnisexNoun, unisexNoun: defaultUnisexNoun,
@ -35,8 +43,6 @@ const defaultState: ExplorerState = {
gender: "masc", gender: "masc",
}, },
}, },
predicateType: "adjective",
subjectType: "pronouns",
}; };
function EquativeExplorer() { function EquativeExplorer() {
@ -46,8 +52,10 @@ function EquativeExplorer() {
unsafeSetState(newState); unsafeSetState(newState);
} }
return <> return <>
<TenseSelector state={state} dispatch={dispatch} />
<div className="row"> <div className="row">
<div className="col-sm">
<TenseSelector state={state} dispatch={dispatch} />
</div>
<div className="col"> <div className="col">
<SubjectSelector state={state} dispatch={dispatch} /> <SubjectSelector state={state} dispatch={dispatch} />
</div> </div>

View File

@ -3,13 +3,13 @@ import { ExplorerState, ExplorerReducerAction } from "./explorer-types";
export function reducer(state: ExplorerState, action: ExplorerReducerAction): ExplorerState { export function reducer(state: ExplorerState, action: ExplorerReducerAction): ExplorerState {
if (action.type === "setPredicate") { if (action.type === "setPredicate") {
const pile = inputs[state.predicateType] as (UnisexNoun | Adjective)[]; const pile = inputs[state.predicate.type] as (UnisexNoun | Adjective)[];
const predicate = (pile.find(p => p.ts === action.payload) || pile[0]); const predicate = (pile.find(p => p.ts === action.payload) || pile[0]);
return { return {
...state, ...state,
predicatesSelected: { predicate: {
...state.predicatesSelected, ...state.predicate,
[state.predicateType]: predicate, [state.predicate.type]: predicate,
}, },
}; };
} }
@ -17,37 +17,46 @@ export function reducer(state: ExplorerState, action: ExplorerReducerAction): Ex
const predicateType = action.payload; const predicateType = action.payload;
return { return {
...state, ...state,
predicateType: (predicateType === "unisexNoun" && state.subjectType === "noun") ? "adjective" : predicateType, predicate: {
...state.predicate,
type: (predicateType === "unisexNoun" && state.subject.type === "noun") ? "adjective" : predicateType,
},
}; };
} }
if (action.type === "setSubjectType") { if (action.type === "setSubjectType") {
const subjectType = action.payload; const subjectType = action.payload;
return { return {
...state, ...state,
predicateType: state.predicateType === "unisexNoun" ? "adjective" : state.predicateType, predicate: {
subjectType, ...state.predicate,
type: state.predicate.type === "unisexNoun" ? "adjective" : state.predicate.type,
},
subject: {
...state.subject,
type: subjectType,
}
}; };
} }
if (action.type === "setSubject") { if (action.type === "setSubject") {
if (state.subjectType === "pronouns") return state; if (state.subject.type === "pronouns") return state;
const pile = inputs[state.subjectType]; const pile = inputs[state.subject.type];
// @ts-ignore // @ts-ignore
const subject = (pile.find(p => p.ts === action.payload) || pile[0]); const subject = (pile.find(p => p.ts === action.payload) || pile[0]);
return { return {
...state, ...state,
subjectsSelected: { subject: {
...state.subjectsSelected, ...state.subject,
[state.subjectType]: subject, [state.subject.type]: subject,
}, },
}; };
} }
if (action.type === "setSubjectPlural") { if (action.type === "setSubjectPlural") {
return { return {
...state, ...state,
subjectsSelected: { subject: {
...state.subjectsSelected, ...state.subject,
info: { info: {
...state.subjectsSelected.info, ...state.subject.info,
plural: action.payload, plural: action.payload,
}, },
}, },
@ -56,10 +65,10 @@ export function reducer(state: ExplorerState, action: ExplorerReducerAction): Ex
if (action.type === "setSubjectGender") { if (action.type === "setSubjectGender") {
return { return {
...state, ...state,
subjectsSelected: { subject: {
...state.subjectsSelected, ...state.subject,
info: { info: {
...state.subjectsSelected.info, ...state.subject.info,
gender: action.payload, gender: action.payload,
}, },
}, },

View File

@ -30,17 +30,17 @@ export function SubjectSelector({ state, dispatch }: {
dispatch({ type: "setSubject", payload: parseInt(value) }); dispatch({ type: "setSubject", payload: parseInt(value) });
} }
const pluralNounSelected = ( const pluralNounSelected = (
state.subjectType === "noun" && isPluralEntry(state.subjectsSelected.noun) state.subject.type === "noun" && isPluralEntry(state.subject.noun)
); );
const options = state.subjectType === "pronouns" const options = state.subject.type === "pronouns"
? [] ? []
: inputs[state.subjectType].map(e => ({ : inputs[state.subject.type].map(e => ({
value: e.ts.toString(), value: e.ts.toString(),
label: makeOptionLabel(e), label: makeOptionLabel(e),
})); }));
const subject = state.subjectType === "pronouns" const subject = state.subject.type === "pronouns"
? undefined ? undefined
: state.subjectsSelected[state.subjectType]; : state.subject[state.subject.type];
return <div className="form-group"> return <div className="form-group">
<label htmlFor="predicate-select"><h5 className="mb-0">Subject:</h5></label> <label htmlFor="predicate-select"><h5 className="mb-0">Subject:</h5></label>
<div className="form-check"> <div className="form-check">
@ -50,7 +50,7 @@ export function SubjectSelector({ state, dispatch }: {
name="pronounsSubjectRadio" name="pronounsSubjectRadio"
id="pronounsSubjectRadio" id="pronounsSubjectRadio"
value="pronouns" value="pronouns"
checked={state.subjectType === "pronouns"} checked={state.subject.type === "pronouns"}
onChange={onTypeSelect} onChange={onTypeSelect}
/> />
<label className="form-check-label" htmlFor="adjectivesPredicateRadio"> <label className="form-check-label" htmlFor="adjectivesPredicateRadio">
@ -64,7 +64,7 @@ export function SubjectSelector({ state, dispatch }: {
name="nounsSubjectRadio" name="nounsSubjectRadio"
id="nounsSubjectRadio" id="nounsSubjectRadio"
value="noun" value="noun"
checked={state.subjectType === "noun"} checked={state.subject.type === "noun"}
onChange={onTypeSelect} onChange={onTypeSelect}
/> />
<label className="form-check-label" htmlFor="unisexNounsPredicateRadio"> <label className="form-check-label" htmlFor="unisexNounsPredicateRadio">
@ -78,7 +78,7 @@ export function SubjectSelector({ state, dispatch }: {
name="unisexNounsSubjectRadio" name="unisexNounsSubjectRadio"
id="unisexNounsSubjectRadio" id="unisexNounsSubjectRadio"
value="unisexNoun" value="unisexNoun"
checked={state.subjectType === "unisexNoun"} checked={state.subject.type === "unisexNoun"}
onChange={onTypeSelect} onChange={onTypeSelect}
/> />
<label className="form-check-label" htmlFor="unisexNounsPredicateRadio"> <label className="form-check-label" htmlFor="unisexNounsPredicateRadio">
@ -92,14 +92,14 @@ export function SubjectSelector({ state, dispatch }: {
name="participlesSubjectRadio" name="participlesSubjectRadio"
id="participlesSubjectRadio" id="participlesSubjectRadio"
value="participle" value="participle"
checked={state.subjectType === "participle"} checked={state.subject.type === "participle"}
onChange={onTypeSelect} onChange={onTypeSelect}
/> />
<label className="form-check-label" htmlFor="unisexNounsPredicateRadio"> <label className="form-check-label" htmlFor="unisexNounsPredicateRadio">
Participles Participles
</label> </label>
</div> </div>
{state.subjectType !== "pronouns" && {state.subject.type !== "pronouns" &&
<> <>
<Select <Select
value={subject?.ts.toString()} value={subject?.ts.toString()}
@ -116,27 +116,27 @@ export function SubjectSelector({ state, dispatch }: {
<ButtonSelect <ButtonSelect
small small
options={[ options={[
...(state.subjectType === "unisexNoun" || (state.subjectType === "participle") || (isMascNoun(state.subjectsSelected[state.subjectType]))) ...(state.subject.type === "unisexNoun" || (state.subject.type === "participle") || (isMascNoun(state.subject[state.subject.type])))
? [{ label: "Masc.", value: "masc" }] : [], ? [{ label: "Masc.", value: "masc" }] : [],
...(state.subjectType === "unisexNoun" || ((state.subjectType !== "participle") && isFemNoun(state.subjectsSelected[state.subjectType]))) ...(state.subject.type === "unisexNoun" || ((state.subject.type !== "participle") && isFemNoun(state.subject[state.subject.type])))
? [{ label: "Fem.", value: "fem" }] : [], ? [{ label: "Fem.", value: "fem" }] : [],
]} ]}
value={state.subjectType === "noun" value={state.subject.type === "noun"
? (isMascNoun(state.subjectsSelected[state.subjectType]) ? "masc" : "fem") ? (isMascNoun(state.subject[state.subject.type]) ? "masc" : "fem")
: state.subjectType === "participle" : state.subject.type === "participle"
? "masc" ? "masc"
: state.subjectsSelected.info.gender} : state.subject.info.gender}
handleChange={state.subjectType === "noun" ? p => null : (p) => dispatch({ type: "setSubjectGender", payload: p as T.Gender })} handleChange={state.subject.type === "noun" ? p => null : (p) => dispatch({ type: "setSubjectGender", payload: p as T.Gender })}
/> />
</div> </div>
<div className="ml-2"> <div className="ml-2">
<ButtonSelect <ButtonSelect
small small
options={[ options={[
...(!pluralNounSelected && state.subjectType !== "participle") ? [{ label: "Singular", value: "singular" }] : [], ...(!pluralNounSelected && state.subject.type !== "participle") ? [{ label: "Singular", value: "singular" }] : [],
{ label: "Plural", value: "plural" }, { label: "Plural", value: "plural" },
]} ]}
value={(state.subjectsSelected.info.plural || pluralNounSelected || state.subjectType === "participle") ? "plural" : "singular"} value={(state.subject.info.plural || pluralNounSelected || state.subject.type === "participle") ? "plural" : "singular"}
handleChange={(p) => dispatch({ type: "setSubjectPlural", payload: p === "plural" ? true : false })} handleChange={(p) => dispatch({ type: "setSubjectPlural", payload: p === "plural" ? true : false })}
/> />
</div> </div>
@ -157,11 +157,11 @@ export function PredicateSelector({ state, dispatch }: {
function onPredicateSelect({ value }: any) { function onPredicateSelect({ value }: any) {
dispatch({ type: "setPredicate", payload: parseInt(value) }); dispatch({ type: "setPredicate", payload: parseInt(value) });
} }
const options = inputs[state.predicateType].map(e => ({ const options = inputs[state.predicate.type].map(e => ({
value: `${e.ts}`, value: `${e.ts}`,
label: makeOptionLabel(e), label: makeOptionLabel(e),
})); }));
const predicate = state.predicatesSelected[state.predicateType]; const predicate = state.predicate[state.predicate.type];
return <div> return <div>
<label htmlFor="predicate-select"><h5 className="mb-0">Predicate:</h5></label> <label htmlFor="predicate-select"><h5 className="mb-0">Predicate:</h5></label>
<div className="form-check"> <div className="form-check">
@ -171,7 +171,7 @@ export function PredicateSelector({ state, dispatch }: {
name="adjectivesPredicateRadio" name="adjectivesPredicateRadio"
id="adjectivesPredicateRadio" id="adjectivesPredicateRadio"
value="adjective" value="adjective"
checked={state.predicateType === "adjective"} checked={state.predicate.type === "adjective"}
onChange={onTypeSelect} onChange={onTypeSelect}
/> />
<label className="form-check-label" htmlFor="adjectivesPredicateRadio"> <label className="form-check-label" htmlFor="adjectivesPredicateRadio">
@ -185,9 +185,9 @@ export function PredicateSelector({ state, dispatch }: {
name="unisexNounsPredicateRadio" name="unisexNounsPredicateRadio"
id="unisexNounsPredicateRadio" id="unisexNounsPredicateRadio"
value="unisexNoun" value="unisexNoun"
checked={state.predicateType === "unisexNoun"} checked={state.predicate.type === "unisexNoun"}
onChange={onTypeSelect} onChange={onTypeSelect}
disabled={state.subjectType !== "pronouns"} disabled={state.subject.type !== "pronouns"}
/> />
<label className="form-check-label" htmlFor="unisexNounsPredicateRadio"> <label className="form-check-label" htmlFor="unisexNounsPredicateRadio">
Unisex Nouns Unisex Nouns

View File

@ -1,22 +1,21 @@
import { Types as T } from "@lingdocs/pashto-inflector"; import { Types as T } from "@lingdocs/pashto-inflector";
import { ParticipleInput } from "../../lib/equative-machine"; import { ParticipleInput } from "../../lib/equative-machine";
export type PredicateType = keyof PredicatesSelected; export type PredicateType = "adjective" | "noun" | "unisexNoun" | "participle";
export type SubjectType = "noun" | "pronouns" | "participle" | "unisexNoun"; export type SubjectType = "pronouns" | "noun" | "unisexNoun" | "participle";
export type ExplorerState = { export type ExplorerState = {
tense: EquativeTense, tense: EquativeTense,
length: "short" | "long", length: "short" | "long",
subjectType: SubjectType, subject: SubjectEntityInfo,
subjectsSelected: SubjectSelected, predicate: PredicateEntityInfo,
predicateType: PredicateType,
predicatesSelected: PredicatesSelected,
}; };
type PredicatesSelected = {
adjective: Adjective, export type SubjectEntityInfo = EntitiyInfo & { type: SubjectType };
unisexNoun: UnisexNoun,
}; export type PredicateEntityInfo = EntitiyInfo & { type: PredicateType, adjective: Adjective };
type SubjectSelected = {
type EntitiyInfo = {
noun: Noun, noun: Noun,
participle: ParticipleInput, participle: ParticipleInput,
unisexNoun: UnisexNoun, unisexNoun: UnisexNoun,