diff --git a/src/components/VerbPicker.tsx b/src/components/VerbPicker.tsx new file mode 100644 index 0000000..e2feb7e --- /dev/null +++ b/src/components/VerbPicker.tsx @@ -0,0 +1,91 @@ +import Select from "react-select"; +import { + makeVerbSelectOption, + zIndexProps, +} from "./np-picker/picker-tools"; +import { + Types as T, +} from "@lingdocs/pashto-inflector"; + +const tenseOptions = [{ + label: "present", + value: "present", +}, { + label: "subjunctive", + value: "subjunctive", +}]; + +function makeVerbSelection(verb: VerbEntry, oldVerbSelection?: VerbSelection): VerbSelection { + function getTransObjFromOldVerbSelection() { + if (!oldVerbSelection || oldVerbSelection.object === "none" || typeof oldVerbSelection.object === "number") return undefined; + return oldVerbSelection.object; + } + // TODO: more complex types and unchangeable dynamic compound objects + const verbType: "intrans" | "trans" | "gramm trans" = verb.entry.c?.includes("v. intrans.") + ? "intrans" + : verb.entry.c?.includes("v. gramm. trans.") + ? "gramm trans" + : "trans"; + const object = verbType === "gramm trans" + ? T.Person.ThirdPlurMale + : verbType === "trans" + ? getTransObjFromOldVerbSelection() + : "none"; + console.log({ verbType, object }); + return { + type: "verb", + verb, + tense: oldVerbSelection ? oldVerbSelection.tense : "present", + object, + }; +} + +function VerbPicker({ onChange, verb, verbs }: { verbs: VerbEntry[], verb: VerbSelection | undefined, onChange: (p: VerbSelection) => void }) { + const options = verbs.map(makeVerbSelectOption) + function onEntrySelect({ value }: { label: string, value: string }) { + const v = verbs.find(v => v.entry.ts.toString() === value); + if (!v) { + console.error("entry not found"); + return; + } + onChange(makeVerbSelection(v, verb)); + } + function onTenseSelect({ value }: { label: string, value: "present" | "subjunctive" }) { + if (verb) { + console.log("changing to", value) + onChange({ + ...verb, + tense: value, + }); + } + } + return
+
Verb:
+ o.value === verb.tense)?.value : "Select Tense..."} + {...zIndexProps} + /> +
; +} + +export default VerbPicker; \ No newline at end of file diff --git a/src/components/np-picker/NPNounPicker.tsx b/src/components/np-picker/NPNounPicker.tsx new file mode 100644 index 0000000..7470b54 --- /dev/null +++ b/src/components/np-picker/NPNounPicker.tsx @@ -0,0 +1,69 @@ +import Select from "react-select"; +import { + makeSelectOption, + zIndexProps, + makeNounSelection, +} from "./picker-tools"; +import { + ButtonSelect, +} from "@lingdocs/pashto-inflector"; + + +function NPNounPicker({ onChange, noun, nouns }: { nouns: NounEntry[], noun: NounSelection | undefined, onChange: (p: NounSelection) => void }) { + const options = nouns.map(makeSelectOption) + function onEntrySelect({ value }: { label: string, value: string }) { + const entry = nouns.find(n => n.ts.toString() === value); + if (!entry) { + console.error("entry not found"); + return; + } + onChange(makeNounSelection(entry)); + } + return
+ o.value === (participle.verb.entry).ts.toString())?.label : "Select Participle..."} + {...zIndexProps} + /> + {participle &&
+
Masc.
+
Plur.
+
} +
; +} + +export default NPParticiplePicker; \ No newline at end of file diff --git a/src/components/np-picker/NPPicker.tsx b/src/components/np-picker/NPPicker.tsx index 18780b3..8bc28aa 100644 --- a/src/components/np-picker/NPPicker.tsx +++ b/src/components/np-picker/NPPicker.tsx @@ -1,9 +1,12 @@ import PronounPicker from "./NPPronounPicker"; -import { getEnglishPronoun } from "../../lib/english-pronoun-tools"; +import NounPicker from "./NPNounPicker"; +import ParticiplePicker from "./NPParticiplePicker"; +// import { getEnglishPronoun } from "../../lib/english-pronoun-tools"; // import { ButtonSelect } from "@lingdocs/pashto-inflector"; import { randomPerson } from "../../lib/np-tools"; import { useState } from "react"; -import { capitalizeFirstLetter } from "../../lib/text-tools"; +import { nouns, verbs } from "../../words/words"; +// import { capitalizeFirstLetter } from "../../lib/text-tools"; const npTypes: NPType[] = ["noun", "pronoun", "participle"]; @@ -19,17 +22,18 @@ function NPPicker({ np, onChange }: { onChange: (nps: NPSelection | undefined) = const person = randomPerson(); const pronoun: PronounSelection = { type: "pronoun", - e: capitalizeFirstLetter(getEnglishPronoun(person, "subject")), person, distance: "far", }; + setNpType(ntp); onChange(pronoun); } else { + onChange(undefined); setNpType(ntp); } } - return
- {!np ? + return
+ {!npType ?
{npTypes.map((npt) => (
- :
X
} - {np && - (np.type === "pronoun" + : } + {np ? + ((np.type === "pronoun" ? - :
Not Implemented
) - } + : np.type === "noun" + ? + : )) + : (npType === "noun") + ? + : (npType === "participle") + ? + : null}
; } diff --git a/src/components/np-picker/NPPronounPicker.tsx b/src/components/np-picker/NPPronounPicker.tsx index c983931..367c6ac 100644 --- a/src/components/np-picker/NPPronounPicker.tsx +++ b/src/components/np-picker/NPPronounPicker.tsx @@ -2,8 +2,6 @@ import { Types as T, ButtonSelect, } from "@lingdocs/pashto-inflector"; -import { getEnglishPronoun } from "../../lib/english-pronoun-tools"; -import { capitalizeFirstLetter } from "../../lib/text-tools"; import useStickyState from "../../useStickyState"; const gColors = { @@ -60,7 +58,6 @@ function NPPronounPicker({ onChange, pronoun }: { pronoun: PronounSelection, onC const person = pickerStateToPerson({ ...p, row, col }); onChange({ ...pronoun, - e: capitalizeFirstLetter(getEnglishPronoun(person, "subject")), person, }); } @@ -68,7 +65,6 @@ function NPPronounPicker({ onChange, pronoun }: { pronoun: PronounSelection, onC const person = pickerStateToPerson({ ...p, gender }); onChange({ ...pronoun, - e: capitalizeFirstLetter(getEnglishPronoun(person, "subject")), person, }); } diff --git a/src/components/np-picker/picker-tools.ts b/src/components/np-picker/picker-tools.ts new file mode 100644 index 0000000..d0663fd --- /dev/null +++ b/src/components/np-picker/picker-tools.ts @@ -0,0 +1,74 @@ +import { + isNounEntry, + isAdjectiveEntry, + isAdverbEntry, + isPluralNounEntry, + isMascNounEntry, + isUnisexNounEntry, + isVerbEntry, +} from "../../lib/type-predicates"; +import { + getEnglishParticiple, + getEnglishVerb, +} from "../../lib/np-tools"; +import { + getEnglishWord, + removeFVarients, +} from "@lingdocs/pashto-inflector"; + +export const zIndexProps = { + menuPortalTarget: document.body, + styles: { menuPortal: (base: any) => ({ ...base, zIndex: 9999 }) }, +}; + +export function makeVerbSelectOption(e: VerbEntry): { value: string, label: string } { + const eng = getEnglishVerb(e.entry); + return { + label: `${e.entry.p} - ${removeFVarients(e.entry.f)} ${eng ? `(${eng})` : ""}`, + value: e.entry.ts.toString(), + }; +} + +export function makeSelectOption(e: VerbEntry | NounEntry | AdjectiveEntry | LocativeAdverbEntry): { value: string, label: string } { + const entry = "entry" in e ? e.entry : e; + const eng = (isVerbEntry(e)) + ? (getEnglishParticiple(e.entry)) + : getEnglishWord(e); + const english = typeof eng === "string" + ? eng + : !eng + ? "" + : ("singular" in eng && eng.singular !== undefined) + ? eng.singular + : eng.plural; + return { + label: `${entry.p} - ${removeFVarients(entry.f)} (${english})`, + value: entry.ts.toString(), + }; +} + +export function makeNounSelection(entry: NounEntry): NounSelection { + const number = isPluralNounEntry(entry) ? "plur" : "sing"; + return { + type: "noun", + entry, + gender: isMascNounEntry(entry) ? "masc" : "fem", + number, + ...isUnisexNounEntry(entry) ? { + changeGender: function(gender: "masc" | "fem"): NounSelection { + return { + ...this, + gender, + }; + }, + } : {}, + ...number === "sing" ? { + changeNumber: function(number: "plur" | "sing"): NounSelection { + return { + ...this, + number, + }; + }, + } : {}, + }; +} \ No newline at end of file diff --git a/src/components/phrase-builder/ObjectDisplay.tsx b/src/components/phrase-builder/ObjectDisplay.tsx new file mode 100644 index 0000000..8b1f9f3 --- /dev/null +++ b/src/components/phrase-builder/ObjectDisplay.tsx @@ -0,0 +1,10 @@ +import NPPicker from "../np-picker/NPPicker"; + +function ObjectDisplay({ object, onChange }: { object: Exclude, onChange: (o: NPSelection | undefined) => void }) { + return (typeof object === "number") + ?
Unspoken 3rd Pers. Masc. Plur.
+ : ; +} + +export default ObjectDisplay; + diff --git a/src/components/phrase-builder/PhraseBuilder.tsx b/src/components/phrase-builder/PhraseBuilder.tsx new file mode 100644 index 0000000..07963f2 --- /dev/null +++ b/src/components/phrase-builder/PhraseBuilder.tsx @@ -0,0 +1,37 @@ +import { useState } from "react"; +import NPPicker from "../np-picker/NPPicker"; +import VerbPicker from "../VerbPicker"; +import ObjectDisplay from "./ObjectDisplay"; +import { verbs } from "../../words/words"; + +export function PhraseBuilder() { + const [subject, setSubject] = useState(undefined); + const [verb, setVerb] = useState(undefined); + function handleObjectChange(object: NPSelection | undefined) { + if (!verb) return; + if ((verb.object === "none") || (typeof verb.object === "number")) return; + setVerb({ + ...verb, + object, + }); + } + console.log({ subject, verb }); + return
+
+
+
Subject
+ +
+ {verb && (verb.object !== "none") &&
+
Object
+ +
} +
+
Verb
+ +
+
+
+} + +export default PhraseBuilder; \ No newline at end of file diff --git a/src/content/index.ts b/src/content/index.ts index ea92984..fb50ab1 100644 --- a/src/content/index.ts +++ b/src/content/index.ts @@ -87,7 +87,7 @@ import * as games from "!babel-loader!@lingdocs/mdx-loader!./games.mdx"; // @ts-ignore import * as pronounPicker from "!babel-loader!@lingdocs/mdx-loader!./practice-tools/pronoun-picker.mdx"; // @ts-ignore -// import * as phraseBuilder from "!babel-loader!@lingdocs/mdx-loader!./practice-tools/phrase-builder.mdx"; +import * as phraseBuilder from "!babel-loader!@lingdocs/mdx-loader!./practice-tools/phrase-builder.mdx"; const contentTree = [ { @@ -284,10 +284,10 @@ const contentTree = [ import: pronounPicker, slug: "pronoun-picker", }, - // { - // import: phraseBuilder, - // slug: "phrase-builder", - // }, + { + import: phraseBuilder, + slug: "phrase-builder", + }, ], }, ]; diff --git a/src/content/practice-tools/phrase-builder.mdx b/src/content/practice-tools/phrase-builder.mdx index d7251a6..d4c482e 100644 --- a/src/content/practice-tools/phrase-builder.mdx +++ b/src/content/practice-tools/phrase-builder.mdx @@ -2,17 +2,8 @@ title: Phrase Builder --- -import NPPicker from "../../components/np-picker/NPPicker"; -import { useState } from "react"; +import PhraseBuilder from "../../components/phrase-builder/PhraseBuilder"; -export function Display() { - const [np, setNp] = useState(undefined); - return
- -
-            {JSON.stringify(np, null, "  ")}
-        
-
-} +This is under construction... It's not quite working yet. 👷🚧 - \ No newline at end of file + \ No newline at end of file diff --git a/src/lib/np-tools.ts b/src/lib/np-tools.ts index 8409dbc..424fe4a 100644 --- a/src/lib/np-tools.ts +++ b/src/lib/np-tools.ts @@ -145,6 +145,20 @@ function getInf(infs: T.InflectorOutput, t: "plural" | "arabicPlural" | "inflect return []; } +export function getEnglishVerb(entry: T.DictionaryEntry): string { + if (!entry.ec) { + console.log("errored verb"); + console.log(entry); + throw new Error("no english information for verb"); + } + if (entry.ep) { + const ec = entry.ec.includes(",") ? parseEc(entry.ec) : entry.ec; + return `to ${ec} ${entry.ep}`; + } + const ec = parseEc(entry.ec); + return `to ${ec[0]}`; +} + export function getEnglishParticiple(entry: T.DictionaryEntry): string { if (!entry.ec) { console.log("errored participle"); diff --git a/src/types/gen-g.d.ts b/src/types/gen-g.d.ts index ac0af83..ff3ad40 100644 --- a/src/types/gen-g.d.ts +++ b/src/types/gen-g.d.ts @@ -4,6 +4,28 @@ // type FemPlurNounEntry = ""; // can change nothing // type UnisexNounEntry = ""; // can change number or gender +type VP = { + subject: NPSelection, + object: NPSelection, + verb: VerbSelection, +}; + +type VerbSelection = { + type: "verb", + verb: VerbEntry, + tense: "present" | "subjunctive", + object: VerbObject, +}; + +type VerbObject = // intransitive verb + "none" | + // transitive verb - object not selected yet + undefined | + // transitive verb - obect selected + NPSelection | + // grammatically transitive verb with unspoken 3rd pers masc plur entity + import("@lingdocs/pashto-inflector").Types.Person.ThirdPlurMale; + type NPSelection = NounSelection | PronounSelection | ParticipleSelection; type NPType = "noun" | "pronoun" | "participle"; @@ -11,13 +33,7 @@ type NPType = "noun" | "pronoun" | "participle"; // TODO require/import Person and PsString type NounSelection = { type: "noun", - ps: import("@lingdocs/pashto-inflector").Types.PsString, - entry: import("@lingdocs/pashto-inflector").Types.DictionaryEntry, - // BETTER TO USE (or keep handy) FULL ENTRY FOR USE WITH INFLECTING - e: { - sing: string, - plur: string, - } | undefined, + entry: NounEntry, gender: "masc" | "fem", number: "sing" | "plur", // TODO: Implement @@ -33,17 +49,14 @@ type NounSelection = { // take an argument for subject/object in rendering English type PronounSelection = { type: "pronoun", - e: string, person: import("@lingdocs/pashto-inflector").Types.Person, distance: "near" | "far", }; type ParticipleSelection = { type: "participle", - ps: import("@lingdocs/pashto-inflector").Types.PsString, - e: string | undefined, - // entry in here -} + verb: VerbEntry, +}; // not object // type Primitive = string | Function | number | boolean | Symbol | undefined | null; diff --git a/tsconfig.json b/tsconfig.json index e18c413..b625491 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,7 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, + "noImplicitThis": true, "noEmit": true, "jsx": "react-jsx", "noFallthroughCasesInSwitch": true