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 {
equativeMachine,
assembleEquativeOutput,
NounInput,
SubjectInput,
} from "../../lib/equative-machine";
import { isPluralEntry, isSingularEntry } from "../../lib/type-predicates";
import { isNoun, isPluralEntry } from "../../lib/type-predicates";
function EquativeDisplay({ state }: { state: ExplorerState }) {
if (state.subjectType === "pronouns") {
@ -23,18 +23,14 @@ function EquativeDisplay({ state }: { state: ExplorerState }) {
/>
}
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,
plural: state.subjectsSelected.info.plural,
} : isPluralEntry(entry) ? {
entry,
plural: true,
} : {
entry: entry as SingularEntry<Noun>,
plural: state.subjectsSelected.info.plural,
};
plural: isPluralEntry(entry) ? true : state.subjectsSelected.info.plural,
} : entry;
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>;
return <div>

View File

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

View File

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

View File

@ -1,20 +1,27 @@
import { nouns, adjectives } from "../../words/words";
import { nouns, adjectives, verbs } from "../../words/words";
import {
isUnisexNoun,
} from "../../lib/type-predicates";
import { sort } from "./explorer-helpers";
import {
ParticipleInput,
} from "../../lib/equative-machine";
const unisexNouns = nouns.filter(x => isUnisexNoun(x)) as UnisexNoun[];
const nonUnisexNouns = nouns.filter(x => !isUnisexNoun(x)) as (MascNoun | FemNoun)[];
const inputs = {
adjective: sort(adjectives),
unisexNoun: sort(unisexNouns),
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 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;

View File

@ -31,6 +31,7 @@ export function reducer(state: ExplorerState, action: ExplorerReducerAction): Ex
if (action.type === "setSubject") {
if (state.subjectType === "pronouns") return state;
const pile = inputs[state.subjectType];
// @ts-ignore
const subject = (pile.find(p => p.ts === action.payload) || pile[0]);
return {
...state,

View File

@ -12,6 +12,98 @@ import {
import { isPluralEntry } from "../../lib/type-predicates";
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 }: {
state: ExplorerState,
dispatch: (action: ExplorerReducerAction) => void,
@ -71,80 +163,3 @@ export function PredicateSelector({ state, dispatch }: {
</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 { ParticipleInput } from "../../lib/equative-machine";
export type PredicateType = keyof PredicatesSelected;
export type SubjectType = "noun" | "pronouns";
export type SubjectType = "noun" | "pronouns" | "participle";
export type ExplorerState = {
subjectType: SubjectType,
@ -15,6 +16,7 @@ type PredicatesSelected = {
};
type SubjectSelected = {
noun: Noun,
participle: ParticipleInput,
info: {
plural: boolean,
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");
const ec = parseEc(entry.ec);
const participle = ec[2];
@ -291,11 +291,11 @@ function getEnglishParticiple(entry: T.DictionaryEntry): string {
: participle;
}
export function isPersonInput(e: EntityInput): e is PersonInput {
export function isPersonInput(e: EntityInput | T.DictionaryEntry): e is PersonInput {
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 ("entry" in e && !("gender" in e)) {
// e
@ -304,7 +304,7 @@ export function isNounInput(e: EntityInput): e is NounInput {
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 ("entry" in e) return false;
return !!e.c?.startsWith("v.");