getting going with stative compounds - spacing
ee is still a bit rough
This commit is contained in:
parent
299aa0ca68
commit
6b8842c9b1
|
@ -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.5.5",
|
"@lingdocs/pashto-inflector": "^1.5.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",
|
||||||
|
|
|
@ -34,7 +34,8 @@ function makeVerbSelection(verb: VerbEntry, oldVerbSelection?: VerbSelection): V
|
||||||
return oldVerbSelection.object;
|
return oldVerbSelection.object;
|
||||||
}
|
}
|
||||||
// TODO: more complex types and unchangeable dynamic compound objects
|
// TODO: more complex types and unchangeable dynamic compound objects
|
||||||
const transitivity: "intransitive" | "transitive" | "grammaticallyTransitive" = verb.entry.c?.includes("v. intrans.")
|
// TODO: use proper type predicates
|
||||||
|
const transitivity: "intransitive" | "transitive" | "grammaticallyTransitive" = verb.entry.c?.includes("intrans.")
|
||||||
? "intransitive"
|
? "intransitive"
|
||||||
: verb.entry.c?.includes("v. gramm. trans.")
|
: verb.entry.c?.includes("v. gramm. trans.")
|
||||||
? "grammaticallyTransitive"
|
? "grammaticallyTransitive"
|
||||||
|
@ -44,12 +45,19 @@ function makeVerbSelection(verb: VerbEntry, oldVerbSelection?: VerbSelection): V
|
||||||
: transitivity === "transitive"
|
: transitivity === "transitive"
|
||||||
? getTransObjFromOldVerbSelection()
|
? getTransObjFromOldVerbSelection()
|
||||||
: "none";
|
: "none";
|
||||||
|
// TODO: better here based on selection of which type
|
||||||
|
const isCompound = verb.entry.c?.includes("stat. comp.")
|
||||||
|
? "stative"
|
||||||
|
: verb.entry.c?.includes("dyn. comp.")
|
||||||
|
? "dynamic"
|
||||||
|
: false;
|
||||||
return {
|
return {
|
||||||
type: "verb",
|
type: "verb",
|
||||||
verb,
|
verb,
|
||||||
tense: oldVerbSelection ? oldVerbSelection.tense : "present",
|
tense: oldVerbSelection ? oldVerbSelection.tense : "present",
|
||||||
object,
|
object,
|
||||||
transitivity,
|
transitivity,
|
||||||
|
isCompound,
|
||||||
negative: oldVerbSelection ? oldVerbSelection.negative : false,
|
negative: oldVerbSelection ? oldVerbSelection.negative : false,
|
||||||
...verb.entry.c?.includes("v. trans./gramm. trans") ? {
|
...verb.entry.c?.includes("v. trans./gramm. trans") ? {
|
||||||
changeTransitivity: function (t) {
|
changeTransitivity: function (t) {
|
||||||
|
|
|
@ -13,59 +13,14 @@ const kingEmoji = "👑";
|
||||||
const servantEmoji = "🙇♂️";
|
const servantEmoji = "🙇♂️";
|
||||||
const verbs = verbsRaw;
|
const verbs = verbsRaw;
|
||||||
|
|
||||||
function verbPhraseComplete({ subject, verb }: { subject: NPSelection | undefined, verb: VerbSelection | undefined }): VPSelection | undefined {
|
|
||||||
if (!subject) return undefined;
|
|
||||||
if (!verb) return undefined;
|
|
||||||
if (verb.object === undefined) return undefined;
|
|
||||||
return {
|
|
||||||
type: "VPSelection",
|
|
||||||
subject,
|
|
||||||
object: verb.object,
|
|
||||||
verb,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function showRole(VP: VPRendered | undefined, member: "subject" | "object") {
|
|
||||||
return VP
|
|
||||||
? <span className="ml-2">
|
|
||||||
{(VP.king === member ? kingEmoji : VP.servant === member ? servantEmoji : "")}
|
|
||||||
</span>
|
|
||||||
: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
type soClump = { subject: NPSelection | undefined, verb: VerbSelection | undefined };
|
|
||||||
function switchSubjObj({ subject, verb }: soClump): soClump {
|
|
||||||
if (!subject|| !verb || !verb.object || !(typeof verb.object === "object")) {
|
|
||||||
return { subject, verb };
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
subject: verb.object,
|
|
||||||
verb: {
|
|
||||||
...verb,
|
|
||||||
object: subject,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: BIG ISSUE, IF YOU OPEN THE OBJECT PRONOUN BOX AND IT CONFLICTS WITH THE SUBJECT
|
|
||||||
// IT CAN SAY THE COMBO IS NOT ALLOWED AND SHOW SOMETHING BLANK
|
|
||||||
// TODO: error handling on error with rendering etc
|
// TODO: error handling on error with rendering etc
|
||||||
export function PhraseBuilder() {
|
export function PhraseBuilder() {
|
||||||
const [subject, setSubject] = useState<NPSelection | undefined>(undefined);
|
const [subject, setSubject] = useState<NPSelection | undefined>(undefined);
|
||||||
const [verb, setVerb] = useState<VerbSelection | undefined>(undefined);
|
const [verb, setVerb] = useState<VerbSelection | undefined>(undefined);
|
||||||
function handleSubjectChange(subject: NPSelection | undefined) {
|
function handleSubjectChange(subject: NPSelection | undefined) {
|
||||||
// check for pronoun conflict
|
if (hasPronounConflict(subject, verb?.object)) {
|
||||||
const objPronoun = (typeof verb?.object === "object" && verb.object.type === "pronoun")
|
|
||||||
? verb.object.person
|
|
||||||
: undefined;
|
|
||||||
if (subject?.type === "pronoun" && objPronoun && isInvalidSubjObjCombo(subject.person, objPronoun)) {
|
|
||||||
alert("That combination of pronouns is not allowed");
|
alert("That combination of pronouns is not allowed");
|
||||||
return;
|
return;
|
||||||
// let newP = 0;
|
|
||||||
// do {
|
|
||||||
// newP = randomPerson();
|
|
||||||
// } while (isInvalidSubjObjCombo(newP, object.person));
|
|
||||||
// return setSubject({ ...incoming, person: newP });
|
|
||||||
}
|
}
|
||||||
setSubject(subject);
|
setSubject(subject);
|
||||||
}
|
}
|
||||||
|
@ -73,19 +28,11 @@ export function PhraseBuilder() {
|
||||||
if (!verb) return;
|
if (!verb) return;
|
||||||
if ((verb.object === "none") || (typeof verb.object === "number")) return;
|
if ((verb.object === "none") || (typeof verb.object === "number")) return;
|
||||||
// check for pronoun conflict
|
// check for pronoun conflict
|
||||||
if (object?.type === "pronoun" && subject?.type === "pronoun" && isInvalidSubjObjCombo(object.person, subject.person)) {
|
if (hasPronounConflict(subject, verb.object)) {
|
||||||
alert("That combination of pronouns is not allowed");
|
alert("That combination of pronouns is not allowed");
|
||||||
return;
|
return;
|
||||||
// let newP = 0;
|
|
||||||
// do {
|
|
||||||
// newP = randomPerson();
|
|
||||||
// } while (isInvalidSubjObjCombo(newP, object.person));
|
|
||||||
// return setSubject({ ...incoming, person: newP });
|
|
||||||
}
|
}
|
||||||
setVerb({
|
setVerb({ ...verb, object });
|
||||||
...verb,
|
|
||||||
object,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
function handleSubjObjSwap() {
|
function handleSubjObjSwap() {
|
||||||
const output = switchSubjObj({ subject, verb });
|
const output = switchSubjObj({ subject, verb });
|
||||||
|
@ -129,4 +76,45 @@ export function PhraseBuilder() {
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PhraseBuilder;
|
export default PhraseBuilder;
|
||||||
|
|
||||||
|
function hasPronounConflict(subject: NPSelection | undefined, object: undefined | VerbObject): boolean {
|
||||||
|
const subjPronoun = (subject && subject.type === "pronoun") ? subject : undefined;
|
||||||
|
const objPronoun = (object && typeof object === "object" && object.type === "pronoun") ? object : undefined;
|
||||||
|
if (!subjPronoun || !objPronoun) return false;
|
||||||
|
return isInvalidSubjObjCombo(subjPronoun.person, objPronoun.person);
|
||||||
|
}
|
||||||
|
|
||||||
|
function verbPhraseComplete({ subject, verb }: { subject: NPSelection | undefined, verb: VerbSelection | undefined }): VPSelection | undefined {
|
||||||
|
if (!subject) return undefined;
|
||||||
|
if (!verb) return undefined;
|
||||||
|
if (verb.object === undefined) return undefined;
|
||||||
|
return {
|
||||||
|
type: "VPSelection",
|
||||||
|
subject,
|
||||||
|
object: verb.object,
|
||||||
|
verb,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function showRole(VP: VPRendered | undefined, member: "subject" | "object") {
|
||||||
|
return VP
|
||||||
|
? <span className="ml-2">
|
||||||
|
{(VP.king === member ? kingEmoji : VP.servant === member ? servantEmoji : "")}
|
||||||
|
</span>
|
||||||
|
: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
type SOClump = { subject: NPSelection | undefined, verb: VerbSelection | undefined };
|
||||||
|
function switchSubjObj({ subject, verb }: SOClump): SOClump {
|
||||||
|
if (!subject|| !verb || !verb.object || !(typeof verb.object === "object")) {
|
||||||
|
return { subject, verb };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
subject: verb.object,
|
||||||
|
verb: {
|
||||||
|
...verb,
|
||||||
|
object: subject,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -8,18 +8,8 @@ import {
|
||||||
import AbbreviationFormSelector from "./AbbreviationFormSelector";
|
import AbbreviationFormSelector from "./AbbreviationFormSelector";
|
||||||
import { isPastTense } from "../../lib/phrase-building/vp-tools";
|
import { isPastTense } from "../../lib/phrase-building/vp-tools";
|
||||||
|
|
||||||
// function buttonClass(active: boolean, side: "l" | "r") {
|
|
||||||
// return classNames(
|
|
||||||
// "btn btn-sm btn-outline-secondary",
|
|
||||||
// { active },
|
|
||||||
// { "mr-1": side === "l" },
|
|
||||||
// { "ml-1": side === "r" },
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
function VPDisplay({ VP }: { VP: VPSelection }) {
|
function VPDisplay({ VP }: { VP: VPSelection }) {
|
||||||
const [form, setForm] = useState<FormVersion>({ removeKing: false, shrinkServant: false });
|
const [form, setForm] = useState<FormVersion>({ removeKing: false, shrinkServant: false });
|
||||||
// TODO: Possibly put the servant shrinking in here after the render
|
|
||||||
const result = compileVP(renderVP(VP), form);
|
const result = compileVP(renderVP(VP), form);
|
||||||
return <div className="text-center mt-2">
|
return <div className="text-center mt-2">
|
||||||
<AbbreviationFormSelector
|
<AbbreviationFormSelector
|
||||||
|
@ -27,18 +17,6 @@ function VPDisplay({ VP }: { VP: VPSelection }) {
|
||||||
form={form}
|
form={form}
|
||||||
onChange={setForm}
|
onChange={setForm}
|
||||||
/>
|
/>
|
||||||
{/* <button
|
|
||||||
onClick={toggleForm("removeKing")}
|
|
||||||
className={buttonClass(form.removeKing, "l")}
|
|
||||||
>
|
|
||||||
🚫 King
|
|
||||||
</button>
|
|
||||||
{servantShrinkable && <button
|
|
||||||
onClick={toggleForm("shrinkServant")}
|
|
||||||
className={buttonClass(form.shrinkServant, "r")}
|
|
||||||
>
|
|
||||||
👶 Servant
|
|
||||||
</button>} */}
|
|
||||||
{"long" in result.ps ?
|
{"long" in result.ps ?
|
||||||
<div>
|
<div>
|
||||||
{/* <div className="h6">Long Verb:</div> */}
|
{/* <div className="h6">Long Verb:</div> */}
|
||||||
|
|
|
@ -19,6 +19,7 @@ export function compileVP(VP: VPRendered, form: FormVersion, combineLengths?: tr
|
||||||
kids,
|
kids,
|
||||||
verb,
|
verb,
|
||||||
negative: VP.verb.negative,
|
negative: VP.verb.negative,
|
||||||
|
isCompound: VP.isCompound,
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
ps: combineLengths ? flattenLengths(psResult) : psResult,
|
ps: combineLengths ? flattenLengths(psResult) : psResult,
|
||||||
|
@ -33,19 +34,20 @@ type CompilePsInput = {
|
||||||
head: T.PsString | undefined,
|
head: T.PsString | undefined,
|
||||||
rest: T.SingleOrLengthOpts<T.PsString[]>,
|
rest: T.SingleOrLengthOpts<T.PsString[]>,
|
||||||
},
|
},
|
||||||
|
isCompound: "stative" | "dynamic" | false,
|
||||||
negative: boolean,
|
negative: boolean,
|
||||||
}
|
}
|
||||||
function compilePs({ NPs, kids, verb: { head, rest }, negative }: CompilePsInput): T.SingleOrLengthOpts<T.PsString[]> {
|
function compilePs({ NPs, kids, verb: { head, rest }, isCompound, negative }: CompilePsInput): T.SingleOrLengthOpts<T.PsString[]> {
|
||||||
if ("long" in rest) {
|
if ("long" in rest) {
|
||||||
return {
|
return {
|
||||||
long: compilePs({ NPs, verb: { head, rest: rest.long }, negative, kids }) as T.PsString[],
|
long: compilePs({ NPs, verb: { head, rest: rest.long }, negative, isCompound, kids }) as T.PsString[],
|
||||||
short: compilePs({ NPs, verb: { head, rest: rest.short }, negative, kids }) as T.PsString[],
|
short: compilePs({ NPs, verb: { head, rest: rest.short }, negative, isCompound, kids }) as T.PsString[],
|
||||||
...rest.mini ? {
|
...rest.mini ? {
|
||||||
mini: compilePs({ NPs, verb: { head, rest: rest.mini }, negative, kids }) as T.PsString[],
|
mini: compilePs({ NPs, verb: { head, rest: rest.mini }, negative, isCompound, kids }) as T.PsString[],
|
||||||
} : {},
|
} : {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const verbWNegativeVersions = arrangeVerbWNegative(head, rest, negative);
|
const verbWNegativeVersions = arrangeVerbWNegative(head, rest, negative, isCompound);
|
||||||
|
|
||||||
// put together all the different possible permutations based on:
|
// put together all the different possible permutations based on:
|
||||||
// a. potential different versions of where the nu goes
|
// a. potential different versions of where the nu goes
|
||||||
|
@ -116,7 +118,7 @@ function putKidsInKidsSection(segments: Segment[], kids: Segment[]): Segment[] {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function arrangeVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[], negative: boolean): Segment[][] {
|
function arrangeVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[], negative: boolean, isCompound: "stative" | "dynamic" | false): Segment[][] {
|
||||||
const rest = makeSegment(restRaw.map(removeBa), ["isVerbRest"]);
|
const rest = makeSegment(restRaw.map(removeBa), ["isVerbRest"]);
|
||||||
const headSegment: Segment | undefined = !head
|
const headSegment: Segment | undefined = !head
|
||||||
? head
|
? head
|
||||||
|
@ -148,7 +150,7 @@ function arrangeVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[
|
||||||
],
|
],
|
||||||
// verbs that have a perfective prefix that is not و or وا can put the
|
// verbs that have a perfective prefix that is not و or وا can put the
|
||||||
// nu *before* the prefix as well // TODO: also وي prefixes?
|
// nu *before* the prefix as well // TODO: also وي prefixes?
|
||||||
...!headSegment.isOoOrWaaHead ? [[
|
...(!headSegment.isOoOrWaaHead && !isCompound) ? [[
|
||||||
makeSegment(nu, ["isNu"]),
|
makeSegment(nu, ["isNu"]),
|
||||||
headSegment.adjust({ ps: removeAccents }),
|
headSegment.adjust({ ps: removeAccents }),
|
||||||
rest.adjust({ ps: removeAccents }),
|
rest.adjust({ ps: removeAccents }),
|
||||||
|
@ -168,10 +170,19 @@ function addSpacesBetweenSegments(segments: Segment[]): (Segment | " " | "" | T.
|
||||||
const next = segments[i+1];
|
const next = segments[i+1];
|
||||||
o.push(current);
|
o.push(current);
|
||||||
if (!next) break;
|
if (!next) break;
|
||||||
if ((next.isKidBetweenHeadAndRest || next.isNu) || (next.isVerbRest && current.isKidBetweenHeadAndRest)) {
|
if (
|
||||||
|
// stative compound part
|
||||||
|
!current.ps[0].p.endsWith(" ")
|
||||||
|
&&
|
||||||
|
(
|
||||||
|
(next.isKidBetweenHeadAndRest || next.isNu)
|
||||||
|
||
|
||||||
|
(next.isVerbRest && current.isKidBetweenHeadAndRest)
|
||||||
|
)
|
||||||
|
) {
|
||||||
o.push({
|
o.push({
|
||||||
f: "-",
|
f: "-",
|
||||||
p: ((current.isVerbHead && next.isMiniPronoun)
|
p: ((current.isVerbHead && (next.isMiniPronoun || next.isNu))
|
||||||
|| (current.isOoOrWaaHead && (next.isBa || next.isNu))) ? "" : " ", // or if its waa head
|
|| (current.isOoOrWaaHead && (next.isBa || next.isNu))) ? "" : " ", // or if its waa head
|
||||||
});
|
});
|
||||||
} else if (current.isVerbHead && next.isVerbRest) {
|
} else if (current.isVerbHead && next.isVerbRest) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
concatPsString,
|
concatPsString,
|
||||||
removeAccents,
|
removeAccents,
|
||||||
getPersonNumber,
|
getPersonNumber,
|
||||||
|
hasBaParticle,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import {
|
import {
|
||||||
psStringFromEntry,
|
psStringFromEntry,
|
||||||
|
@ -20,7 +21,6 @@ import {
|
||||||
isPastTense,
|
isPastTense,
|
||||||
} from "./vp-tools";
|
} from "./vp-tools";
|
||||||
import { isPattern4Entry } from "../type-predicates";
|
import { isPattern4Entry } from "../type-predicates";
|
||||||
import { hasBaParticle } from "@lingdocs/pashto-inflector/dist/lib/p-text-helpers";
|
|
||||||
|
|
||||||
// TODO: ISSUE GETTING SPLIT HEAD NOT MATCHING WITH FUTURE VERBS
|
// TODO: ISSUE GETTING SPLIT HEAD NOT MATCHING WITH FUTURE VERBS
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ export function renderVP(VP: VPSelection): VPRendered {
|
||||||
servant,
|
servant,
|
||||||
isPast,
|
isPast,
|
||||||
isTransitive,
|
isTransitive,
|
||||||
|
isCompound: VP.verb.isCompound,
|
||||||
subject: renderNPSelection(VP.subject, inflectSubject, false, "subject"),
|
subject: renderNPSelection(VP.subject, inflectSubject, false, "subject"),
|
||||||
object: renderNPSelection(VP.object, inflectObject, true, "object"),
|
object: renderNPSelection(VP.object, inflectObject, true, "object"),
|
||||||
verb: renderVerbSelection(VP.verb, kingPerson, objectPerson),
|
verb: renderVerbSelection(VP.verb, kingPerson, objectPerson),
|
||||||
|
|
|
@ -19,6 +19,7 @@ type VPRendered = {
|
||||||
servant: "subject" | "object" | undefined,
|
servant: "subject" | "object" | undefined,
|
||||||
isPast: boolean,
|
isPast: boolean,
|
||||||
isTransitive: boolean,
|
isTransitive: boolean,
|
||||||
|
isCompound: "stative" | "dynamic" | false,
|
||||||
subject: Rendered<NPSelection>,
|
subject: Rendered<NPSelection>,
|
||||||
object: Rendered<NPSelection> | ObjectNP,
|
object: Rendered<NPSelection> | ObjectNP,
|
||||||
verb: VerbRendered,
|
verb: VerbRendered,
|
||||||
|
@ -33,6 +34,7 @@ type VerbSelection = {
|
||||||
tense: VerbTense,
|
tense: VerbTense,
|
||||||
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: "transitive" | "intransitive" | "grammaticallyTransitive",
|
transitivity: "transitive" | "intransitive" | "grammaticallyTransitive",
|
||||||
|
isCompound: "stative" | "dynamic" | false,
|
||||||
changeTransitivity?: (t: "transitive" | "grammaticallyTransitive") => VerbSelection,
|
changeTransitivity?: (t: "transitive" | "grammaticallyTransitive") => VerbSelection,
|
||||||
// TODO: changeStativeDynamic
|
// TODO: changeStativeDynamic
|
||||||
// TODO: add in aspect element here??
|
// TODO: add in aspect element here??
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = [
|
||||||
|
{ ts: 1581906176268, e: "to be cooked" }, // پخېدل
|
||||||
|
{ ts: 1591033069786, e: "to get tired" }, // ستړی کېدل
|
||||||
|
]
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = [
|
||||||
|
{ ts: 1527815444, e: "to learn" }, // زده کول
|
||||||
|
{ ts: 1571859113828, e: "to cook" }, // پخول
|
||||||
|
]
|
Loading…
Reference in New Issue