a bit rough but support for participles in subject

This commit is contained in:
lingdocs 2021-10-20 10:33:21 -04:00
parent 9212c89c64
commit cb1ea724d8
8 changed files with 125 additions and 99 deletions

View File

@ -11,9 +11,9 @@ import {
import { import {
equativeMachine, equativeMachine,
assembleEquativeOutput, assembleEquativeOutput,
NounInput, SubjectInput,
} from "../../lib/equative-machine"; } from "../../lib/equative-machine";
import { isPluralEntry, isSingularEntry } from "../../lib/type-predicates"; import { isNoun, isPluralEntry } from "../../lib/type-predicates";
function EquativeDisplay({ state }: { state: ExplorerState }) { function EquativeDisplay({ state }: { state: ExplorerState }) {
if (state.subjectType === "pronouns") { if (state.subjectType === "pronouns") {
@ -23,18 +23,14 @@ function EquativeDisplay({ state }: { state: ExplorerState }) {
/> />
} }
const entry = state.subjectsSelected[state.subjectType]; const entry = state.subjectsSelected[state.subjectType];
const nounInput: NounInput = isSingularEntry(entry) ? { // @ts-ignore - TODO: safer and for use with unisex nouns
const subjInput: SubjectInput = isNoun(entry) ? {
entry, entry,
plural: state.subjectsSelected.info.plural, plural: isPluralEntry(entry) ? true : state.subjectsSelected.info.plural,
} : isPluralEntry(entry) ? { } : entry;
entry,
plural: true,
} : {
entry: entry as SingularEntry<Noun>,
plural: state.subjectsSelected.info.plural,
};
const eq = assembleEquativeOutput( const eq = assembleEquativeOutput(
equativeMachine(nounInput, state.predicatesSelected[state.predicateType]) equativeMachine(subjInput, state.predicatesSelected[state.predicateType])
); );
if ("short" in eq) return <div>length options not supported yet</div>; if ("short" in eq) return <div>length options not supported yet</div>;
return <div> return <div>

View File

@ -14,6 +14,7 @@ import {
defaultUnisexNoun, defaultUnisexNoun,
defaultAdjective, defaultAdjective,
defaultNoun, defaultNoun,
defaultParticiple,
} from "./explorer-inputs"; } from "./explorer-inputs";
import EquativeDisplay from "./EquativeDisplay"; import EquativeDisplay from "./EquativeDisplay";
@ -26,6 +27,7 @@ const defaultState: ExplorerState = {
}, },
subjectsSelected: { subjectsSelected: {
noun: defaultNoun, noun: defaultNoun,
participle: defaultParticiple,
info: { info: {
plural: false, plural: false,
gender: "masc", gender: "masc",

View File

@ -6,10 +6,13 @@ import {
import { import {
equativeMachine, equativeMachine,
assembleEquativeOutput, assembleEquativeOutput,
ParticipleInput,
isParticipleInput,
getEnglishParticiple,
} from "../../lib/equative-machine"; } from "../../lib/equative-machine";
export function sort<T extends (Adjective | Noun)>(arr: T[]): T[] { export function sort<T extends (Adjective | Noun | ParticipleInput)>(arr: Readonly<T[]>): T[] {
return arr.sort((a, b) => a.p.localeCompare(b.p)); return [...arr].sort((a, b) => a.p.localeCompare(b.p));
} }
export function makeBlockWPronouns(e: Adjective | UnisexNoun): T.VerbBlock { export function makeBlockWPronouns(e: Adjective | UnisexNoun): T.VerbBlock {
@ -28,7 +31,7 @@ export function makeBlockWPronouns(e: Adjective | UnisexNoun): T.VerbBlock {
} }
export function makeOptionLabel(e: T.DictionaryEntry): string { export function makeOptionLabel(e: T.DictionaryEntry): string {
const eng = getEnglishWord(e); const eng = (isParticipleInput(e)) ? getEnglishParticiple(e) : getEnglishWord(e);
const english = typeof eng === "string" const english = typeof eng === "string"
? eng ? eng
: !eng : !eng

View File

@ -1,20 +1,27 @@
import { nouns, adjectives } from "../../words/words"; import { nouns, adjectives, verbs } from "../../words/words";
import { import {
isUnisexNoun, isUnisexNoun,
} from "../../lib/type-predicates"; } from "../../lib/type-predicates";
import { sort } from "./explorer-helpers"; import { sort } from "./explorer-helpers";
import {
ParticipleInput,
} from "../../lib/equative-machine";
const unisexNouns = nouns.filter(x => isUnisexNoun(x)) as UnisexNoun[]; const unisexNouns = nouns.filter(x => isUnisexNoun(x)) as UnisexNoun[];
const nonUnisexNouns = nouns.filter(x => !isUnisexNoun(x)) as (MascNoun | FemNoun)[]; const nonUnisexNouns = nouns.filter(x => !isUnisexNoun(x)) as (MascNoun | FemNoun)[];
const inputs = { const inputs = {
adjective: sort(adjectives), adjective: sort(adjectives),
unisexNoun: sort(unisexNouns), unisexNoun: sort(unisexNouns),
noun: sort(nonUnisexNouns), noun: sort(nonUnisexNouns),
// @ts-ignore
participle: sort(verbs.map(e => e.entry) as ParticipleInput[]),
}; };
export const defaultAdjective = inputs.adjective.find(ps => ps.p === "ستړی") || inputs.adjective[0]; export const defaultAdjective = inputs.adjective.find(ps => ps.p === "زوړ") || inputs.adjective[0];
export const defaultUnisexNoun = inputs.unisexNoun.find(ps => ps.p === "پښتون") || inputs.unisexNoun[0]; export const defaultUnisexNoun = inputs.unisexNoun.find(ps => ps.p === "پښتون") || inputs.unisexNoun[0];
export const defaultNoun = inputs.noun.find(ps => ps.p === "کتاب") || inputs.noun[0]; export const defaultNoun = inputs.noun.find(ps => ps.p === "کتاب") || inputs.noun[0];
export const defaultParticiple = inputs.participle.find(ps => ps.p === "لیکل") || inputs.participle[0];
export default inputs; export default inputs;

View File

@ -31,6 +31,7 @@ export function reducer(state: ExplorerState, action: ExplorerReducerAction): Ex
if (action.type === "setSubject") { if (action.type === "setSubject") {
if (state.subjectType === "pronouns") return state; if (state.subjectType === "pronouns") return state;
const pile = inputs[state.subjectType]; const pile = inputs[state.subjectType];
// @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,

View File

@ -12,6 +12,98 @@ import {
import { isPluralEntry } from "../../lib/type-predicates"; import { isPluralEntry } from "../../lib/type-predicates";
import Select from "react-select"; import Select from "react-select";
export function SubjectSelector({ state, dispatch }: {
state: ExplorerState,
dispatch: (action: ExplorerReducerAction) => void,
}) {
function onTypeSelect(e: React.ChangeEvent<HTMLInputElement>) {
const t = e.target.value as SubjectType;
dispatch({ type: "setSubjectType", payload: t });
}
function onSubjectSelect({ value }: any) {
dispatch({ type: "setSubject", payload: parseInt(value) });
}
const pluralNounSelected = (
state.subjectType === "noun" && isPluralEntry(state.subjectsSelected.noun)
);
const options = state.subjectType === "pronouns"
? []
: inputs[state.subjectType].map(e => ({
value: e.ts.toString(),
label: makeOptionLabel(e),
}));
const subject = state.subjectType === "pronouns"
? undefined
: state.subjectsSelected[state.subjectType];
return <div className="form-group mr-2 flex-fill">
<label htmlFor="predicate-select"><strong>Subject:</strong></label>
<div className="form-check">
<input
className="form-check-input"
type="radio"
name="pronounsSubjectRadio"
id="pronounsSubjectRadio"
value="pronouns"
checked={state.subjectType === "pronouns"}
onChange={onTypeSelect}
/>
<label className="form-check-label" htmlFor="adjectivesPredicateRadio">
Pronouns
</label>
</div>
<div className="form-check">
<input
className="form-check-input"
type="radio"
name="nounsSubjectRadio"
id="nounsSubjectRadio"
value="noun"
checked={state.subjectType === "noun"}
onChange={onTypeSelect}
/>
<label className="form-check-label" htmlFor="unisexNounsPredicateRadio">
Nouns
</label>
</div>
<div className="form-check mb-2">
<input
className="form-check-input"
type="radio"
name="participlesSubjectRadio"
id="participlesSubjectRadio"
value="participle"
checked={state.subjectType === "participle"}
onChange={onTypeSelect}
/>
<label className="form-check-label" htmlFor="unisexNounsPredicateRadio">
Participles
</label>
</div>
{state.subjectType !== "pronouns" &&
<>
<Select
value={subject?.ts.toString()}
onChange={onSubjectSelect}
className="mb-2"
// @ts-ignore
options={options}
isSearchable
placeholder={options.find(o => o.value === subject?.ts.toString())?.label}
/>
{state.subjectType === "noun" && <ButtonSelect
small
options={[
...!pluralNounSelected ? [{ label: "Singular", value: "singular" }] : [],
{ label: "Plural", value: "plural" },
]}
value={(state.subjectsSelected.info.plural || pluralNounSelected) ? "plural" : "singular"}
handleChange={(p) => dispatch({ type: "setSubjectPlural", payload: p === "plural" ? true : false })}
/>}
</>
}
</div>;
}
export function PredicateSelector({ state, dispatch }: { export function PredicateSelector({ state, dispatch }: {
state: ExplorerState, state: ExplorerState,
dispatch: (action: ExplorerReducerAction) => void, dispatch: (action: ExplorerReducerAction) => void,
@ -71,80 +163,3 @@ export function PredicateSelector({ state, dispatch }: {
</div>; </div>;
} }
export function SubjectSelector({ state, dispatch }: {
state: ExplorerState,
dispatch: (action: ExplorerReducerAction) => void,
}) {
function onTypeSelect(e: React.ChangeEvent<HTMLInputElement>) {
const t = e.target.value as SubjectType;
dispatch({ type: "setSubjectType", payload: t });
}
function onSubjectSelect({ value }: any) {
dispatch({ type: "setSubject", payload: parseInt(value) });
}
const pluralNounSelected = (
state.subjectType === "noun" && isPluralEntry(state.subjectsSelected.noun)
);
const options = state.subjectType === "pronouns"
? []
: inputs[state.subjectType].map(e => ({
value: e.ts.toString(),
label: makeOptionLabel(e),
}));
const subject = state.subjectType === "pronouns"
? undefined
: state.subjectsSelected[state.subjectType]
return <div className="form-group mr-2 flex-fill">
<label htmlFor="predicate-select"><strong>Subject:</strong></label>
<div className="form-check">
<input
className="form-check-input"
type="radio"
name="pronounsSubjectRadio"
id="pronounsSubjectRadio"
value="pronouns"
checked={state.subjectType === "pronouns"}
onChange={onTypeSelect}
/>
<label className="form-check-label" htmlFor="adjectivesPredicateRadio">
Pronouns
</label>
</div>
<div className="form-check mb-2">
<input
className="form-check-input"
type="radio"
name="nounsSubjectRadio"
id="nounsSubjectRadio"
value="noun"
checked={state.subjectType === "noun"}
onChange={onTypeSelect}
/>
<label className="form-check-label" htmlFor="unisexNounsPredicateRadio">
Nouns
</label>
</div>
{state.subjectType !== "pronouns" &&
<>
<Select
value={subject?.ts.toString()}
onChange={onSubjectSelect}
className="mb-2"
// @ts-ignore
options={options}
isSearchable
placeholder={options.find(o => o.value === subject?.ts.toString())?.label}
/>
<ButtonSelect
small
options={[
...!pluralNounSelected ? [{ label: "Singular", value: "singular" }] : [],
{ label: "Plural", value: "plural" },
]}
value={(state.subjectsSelected.info.plural || pluralNounSelected) ? "plural" : "singular"}
handleChange={(p) => dispatch({ type: "setSubjectPlural", payload: p === "plural" ? true : false })}
/>
</>
}
</div>;
}

View File

@ -1,7 +1,8 @@
import { Types as T } from "@lingdocs/pashto-inflector"; import { Types as T } from "@lingdocs/pashto-inflector";
import { ParticipleInput } from "../../lib/equative-machine";
export type PredicateType = keyof PredicatesSelected; export type PredicateType = keyof PredicatesSelected;
export type SubjectType = "noun" | "pronouns"; export type SubjectType = "noun" | "pronouns" | "participle";
export type ExplorerState = { export type ExplorerState = {
subjectType: SubjectType, subjectType: SubjectType,
@ -15,6 +16,7 @@ type PredicatesSelected = {
}; };
type SubjectSelected = { type SubjectSelected = {
noun: Noun, noun: Noun,
participle: ParticipleInput,
info: { info: {
plural: boolean, plural: boolean,
gender: T.Gender, gender: T.Gender,

View File

@ -282,7 +282,7 @@ function psStringFromEntry(entry: T.DictionaryEntry, e: string): T.PsString {
}; };
} }
function getEnglishParticiple(entry: T.DictionaryEntry): string { export function getEnglishParticiple(entry: T.DictionaryEntry): string {
if (!entry.ec) throw new Error("no english information for participle"); if (!entry.ec) throw new Error("no english information for participle");
const ec = parseEc(entry.ec); const ec = parseEc(entry.ec);
const participle = ec[2]; const participle = ec[2];
@ -291,11 +291,11 @@ function getEnglishParticiple(entry: T.DictionaryEntry): string {
: participle; : participle;
} }
export function isPersonInput(e: EntityInput): e is PersonInput { export function isPersonInput(e: EntityInput | T.DictionaryEntry): e is PersonInput {
return typeof e === "number"; return typeof e === "number";
} }
export function isNounInput(e: EntityInput): e is NounInput { export function isNounInput(e: EntityInput | T.DictionaryEntry): e is NounInput {
if (isPersonInput(e)) return false; if (isPersonInput(e)) return false;
if ("entry" in e && !("gender" in e)) { if ("entry" in e && !("gender" in e)) {
// e // e
@ -304,7 +304,7 @@ export function isNounInput(e: EntityInput): e is NounInput {
return false; return false;
} }
export function isParticipleInput(e: EntityInput): e is ParticipleInput { export function isParticipleInput(e: EntityInput | T.DictionaryEntry): e is ParticipleInput {
if (isPersonInput(e)) return false; if (isPersonInput(e)) return false;
if ("entry" in e) return false; if ("entry" in e) return false;
return !!e.c?.startsWith("v."); return !!e.c?.startsWith("v.");