pretty much working with new verb engine and verb explorer ... quiz doesn't seem to be working right now
This commit is contained in:
parent
5f8c4ba876
commit
3b6d013402
|
@ -10,6 +10,7 @@
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"fp-ts": "^2.16.0",
|
||||||
"react-select": "^5.4.0"
|
"react-select": "^5.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -10735,6 +10736,11 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fp-ts": {
|
||||||
|
"version": "2.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.0.tgz",
|
||||||
|
"integrity": "sha512-bLq+KgbiXdTEoT1zcARrWEpa5z6A/8b7PcDW7Gef3NSisQ+VS7ll2Xbf1E+xsgik0rWub/8u0qP/iTTjj+PhxQ=="
|
||||||
|
},
|
||||||
"node_modules/fragment-cache": {
|
"node_modules/fragment-cache": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
|
||||||
|
@ -31006,6 +31012,11 @@
|
||||||
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
|
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"fp-ts": {
|
||||||
|
"version": "2.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.0.tgz",
|
||||||
|
"integrity": "sha512-bLq+KgbiXdTEoT1zcARrWEpa5z6A/8b7PcDW7Gef3NSisQ+VS7ll2Xbf1E+xsgik0rWub/8u0qP/iTTjj+PhxQ=="
|
||||||
|
},
|
||||||
"fragment-cache": {
|
"fragment-cache": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
|
||||||
|
|
|
@ -77,7 +77,6 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fp-ts": "^2.16.0",
|
"fp-ts": "^2.16.0",
|
||||||
"react-media-hook": "^0.5.0",
|
|
||||||
"react-select": "^5.4.0"
|
"react-select": "^5.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
320
src/App.tsx
320
src/App.tsx
|
@ -9,9 +9,7 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
import ButtonSelect from "./components/src/ButtonSelect";
|
import ButtonSelect from "./components/src/ButtonSelect";
|
||||||
import {
|
import { Modal } from "react-bootstrap";
|
||||||
Modal
|
|
||||||
} from "react-bootstrap";
|
|
||||||
import * as T from "./types";
|
import * as T from "./types";
|
||||||
import defualtTextOptions from "./lib/src/default-text-options";
|
import defualtTextOptions from "./lib/src/default-text-options";
|
||||||
import useStickyState from "./components/src/useStickyState";
|
import useStickyState from "./components/src/useStickyState";
|
||||||
|
@ -23,148 +21,196 @@ import InflectionDemo from "./demo-components/InflectionDemo";
|
||||||
import SpellingDemo from "./demo-components/SpellingDemo";
|
import SpellingDemo from "./demo-components/SpellingDemo";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [showingTextOptions, setShowingTextOptions] = useStickyState<boolean>(false, "showTextOpts1");
|
const [showingTextOptions, setShowingTextOptions] = useStickyState<boolean>(
|
||||||
const [textOptions, setTextOptions] = useStickyState<T.TextOptions>(defualtTextOptions, "textOpts1");
|
false,
|
||||||
const [theme, setTheme] = useStickyState<"light" | "dark">("light", "theme1");
|
"showTextOpts1"
|
||||||
const [showing, setShowing] = useState<string>("");
|
);
|
||||||
function handleHiderClick(label: string) {
|
const [textOptions, setTextOptions] = useStickyState<T.TextOptions>(
|
||||||
setShowing(os => os === label
|
defualtTextOptions,
|
||||||
? ""
|
"textOpts1"
|
||||||
: label);
|
);
|
||||||
}
|
const [theme, setTheme] = useStickyState<"light" | "dark">("light", "theme1");
|
||||||
useEffect(() => {
|
const [showing, setShowing] = useState<string>("");
|
||||||
document.documentElement.setAttribute("data-theme", theme);
|
function handleHiderClick(label: string) {
|
||||||
}, [theme]);
|
setShowing((os) => (os === label ? "" : label));
|
||||||
|
}
|
||||||
|
useEffect(() => {
|
||||||
|
document.documentElement.setAttribute("data-theme", theme);
|
||||||
|
}, [theme]);
|
||||||
|
|
||||||
return <>
|
return (
|
||||||
<main className="flex-shrink-0 mb-4">
|
<>
|
||||||
<div className="container" style={{ maxWidth: "800px" }}>
|
<main className="flex-shrink-0 mb-4">
|
||||||
<div style={{ position: "absolute", top: "1.5rem", right: "1.5rem", display: "flex", flexDirection: "row" }}>
|
<div className="container" style={{ maxWidth: "800px" }}>
|
||||||
<div
|
<div
|
||||||
className="clickable mr-3"
|
style={{
|
||||||
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
|
position: "absolute",
|
||||||
>
|
top: "1.5rem",
|
||||||
<i className={`fa-lg fas fa-${theme === "light" ? "sun" : "moon"}`} />
|
right: "1.5rem",
|
||||||
</div>
|
display: "flex",
|
||||||
<div
|
flexDirection: "row",
|
||||||
className="clickable"
|
}}
|
||||||
onClick={() => setShowingTextOptions(true)}
|
>
|
||||||
>
|
<div
|
||||||
<i className="fa-lg fas fa-cog" />
|
className="clickable mr-3"
|
||||||
</div>
|
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className={`fa-lg fas fa-${theme === "light" ? "sun" : "moon"}`}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-center mb-4" style={{ marginTop: "3rem", marginBottom: "1rem" }}>
|
<div
|
||||||
<h1 className="display-4 mt-2"><code>Pashto Inflector</code></h1>
|
className="clickable"
|
||||||
<p className="lead my-3" style={{ maxWidth: "600px", margin: "0 auto" }}>
|
onClick={() => setShowingTextOptions(true)}
|
||||||
An open source TypeScript/React library for Pashto inflection, verb conjugation, phrase generation, text conversion, and more
|
>
|
||||||
</p>
|
<i className="fa-lg fas fa-cog" />
|
||||||
<p>Used in the <a href="https://dictionary.lingdocs.com">LingDocs Pashto Dictionary</a> and <a href="https://grammar.lingdocs.com">LingDocs Pashto Grammar</a></p>
|
|
||||||
<p>by <a href="https://adueck.github.io">Adam Dueck</a> - GPLv3 licensed <a href="https://github.com/lingdocs/pashto-inflector">Source Code</a> on GitHub</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<h2 className="mb-3">Demos:</h2>
|
|
||||||
<Hider
|
|
||||||
label="Verb Conjugation / Verb Phrase Engine"
|
|
||||||
hLevel={3}
|
|
||||||
showing={showing === "verbs"}
|
|
||||||
handleChange={() => handleHiderClick("verbs")}
|
|
||||||
>
|
|
||||||
<VPBuilderDemo opts={textOptions} />
|
|
||||||
</Hider>
|
|
||||||
<Hider
|
|
||||||
label="Equative Phrase Engine"
|
|
||||||
hLevel={3}
|
|
||||||
showing={showing === "equatives"}
|
|
||||||
handleChange={() => handleHiderClick("equatives")}
|
|
||||||
>
|
|
||||||
<div className="mt-4" style={{ paddingBottom: "20px" }}>
|
|
||||||
<EPExplorer
|
|
||||||
opts={textOptions}
|
|
||||||
entryFeeder={entryFeeder}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Hider>
|
|
||||||
<Hider
|
|
||||||
label="Inflection Engine"
|
|
||||||
hLevel={3}
|
|
||||||
showing={showing === "inflection"}
|
|
||||||
handleChange={() => handleHiderClick("inflection")}
|
|
||||||
>
|
|
||||||
<InflectionDemo opts={textOptions} />
|
|
||||||
</Hider>
|
|
||||||
<Hider
|
|
||||||
label="Spelling Conversion / Diacritics Engine"
|
|
||||||
hLevel={3}
|
|
||||||
showing={showing === "spelling"}
|
|
||||||
handleChange={() => handleHiderClick("spelling")}
|
|
||||||
>
|
|
||||||
<SpellingDemo opts={textOptions} onChange={setTextOptions} />
|
|
||||||
</Hider>
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</div>
|
||||||
<Modal show={showingTextOptions} onHide={() => setShowingTextOptions(false)}>
|
<div
|
||||||
<Modal.Header closeButton>
|
className="text-center mb-4"
|
||||||
<Modal.Title>Settings</Modal.Title>
|
style={{ marginTop: "3rem", marginBottom: "1rem" }}
|
||||||
</Modal.Header>
|
>
|
||||||
<Modal.Body>
|
<h1 className="display-4 mt-2">
|
||||||
<h6>Pashto Spelling</h6>
|
<code>Pashto Inflector</code>
|
||||||
<ButtonSelect
|
</h1>
|
||||||
options={[
|
<p
|
||||||
{ label: "Afghan", value: "Afghan" },
|
className="lead my-3"
|
||||||
{ label: "Pakistani ي", value: "Pakistani ي" },
|
style={{ maxWidth: "600px", margin: "0 auto" }}
|
||||||
{ label: "Pakistani ی", value: "Pakistani ی" },
|
>
|
||||||
]}
|
An open source TypeScript/React library for Pashto inflection,
|
||||||
value={textOptions.spelling}
|
verb conjugation, phrase generation, text conversion, and more
|
||||||
handleChange={(p) => {
|
</p>
|
||||||
setTextOptions({
|
<p>
|
||||||
...textOptions,
|
Used in the{" "}
|
||||||
spelling: p,
|
<a href="https://dictionary.lingdocs.com">
|
||||||
});
|
LingDocs Pashto Dictionary
|
||||||
}}
|
</a>{" "}
|
||||||
/>
|
and{" "}
|
||||||
<h6 className="mt-3">Diacritics</h6>
|
<a href="https://grammar.lingdocs.com">LingDocs Pashto Grammar</a>
|
||||||
<ButtonSelect
|
</p>
|
||||||
options={[
|
<p>
|
||||||
{ label: "On", value: "true" },
|
by <a href="https://adueck.github.io">Adam Dueck</a> - GPLv3
|
||||||
{ label: "Off", value: "false" },
|
licensed{" "}
|
||||||
]}
|
<a href="https://github.com/lingdocs/pashto-inflector">
|
||||||
value={textOptions.diacritics.toString()}
|
Source Code
|
||||||
handleChange={(p) => setTextOptions({ ...textOptions, diacritics: p === "true" })}
|
</a>{" "}
|
||||||
/>
|
on GitHub
|
||||||
<h6 className="mt-3">Pashto Text Size</h6>
|
</p>
|
||||||
<ButtonSelect
|
</div>
|
||||||
options={[
|
<h2 className="mb-3">Demos:</h2>
|
||||||
{ label: "Normal", value: "normal" },
|
<Hider
|
||||||
{ label: "Large", value: "larger" },
|
label="Verb Conjugation / Verb Phrase Engine"
|
||||||
{ label: "X-Large", value: "largest" },
|
hLevel={3}
|
||||||
]}
|
showing={showing === "verbs"}
|
||||||
value={textOptions.pTextSize}
|
handleChange={() => handleHiderClick("verbs")}
|
||||||
handleChange={(p) => setTextOptions({ ...textOptions, pTextSize: p })}
|
>
|
||||||
/>
|
<VPBuilderDemo opts={textOptions} />
|
||||||
<h6 className="mt-3">Phonetics</h6>
|
</Hider>
|
||||||
<ButtonSelect
|
<Hider
|
||||||
options={[
|
label="Equative Phrase Engine"
|
||||||
{ label: "LingDocs", value: "lingdocs" },
|
hLevel={3}
|
||||||
{ label: "IPA", value: "ipa" },
|
showing={showing === "equatives"}
|
||||||
{ label: "ALAC", value: "alalc" },
|
handleChange={() => handleHiderClick("equatives")}
|
||||||
// { label: "None", value: "none" },
|
>
|
||||||
]}
|
<div className="mt-4" style={{ paddingBottom: "20px" }}>
|
||||||
value={textOptions.phonetics}
|
<EPExplorer opts={textOptions} entryFeeder={entryFeeder} />
|
||||||
handleChange={(p) => setTextOptions({ ...textOptions, phonetics: p })}
|
</div>
|
||||||
/>
|
</Hider>
|
||||||
</Modal.Body>
|
<Hider
|
||||||
<Modal.Footer>
|
label="Inflection Engine"
|
||||||
<button type="button" className="btn btn-primary clb" onClick={() => setShowingTextOptions(false)}>
|
hLevel={3}
|
||||||
Close
|
showing={showing === "inflection"}
|
||||||
</button>
|
handleChange={() => handleHiderClick("inflection")}
|
||||||
</Modal.Footer>
|
>
|
||||||
</Modal>
|
<InflectionDemo opts={textOptions} />
|
||||||
{/* <footer className="footer mt-auto py-3" style={{ backgroundColor: "#f5f5f5" }}>
|
</Hider>
|
||||||
|
<Hider
|
||||||
|
label="Spelling Conversion / Diacritics Engine"
|
||||||
|
hLevel={3}
|
||||||
|
showing={showing === "spelling"}
|
||||||
|
handleChange={() => handleHiderClick("spelling")}
|
||||||
|
>
|
||||||
|
<SpellingDemo opts={textOptions} onChange={setTextOptions} />
|
||||||
|
</Hider>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<Modal
|
||||||
|
show={showingTextOptions}
|
||||||
|
onHide={() => setShowingTextOptions(false)}
|
||||||
|
>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title>Settings</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
<h6>Pashto Spelling</h6>
|
||||||
|
<ButtonSelect
|
||||||
|
options={[
|
||||||
|
{ label: "Afghan", value: "Afghan" },
|
||||||
|
{ label: "Pakistani ي", value: "Pakistani ي" },
|
||||||
|
{ label: "Pakistani ی", value: "Pakistani ی" },
|
||||||
|
]}
|
||||||
|
value={textOptions.spelling}
|
||||||
|
handleChange={(p) => {
|
||||||
|
setTextOptions({
|
||||||
|
...textOptions,
|
||||||
|
spelling: p,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<h6 className="mt-3">Diacritics</h6>
|
||||||
|
<ButtonSelect
|
||||||
|
options={[
|
||||||
|
{ label: "On", value: "true" },
|
||||||
|
{ label: "Off", value: "false" },
|
||||||
|
]}
|
||||||
|
value={textOptions.diacritics.toString()}
|
||||||
|
handleChange={(p) =>
|
||||||
|
setTextOptions({ ...textOptions, diacritics: p === "true" })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<h6 className="mt-3">Pashto Text Size</h6>
|
||||||
|
<ButtonSelect
|
||||||
|
options={[
|
||||||
|
{ label: "Normal", value: "normal" },
|
||||||
|
{ label: "Large", value: "larger" },
|
||||||
|
{ label: "X-Large", value: "largest" },
|
||||||
|
]}
|
||||||
|
value={textOptions.pTextSize}
|
||||||
|
handleChange={(p) =>
|
||||||
|
setTextOptions({ ...textOptions, pTextSize: p })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<h6 className="mt-3">Phonetics</h6>
|
||||||
|
<ButtonSelect
|
||||||
|
options={[
|
||||||
|
{ label: "LingDocs", value: "lingdocs" },
|
||||||
|
{ label: "IPA", value: "ipa" },
|
||||||
|
{ label: "ALAC", value: "alalc" },
|
||||||
|
// { label: "None", value: "none" },
|
||||||
|
]}
|
||||||
|
value={textOptions.phonetics}
|
||||||
|
handleChange={(p) =>
|
||||||
|
setTextOptions({ ...textOptions, phonetics: p })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-primary clb"
|
||||||
|
onClick={() => setShowingTextOptions(false)}
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
|
{/* <footer className="footer mt-auto py-3" style={{ backgroundColor: "#f5f5f5" }}>
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<span className="text-muted">Copyright © 2022 <a href="https://www.lingdocs.com">lingdocs.com</a> - <a href="https://github.com/lingdocs/pashto-inflector/blob/master/LICENSE">MIT License</a></span>
|
<span className="text-muted">Copyright © 2022 <a href="https://www.lingdocs.com">lingdocs.com</a> - <a href="https://github.com/lingdocs/pashto-inflector/blob/master/LICENSE">MIT License</a></span>
|
||||||
</div>
|
</div>
|
||||||
</footer> */}
|
</footer> */}
|
||||||
</>
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -47,4 +47,4 @@
|
||||||
"babel-loader": "^8.3.0",
|
"babel-loader": "^8.3.0",
|
||||||
"fs-extra": "^10.1.0"
|
"fs-extra": "^10.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,4 @@
|
||||||
import {
|
import { makeNounSelection } from "../../../lib/src/phrase-building/make-selections";
|
||||||
makeNounSelection,
|
|
||||||
} from "../../../lib/src/phrase-building/make-selections";
|
|
||||||
|
|
||||||
import * as T from "../../../types";
|
import * as T from "../../../types";
|
||||||
import ButtonSelect from "../ButtonSelect";
|
import ButtonSelect from "../ButtonSelect";
|
||||||
|
@ -57,45 +55,49 @@ import AdjectiveManager from "./AdjectiveManager";
|
||||||
// }
|
// }
|
||||||
|
|
||||||
function NPNounPicker(props: {
|
function NPNounPicker(props: {
|
||||||
entryFeeder: T.EntryFeeder,
|
entryFeeder: T.EntryFeeder;
|
||||||
noun: T.NounSelection | undefined,
|
noun: T.NounSelection | undefined;
|
||||||
onChange: (p: T.NounSelection | undefined) => void,
|
onChange: (p: T.NounSelection | undefined) => void;
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions;
|
||||||
phraseIsComplete: boolean,
|
phraseIsComplete: boolean;
|
||||||
}) {
|
}) {
|
||||||
// const [patternFilter, setPatternFilter] = useState<FilterPattern | undefined>(undefined);
|
console.log({ noun: props.noun });
|
||||||
// const [showFilter, setShowFilter] = useState<boolean>(false)
|
// const [patternFilter, setPatternFilter] = useState<FilterPattern | undefined>(undefined);
|
||||||
// const nounsFiltered = props.nouns
|
// const [showFilter, setShowFilter] = useState<boolean>(false)
|
||||||
// .filter(nounFilter(patternFilter))
|
// const nounsFiltered = props.nouns
|
||||||
// .sort((a, b) => (a.p.localeCompare(b.p, "af-PS")));
|
// .filter(nounFilter(patternFilter))
|
||||||
function onEntrySelect(entry: T.NounEntry | undefined) {
|
// .sort((a, b) => (a.p.localeCompare(b.p, "af-PS")));
|
||||||
if (!entry) {
|
function onEntrySelect(entry: T.NounEntry | undefined) {
|
||||||
return props.onChange(undefined);
|
if (!entry) {
|
||||||
}
|
return props.onChange(undefined);
|
||||||
props.onChange(makeNounSelection(entry, props.noun));
|
|
||||||
}
|
}
|
||||||
// function handleFilterClose() {
|
props.onChange(makeNounSelection(entry, props.noun));
|
||||||
// setPatternFilter(undefined);
|
}
|
||||||
// setShowFilter(false);
|
// function handleFilterClose() {
|
||||||
// }
|
// setPatternFilter(undefined);
|
||||||
function handelAdjectivesUpdate(adjectives: T.AdjectiveSelection[]) {
|
// setShowFilter(false);
|
||||||
if (props.noun) {
|
// }
|
||||||
props.onChange({
|
function handelAdjectivesUpdate(adjectives: T.AdjectiveSelection[]) {
|
||||||
...props.noun,
|
if (props.noun) {
|
||||||
adjectives,
|
props.onChange({
|
||||||
});
|
...props.noun,
|
||||||
}
|
adjectives,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
function handleDemonstrativeUpdate(demonstrative: undefined | T.NounSelection["demonstrative"]) {
|
}
|
||||||
if (props.noun) {
|
function handleDemonstrativeUpdate(
|
||||||
props.onChange({
|
demonstrative: undefined | T.NounSelection["demonstrative"]
|
||||||
...props.noun,
|
) {
|
||||||
demonstrative,
|
if (props.noun) {
|
||||||
});
|
props.onChange({
|
||||||
}
|
...props.noun,
|
||||||
|
demonstrative,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return <div style={{ maxWidth: "225px", minWidth: "125px" }}>
|
}
|
||||||
{/* {showFilter && <div className="mb-2 text-center">
|
return (
|
||||||
|
<div style={{ maxWidth: "225px", minWidth: "125px" }}>
|
||||||
|
{/* {showFilter && <div className="mb-2 text-center">
|
||||||
<div className="d-flex flex-row justify-content-between">
|
<div className="d-flex flex-row justify-content-between">
|
||||||
<div className="text-small mb-1">Filter by inflection pattern</div>
|
<div className="text-small mb-1">Filter by inflection pattern</div>
|
||||||
<div className="clickable" onClick={handleFilterClose}>X</div>
|
<div className="clickable" onClick={handleFilterClose}>X</div>
|
||||||
|
@ -108,72 +110,102 @@ function NPNounPicker(props: {
|
||||||
handleChange={setPatternFilter}
|
handleChange={setPatternFilter}
|
||||||
/>
|
/>
|
||||||
</div>} */}
|
</div>} */}
|
||||||
{props.noun && <AdjectiveManager
|
{props.noun && (
|
||||||
phraseIsComplete={props.phraseIsComplete}
|
<AdjectiveManager
|
||||||
adjectives={props.noun?.adjectives}
|
phraseIsComplete={props.phraseIsComplete}
|
||||||
demonstrative={props.noun.demonstrative}
|
adjectives={props.noun?.adjectives}
|
||||||
entryFeeder={props.entryFeeder}
|
demonstrative={props.noun.demonstrative}
|
||||||
|
entryFeeder={props.entryFeeder}
|
||||||
|
opts={props.opts}
|
||||||
|
onChange={handelAdjectivesUpdate}
|
||||||
|
onDemonstrativeChange={handleDemonstrativeUpdate}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div className="h6">Noun</div>
|
||||||
|
{!(
|
||||||
|
props.noun &&
|
||||||
|
(props.noun.dynamicComplement || props.noun.genStativeComplement)
|
||||||
|
) ? (
|
||||||
|
<div>
|
||||||
|
<EntrySelect
|
||||||
|
value={props.noun?.entry}
|
||||||
|
entryFeeder={props.entryFeeder.nouns}
|
||||||
|
onChange={onEntrySelect}
|
||||||
|
name="Noun"
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
onChange={handelAdjectivesUpdate}
|
/>
|
||||||
onDemonstrativeChange={handleDemonstrativeUpdate}
|
</div>
|
||||||
/>}
|
) : (
|
||||||
<div className="h6">Noun</div>
|
<div>
|
||||||
{!(props.noun && props.noun.dynamicComplement) ? <div>
|
{props.noun && (
|
||||||
<EntrySelect
|
|
||||||
value={props.noun?.entry}
|
|
||||||
entryFeeder={props.entryFeeder.nouns}
|
|
||||||
onChange={onEntrySelect}
|
|
||||||
name="Noun"
|
|
||||||
opts={props.opts}
|
|
||||||
/>
|
|
||||||
</div> : <div>
|
|
||||||
{props.noun && <div>
|
|
||||||
<div className="mb-2">Included in Dyn. Compound:</div>
|
|
||||||
<div className="mb-3 text-center">
|
|
||||||
<InlinePs opts={props.opts}>
|
|
||||||
{{ p: props.noun.entry.p, f: props.noun.entry.f }}
|
|
||||||
</InlinePs>
|
|
||||||
<div className="text-muted">{props.noun.entry.e}</div>
|
|
||||||
</div>
|
|
||||||
</div>}
|
|
||||||
</div>}
|
|
||||||
{props.noun && <div className="my-2 d-flex flex-row justify-content-around align-items-center">
|
|
||||||
<div>
|
<div>
|
||||||
{props.noun.genderCanChange ? <ButtonSelect
|
<div className="mb-2">
|
||||||
small
|
Included in{" "}
|
||||||
options={[
|
{props.noun.genStativeComplement ? "Gen. Stat." : "Dyn."}{" "}
|
||||||
{ label: "Masc", value: "masc" },
|
Compound:
|
||||||
{ label: "Fem", value: "fem" },
|
</div>
|
||||||
]}
|
<div className="mb-3 text-center">
|
||||||
value={props.noun.gender}
|
<InlinePs opts={props.opts}>
|
||||||
handleChange={(gender) => {
|
{{ p: props.noun.entry.p, f: props.noun.entry.f }}
|
||||||
if (!props.noun || !props.noun.genderCanChange) return;
|
</InlinePs>
|
||||||
props.onChange({
|
<div className="text-muted">{props.noun.entry.e}</div>
|
||||||
...props.noun,
|
</div>
|
||||||
gender,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/> : props.noun.gender === "masc" ? "Masc." : "Fem."}
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
)}
|
||||||
{props.noun.numberCanChange ? <ButtonSelect
|
</div>
|
||||||
small
|
)}
|
||||||
options={[
|
{props.noun && (
|
||||||
{ label: "Sing.", value: "singular" },
|
<div className="my-2 d-flex flex-row justify-content-around align-items-center">
|
||||||
{ label: "Plur.", value: "plural" },
|
<div>
|
||||||
]}
|
{props.noun.genderCanChange ? (
|
||||||
value={props.noun.number}
|
<ButtonSelect
|
||||||
handleChange={(number) => {
|
small
|
||||||
if (!props.noun || !props.noun.numberCanChange) return;
|
options={[
|
||||||
props.onChange({
|
{ label: "Masc", value: "masc" },
|
||||||
...props.noun,
|
{ label: "Fem", value: "fem" },
|
||||||
number,
|
]}
|
||||||
});
|
value={props.noun.gender}
|
||||||
}}
|
handleChange={(gender) => {
|
||||||
/> : props.noun.number === "singular" ? "Sing." : "Plur."}
|
if (!props.noun || !props.noun.genderCanChange) return;
|
||||||
</div>
|
props.onChange({
|
||||||
</div>}
|
...props.noun,
|
||||||
</div>;
|
gender,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : props.noun.gender === "masc" ? (
|
||||||
|
"Masc."
|
||||||
|
) : (
|
||||||
|
"Fem."
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{props.noun.numberCanChange ? (
|
||||||
|
<ButtonSelect
|
||||||
|
small
|
||||||
|
options={[
|
||||||
|
{ label: "Sing.", value: "singular" },
|
||||||
|
{ label: "Plur.", value: "plural" },
|
||||||
|
]}
|
||||||
|
value={props.noun.number}
|
||||||
|
handleChange={(number) => {
|
||||||
|
if (!props.noun || !props.noun.numberCanChange) return;
|
||||||
|
props.onChange({
|
||||||
|
...props.noun,
|
||||||
|
number,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : props.noun.number === "singular" ? (
|
||||||
|
"Sing."
|
||||||
|
) : (
|
||||||
|
"Plur."
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NPNounPicker;
|
export default NPNounPicker;
|
||||||
|
|
|
@ -9,13 +9,21 @@ import Hider from "../Hider";
|
||||||
import * as T from "../../../types";
|
import * as T from "../../../types";
|
||||||
import useStickyState from "../useStickyState";
|
import useStickyState from "../useStickyState";
|
||||||
import { isImperativeTense } from "../../../lib/src/type-predicates";
|
import { isImperativeTense } from "../../../lib/src/type-predicates";
|
||||||
|
import ButtonSelect from "../ButtonSelect";
|
||||||
|
import { VpsReducerAction } from "../../../lib/src/phrase-building/vps-reducer";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { statVerb } from "../../../lib/src/new-verb-engine/roots-and-stems";
|
||||||
// import { conjugateVerb } from "../../../lib/src/verb-conjugation";
|
// import { conjugateVerb } from "../../../lib/src/verb-conjugation";
|
||||||
|
|
||||||
function AllTensesDisplay({
|
function AllTensesDisplay({
|
||||||
VS,
|
VS,
|
||||||
opts,
|
opts,
|
||||||
|
onChange,
|
||||||
|
object,
|
||||||
}: {
|
}: {
|
||||||
|
onChange: (p: VpsReducerAction) => void;
|
||||||
VS: T.VerbSelection;
|
VS: T.VerbSelection;
|
||||||
|
object: T.NPSelection | T.ObjectNP | undefined;
|
||||||
opts: T.TextOptions;
|
opts: T.TextOptions;
|
||||||
}) {
|
}) {
|
||||||
const [showing, setShowing] = useStickyState<string[]>([], "VPTensesShowing");
|
const [showing, setShowing] = useStickyState<string[]>([], "VPTensesShowing");
|
||||||
|
@ -23,6 +31,11 @@ function AllTensesDisplay({
|
||||||
false,
|
false,
|
||||||
"showFormulasWithCharts"
|
"showFormulasWithCharts"
|
||||||
);
|
);
|
||||||
|
const [objectNPNumber, setObjectNPNumber] = useState<T.NounNumber>(
|
||||||
|
object && typeof object === "object" && object.selection.type === "noun"
|
||||||
|
? object.selection.number
|
||||||
|
: "singular"
|
||||||
|
);
|
||||||
const adjustShowing = (v: string) => {
|
const adjustShowing = (v: string) => {
|
||||||
if (showing.includes(v)) {
|
if (showing.includes(v)) {
|
||||||
setShowing((os) => os.filter((x) => x !== v));
|
setShowing((os) => os.filter((x) => x !== v));
|
||||||
|
@ -56,14 +69,69 @@ function AllTensesDisplay({
|
||||||
? (`${baseTense}Modal` as T.AbilityTense)
|
? (`${baseTense}Modal` as T.AbilityTense)
|
||||||
: baseTense;
|
: baseTense;
|
||||||
}
|
}
|
||||||
|
const objectNP: T.NPSelection | undefined =
|
||||||
|
object && typeof object === "object" && object.selection.type === "noun"
|
||||||
|
? object
|
||||||
|
: undefined;
|
||||||
|
const verb =
|
||||||
|
VS.isCompound === "generative stative"
|
||||||
|
? statVerb[
|
||||||
|
VS.transitivity === "intransitive" ? "intransitive" : "transitive"
|
||||||
|
]
|
||||||
|
: VS.dynAuxVerb
|
||||||
|
? VS.dynAuxVerb
|
||||||
|
: VS.verb;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
className="clickable mb-2 small text-center"
|
|
||||||
onClick={() => setShowFormulas((x) => !x)}
|
onClick={() => setShowFormulas((x) => !x)}
|
||||||
|
className="small clickable text-right mb-2"
|
||||||
>
|
>
|
||||||
🧪 {!showFormulas ? "Show" : "Hide"} Formulas
|
🧪 {!showFormulas ? "Show" : "Hide"} Formulas
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mb-2 d-flex flex-row justify-content-around align-items-center">
|
||||||
|
{objectNP?.selection.type === "noun" &&
|
||||||
|
objectNP.selection.numberCanChange && (
|
||||||
|
<div>
|
||||||
|
<span className="text-muted small mr-2">comp. noun:</span>
|
||||||
|
<ButtonSelect
|
||||||
|
xSmall
|
||||||
|
value={objectNPNumber}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: "sing.",
|
||||||
|
value: "singular",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "plur.",
|
||||||
|
value: "plural",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
handleChange={(number) => {
|
||||||
|
setObjectNPNumber(number);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<ButtonSelect
|
||||||
|
xSmall
|
||||||
|
value={VS.negative.toString() as "true" | "false"}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: "Pos.",
|
||||||
|
value: "false",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Neg.",
|
||||||
|
value: "true",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
handleChange={(payload) =>
|
||||||
|
onChange({ type: "set negativity", payload })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{options.map((tense) => {
|
{options.map((tense) => {
|
||||||
const t = getTense(tense.value);
|
const t = getTense(tense.value);
|
||||||
return (
|
return (
|
||||||
|
@ -81,7 +149,20 @@ function AllTensesDisplay({
|
||||||
)}
|
)}
|
||||||
{showing && (
|
{showing && (
|
||||||
<ChartDisplay
|
<ChartDisplay
|
||||||
verb={VS.verb}
|
verb={verb}
|
||||||
|
objectNP={
|
||||||
|
objectNP?.selection.type === "noun"
|
||||||
|
? {
|
||||||
|
...objectNP,
|
||||||
|
selection: {
|
||||||
|
...objectNP.selection,
|
||||||
|
number: objectNP.selection.numberCanChange
|
||||||
|
? objectNPNumber
|
||||||
|
: objectNP.selection.number,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
negative={VS.negative}
|
negative={VS.negative}
|
||||||
tense={t}
|
tense={t}
|
||||||
transitivity={VS.transitivity}
|
transitivity={VS.transitivity}
|
||||||
|
|
|
@ -8,7 +8,13 @@ import { choosePersInf, getLength } from "../../../lib/src/p-text-helpers";
|
||||||
import genderColors from "../gender-colors";
|
import genderColors from "../gender-colors";
|
||||||
import { eqPsStringWVars } from "../../../lib/src/fp-ps";
|
import { eqPsStringWVars } from "../../../lib/src/fp-ps";
|
||||||
import PersInfsPicker from "../PersInfsPicker";
|
import PersInfsPicker from "../PersInfsPicker";
|
||||||
import { useMediaPredicate } from "react-media-hook";
|
import "./form-display.css";
|
||||||
|
import {
|
||||||
|
makeBlock,
|
||||||
|
makeKid,
|
||||||
|
} from "../../../lib/src/phrase-building/blocks-utils";
|
||||||
|
import InlinePs from "../InlinePs";
|
||||||
|
import { personToGenNum } from "../../../lib/src/misc-helpers";
|
||||||
|
|
||||||
export const roleIcon = {
|
export const roleIcon = {
|
||||||
king: <i className="mx-1 fas fa-crown" />,
|
king: <i className="mx-1 fas fa-crown" />,
|
||||||
|
@ -21,14 +27,21 @@ function VerbChartDisplay({
|
||||||
shortDefault,
|
shortDefault,
|
||||||
transitivity,
|
transitivity,
|
||||||
past,
|
past,
|
||||||
|
negative,
|
||||||
|
imperative,
|
||||||
}: {
|
}: {
|
||||||
chart: T.OptionalPersonInflections<
|
chart: {
|
||||||
T.SingleOrLengthOpts<T.RenderVerbOutput[]>
|
objNP: T.Rendered<T.NPSelection> | undefined;
|
||||||
>;
|
vbs: T.OptionalPersonInflections<
|
||||||
|
T.SingleOrLengthOpts<T.RenderVerbOutput[]>
|
||||||
|
>;
|
||||||
|
};
|
||||||
opts: T.TextOptions;
|
opts: T.TextOptions;
|
||||||
shortDefault?: boolean;
|
shortDefault?: boolean;
|
||||||
transitivity: T.Transitivity;
|
transitivity: T.Transitivity;
|
||||||
past: boolean;
|
past: boolean;
|
||||||
|
negative: boolean;
|
||||||
|
imperative: boolean;
|
||||||
}) {
|
}) {
|
||||||
const [length, setLength] = useState<T.Length>(
|
const [length, setLength] = useState<T.Length>(
|
||||||
shortDefault ? "short" : "long"
|
shortDefault ? "short" : "long"
|
||||||
|
@ -37,13 +50,23 @@ function VerbChartDisplay({
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLength("long");
|
setLength("long");
|
||||||
}, [chart]);
|
}, [chart]);
|
||||||
const desktop = useMediaPredicate("(min-width: 600px)");
|
const chartWPers = choosePersInf(chart.vbs, persInf);
|
||||||
const chartWPers = choosePersInf(chart, persInf);
|
|
||||||
const chartWLength = getLength(chartWPers, length);
|
const chartWLength = getLength(chartWPers, length);
|
||||||
|
|
||||||
const x = chartWLength.map(renderVerbOutputToText(false));
|
const x = chartWLength.map(
|
||||||
|
renderVerbOutputToText({
|
||||||
|
objNP: chart.objNP,
|
||||||
|
negative,
|
||||||
|
hasBa: chartWLength[0].hasBa,
|
||||||
|
imperative,
|
||||||
|
intransitive: transitivity === "intransitive",
|
||||||
|
})
|
||||||
|
);
|
||||||
const verbBlock =
|
const verbBlock =
|
||||||
x.length === 12
|
x.length === 1
|
||||||
|
? // unchanging gramm trans or dynamic compound past transitive
|
||||||
|
[[[x[0]]]]
|
||||||
|
: x.length === 12
|
||||||
? [
|
? [
|
||||||
// 1st pers
|
// 1st pers
|
||||||
[
|
[
|
||||||
|
@ -83,10 +106,15 @@ function VerbChartDisplay({
|
||||||
</div>
|
</div>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<AgreementInfo transitivity={transitivity} past={past} />
|
<AgreementInfo
|
||||||
|
opts={opts}
|
||||||
|
transitivity={transitivity}
|
||||||
|
past={past}
|
||||||
|
objNP={chart.objNP}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col">
|
<div className="col">
|
||||||
{"long" in chartWPers && (
|
{"long" in chartWPers && lengthsMakeADiff(chartWPers) && (
|
||||||
<LengthSelection
|
<LengthSelection
|
||||||
hasMini={"mini" in chartWPers}
|
hasMini={"mini" in chartWPers}
|
||||||
value={length}
|
value={length}
|
||||||
|
@ -94,30 +122,36 @@ function VerbChartDisplay({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{desktop && <div className="col" />}
|
<div className="hide-on-mobile col" />
|
||||||
</div>
|
</div>
|
||||||
<table className="table mt-2" style={{ tableLayout: "fixed" }}>
|
{verbBlock.length === 1 ? (
|
||||||
<thead>
|
<div className="d-flex flex-row justify-content-center mt-3 text-center">
|
||||||
<tr>
|
<TableCell item={verbBlock[0][0][0]} textOptions={opts} />
|
||||||
<th scope="col" style={{ width: "3rem" }}>
|
</div>
|
||||||
Pers.
|
) : (
|
||||||
</th>
|
<table className="table mt-2" style={{ tableLayout: "fixed" }}>
|
||||||
<th scope="col">Singular</th>
|
<thead>
|
||||||
<th scope="col">Plural</th>
|
<tr>
|
||||||
</tr>
|
<th scope="col" style={{ width: "3rem" }}>
|
||||||
</thead>
|
Pers.
|
||||||
<tbody>
|
</th>
|
||||||
{verbBlock.map((personRow, i) => (
|
<th scope="col">Singular</th>
|
||||||
<PersonRow
|
<th scope="col">Plural</th>
|
||||||
key={Math.random()}
|
</tr>
|
||||||
// get proper version for imperative blocks
|
</thead>
|
||||||
person={verbBlock.length === 1 ? 1 : i}
|
<tbody>
|
||||||
item={personRow}
|
{verbBlock.map((personRow, i) => (
|
||||||
opts={opts}
|
<PersonRow
|
||||||
/>
|
key={Math.random()}
|
||||||
))}
|
// get proper version for imperative blocks
|
||||||
</tbody>
|
person={verbBlock.length === 1 ? 1 : i}
|
||||||
</table>
|
item={personRow}
|
||||||
|
opts={opts}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -224,32 +258,93 @@ function LengthSelection({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderVerbOutputToText(negative: boolean) {
|
function renderVerbOutputToText({
|
||||||
|
objNP,
|
||||||
|
negative,
|
||||||
|
hasBa,
|
||||||
|
imperative,
|
||||||
|
intransitive,
|
||||||
|
}: {
|
||||||
|
objNP: T.Rendered<T.NPSelection> | undefined;
|
||||||
|
negative: boolean;
|
||||||
|
hasBa: boolean;
|
||||||
|
imperative: boolean;
|
||||||
|
intransitive: boolean;
|
||||||
|
}) {
|
||||||
return function (v: T.RenderVerbOutput): T.PsString[] {
|
return function (v: T.RenderVerbOutput): T.PsString[] {
|
||||||
const blocks = insertNegative(
|
const blocks: T.Block[][] = insertNegative(v.vbs, negative, imperative).map(
|
||||||
v.vbs,
|
(b) => {
|
||||||
negative,
|
if (!objNP) return b;
|
||||||
false /* TODO: apply imperative */
|
return [
|
||||||
|
...(objNP
|
||||||
|
? [makeBlock({ type: "objectSelection", selection: objNP })]
|
||||||
|
: []),
|
||||||
|
...b,
|
||||||
|
];
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return combineIntoText(blocks, 0 /* TODO: why is this needed */);
|
|
||||||
|
const b = hasBa
|
||||||
|
? blocks.flatMap((v) => [
|
||||||
|
[
|
||||||
|
{ p: " ... ", f: " ... " },
|
||||||
|
...[makeKid({ type: "ba" }), { p: " ... ", f: " ... " }],
|
||||||
|
...v,
|
||||||
|
],
|
||||||
|
...(v.length > 1 && intransitive
|
||||||
|
? [[v[0], makeKid({ type: "ba" }), ...v.slice(1)]]
|
||||||
|
: []),
|
||||||
|
])
|
||||||
|
: blocks;
|
||||||
|
return combineIntoText(b, 0 /* TODO: why is this needed */);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function AgreementInfo({
|
function AgreementInfo({
|
||||||
transitivity,
|
transitivity,
|
||||||
past,
|
past,
|
||||||
|
objNP,
|
||||||
|
opts,
|
||||||
}: {
|
}: {
|
||||||
transitivity: T.Transitivity;
|
transitivity: T.Transitivity;
|
||||||
past: boolean;
|
past: boolean;
|
||||||
|
objNP: T.Rendered<T.NPSelection> | undefined;
|
||||||
|
opts: T.TextOptions;
|
||||||
}) {
|
}) {
|
||||||
|
function printGenNum({ gender, number }: T.GenderNumber): string {
|
||||||
|
return `${gender === "masc" ? "m." : "f."} ${
|
||||||
|
number === "singular" ? "s." : "pl."
|
||||||
|
}`;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div className="text-muted small mt-1">
|
<div className="text-muted small mt-1">
|
||||||
{roleIcon.king} agrees w/{" "}
|
<div>
|
||||||
<strong>
|
{roleIcon.king} agrees w/{" "}
|
||||||
{transitivity !== "intransitive" && past ? "object" : "subject"}
|
<strong>
|
||||||
</strong>
|
{transitivity !== "intransitive" && past ? "object" : "subject"}
|
||||||
|
</strong>
|
||||||
|
{transitivity === "transitive" && past && objNP ? " noun" : ""}
|
||||||
|
</div>
|
||||||
|
{transitivity === "transitive" && past && objNP && (
|
||||||
|
<div>
|
||||||
|
<InlinePs opts={opts}>{objNP.selection.ps[0]}</InlinePs>
|
||||||
|
{` `}({printGenNum(personToGenNum(objNP.selection.person))})
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{transitivity === "grammatically transitive" && past && (
|
||||||
|
<div>(implied 3rd pers. m. pl.)</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function lengthsMakeADiff(v: T.LengthOptions<T.RenderVerbOutput[]>): boolean {
|
||||||
|
if (v.long.length > 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const longSample = combineIntoText([[makeBlock(v.long[0].vbs[1][0])]], 0);
|
||||||
|
const shortSample = combineIntoText([[makeBlock(v.short[0].vbs[1][0])]], 0);
|
||||||
|
return !eqPsStringWVars.equals(longSample, shortSample);
|
||||||
|
}
|
||||||
|
|
||||||
export default VerbChartDisplay;
|
export default VerbChartDisplay;
|
||||||
|
|
|
@ -3,6 +3,8 @@ import * as T from "../../../types";
|
||||||
import { buildVerbChart } from "./chart-builder";
|
import { buildVerbChart } from "./chart-builder";
|
||||||
import { isPastTense } from "../../library";
|
import { isPastTense } from "../../library";
|
||||||
|
|
||||||
|
// TODO - combine this with NewVerbFormDisplay
|
||||||
|
|
||||||
function ChartDisplay({
|
function ChartDisplay({
|
||||||
verb,
|
verb,
|
||||||
tense,
|
tense,
|
||||||
|
@ -11,6 +13,7 @@ function ChartDisplay({
|
||||||
imperative,
|
imperative,
|
||||||
negative,
|
negative,
|
||||||
transitivity,
|
transitivity,
|
||||||
|
objectNP,
|
||||||
}: {
|
}: {
|
||||||
verb: T.VerbEntry;
|
verb: T.VerbEntry;
|
||||||
tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense;
|
tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense;
|
||||||
|
@ -19,6 +22,7 @@ function ChartDisplay({
|
||||||
imperative: boolean;
|
imperative: boolean;
|
||||||
negative: boolean;
|
negative: boolean;
|
||||||
transitivity: T.Transitivity;
|
transitivity: T.Transitivity;
|
||||||
|
objectNP: T.NPSelection | undefined;
|
||||||
}) {
|
}) {
|
||||||
const verbChart = buildVerbChart({
|
const verbChart = buildVerbChart({
|
||||||
verb,
|
verb,
|
||||||
|
@ -27,10 +31,13 @@ function ChartDisplay({
|
||||||
negative,
|
negative,
|
||||||
transitivity,
|
transitivity,
|
||||||
imperative,
|
imperative,
|
||||||
|
objectNP,
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<NewVerbFormDisplay
|
<NewVerbFormDisplay
|
||||||
|
imperative={imperative}
|
||||||
|
negative={negative}
|
||||||
chart={verbChart}
|
chart={verbChart}
|
||||||
opts={opts}
|
opts={opts}
|
||||||
transitivity={transitivity}
|
transitivity={transitivity}
|
||||||
|
|
|
@ -28,213 +28,244 @@ export const vpPhraseURLParam = "vp";
|
||||||
// TODO: error handling on error with rendering etc
|
// TODO: error handling on error with rendering etc
|
||||||
|
|
||||||
function VPExplorer(props: {
|
function VPExplorer(props: {
|
||||||
loaded?: T.VPSelectionState,
|
loaded?: T.VPSelectionState;
|
||||||
verb: T.VerbEntry,
|
verb: T.VerbEntry;
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions;
|
||||||
handleLinkClick: ((ts: number) => void) | "none",
|
handleLinkClick: ((ts: number) => void) | "none";
|
||||||
entryFeeder: T.EntryFeeder,
|
entryFeeder: T.EntryFeeder;
|
||||||
onlyPhrases?: boolean,
|
onlyPhrases?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const [vps, adjustVps] = useStickyReducer(
|
const [vps, adjustVps] = useStickyReducer(
|
||||||
vpsReducer,
|
vpsReducer,
|
||||||
props.loaded
|
props.loaded
|
||||||
? props.loaded
|
? props.loaded
|
||||||
: savedVps => makeVPSelectionState(props.verb, savedVps),
|
: (savedVps) => makeVPSelectionState(props.verb, savedVps),
|
||||||
"vpsState16",
|
"vpsState16",
|
||||||
flashMessage,
|
flashMessage
|
||||||
);
|
);
|
||||||
const [mode, setMode] = useStickyState<"charts" | "phrases" | "quiz">(
|
const [mode, setMode] = useStickyState<"charts" | "phrases" | "quiz">(
|
||||||
savedMode => {
|
(savedMode) => {
|
||||||
if (!savedMode) return props.onlyPhrases ? "phrases" : "charts";
|
if (!savedMode) return props.onlyPhrases ? "phrases" : "charts";
|
||||||
if (savedMode === "quiz") return "phrases";
|
if (savedMode === "quiz") return "phrases";
|
||||||
return savedMode;
|
return savedMode;
|
||||||
},
|
},
|
||||||
"verbExplorerMode2",
|
"verbExplorerMode2"
|
||||||
);
|
);
|
||||||
const [showClipped, setShowClipped] = useState<string>("");
|
const [showClipped, setShowClipped] = useState<string>("");
|
||||||
const [
|
const [
|
||||||
alertMsg,
|
alertMsg,
|
||||||
// setAlertMsg,
|
// setAlertMsg,
|
||||||
] = useState<string | undefined>(undefined);
|
] = useState<string | undefined>(undefined);
|
||||||
function flashMessage(msg: string) {
|
function flashMessage(msg: string) {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
// for some crazy reason this causes it to go through with the state change
|
// for some crazy reason this causes it to go through with the state change
|
||||||
// we're trying to avoid when there's a potential errored state
|
// we're trying to avoid when there's a potential errored state
|
||||||
// setAlertMsg(msg);
|
// setAlertMsg(msg);
|
||||||
// setTimeout(() => {
|
// setTimeout(() => {
|
||||||
// setAlertMsg(undefined);
|
// setAlertMsg(undefined);
|
||||||
// }, 2000);
|
// }, 2000);
|
||||||
|
}
|
||||||
|
useEffect(() => {
|
||||||
|
adjustVps({
|
||||||
|
type: "set verb",
|
||||||
|
payload: props.verb,
|
||||||
|
});
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, [props.verb]);
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.loaded) {
|
||||||
|
adjustVps({
|
||||||
|
type: "load vps",
|
||||||
|
payload: props.loaded,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
useEffect(() => {
|
// eslint-disable-next-line
|
||||||
adjustVps({
|
}, [props.loaded]);
|
||||||
type: "set verb",
|
useEffect(() => {
|
||||||
payload: props.verb,
|
const VPSFromUrl = getVPSFromUrl();
|
||||||
});
|
if (VPSFromUrl) {
|
||||||
// eslint-disable-next-line
|
setMode("phrases");
|
||||||
}, [props.verb]);
|
adjustVps({
|
||||||
useEffect(() => {
|
type: "load vps",
|
||||||
if (props.loaded) {
|
payload: VPSFromUrl,
|
||||||
adjustVps({
|
});
|
||||||
type: "load vps",
|
|
||||||
payload: props.loaded,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, [props.loaded]);
|
|
||||||
useEffect(() => {
|
|
||||||
const VPSFromUrl = getVPSFromUrl();
|
|
||||||
if (VPSFromUrl) {
|
|
||||||
setMode("phrases");
|
|
||||||
adjustVps({
|
|
||||||
type: "load vps",
|
|
||||||
payload: VPSFromUrl
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, []);
|
|
||||||
function handleSubjObjSwap() {
|
|
||||||
adjustVps({ type: "swap subj/obj" });
|
|
||||||
}
|
}
|
||||||
function quizLock<T>(f: T) {
|
// eslint-disable-next-line
|
||||||
if (mode === "quiz") {
|
}, []);
|
||||||
return () => {
|
function handleSubjObjSwap() {
|
||||||
flashMessage("to adjust this, get out of quiz mode");
|
adjustVps({ type: "swap subj/obj" });
|
||||||
return null;
|
}
|
||||||
};
|
function quizLock<T>(f: T) {
|
||||||
}
|
if (mode === "quiz") {
|
||||||
return f;
|
return () => {
|
||||||
|
flashMessage("to adjust this, get out of quiz mode");
|
||||||
|
return null;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
function handleSetForm(form: T.FormVersion) {
|
return f;
|
||||||
adjustVps({
|
}
|
||||||
type: "set form",
|
function handleSetForm(form: T.FormVersion) {
|
||||||
payload: form,
|
adjustVps({
|
||||||
});
|
type: "set form",
|
||||||
}
|
payload: form,
|
||||||
function flashClippedMessage(m: string) {
|
});
|
||||||
setShowClipped(m);
|
}
|
||||||
setTimeout(() => {
|
function flashClippedMessage(m: string) {
|
||||||
setShowClipped("");
|
setShowClipped(m);
|
||||||
}, 1250);
|
setTimeout(() => {
|
||||||
}
|
setShowClipped("");
|
||||||
// for some crazy reason I can't get the URI share thing to encode and decode properly
|
}, 1250);
|
||||||
function handleCopyShareLink() {
|
}
|
||||||
const shareUrl = getShareUrl(vps);
|
// for some crazy reason I can't get the URI share thing to encode and decode properly
|
||||||
navigator.clipboard.writeText(shareUrl);
|
function handleCopyShareLink() {
|
||||||
flashClippedMessage("Copied phrase URL to clipboard");
|
const shareUrl = getShareUrl(vps);
|
||||||
}
|
navigator.clipboard.writeText(shareUrl);
|
||||||
function handleCopyCode() {
|
flashClippedMessage("Copied phrase URL to clipboard");
|
||||||
const code = getCode(vps);
|
}
|
||||||
navigator.clipboard.writeText(code);
|
function handleCopyCode() {
|
||||||
flashClippedMessage("Copied phrase code to clipboard");
|
const code = getCode(vps);
|
||||||
}
|
navigator.clipboard.writeText(code);
|
||||||
const object = getObjectSelection(vps.blocks).selection;
|
flashClippedMessage("Copied phrase code to clipboard");
|
||||||
const VPS = completeVPSelection(vps);
|
}
|
||||||
const phraseIsComplete = !!VPS;
|
const object = getObjectSelection(vps.blocks).selection;
|
||||||
return <div className="mt-3" style={{ maxWidth: "950px"}}>
|
const VPS = completeVPSelection(vps);
|
||||||
<VerbPicker
|
const phraseIsComplete = !!VPS;
|
||||||
vps={vps}
|
return (
|
||||||
onChange={quizLock(adjustVps)}
|
<div className="mt-3" style={{ maxWidth: "950px" }}>
|
||||||
opts={props.opts}
|
<VerbPicker
|
||||||
handleLinkClick={props.handleLinkClick}
|
vps={vps}
|
||||||
|
onChange={quizLock(adjustVps)}
|
||||||
|
opts={props.opts}
|
||||||
|
handleLinkClick={props.handleLinkClick}
|
||||||
|
/>
|
||||||
|
{!props.onlyPhrases && (
|
||||||
|
<div className="mt-2 mb-3 d-flex flex-row justify-content-between align-items-center">
|
||||||
|
<div style={{ width: "1rem" }}></div>
|
||||||
|
<ButtonSelect
|
||||||
|
value={mode}
|
||||||
|
options={[
|
||||||
|
{ label: "Charts", value: "charts" },
|
||||||
|
{ label: "Phrases", value: "phrases" },
|
||||||
|
{ label: "Quiz", value: "quiz" },
|
||||||
|
]}
|
||||||
|
handleChange={setMode}
|
||||||
|
/>
|
||||||
|
<div className="d-flex flex-row">
|
||||||
|
<div
|
||||||
|
className="clickable mr-4"
|
||||||
|
onClick={mode === "phrases" ? handleCopyCode : undefined}
|
||||||
|
style={{ width: "1rem" }}
|
||||||
|
>
|
||||||
|
{mode === "phrases" && phraseIsComplete ? (
|
||||||
|
<i className="fas fa-code" />
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="clickable"
|
||||||
|
onClick={mode === "phrases" ? handleCopyShareLink : undefined}
|
||||||
|
style={{ width: "1rem" }}
|
||||||
|
>
|
||||||
|
{mode === "phrases" ? <i className="fas fa-share-alt" /> : ""}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{vps.verb &&
|
||||||
|
typeof object === "object" &&
|
||||||
|
vps.verb.isCompound !== "dynamic" &&
|
||||||
|
vps.verb.tenseCategory !== "imperative" &&
|
||||||
|
mode === "phrases" && (
|
||||||
|
<div className="text-center my-2">
|
||||||
|
<button
|
||||||
|
onClick={handleSubjObjSwap}
|
||||||
|
className="btn btn-sm btn-light"
|
||||||
|
>
|
||||||
|
<i className="fas fa-exchange-alt mr-2" /> subj/obj
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{mode === "phrases" && (
|
||||||
|
<VPPicker
|
||||||
|
opts={props.opts}
|
||||||
|
entryFeeder={props.entryFeeder}
|
||||||
|
onChange={(payload) => adjustVps({ type: "load vps", payload })}
|
||||||
|
vps={vps}
|
||||||
/>
|
/>
|
||||||
{!props.onlyPhrases && <div className="mt-2 mb-3 d-flex flex-row justify-content-between align-items-center">
|
)}
|
||||||
<div style={{ width: "1rem" }}>
|
{mode !== "phrases" && (
|
||||||
</div>
|
<div className="my-2">
|
||||||
<ButtonSelect
|
<TensePicker vps={vps} onChange={adjustVps} mode={mode} />
|
||||||
value={mode}
|
</div>
|
||||||
options={[
|
)}
|
||||||
{ label: "Charts", value: "charts" },
|
{mode === "phrases" && (
|
||||||
{ label: "Phrases", value: "phrases" },
|
<VPDisplay VPS={vps} opts={props.opts} setForm={handleSetForm} />
|
||||||
{ label: "Quiz", value: "quiz" },
|
)}
|
||||||
]}
|
{mode === "charts" && (
|
||||||
handleChange={setMode}
|
<AllTensesDisplay
|
||||||
/>
|
object={object}
|
||||||
<div className="d-flex flex-row">
|
VS={vps.verb}
|
||||||
<div
|
opts={props.opts}
|
||||||
className="clickable mr-4"
|
onChange={adjustVps}
|
||||||
onClick={mode === "phrases" ? handleCopyCode : undefined}
|
/>
|
||||||
style={{ width: "1rem" }}
|
)}
|
||||||
>
|
{mode === "quiz" && <VPExplorerQuiz opts={props.opts} vps={vps} />}
|
||||||
{(mode === "phrases" && phraseIsComplete) ? <i className="fas fa-code" /> : ""}
|
{showClipped && (
|
||||||
</div>
|
<div
|
||||||
<div
|
className="alert alert-primary text-center"
|
||||||
className="clickable"
|
role="alert"
|
||||||
onClick={mode === "phrases" ? handleCopyShareLink : undefined}
|
style={{
|
||||||
style={{ width: "1rem" }}
|
|
||||||
>
|
|
||||||
{mode === "phrases" ? <i className="fas fa-share-alt" /> : ""}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>}
|
|
||||||
{(vps.verb && (typeof object === "object") && (vps.verb.isCompound !== "dynamic") && (vps.verb.tenseCategory !== "imperative") &&(mode === "phrases")) &&
|
|
||||||
<div className="text-center my-2">
|
|
||||||
<button onClick={handleSubjObjSwap} className="btn btn-sm btn-light">
|
|
||||||
<i className="fas fa-exchange-alt mr-2" /> subj/obj
|
|
||||||
</button>
|
|
||||||
</div>}
|
|
||||||
{mode === "phrases" && <VPPicker
|
|
||||||
opts={props.opts}
|
|
||||||
entryFeeder={props.entryFeeder}
|
|
||||||
onChange={(payload) => adjustVps({ type: "load vps", payload })}
|
|
||||||
vps={vps}
|
|
||||||
/>}
|
|
||||||
{mode !== "phrases" && <div className="my-2">
|
|
||||||
<TensePicker
|
|
||||||
vps={vps}
|
|
||||||
onChange={adjustVps}
|
|
||||||
mode={mode}
|
|
||||||
/>
|
|
||||||
</div>}
|
|
||||||
{mode === "phrases" && <VPDisplay
|
|
||||||
VPS={vps}
|
|
||||||
opts={props.opts}
|
|
||||||
setForm={handleSetForm}
|
|
||||||
/>}
|
|
||||||
{mode === "charts" && <AllTensesDisplay VS={vps.verb} opts={props.opts} />}
|
|
||||||
{mode === "quiz" && <VPExplorerQuiz opts={props.opts} vps={vps} />}
|
|
||||||
{showClipped && <div className="alert alert-primary text-center" role="alert" style={{
|
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
top: "30%",
|
top: "30%",
|
||||||
left: "50%",
|
left: "50%",
|
||||||
transform: "translate(-50%, -50%)",
|
transform: "translate(-50%, -50%)",
|
||||||
zIndex: 9999999999999,
|
zIndex: 9999999999999,
|
||||||
}}>
|
}}
|
||||||
{showClipped}
|
>
|
||||||
</div>}
|
{showClipped}
|
||||||
{alertMsg && <div className="alert alert-warning text-center" role="alert" style={{
|
</div>
|
||||||
|
)}
|
||||||
|
{alertMsg && (
|
||||||
|
<div
|
||||||
|
className="alert alert-warning text-center"
|
||||||
|
role="alert"
|
||||||
|
style={{
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
top: "30%",
|
top: "30%",
|
||||||
left: "50%",
|
left: "50%",
|
||||||
transform: "translate(-50%, -50%)",
|
transform: "translate(-50%, -50%)",
|
||||||
zIndex: 9999999999999,
|
zIndex: 9999999999999,
|
||||||
}}>
|
}}
|
||||||
{alertMsg}
|
>
|
||||||
</div>}
|
{alertMsg}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default VPExplorer;
|
export default VPExplorer;
|
||||||
|
|
||||||
function getShareUrl(vps: T.VPSelectionState): string {
|
function getShareUrl(vps: T.VPSelectionState): string {
|
||||||
const code = getCode(vps);
|
const code = getCode(vps);
|
||||||
const encoded = LZString.compressToEncodedURIComponent(code);
|
const encoded = LZString.compressToEncodedURIComponent(code);
|
||||||
const url = new URL(window.location.href);
|
const url = new URL(window.location.href);
|
||||||
// need to delete or else you could just get a second param written after
|
// need to delete or else you could just get a second param written after
|
||||||
// which gets ignored
|
// which gets ignored
|
||||||
url.searchParams.delete(vpPhraseURLParam);
|
url.searchParams.delete(vpPhraseURLParam);
|
||||||
url.searchParams.append(vpPhraseURLParam, encoded);
|
url.searchParams.append(vpPhraseURLParam, encoded);
|
||||||
return url.toString();
|
return url.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCode(vps: T.VPSelectionState): string {
|
function getCode(vps: T.VPSelectionState): string {
|
||||||
return JSON.stringify(vps);
|
return JSON.stringify(vps);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVPSFromUrl(): T.VPSelectionState | undefined {
|
function getVPSFromUrl(): T.VPSelectionState | undefined {
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const fromParams = params.get(vpPhraseURLParam);
|
const fromParams = params.get(vpPhraseURLParam);
|
||||||
if (!fromParams) return;
|
if (!fromParams) return;
|
||||||
const decoded = LZString.decompressFromEncodedURIComponent(fromParams);
|
const decoded = LZString.decompressFromEncodedURIComponent(fromParams);
|
||||||
return JSON.parse(decoded) as T.VPSelectionState;
|
return JSON.parse(decoded) as T.VPSelectionState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,232 +2,435 @@ import NPPicker, { shrunkenBackground } from "../../src/np-picker/NPPicker";
|
||||||
import TensePicker from "./TensePicker";
|
import TensePicker from "./TensePicker";
|
||||||
import * as T from "../../../types";
|
import * as T from "../../../types";
|
||||||
import {
|
import {
|
||||||
// useEffect,
|
// useEffect,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { getKingAndServant, renderVP } from "../../../lib/src/phrase-building/render-vp";
|
import {
|
||||||
import { completeVPSelection, isPastTense } from "../../../lib/src/phrase-building/vp-tools";
|
getKingAndServant,
|
||||||
import VPExplorerExplanationModal, { roleIcon } from "./VPExplorerExplanationModal";
|
renderVP,
|
||||||
|
} from "../../../lib/src/phrase-building/render-vp";
|
||||||
|
import {
|
||||||
|
completeVPSelection,
|
||||||
|
isPastTense,
|
||||||
|
} from "../../../lib/src/phrase-building/vp-tools";
|
||||||
|
import VPExplorerExplanationModal, {
|
||||||
|
roleIcon,
|
||||||
|
} from "./VPExplorerExplanationModal";
|
||||||
import APPicker from "../../src/ap-picker/APPicker";
|
import APPicker from "../../src/ap-picker/APPicker";
|
||||||
// import autoAnimate from "@formkit/auto-animate";
|
// import autoAnimate from "@formkit/auto-animate";
|
||||||
import {
|
import {
|
||||||
getObjectSelection,
|
getObjectSelection,
|
||||||
getSubjectSelection,
|
getSubjectSelection,
|
||||||
includesShrunkenServant,
|
includesShrunkenServant,
|
||||||
isNoObject,
|
isNoObject,
|
||||||
} from "../../../lib/src/phrase-building/blocks-utils";
|
} from "../../../lib/src/phrase-building/blocks-utils";
|
||||||
import ComplementPicker from "../ComplementPicker";
|
import ComplementPicker from "../ComplementPicker";
|
||||||
import { vpsReducer, VpsReducerAction } from "../../../lib/src/phrase-building/vps-reducer";
|
import {
|
||||||
|
vpsReducer,
|
||||||
|
VpsReducerAction,
|
||||||
|
} from "../../../lib/src/phrase-building/vps-reducer";
|
||||||
|
|
||||||
function VPPicker({ opts, vps, onChange, entryFeeder }: {
|
function VPPicker({
|
||||||
opts: T.TextOptions,
|
opts,
|
||||||
vps: T.VPSelectionState,
|
vps,
|
||||||
onChange: (vps: T.VPSelectionState) => void,
|
onChange,
|
||||||
entryFeeder: T.EntryFeeder,
|
entryFeeder,
|
||||||
|
}: {
|
||||||
|
opts: T.TextOptions;
|
||||||
|
vps: T.VPSelectionState;
|
||||||
|
onChange: (vps: T.VPSelectionState) => void;
|
||||||
|
entryFeeder: T.EntryFeeder;
|
||||||
}) {
|
}) {
|
||||||
const parent = useRef<HTMLDivElement>(null);
|
const parent = useRef<HTMLDivElement>(null);
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// parent.current && autoAnimate(parent.current);
|
// parent.current && autoAnimate(parent.current);
|
||||||
// }, [parent]);
|
// }, [parent]);
|
||||||
const [showingExplanation, setShowingExplanation] = useState<{ role: "servant" | "king", item: "subject" | "object" } | false>(false);
|
const [showingExplanation, setShowingExplanation] =
|
||||||
function adjustVps(action: VpsReducerAction) {
|
useState<{ role: "servant" | "king"; item: "subject" | "object" } | false>(
|
||||||
onChange(vpsReducer(vps, action));
|
false
|
||||||
}
|
|
||||||
function handleSubjectChange(subject: T.NPSelection | undefined, skipPronounConflictCheck?: boolean) {
|
|
||||||
adjustVps({
|
|
||||||
type: "set subject",
|
|
||||||
payload: { subject, skipPronounConflictCheck },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function handleObjectChange(object: T.NPSelection | undefined) {
|
|
||||||
adjustVps({
|
|
||||||
type: "set object",
|
|
||||||
payload: object,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const object = getObjectSelection(vps.blocks).selection;
|
|
||||||
const subject = getSubjectSelection(vps.blocks).selection;
|
|
||||||
const VPS = completeVPSelection(vps);
|
|
||||||
const phraseIsComplete = !!VPS;
|
|
||||||
const rendered = VPS ? renderVP(VPS) : undefined;
|
|
||||||
const servantIsShrunk = includesShrunkenServant(rendered?.kids);
|
|
||||||
const isPast = isPastTense(vps.verb.tenseCategory === "perfect" ? vps.verb.perfectTense : vps.verb.verbTense);
|
|
||||||
const roles = getKingAndServant(
|
|
||||||
isPast,
|
|
||||||
vps.verb.transitivity !== "intransitive",
|
|
||||||
);
|
);
|
||||||
return <div>
|
function adjustVps(action: VpsReducerAction) {
|
||||||
<div className="clickable h5" onClick={() => adjustVps({ type: "insert new AP" })}>+ AP</div>
|
onChange(vpsReducer(vps, action));
|
||||||
<div ref={parent} className="d-flex flex-row justify-content-around flex-wrap" style={{ marginLeft: "-0.5rem", marginRight: "-0.5rem" }}>
|
}
|
||||||
{vps.blocks.map(({ block, key }, i, blocks) => {
|
function handleSubjectChange(
|
||||||
if (isNoObject(block)) return null;
|
subject: T.NPSelection | undefined,
|
||||||
return <div className="my-2 card block-card p-1 mx-1" key={key} style={{
|
skipPronounConflictCheck?: boolean
|
||||||
background: (servantIsShrunk && (
|
) {
|
||||||
(roles.servant === "subject" && block?.type === "subjectSelection")
|
adjustVps({
|
||||||
||
|
type: "set subject",
|
||||||
(roles.servant === "object" && block?.type === "objectSelection")
|
payload: { subject, skipPronounConflictCheck },
|
||||||
)) ? shrunkenBackground : "inherit",
|
});
|
||||||
}}>
|
}
|
||||||
<div className="d-flex flex-row justify-content-between mb-1" style={{ height: "1rem" }}>
|
function handleObjectChange(object: T.NPSelection | undefined) {
|
||||||
{(i > 0 && !isNoObject(blocks[i - 1].block)) ? <div
|
adjustVps({
|
||||||
className="small clickable ml-1"
|
type: "set object",
|
||||||
onClick={() => adjustVps({ type: "shift block", payload: { index: i, direction: "back" }})}
|
payload: object,
|
||||||
>
|
});
|
||||||
<i className="fas fa-chevron-left" />
|
}
|
||||||
</div> : <div/>}
|
const object = getObjectSelection(vps.blocks).selection;
|
||||||
{(i < vps.blocks.length - 1 && !isNoObject(blocks[i + 1].block)) ? <div
|
const subject = getSubjectSelection(vps.blocks).selection;
|
||||||
className="small clickable mr-1"
|
const VPS = completeVPSelection(vps);
|
||||||
onClick={() => adjustVps({ type: "shift block", payload: { index: i, direction: "forward" }})}
|
const phraseIsComplete = !!VPS;
|
||||||
>
|
const rendered = VPS ? renderVP(VPS) : undefined;
|
||||||
<i className="fas fa-chevron-right" />
|
const servantIsShrunk = includesShrunkenServant(rendered?.kids);
|
||||||
</div> : <div/>}
|
const isPast = isPastTense(
|
||||||
</div>
|
vps.verb.tenseCategory === "perfect"
|
||||||
{(!block || block.type === "AP")
|
? vps.verb.perfectTense
|
||||||
? <APPicker
|
: vps.verb.verbTense
|
||||||
phraseIsComplete={phraseIsComplete}
|
);
|
||||||
heading="AP"
|
const roles = getKingAndServant(
|
||||||
entryFeeder={entryFeeder}
|
isPast,
|
||||||
AP={block}
|
vps.verb.transitivity !== "intransitive"
|
||||||
opts={opts}
|
);
|
||||||
onChange={AP => adjustVps({ type: "set AP", payload: { index: i, AP } })}
|
return (
|
||||||
onRemove={() => adjustVps({ type: "remove AP", payload: i })}
|
<div>
|
||||||
/>
|
<div
|
||||||
: (block?.type === "subjectSelection")
|
className="clickable h5"
|
||||||
? <NPPicker
|
onClick={() => adjustVps({ type: "insert new AP" })}
|
||||||
phraseIsComplete={phraseIsComplete}
|
>
|
||||||
heading={roles.king === "subject"
|
+ AP
|
||||||
? <div className="h5 text-center">
|
</div>
|
||||||
Subj. <span onClick={() => setShowingExplanation({ role: "king", item: "subject" })}>{roleIcon.king}</span>
|
<div
|
||||||
{(rendered && rendered.whatsAdjustable !== "servant") &&
|
ref={parent}
|
||||||
<KingRemover
|
className="d-flex flex-row justify-content-around flex-wrap"
|
||||||
onChange={() => adjustVps({ type: "toggle king remove" })}
|
style={{ marginLeft: "-0.5rem", marginRight: "-0.5rem" }}
|
||||||
showKing={!VPS?.form.removeKing}
|
>
|
||||||
/>
|
{vps.blocks.map(({ block, key }, i, blocks) => {
|
||||||
}
|
if (isNoObject(block)) return null;
|
||||||
</div>
|
return (
|
||||||
: <div className="h5 text-center">
|
<div
|
||||||
Subj.
|
className="my-2 card block-card p-1 mx-1"
|
||||||
{` `}
|
key={key}
|
||||||
<span className="clickable" onClick={() => setShowingExplanation({ role: "servant", item: "subject" })}>{roleIcon.servant}</span>
|
style={{
|
||||||
{` `}
|
background:
|
||||||
{(rendered && rendered.whatsAdjustable !== "king") &&
|
servantIsShrunk &&
|
||||||
<ServantShrinker
|
((roles.servant === "subject" &&
|
||||||
shrunk={servantIsShrunk}
|
block?.type === "subjectSelection") ||
|
||||||
onClick={() => adjustVps({ type: "toggle servant shrink" })}
|
(roles.servant === "object" &&
|
||||||
/>
|
block?.type === "objectSelection"))
|
||||||
}
|
? shrunkenBackground
|
||||||
</div>}
|
: "inherit",
|
||||||
entryFeeder={entryFeeder}
|
}}
|
||||||
np={block.selection}
|
>
|
||||||
counterPart={vps.verb ? object : undefined}
|
<div
|
||||||
role={(isPast && vps.verb.transitivity !== "intransitive")
|
className="d-flex flex-row justify-content-between mb-1"
|
||||||
? "ergative"
|
style={{ height: "1rem" }}
|
||||||
: "subject"
|
>
|
||||||
}
|
{i > 0 &&
|
||||||
onChange={handleSubjectChange}
|
!isNoObject(blocks[i - 1].block) &&
|
||||||
opts={opts}
|
!isGenStatCompNoun(block) ? (
|
||||||
isShrunk={(servantIsShrunk && roles.servant === "subject")}
|
<div
|
||||||
isRemoved={roles.king === "subject" && VPS?.form.removeKing}
|
className="small clickable ml-1"
|
||||||
/>
|
onClick={() =>
|
||||||
: (vps.verb && block?.type === "objectSelection" && block.selection !== "none")
|
adjustVps({
|
||||||
? <div className="my-2" style={{ background: (servantIsShrunk && roles.servant === "object") ? shrunkenBackground : "inherit" }}>
|
type: "shift block",
|
||||||
{(typeof block.selection === "number")
|
payload: { index: i, direction: "back" },
|
||||||
? <div>
|
})
|
||||||
{roles.king === "object"
|
|
||||||
? <div className="h5 text-center clickable" onClick={() => setShowingExplanation({ role: "king", item: "object" })}>Object {roleIcon.king}</div>
|
|
||||||
: roles.servant === "object"
|
|
||||||
? <div className="h5 text-center clickable" onClick={() => setShowingExplanation({ role: "servant", item: "object" })}>Object {roleIcon.servant}</div>
|
|
||||||
: <div className="h5 text-center">Object</div>}
|
|
||||||
<div className="text-muted text-center">
|
|
||||||
<div className="mt-3 mb-1">Unspoken</div>
|
|
||||||
<div>3rd Pers. Masc. Plur.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
: <NPPicker
|
|
||||||
phraseIsComplete={phraseIsComplete}
|
|
||||||
heading={roles.king === "object"
|
|
||||||
? <div className="h5 text-center">
|
|
||||||
Obj. <span onClick={() => setShowingExplanation({ role: "king", item: "object" })}>{roleIcon.king}</span>
|
|
||||||
{(rendered && rendered.whatsAdjustable !== "servant") &&
|
|
||||||
<KingRemover
|
|
||||||
onChange={() => adjustVps({ type: "toggle king remove" })}
|
|
||||||
showKing={!VPS?.form.removeKing}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
: <div className="h5 text-center">
|
|
||||||
Obj.
|
|
||||||
{` `}
|
|
||||||
<span className="clickable" onClick={() => setShowingExplanation({ role: "servant", item: "object" })}>{roleIcon.servant}</span>
|
|
||||||
{` `}
|
|
||||||
{(rendered && rendered.whatsAdjustable !== "king") &&
|
|
||||||
<ServantShrinker shrunk={servantIsShrunk} onClick={() => adjustVps({ type: "toggle servant shrink" })} />
|
|
||||||
}
|
|
||||||
</div>}
|
|
||||||
entryFeeder={entryFeeder}
|
|
||||||
role="object"
|
|
||||||
np={block.selection}
|
|
||||||
counterPart={subject}
|
|
||||||
onChange={handleObjectChange}
|
|
||||||
opts={opts}
|
|
||||||
isShrunk={(servantIsShrunk && roles.servant === "object")}
|
|
||||||
isRemoved={roles.king === "object" && VPS?.form.removeKing}
|
|
||||||
/>}
|
|
||||||
</div>
|
|
||||||
: null}
|
|
||||||
</div>;
|
|
||||||
})}
|
|
||||||
{vps.externalComplement && <div className="my-2 card block-card p-1 mr-1" key="complementPicker">
|
|
||||||
<div className="h5 text-center">Complement</div>
|
|
||||||
<ComplementPicker
|
|
||||||
phraseIsComplete={phraseIsComplete}
|
|
||||||
comp={vps.externalComplement.selection.type === "unselected"
|
|
||||||
? undefined
|
|
||||||
: vps.externalComplement as T.ComplementSelection // TODO: just typescript being dumb? - looks like it
|
|
||||||
}
|
}
|
||||||
onChange={payload => adjustVps({ type: "set externalComplement", payload })}
|
>
|
||||||
opts={opts}
|
<i className="fas fa-chevron-left" />
|
||||||
entryFeeder={entryFeeder}
|
</div>
|
||||||
|
) : (
|
||||||
|
<div />
|
||||||
|
)}
|
||||||
|
{i < vps.blocks.length - 1 &&
|
||||||
|
!isNoObject(blocks[i + 1].block) &&
|
||||||
|
!isGenStatCompNoun(block) ? (
|
||||||
|
<div
|
||||||
|
className="small clickable mr-1"
|
||||||
|
onClick={() =>
|
||||||
|
adjustVps({
|
||||||
|
type: "shift block",
|
||||||
|
payload: { index: i, direction: "forward" },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<i className="fas fa-chevron-right" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{!block || block.type === "AP" ? (
|
||||||
|
<APPicker
|
||||||
|
phraseIsComplete={phraseIsComplete}
|
||||||
|
heading="AP"
|
||||||
|
entryFeeder={entryFeeder}
|
||||||
|
AP={block}
|
||||||
|
opts={opts}
|
||||||
|
onChange={(AP) =>
|
||||||
|
adjustVps({ type: "set AP", payload: { index: i, AP } })
|
||||||
|
}
|
||||||
|
onRemove={() => adjustVps({ type: "remove AP", payload: i })}
|
||||||
/>
|
/>
|
||||||
</div>}
|
) : block?.type === "subjectSelection" ? (
|
||||||
<div className="my-2">
|
<NPPicker
|
||||||
<TensePicker
|
phraseIsComplete={phraseIsComplete}
|
||||||
vps={vps}
|
heading={
|
||||||
onChange={adjustVps}
|
roles.king === "subject" ? (
|
||||||
mode="phrases"
|
<div className="h5 text-center">
|
||||||
|
Subj.{" "}
|
||||||
|
<span
|
||||||
|
onClick={() =>
|
||||||
|
setShowingExplanation({
|
||||||
|
role: "king",
|
||||||
|
item: "subject",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{roleIcon.king}
|
||||||
|
</span>
|
||||||
|
{rendered && rendered.whatsAdjustable !== "servant" && (
|
||||||
|
<KingRemover
|
||||||
|
onChange={() =>
|
||||||
|
adjustVps({ type: "toggle king remove" })
|
||||||
|
}
|
||||||
|
showKing={!VPS?.form.removeKing}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="h5 text-center">
|
||||||
|
Subj.
|
||||||
|
{` `}
|
||||||
|
<span
|
||||||
|
className="clickable"
|
||||||
|
onClick={() =>
|
||||||
|
setShowingExplanation({
|
||||||
|
role: "servant",
|
||||||
|
item: "subject",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{roleIcon.servant}
|
||||||
|
</span>
|
||||||
|
{` `}
|
||||||
|
{rendered && rendered.whatsAdjustable !== "king" && (
|
||||||
|
<ServantShrinker
|
||||||
|
shrunk={servantIsShrunk}
|
||||||
|
onClick={() =>
|
||||||
|
adjustVps({ type: "toggle servant shrink" })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
entryFeeder={entryFeeder}
|
||||||
|
np={block.selection}
|
||||||
|
counterPart={vps.verb ? object : undefined}
|
||||||
|
role={
|
||||||
|
isPast && vps.verb.transitivity !== "intransitive"
|
||||||
|
? "ergative"
|
||||||
|
: "subject"
|
||||||
|
}
|
||||||
|
onChange={handleSubjectChange}
|
||||||
|
opts={opts}
|
||||||
|
isShrunk={servantIsShrunk && roles.servant === "subject"}
|
||||||
|
isRemoved={roles.king === "subject" && VPS?.form.removeKing}
|
||||||
/>
|
/>
|
||||||
|
) : vps.verb &&
|
||||||
|
block?.type === "objectSelection" &&
|
||||||
|
block.selection !== "none" ? (
|
||||||
|
<div
|
||||||
|
className="my-2"
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
servantIsShrunk && roles.servant === "object"
|
||||||
|
? shrunkenBackground
|
||||||
|
: "inherit",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{typeof block.selection === "number" ? (
|
||||||
|
<div>
|
||||||
|
{roles.king === "object" ? (
|
||||||
|
<div
|
||||||
|
className="h5 text-center clickable"
|
||||||
|
onClick={() =>
|
||||||
|
setShowingExplanation({
|
||||||
|
role: "king",
|
||||||
|
item: "object",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Object {roleIcon.king}
|
||||||
|
</div>
|
||||||
|
) : roles.servant === "object" ? (
|
||||||
|
<div
|
||||||
|
className="h5 text-center clickable"
|
||||||
|
onClick={() =>
|
||||||
|
setShowingExplanation({
|
||||||
|
role: "servant",
|
||||||
|
item: "object",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Object {roleIcon.servant}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="h5 text-center">Object</div>
|
||||||
|
)}
|
||||||
|
<div className="text-muted text-center">
|
||||||
|
<div className="mt-3 mb-1">Unspoken</div>
|
||||||
|
<div>3rd Pers. Masc. Plur.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<NPPicker
|
||||||
|
phraseIsComplete={phraseIsComplete}
|
||||||
|
heading={
|
||||||
|
roles.king === "object" ? (
|
||||||
|
<div className="h5 text-center">
|
||||||
|
Obj.{" "}
|
||||||
|
<span
|
||||||
|
onClick={() =>
|
||||||
|
setShowingExplanation({
|
||||||
|
role: "king",
|
||||||
|
item: "object",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{roleIcon.king}
|
||||||
|
</span>
|
||||||
|
{rendered &&
|
||||||
|
rendered.whatsAdjustable !== "servant" && (
|
||||||
|
<KingRemover
|
||||||
|
onChange={() =>
|
||||||
|
adjustVps({ type: "toggle king remove" })
|
||||||
|
}
|
||||||
|
showKing={!VPS?.form.removeKing}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="h5 text-center">
|
||||||
|
Obj.
|
||||||
|
{` `}
|
||||||
|
<span
|
||||||
|
className="clickable"
|
||||||
|
onClick={() =>
|
||||||
|
setShowingExplanation({
|
||||||
|
role: "servant",
|
||||||
|
item: "object",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{roleIcon.servant}
|
||||||
|
</span>
|
||||||
|
{` `}
|
||||||
|
{rendered &&
|
||||||
|
rendered.whatsAdjustable !== "king" && (
|
||||||
|
<ServantShrinker
|
||||||
|
shrunk={servantIsShrunk}
|
||||||
|
onClick={() =>
|
||||||
|
adjustVps({ type: "toggle servant shrink" })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
entryFeeder={entryFeeder}
|
||||||
|
role="object"
|
||||||
|
np={block.selection}
|
||||||
|
counterPart={subject}
|
||||||
|
onChange={handleObjectChange}
|
||||||
|
opts={opts}
|
||||||
|
isShrunk={servantIsShrunk && roles.servant === "object"}
|
||||||
|
isRemoved={
|
||||||
|
roles.king === "object" && VPS?.form.removeKing
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{vps.externalComplement && (
|
||||||
|
<div className="my-2 card block-card p-1 mr-1" key="complementPicker">
|
||||||
|
<div className="h5 text-center">Complement</div>
|
||||||
|
<ComplementPicker
|
||||||
|
phraseIsComplete={phraseIsComplete}
|
||||||
|
comp={
|
||||||
|
vps.externalComplement.selection.type === "unselected"
|
||||||
|
? undefined
|
||||||
|
: (vps.externalComplement as T.ComplementSelection) // TODO: just typescript being dumb? - looks like it
|
||||||
|
}
|
||||||
|
onChange={(payload) =>
|
||||||
|
adjustVps({ type: "set externalComplement", payload })
|
||||||
|
}
|
||||||
|
opts={opts}
|
||||||
|
entryFeeder={entryFeeder}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="my-2">
|
||||||
|
<TensePicker vps={vps} onChange={adjustVps} mode="phrases" />
|
||||||
</div>
|
</div>
|
||||||
<VPExplorerExplanationModal
|
</div>
|
||||||
showing={showingExplanation}
|
<VPExplorerExplanationModal
|
||||||
setShowing={setShowingExplanation}
|
showing={showingExplanation}
|
||||||
/>
|
setShowing={setShowingExplanation}
|
||||||
</div>;
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ServantShrinker({ shrunk, onClick }: {
|
function ServantShrinker({
|
||||||
shrunk: boolean;
|
shrunk,
|
||||||
onClick: () => void;
|
onClick,
|
||||||
|
}: {
|
||||||
|
shrunk: boolean;
|
||||||
|
onClick: () => void;
|
||||||
}) {
|
}) {
|
||||||
return <span className="mx-2 clickable" onClick={onClick}>
|
return (
|
||||||
{!shrunk ? "🪄" : "👶"}
|
<span className="mx-2 clickable" onClick={onClick}>
|
||||||
</span>;
|
{!shrunk ? "🪄" : "👶"}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function KingRemover({ showKing, onChange }: {
|
function KingRemover({
|
||||||
showKing: boolean;
|
showKing,
|
||||||
onChange: () => void;
|
onChange,
|
||||||
|
}: {
|
||||||
|
showKing: boolean;
|
||||||
|
onChange: () => void;
|
||||||
}) {
|
}) {
|
||||||
return <span className="form-check form-check-inline ml-3">
|
return (
|
||||||
<input
|
<span className="form-check form-check-inline ml-3">
|
||||||
checked={showKing}
|
<input
|
||||||
onChange={onChange}
|
checked={showKing}
|
||||||
className="form-check-input"
|
onChange={onChange}
|
||||||
type="checkbox"
|
className="form-check-input"
|
||||||
id="showKingCheck"
|
type="checkbox"
|
||||||
/>
|
id="showKingCheck"
|
||||||
</span>;
|
/>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default VPPicker;
|
function isGenStatCompNoun(
|
||||||
|
block:
|
||||||
|
| T.APSelection
|
||||||
|
| T.ComplementSelection
|
||||||
|
| T.SubjectSelection
|
||||||
|
| T.ObjectSelection
|
||||||
|
| undefined
|
||||||
|
) {
|
||||||
|
if (!block) return false;
|
||||||
|
console.log({ block });
|
||||||
|
if (
|
||||||
|
block.type === "objectSelection" &&
|
||||||
|
typeof block.selection === "object" &&
|
||||||
|
block.selection.selection.type === "noun" &&
|
||||||
|
block.selection.selection.genStativeComplement
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VPPicker;
|
||||||
|
|
|
@ -1,141 +1,213 @@
|
||||||
import * as T from "../../../types";
|
import * as T from "../../../types";
|
||||||
import ButtonSelect from "../ButtonSelect";
|
import ButtonSelect from "../ButtonSelect";
|
||||||
import { RootsAndStems } from "../verb-info/VerbInfo";
|
import { RootsAndStems } from "../verb-info/VerbInfo";
|
||||||
import { getAbilityRootsAndStems, getPassiveRootsAndStems, getVerbInfo } from "../../../lib/src/verb-info";
|
import {
|
||||||
|
getAbilityRootsAndStems,
|
||||||
|
getPassiveRootsAndStems,
|
||||||
|
getVerbInfo,
|
||||||
|
} from "../../../lib/src/verb-info";
|
||||||
import Hider from "../Hider";
|
import Hider from "../Hider";
|
||||||
import useStickyState from "../useStickyState";
|
import useStickyState from "../useStickyState";
|
||||||
import CompoundDisplay from "./CompoundDisplay";
|
import CompoundDisplay from "./CompoundDisplay";
|
||||||
import {
|
import { VpsReducerAction } from "../../../lib/src/phrase-building/vps-reducer";
|
||||||
VpsReducerAction
|
|
||||||
} from "../../../lib/src/phrase-building/vps-reducer";
|
|
||||||
import { ensureNonComboVerbInfo } from "../../../lib/src/misc-helpers";
|
import { ensureNonComboVerbInfo } from "../../../lib/src/misc-helpers";
|
||||||
|
|
||||||
// TODO: dark on past tense selecitons
|
// TODO: dark on past tense selecitons
|
||||||
|
|
||||||
function VerbPicker(props: {
|
function VerbPicker(props: {
|
||||||
vps: T.VPSelectionState,
|
vps: T.VPSelectionState;
|
||||||
onChange: (a: VpsReducerAction) => void,
|
onChange: (a: VpsReducerAction) => void;
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions;
|
||||||
handleLinkClick: ((ts: number) => void) | "none",
|
handleLinkClick: ((ts: number) => void) | "none";
|
||||||
}) {
|
}) {
|
||||||
const [showRootsAndStems, setShowRootsAndStems] = useStickyState<boolean>(false, "showRootsAndStems");
|
const [showRootsAndStems, setShowRootsAndStems] = useStickyState<boolean>(
|
||||||
const infoRaw = props.vps.verb ? getVerbInfo(props.vps.verb.verb.entry, props.vps.verb.verb.complement) : undefined;
|
false,
|
||||||
const info = (!infoRaw || !props.vps.verb)
|
"showRootsAndStems"
|
||||||
? undefined
|
);
|
||||||
: ("stative" in infoRaw)
|
const infoRaw = props.vps.verb
|
||||||
? infoRaw[props.vps.verb.isCompound === "stative" ? "stative" : "dynamic"]
|
? getVerbInfo(props.vps.verb.verb.entry, props.vps.verb.verb.complement)
|
||||||
: ("transitive" in infoRaw)
|
: undefined;
|
||||||
? infoRaw[props.vps.verb.transitivity === "grammatically transitive" ? "grammaticallyTransitive" : "transitive"]
|
const info =
|
||||||
: infoRaw;
|
!infoRaw || !props.vps.verb
|
||||||
if (info && ("stative" in info || "transitive" in info)) {
|
? undefined
|
||||||
return <div>ERROR: Verb version should be select first</div>;
|
: "stative" in infoRaw
|
||||||
|
? infoRaw[
|
||||||
|
props.vps.verb.isCompound === "stative" ||
|
||||||
|
props.vps.verb.isCompound === "generative stative"
|
||||||
|
? "stative"
|
||||||
|
: "dynamic"
|
||||||
|
]
|
||||||
|
: "transitive" in infoRaw
|
||||||
|
? infoRaw[
|
||||||
|
props.vps.verb.transitivity === "grammatically transitive"
|
||||||
|
? "grammaticallyTransitive"
|
||||||
|
: "transitive"
|
||||||
|
]
|
||||||
|
: infoRaw;
|
||||||
|
if (info && ("stative" in info || "transitive" in info)) {
|
||||||
|
return <div>ERROR: Verb version should be select first</div>;
|
||||||
|
}
|
||||||
|
function onVoiceSelect(value: "active" | "passive") {
|
||||||
|
props.onChange({
|
||||||
|
type: "set voice",
|
||||||
|
payload: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function notInstransitive(
|
||||||
|
t: "transitive" | "intransitive" | "grammatically transitive"
|
||||||
|
): "transitive" | "grammatically transitive" {
|
||||||
|
return t === "intransitive" ? "transitive" : t;
|
||||||
|
}
|
||||||
|
function handleChangeTransitivity(
|
||||||
|
payload: "transitive" | "grammatically transitive"
|
||||||
|
) {
|
||||||
|
props.onChange({
|
||||||
|
type: "set transitivity",
|
||||||
|
payload,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function handleChangeStatDyn(payload: "stative" | "dynamic") {
|
||||||
|
props.onChange({
|
||||||
|
type: "set statDyn",
|
||||||
|
payload,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const passiveRootsAndStems =
|
||||||
|
info && props.vps.verb.voice === "passive"
|
||||||
|
? getPassiveRootsAndStems(info)
|
||||||
|
: undefined;
|
||||||
|
const abilityRootsAndStems = (() => {
|
||||||
|
try {
|
||||||
|
return info && props.vps.verb.tenseCategory === "modal"
|
||||||
|
? getAbilityRootsAndStems(info)
|
||||||
|
: undefined;
|
||||||
|
} catch (e) {
|
||||||
|
console.log("error making ability roots and stems", e);
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
function onVoiceSelect(value: "active" | "passive") {
|
})();
|
||||||
props.onChange({
|
return (
|
||||||
type: "set voice",
|
<div className="mb-3">
|
||||||
payload: value,
|
{info && (
|
||||||
});
|
<CompoundDisplay
|
||||||
}
|
info={info}
|
||||||
function notInstransitive(t: "transitive" | "intransitive" | "grammatically transitive"): "transitive" | "grammatically transitive" {
|
opts={props.opts}
|
||||||
return t === "intransitive" ? "transitive" : t;
|
handleLinkClick={props.handleLinkClick}
|
||||||
}
|
/>
|
||||||
function handleChangeTransitivity(payload: "transitive" | "grammatically transitive") {
|
)}
|
||||||
props.onChange({
|
{info && (
|
||||||
type: "set transitivity",
|
<div className="mt-3 mb-1 text-center">
|
||||||
payload,
|
<Hider
|
||||||
});
|
showing={showRootsAndStems}
|
||||||
}
|
label={`🌳 ${
|
||||||
function handleChangeStatDyn(payload: "stative" | "dynamic") {
|
passiveRootsAndStems
|
||||||
props.onChange({
|
? "Passive"
|
||||||
type: "set statDyn",
|
: abilityRootsAndStems
|
||||||
payload,
|
? "Ability"
|
||||||
});
|
: ""
|
||||||
}
|
} Roots and Stems${
|
||||||
const passiveRootsAndStems = (info && props.vps.verb.voice === "passive") ? getPassiveRootsAndStems(info) : undefined;
|
info.type === "dynamic compound" ? " for Aux. Verb" : ""
|
||||||
const abilityRootsAndStems = (() => {
|
}`}
|
||||||
try {
|
handleChange={() => setShowRootsAndStems((p) => !p)}
|
||||||
return (info && props.vps.verb.tenseCategory === "modal") ? getAbilityRootsAndStems(info) : undefined;
|
hLevel={5}
|
||||||
} catch (e) {
|
>
|
||||||
console.log("error making ability roots and stems", e);
|
<RootsAndStems
|
||||||
return undefined;
|
textOptions={props.opts}
|
||||||
}
|
info={
|
||||||
})();
|
passiveRootsAndStems
|
||||||
return <div className="mb-3">
|
? passiveRootsAndStems
|
||||||
{info && <CompoundDisplay
|
: abilityRootsAndStems
|
||||||
info={info}
|
? abilityRootsAndStems
|
||||||
opts={props.opts}
|
: info.type === "dynamic compound"
|
||||||
handleLinkClick={props.handleLinkClick}
|
? ensureNonComboVerbInfo(getVerbInfo(info.auxVerb))
|
||||||
/>}
|
: info
|
||||||
{info && <div className="mt-3 mb-1 text-center">
|
}
|
||||||
<Hider
|
/>
|
||||||
showing={showRootsAndStems}
|
</Hider>
|
||||||
label={`🌳 ${passiveRootsAndStems ? "Passive" : abilityRootsAndStems ? "Ability" : ""} Roots and Stems${info.type === "dynamic compound" ? " for Aux. Verb" : ""}`}
|
|
||||||
handleChange={() => setShowRootsAndStems(p => !p)}
|
|
||||||
hLevel={5}
|
|
||||||
>
|
|
||||||
<RootsAndStems
|
|
||||||
textOptions={props.opts}
|
|
||||||
info={passiveRootsAndStems
|
|
||||||
? passiveRootsAndStems
|
|
||||||
: abilityRootsAndStems
|
|
||||||
? abilityRootsAndStems
|
|
||||||
: info.type === "dynamic compound"
|
|
||||||
? ensureNonComboVerbInfo(getVerbInfo(info.auxVerb))
|
|
||||||
: info}
|
|
||||||
/>
|
|
||||||
</Hider>
|
|
||||||
</div>}
|
|
||||||
<div className="d-flex flex-row justify-content-around flex-wrap" style={{ maxWidth: "400px", margin: "0 auto" }}>
|
|
||||||
{props.vps.verb && props.vps.verb.canChangeTransitivity && <div className="text-center my-2">
|
|
||||||
<ButtonSelect
|
|
||||||
small
|
|
||||||
options={[{
|
|
||||||
label: "gramm. trans.",
|
|
||||||
value: "grammatically transitive",
|
|
||||||
}, {
|
|
||||||
label: "trans.",
|
|
||||||
value: "transitive",
|
|
||||||
}]}
|
|
||||||
value={notInstransitive(props.vps.verb.transitivity)}
|
|
||||||
handleChange={handleChangeTransitivity}
|
|
||||||
/>
|
|
||||||
</div>}
|
|
||||||
{props.vps.verb && props.vps.verb.canChangeVoice && <div className="text-center my-2">
|
|
||||||
<ButtonSelect
|
|
||||||
small
|
|
||||||
value={props.vps.verb.voice}
|
|
||||||
options={(props.vps.verb.tenseCategory === "imperative") // || props.vps.verb.tenseCategory === "modal")
|
|
||||||
? [{
|
|
||||||
label: "Active",
|
|
||||||
value: "active",
|
|
||||||
}]
|
|
||||||
: [{
|
|
||||||
label: "Active",
|
|
||||||
value: "active",
|
|
||||||
}, {
|
|
||||||
label: "Passive",
|
|
||||||
value: "passive",
|
|
||||||
}]}
|
|
||||||
handleChange={onVoiceSelect}
|
|
||||||
/>
|
|
||||||
</div>}
|
|
||||||
{props.vps.verb && props.vps.verb.canChangeStatDyn && <div className="text-center my-2">
|
|
||||||
<ButtonSelect
|
|
||||||
small
|
|
||||||
options={[{
|
|
||||||
label: "stative",
|
|
||||||
value: "stative",
|
|
||||||
}, {
|
|
||||||
label: "dynamic",
|
|
||||||
value: "dynamic",
|
|
||||||
}]}
|
|
||||||
value={props.vps.verb.isCompound ? props.vps.verb.isCompound : "stative"}
|
|
||||||
handleChange={handleChangeStatDyn}
|
|
||||||
/>
|
|
||||||
</div>}
|
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
)}
|
||||||
|
<div
|
||||||
|
className="d-flex flex-row justify-content-around flex-wrap"
|
||||||
|
style={{ maxWidth: "400px", margin: "0 auto" }}
|
||||||
|
>
|
||||||
|
{props.vps.verb && props.vps.verb.canChangeTransitivity && (
|
||||||
|
<div className="text-center my-2">
|
||||||
|
<ButtonSelect
|
||||||
|
small
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: "gramm. trans.",
|
||||||
|
value: "grammatically transitive",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "trans.",
|
||||||
|
value: "transitive",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
value={notInstransitive(props.vps.verb.transitivity)}
|
||||||
|
handleChange={handleChangeTransitivity}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{props.vps.verb && props.vps.verb.canChangeVoice && (
|
||||||
|
<div className="text-center my-2">
|
||||||
|
<ButtonSelect
|
||||||
|
small
|
||||||
|
value={props.vps.verb.voice}
|
||||||
|
options={
|
||||||
|
props.vps.verb.tenseCategory === "imperative" // || props.vps.verb.tenseCategory === "modal")
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
label: "Active",
|
||||||
|
value: "active",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
label: "Active",
|
||||||
|
value: "active",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Passive",
|
||||||
|
value: "passive",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
handleChange={onVoiceSelect}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{props.vps.verb && props.vps.verb.canChangeStatDyn && (
|
||||||
|
<div className="text-center my-2">
|
||||||
|
<ButtonSelect
|
||||||
|
small
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label:
|
||||||
|
infoRaw?.type === "dynamic or generative stative compound"
|
||||||
|
? "gen. stative"
|
||||||
|
: "stative",
|
||||||
|
value: "stative",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "dynamic",
|
||||||
|
value: "dynamic",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
value={
|
||||||
|
props.vps.verb.isCompound === "generative stative"
|
||||||
|
? "stative"
|
||||||
|
: props.vps.verb.isCompound
|
||||||
|
? props.vps.verb.isCompound
|
||||||
|
: "stative"
|
||||||
|
}
|
||||||
|
handleChange={handleChangeStatDyn}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default VerbPicker;
|
||||||
export default VerbPicker;
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { renderVerb } from "../../../lib/src/new-verb-engine/render-verb";
|
import { renderVerb } from "../../../lib/src/new-verb-engine/render-verb";
|
||||||
import * as T from "../../../types";
|
import * as T from "../../../types";
|
||||||
import { equals } from "rambda";
|
import { equals } from "rambda";
|
||||||
import { isPastTense } from "../../library";
|
import { isPastTense, renderNPSelection } from "../../library";
|
||||||
|
import { getPersonFromNP } from "../../../lib/src/phrase-building/vp-tools";
|
||||||
|
|
||||||
export function buildVerbChart({
|
export function buildVerbChart({
|
||||||
verb,
|
verb,
|
||||||
|
@ -10,6 +11,7 @@ export function buildVerbChart({
|
||||||
voice,
|
voice,
|
||||||
imperative,
|
imperative,
|
||||||
negative,
|
negative,
|
||||||
|
objectNP,
|
||||||
}: {
|
}: {
|
||||||
verb: T.VerbEntry;
|
verb: T.VerbEntry;
|
||||||
tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense;
|
tense: T.VerbTense | T.PerfectTense | T.AbilityTense | T.ImperativeTense;
|
||||||
|
@ -17,7 +19,11 @@ export function buildVerbChart({
|
||||||
imperative: boolean;
|
imperative: boolean;
|
||||||
voice: T.VerbSelection["voice"];
|
voice: T.VerbSelection["voice"];
|
||||||
negative: boolean;
|
negative: boolean;
|
||||||
}): T.OptionalPersonInflections<T.SingleOrLengthOpts<T.RenderVerbOutput[]>> {
|
objectNP: T.NPSelection | undefined;
|
||||||
|
}): {
|
||||||
|
objNP: T.Rendered<T.NPSelection> | undefined;
|
||||||
|
vbs: T.OptionalPersonInflections<T.SingleOrLengthOpts<T.RenderVerbOutput[]>>;
|
||||||
|
} {
|
||||||
const allPersons = imperative
|
const allPersons = imperative
|
||||||
? [
|
? [
|
||||||
T.Person.SecondSingMale,
|
T.Person.SecondSingMale,
|
||||||
|
@ -27,6 +33,9 @@ export function buildVerbChart({
|
||||||
]
|
]
|
||||||
: ([...Array(12).keys()] as T.Person[]);
|
: ([...Array(12).keys()] as T.Person[]);
|
||||||
const isPast = isPastTense(tense);
|
const isPast = isPastTense(tense);
|
||||||
|
const objNP: T.Rendered<T.NPSelection> | undefined = objectNP
|
||||||
|
? renderNPSelection(objectNP, false, false, "object", "none", false)
|
||||||
|
: undefined;
|
||||||
function conjugateAllPers(
|
function conjugateAllPers(
|
||||||
p?: T.Person
|
p?: T.Person
|
||||||
): T.SingleOrLengthOpts<T.RenderVerbOutput[]> {
|
): T.SingleOrLengthOpts<T.RenderVerbOutput[]> {
|
||||||
|
@ -46,19 +55,51 @@ export function buildVerbChart({
|
||||||
negative,
|
negative,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
const hasLengths = vIsLength("long")(ps[0]);
|
return pullOutLengths(ps);
|
||||||
const hasMini = vIsLength("mini")(ps[0]);
|
|
||||||
return pullOutLengths(hasLengths, hasMini, ps);
|
|
||||||
}
|
}
|
||||||
if (transitivity === "transitive" && !isPast) {
|
if (transitivity === "transitive" && !isPast) {
|
||||||
return conflateIfNoCompGenNumDiff({
|
return {
|
||||||
mascSing: conjugateAllPers(T.Person.FirstSingMale),
|
objNP,
|
||||||
mascPlur: conjugateAllPers(T.Person.FirstPlurMale),
|
vbs: conflateIfNoCompGenNumDiff({
|
||||||
femSing: conjugateAllPers(T.Person.FirstSingFemale),
|
mascSing: conjugateAllPers(T.Person.FirstSingMale),
|
||||||
femPlur: conjugateAllPers(T.Person.FirstPlurFemale),
|
mascPlur: conjugateAllPers(T.Person.FirstPlurMale),
|
||||||
});
|
femSing: conjugateAllPers(T.Person.FirstSingFemale),
|
||||||
|
femPlur: conjugateAllPers(T.Person.FirstPlurFemale),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
} else if (objNP && isPast) {
|
||||||
|
return {
|
||||||
|
objNP,
|
||||||
|
vbs: pullOutLengths([
|
||||||
|
renderVerb({
|
||||||
|
verb,
|
||||||
|
tense,
|
||||||
|
subject: 0,
|
||||||
|
object: getPersonFromNP(objNP),
|
||||||
|
voice,
|
||||||
|
negative,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
} else if (isPast && transitivity === "grammatically transitive") {
|
||||||
|
return {
|
||||||
|
objNP,
|
||||||
|
vbs: pullOutLengths([
|
||||||
|
renderVerb({
|
||||||
|
verb,
|
||||||
|
tense,
|
||||||
|
subject: 0,
|
||||||
|
object: T.Person.ThirdPlurMale,
|
||||||
|
voice,
|
||||||
|
negative,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
return conjugateAllPers();
|
return {
|
||||||
|
objNP: undefined,
|
||||||
|
vbs: conjugateAllPers(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,23 +147,21 @@ function grabLength(
|
||||||
if (v.length === 2) {
|
if (v.length === 2) {
|
||||||
const [vb, vbe] = v;
|
const [vb, vbe] = v;
|
||||||
return {
|
return {
|
||||||
objComp: undefined,
|
|
||||||
hasBa,
|
hasBa,
|
||||||
vbs: [ph, [grabVBLength(vb), vbe]],
|
vbs: [ph, [grabVBLength(vb), vbe]],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
objComp: undefined,
|
|
||||||
hasBa,
|
hasBa,
|
||||||
vbs: [ph, [grabVBLength(v[0])]],
|
vbs: [ph, [grabVBLength(v[0])]],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function pullOutLengths(
|
function pullOutLengths(
|
||||||
hasLengths: boolean,
|
|
||||||
hasMini: boolean,
|
|
||||||
ps: T.RenderVerbOutput[]
|
ps: T.RenderVerbOutput[]
|
||||||
): T.SingleOrLengthOpts<T.RenderVerbOutput[]> {
|
): T.SingleOrLengthOpts<T.RenderVerbOutput[]> {
|
||||||
|
const hasLengths = vIsLength("long")(ps[0]);
|
||||||
|
const hasMini = vIsLength("mini")(ps[0]);
|
||||||
if (!hasLengths) {
|
if (!hasLengths) {
|
||||||
return ps;
|
return ps;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.hide-on-mobile {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,85 +0,0 @@
|
||||||
import * as T from "../../types";
|
|
||||||
|
|
||||||
export function fmapSingleOrLengthOpts<A extends object, B extends object>(f: (x: A) => B, x: T.SingleOrLengthOpts<A>): T.SingleOrLengthOpts<B> {
|
|
||||||
if ("long" in x) {
|
|
||||||
return {
|
|
||||||
long: f(x.long),
|
|
||||||
short: f(x.short),
|
|
||||||
..."mini" in x && x.mini ? {
|
|
||||||
mini: f(x.mini),
|
|
||||||
} : {},
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return f(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mapInflections(f: (x: T.PsString) => T.PsString, inf: T.UnisexInflections): T.UnisexInflections {
|
|
||||||
function handleSide(inf: T.InflectionSet): T.InflectionSet {
|
|
||||||
return inf.map(x => x.map(f)) as T.ArrayFixed<T.ArrayOneOrMore<T.PsString>, 3>;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
masc: handleSide(inf.masc),
|
|
||||||
fem: handleSide(inf.fem),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mapVerbRenderedOutput(f: (a: T.PsString) => T.PsString, [a, b]: T.VerbRenderedOutput): T.VerbRenderedOutput {
|
|
||||||
return [
|
|
||||||
fmapVHead(a),
|
|
||||||
fmapV(b),
|
|
||||||
];
|
|
||||||
function fmapVHead([v]: [T.VHead] | []): [T.VHead] | [] {
|
|
||||||
if (v === undefined) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
if (v.type === "PH") {
|
|
||||||
return [{
|
|
||||||
...v,
|
|
||||||
ps: f(v.ps),
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
return [{
|
|
||||||
...v,
|
|
||||||
comp: fmapComp(v.comp),
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
function fmapComp(comp: T.Comp): T.Comp {
|
|
||||||
return {
|
|
||||||
...comp,
|
|
||||||
ps: f(comp.ps),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function fmapV(v: [T.VB, T.VBE] | [T.VBE]): [T.VB, T.VBE]| [T.VBE] {
|
|
||||||
return v.map(fmapVB) as [T.VB, T.VBE]| [T.VBE];
|
|
||||||
}
|
|
||||||
function fmapVB<V extends T.VB | T.VBE>(v: V): V {
|
|
||||||
if (v.type === "welded") {
|
|
||||||
return {
|
|
||||||
...v,
|
|
||||||
left: fmapWeldedLeft(v.left),
|
|
||||||
right: fmapVB(v.right),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...v,
|
|
||||||
ps: fmapSingleOrLengthOpts((x) => x.map(f), v.ps),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function fmapWeldedLeft(v: T.NComp | T.VBBasic | T.Welded) {
|
|
||||||
if (v.type === "NComp") {
|
|
||||||
return {
|
|
||||||
...v,
|
|
||||||
comp: fmapComp(v.comp),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return fmapVB(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,3 +41,95 @@ export const monoidPsStringWVars: Monoid<T.PsString[]> = {
|
||||||
concat: semigroupPsStringWVars.concat,
|
concat: semigroupPsStringWVars.concat,
|
||||||
empty: [monoidPsString.empty],
|
empty: [monoidPsString.empty],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function fmapSingleOrLengthOpts<A extends object, B extends object>(
|
||||||
|
f: (x: A) => B,
|
||||||
|
x: T.SingleOrLengthOpts<A>
|
||||||
|
): T.SingleOrLengthOpts<B> {
|
||||||
|
if ("long" in x) {
|
||||||
|
return {
|
||||||
|
long: f(x.long),
|
||||||
|
short: f(x.short),
|
||||||
|
...("mini" in x && x.mini
|
||||||
|
? {
|
||||||
|
mini: f(x.mini),
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return f(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapInflections(
|
||||||
|
f: (x: T.PsString) => T.PsString,
|
||||||
|
inf: T.UnisexInflections
|
||||||
|
): T.UnisexInflections {
|
||||||
|
function handleSide(inf: T.InflectionSet): T.InflectionSet {
|
||||||
|
return inf.map((x) => x.map(f)) as T.ArrayFixed<
|
||||||
|
T.ArrayOneOrMore<T.PsString>,
|
||||||
|
3
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
masc: handleSide(inf.masc),
|
||||||
|
fem: handleSide(inf.fem),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapVerbRenderedOutput(
|
||||||
|
f: (a: T.PsString) => T.PsString,
|
||||||
|
[a, b]: T.VerbRenderedOutput
|
||||||
|
): T.VerbRenderedOutput {
|
||||||
|
return [fmapVHead(a), fmapV(b)];
|
||||||
|
function fmapVHead([v]: [T.VHead] | []): [T.VHead] | [] {
|
||||||
|
if (v === undefined) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (v.type === "PH") {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
...v,
|
||||||
|
ps: f(v.ps),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
...v,
|
||||||
|
comp: fmapComp(v.comp),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
function fmapComp(comp: T.Comp): T.Comp {
|
||||||
|
return {
|
||||||
|
...comp,
|
||||||
|
ps: f(comp.ps),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function fmapV(v: [T.VB, T.VBE] | [T.VBE]): [T.VB, T.VBE] | [T.VBE] {
|
||||||
|
return v.map(fmapVB) as [T.VB, T.VBE] | [T.VBE];
|
||||||
|
}
|
||||||
|
function fmapVB<V extends T.VB | T.VBE>(v: V): V {
|
||||||
|
if (v.type === "welded") {
|
||||||
|
return {
|
||||||
|
...v,
|
||||||
|
left: fmapWeldedLeft(v.left),
|
||||||
|
right: fmapVB(v.right),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...v,
|
||||||
|
ps: fmapSingleOrLengthOpts((x) => x.map(f), v.ps),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function fmapWeldedLeft(v: T.NComp | T.VBBasic | T.Welded) {
|
||||||
|
if (v.type === "NComp") {
|
||||||
|
return {
|
||||||
|
...v,
|
||||||
|
comp: fmapComp(v.comp),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return fmapVB(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as T from "../../types";
|
import * as T from "../../types";
|
||||||
import { fmapSingleOrLengthOpts } from "./fmaps";
|
import { fmapSingleOrLengthOpts } from "./fp-ps";
|
||||||
|
|
||||||
export const blank: T.PsString = {
|
export const blank: T.PsString = {
|
||||||
p: "_____",
|
p: "_____",
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
personNumber,
|
personNumber,
|
||||||
personToGenNum,
|
personToGenNum,
|
||||||
} from "../misc-helpers";
|
} from "../misc-helpers";
|
||||||
import { fmapSingleOrLengthOpts } from "../fmaps";
|
import { fmapSingleOrLengthOpts } from "../fp-ps";
|
||||||
import { concatPsString, getLength } from "../p-text-helpers";
|
import { concatPsString, getLength } from "../p-text-helpers";
|
||||||
import {
|
import {
|
||||||
presentEndings,
|
presentEndings,
|
||||||
|
@ -18,6 +18,7 @@ import {
|
||||||
isAbilityTense,
|
isAbilityTense,
|
||||||
isPerfectTense,
|
isPerfectTense,
|
||||||
isTlulVerb,
|
isTlulVerb,
|
||||||
|
isImperativeTense,
|
||||||
} from "../type-predicates";
|
} from "../type-predicates";
|
||||||
import { perfectTenseHasBa } from "../phrase-building/vp-tools";
|
import { perfectTenseHasBa } from "../phrase-building/vp-tools";
|
||||||
import { makePsString, removeFVarients } from "../accent-and-ps-utils";
|
import { makePsString, removeFVarients } from "../accent-and-ps-utils";
|
||||||
|
@ -100,6 +101,7 @@ export function renderVerb({
|
||||||
subject,
|
subject,
|
||||||
object,
|
object,
|
||||||
voice,
|
voice,
|
||||||
|
negative,
|
||||||
}: {
|
}: {
|
||||||
verb: T.VerbEntry;
|
verb: T.VerbEntry;
|
||||||
negative: boolean;
|
negative: boolean;
|
||||||
|
@ -126,7 +128,7 @@ export function renderVerb({
|
||||||
const [vHead, rest] = getRootStem({
|
const [vHead, rest] = getRootStem({
|
||||||
verb,
|
verb,
|
||||||
rs: isPast ? "root" : "stem",
|
rs: isPast ? "root" : "stem",
|
||||||
aspect,
|
aspect: negative && isImperativeTense(tense) ? "imperfective" : aspect,
|
||||||
voice,
|
voice,
|
||||||
type,
|
type,
|
||||||
genderNumber: personToGenNum(transitive ? object : subject),
|
genderNumber: personToGenNum(transitive ? object : subject),
|
||||||
|
@ -136,7 +138,6 @@ export function renderVerb({
|
||||||
const ending = getEnding(king, tenseC, aspect);
|
const ending = getEnding(king, tenseC, aspect);
|
||||||
return {
|
return {
|
||||||
hasBa,
|
hasBa,
|
||||||
objComp: undefined,
|
|
||||||
vbs: [
|
vbs: [
|
||||||
vHead,
|
vHead,
|
||||||
addEnding({
|
addEnding({
|
||||||
|
|
|
@ -31,9 +31,9 @@ import {
|
||||||
isKedul,
|
isKedul,
|
||||||
} from "./rs-helpers";
|
} from "./rs-helpers";
|
||||||
import { inflectPattern3 } from "./new-inflectors";
|
import { inflectPattern3 } from "./new-inflectors";
|
||||||
import { fmapSingleOrLengthOpts } from "../fmaps";
|
import { fmapSingleOrLengthOpts } from "../fp-ps";
|
||||||
|
|
||||||
const statVerb = {
|
export const statVerb = {
|
||||||
intransitive: vEntry({
|
intransitive: vEntry({
|
||||||
ts: 1581086654898,
|
ts: 1581086654898,
|
||||||
i: 11100,
|
i: 11100,
|
||||||
|
|
|
@ -30,7 +30,7 @@ import {
|
||||||
splitUpSyllables,
|
splitUpSyllables,
|
||||||
} from "./accent-helpers";
|
} from "./accent-helpers";
|
||||||
import * as T from "../../types";
|
import * as T from "../../types";
|
||||||
import { fmapSingleOrLengthOpts } from "./fmaps";
|
import { fmapSingleOrLengthOpts } from "./fp-ps";
|
||||||
|
|
||||||
const endingInSingleARegex = /[^a]'?’?[aá]'?’?$/;
|
const endingInSingleARegex = /[^a]'?’?[aá]'?’?$/;
|
||||||
const endingInHeyOrAynRegex = /[^ا][هع]$/;
|
const endingInHeyOrAynRegex = /[^ا][هع]$/;
|
||||||
|
@ -42,24 +42,29 @@ export function inflectWord(word: T.DictionaryEntry): T.InflectorOutput {
|
||||||
const w = removeFVarients(word);
|
const w = removeFVarients(word);
|
||||||
if (w.c?.includes("doub.")) {
|
if (w.c?.includes("doub.")) {
|
||||||
const words = splitDoubleWord(w);
|
const words = splitDoubleWord(w);
|
||||||
const inflected = words.map((x) => ensureUnisexInflections(inflectWord(x), x));
|
const inflected = words.map((x) =>
|
||||||
|
ensureUnisexInflections(inflectWord(x), x)
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
inflections: concatInflections(
|
inflections: concatInflections(
|
||||||
inflected[0].inflections,
|
inflected[0].inflections,
|
||||||
inflected[1].inflections,
|
inflected[1].inflections
|
||||||
) as T.UnisexInflections,
|
) as T.UnisexInflections,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (w.c && w.c.includes("pl.")) {
|
if (w.c && w.c.includes("pl.")) {
|
||||||
return handlePluralNounOrAdj(w);
|
return handlePluralNounOrAdj(w);
|
||||||
}
|
}
|
||||||
if (w.c && (w.c.includes("adj.") || w.c.includes("unisex") || w.c.includes("num"))) {
|
if (
|
||||||
|
w.c &&
|
||||||
|
(w.c.includes("adj.") || w.c.includes("unisex") || w.c.includes("num"))
|
||||||
|
) {
|
||||||
return handleUnisexWord(w);
|
return handleUnisexWord(w);
|
||||||
}
|
}
|
||||||
if (w.c && (w.c.includes("n. m."))) {
|
if (w.c && w.c.includes("n. m.")) {
|
||||||
return handleMascNoun(w);
|
return handleMascNoun(w);
|
||||||
}
|
}
|
||||||
if (w.c && (w.c.includes("n. f."))) {
|
if (w.c && w.c.includes("n. f.")) {
|
||||||
return handleFemNoun(w);
|
return handleFemNoun(w);
|
||||||
}
|
}
|
||||||
// It's not a noun/adj
|
// It's not a noun/adj
|
||||||
|
@ -78,8 +83,8 @@ function handleUnisexWord(word: T.DictionaryEntryNoFVars): T.InflectorOutput {
|
||||||
if (word.infap && word.infaf && word.infbp && word.infbf) {
|
if (word.infap && word.infaf && word.infbp && word.infbf) {
|
||||||
return {
|
return {
|
||||||
inflections: inflectIrregularUnisex(word.p, word.f, [
|
inflections: inflectIrregularUnisex(word.p, word.f, [
|
||||||
{p: word.infap, f: word.infaf},
|
{ p: word.infap, f: word.infaf },
|
||||||
{p: word.infbp, f: word.infbf},
|
{ p: word.infbp, f: word.infbf },
|
||||||
]),
|
]),
|
||||||
...plurals,
|
...plurals,
|
||||||
};
|
};
|
||||||
|
@ -88,10 +93,16 @@ function handleUnisexWord(word: T.DictionaryEntryNoFVars): T.InflectorOutput {
|
||||||
return { inflections: inflectRegularYeyUnisex(word.p, word.f), ...plurals };
|
return { inflections: inflectRegularYeyUnisex(word.p, word.f), ...plurals };
|
||||||
}
|
}
|
||||||
if (pEnd === "ه" && word.g.slice(-1) === "u") {
|
if (pEnd === "ه" && word.g.slice(-1) === "u") {
|
||||||
return { inflections: inflectRegularShwaEndingUnisex(word.p, word.f), ...plurals };
|
return {
|
||||||
|
inflections: inflectRegularShwaEndingUnisex(word.p, word.f),
|
||||||
|
...plurals,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (pEnd === "ی" && word.f.slice(-2) === "éy") {
|
if (pEnd === "ی" && word.f.slice(-2) === "éy") {
|
||||||
return { inflections: inflectEmphasizedYeyUnisex(word.p, word.f), ...plurals };
|
return {
|
||||||
|
inflections: inflectEmphasizedYeyUnisex(word.p, word.f),
|
||||||
|
...plurals,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
pashtoConsonants.includes(pEnd) ||
|
pashtoConsonants.includes(pEnd) ||
|
||||||
|
@ -100,7 +111,10 @@ function handleUnisexWord(word: T.DictionaryEntryNoFVars): T.InflectorOutput {
|
||||||
word.f.slice(-1) === "w" ||
|
word.f.slice(-1) === "w" ||
|
||||||
(word.p.slice(-1) === "ه" && word.f.slice(-1) === "h")
|
(word.p.slice(-1) === "ه" && word.f.slice(-1) === "h")
|
||||||
) {
|
) {
|
||||||
return { inflections: inflectConsonantEndingUnisex(word.p, word.f), ...plurals };
|
return {
|
||||||
|
inflections: inflectConsonantEndingUnisex(word.p, word.f),
|
||||||
|
...plurals,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (plurals) return plurals;
|
if (plurals) return plurals;
|
||||||
return false;
|
return false;
|
||||||
|
@ -128,13 +142,16 @@ function handleMascNoun(w: T.DictionaryEntryNoFVars): T.InflectorOutput {
|
||||||
if (w.infap && w.infaf && w.infbp && w.infbf) {
|
if (w.infap && w.infaf && w.infbp && w.infbf) {
|
||||||
return {
|
return {
|
||||||
inflections: inflectIrregularMasc(w.p, w.f, [
|
inflections: inflectIrregularMasc(w.p, w.f, [
|
||||||
{p: w.infap, f: w.infaf},
|
{ p: w.infap, f: w.infaf },
|
||||||
{p: w.infbp, f: w.infbf},
|
{ p: w.infbp, f: w.infbf },
|
||||||
]),
|
]),
|
||||||
...plurals,
|
...plurals,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const isTobEnding = (w.p.slice(-3) === "توب" && ["tób", "tob"].includes(w.f.slice(-3)) && w.p.length > 3);
|
const isTobEnding =
|
||||||
|
w.p.slice(-3) === "توب" &&
|
||||||
|
["tób", "tob"].includes(w.f.slice(-3)) &&
|
||||||
|
w.p.length > 3;
|
||||||
if (isTobEnding) {
|
if (isTobEnding) {
|
||||||
return { inflections: inflectTobMasc(w.p, w.f), ...plurals };
|
return { inflections: inflectTobMasc(w.p, w.f), ...plurals };
|
||||||
}
|
}
|
||||||
|
@ -142,9 +159,12 @@ function handleMascNoun(w: T.DictionaryEntryNoFVars): T.InflectorOutput {
|
||||||
return { inflections: inflectRegularYeyMasc(w.p, w.f), ...plurals };
|
return { inflections: inflectRegularYeyMasc(w.p, w.f), ...plurals };
|
||||||
}
|
}
|
||||||
if (pEnd === "ی" && fEnd === "éy") {
|
if (pEnd === "ی" && fEnd === "éy") {
|
||||||
return { inflections: inflectRegularEmphasizedYeyMasc(w.p, w.f), ...plurals };
|
return {
|
||||||
|
inflections: inflectRegularEmphasizedYeyMasc(w.p, w.f),
|
||||||
|
...plurals,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return plurals ? { ...plurals } : false
|
return plurals ? { ...plurals } : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFemNoun(word: T.DictionaryEntryNoFVars): T.InflectorOutput {
|
function handleFemNoun(word: T.DictionaryEntryNoFVars): T.InflectorOutput {
|
||||||
|
@ -163,13 +183,22 @@ function handleFemNoun(word: T.DictionaryEntryNoFVars): T.InflectorOutput {
|
||||||
return { inflections: inflectRegularAFem(word.p, word.f), ...plurals };
|
return { inflections: inflectRegularAFem(word.p, word.f), ...plurals };
|
||||||
}
|
}
|
||||||
if (word.p.slice(-1) === "ح" && endingInSingleARegex.test(word.f)) {
|
if (word.p.slice(-1) === "ح" && endingInSingleARegex.test(word.f)) {
|
||||||
return { inflections: inflectRegularAWithHimPEnding(word.p, word.f), ...plurals };
|
return {
|
||||||
|
inflections: inflectRegularAWithHimPEnding(word.p, word.f),
|
||||||
|
...plurals,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// TODO: better reusable function to check if something ends with a consonant
|
// TODO: better reusable function to check if something ends with a consonant
|
||||||
if ((pashtoConsonants.includes(pEnd) || word.f.slice(-1) === "w") && !animate) {
|
if (
|
||||||
return { inflections: inflectRegularInanMissingAFem(word.p, word.f), ...plurals };
|
(pashtoConsonants.includes(pEnd) || word.f.slice(-1) === "w") &&
|
||||||
|
!animate
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
inflections: inflectRegularInanMissingAFem(word.p, word.f),
|
||||||
|
...plurals,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (pEnd === "ي" && (!animate)) {
|
if (pEnd === "ي" && !animate) {
|
||||||
return { inflections: inflectRegularInanEeFem(word.p, word.f), ...plurals };
|
return { inflections: inflectRegularInanEeFem(word.p, word.f), ...plurals };
|
||||||
}
|
}
|
||||||
if (pEnd === "ۍ") {
|
if (pEnd === "ۍ") {
|
||||||
|
@ -182,59 +211,74 @@ function handleFemNoun(word: T.DictionaryEntryNoFVars): T.InflectorOutput {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LEVEL 3 FUNCTIONS
|
// LEVEL 3 FUNCTIONS
|
||||||
function inflectIrregularUnisex(p: string, f: string, inflections: Array<{p: string, f: string}>): T.Inflections {
|
function inflectIrregularUnisex(
|
||||||
|
p: string,
|
||||||
|
f: string,
|
||||||
|
inflections: Array<{ p: string; f: string }>
|
||||||
|
): T.Inflections {
|
||||||
const inf1 = removeAccents(inflections[1]);
|
const inf1 = removeAccents(inflections[1]);
|
||||||
const inf0 = removeAccents(inflections[0]);
|
const inf0 = removeAccents(inflections[0]);
|
||||||
const inf0fSyls = splitUpSyllables(inf0.f).length;
|
const inf0fSyls = splitUpSyllables(inf0.f).length;
|
||||||
return {
|
return {
|
||||||
masc: [
|
masc: [
|
||||||
[{p, f}],
|
[{ p, f }],
|
||||||
[{p: inflections[0].p, f: `${inf0.f.slice(0, -1)}${inf0fSyls === 1 ? "u" : "ú"}` }],
|
[
|
||||||
[{p: `${inf1.p}و`, f: `${inf1.f}${inf0fSyls === 1 ? "o" : "ó"}`}],
|
{
|
||||||
|
p: inflections[0].p,
|
||||||
|
f: `${inf0.f.slice(0, -1)}${inf0fSyls === 1 ? "u" : "ú"}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[{ p: `${inf1.p}و`, f: `${inf1.f}${inf0fSyls === 1 ? "o" : "ó"}` }],
|
||||||
],
|
],
|
||||||
fem: [
|
fem: [
|
||||||
[{p: `${inf1.p}ه`, f: `${inf1.f}${inf0fSyls === 1 ? "a" : "á"}`}],
|
[{ p: `${inf1.p}ه`, f: `${inf1.f}${inf0fSyls === 1 ? "a" : "á"}` }],
|
||||||
[{p: `${inf1.p}ې`, f: `${inf1.f}${inf0fSyls === 1 ? "e" : "é"}`}],
|
[{ p: `${inf1.p}ې`, f: `${inf1.f}${inf0fSyls === 1 ? "e" : "é"}` }],
|
||||||
[{p: `${inf1.p}و`, f: `${inf1.f}${inf0fSyls === 1 ? "o" : "ó"}`}],
|
[{ p: `${inf1.p}و`, f: `${inf1.f}${inf0fSyls === 1 ? "o" : "ó"}` }],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function inflectRegularYeyUnisex(p: string, f: string): T.UnisexInflections {
|
export function inflectRegularYeyUnisex(
|
||||||
|
p: string,
|
||||||
|
f: string
|
||||||
|
): T.UnisexInflections {
|
||||||
const baseP = p.slice(0, -1);
|
const baseP = p.slice(0, -1);
|
||||||
const baseF = f.slice(0, -2);
|
const baseF = f.slice(0, -2);
|
||||||
return {
|
return {
|
||||||
masc: [
|
masc: [
|
||||||
[{p, f}],
|
[{ p, f }],
|
||||||
[{p: `${baseP}ي`, f: `${baseF}ee`}],
|
[{ p: `${baseP}ي`, f: `${baseF}ee` }],
|
||||||
[
|
[
|
||||||
{p: `${baseP}یو`, f: `${baseF}iyo`},
|
{ p: `${baseP}یو`, f: `${baseF}iyo` },
|
||||||
{p: `${baseP}و`, f: `${baseF}o`},
|
{ p: `${baseP}و`, f: `${baseF}o` },
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
fem: [
|
fem: [
|
||||||
[{p: `${baseP}ې`, f: `${baseF}e`}],
|
[{ p: `${baseP}ې`, f: `${baseF}e` }],
|
||||||
[{p: `${baseP}ې`, f: `${baseF}e`}],
|
[{ p: `${baseP}ې`, f: `${baseF}e` }],
|
||||||
[{p: `${baseP}و`, f: `${baseF}o`}],
|
[{ p: `${baseP}و`, f: `${baseF}o` }],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function inflectRegularShwaEndingUnisex(pr: string, fr: string): T.UnisexInflections {
|
export function inflectRegularShwaEndingUnisex(
|
||||||
|
pr: string,
|
||||||
|
fr: string
|
||||||
|
): T.UnisexInflections {
|
||||||
const { p, f } = removeAccents(makePsString(pr, fr));
|
const { p, f } = removeAccents(makePsString(pr, fr));
|
||||||
const accented = fr.slice(-1) === "ú";
|
const accented = fr.slice(-1) === "ú";
|
||||||
const baseP = p.slice(0, -1);
|
const baseP = p.slice(0, -1);
|
||||||
const baseF = f.slice(0, -1);
|
const baseF = f.slice(0, -1);
|
||||||
return {
|
return {
|
||||||
masc: [
|
masc: [
|
||||||
[{p: `${baseP}ه`, f: `${baseF}${accented ? "ú" : "u"}`}],
|
[{ p: `${baseP}ه`, f: `${baseF}${accented ? "ú" : "u"}` }],
|
||||||
[{p: `${baseP}ه`, f: `${baseF}${accented ? "ú" : "u"}`}],
|
[{ p: `${baseP}ه`, f: `${baseF}${accented ? "ú" : "u"}` }],
|
||||||
[{p: `${baseP}و`, f: `${baseF}${accented ? "ó" : "o"}`}],
|
[{ p: `${baseP}و`, f: `${baseF}${accented ? "ó" : "o"}` }],
|
||||||
],
|
],
|
||||||
fem: [
|
fem: [
|
||||||
[{p: `${baseP}ه`, f: `${baseF}${accented ? "á" : "a"}`}],
|
[{ p: `${baseP}ه`, f: `${baseF}${accented ? "á" : "a"}` }],
|
||||||
[{p: `${baseP}ې`, f: `${baseF}${accented ? "é" : "e"}`}],
|
[{ p: `${baseP}ې`, f: `${baseF}${accented ? "é" : "e"}` }],
|
||||||
[{p: `${baseP}و`, f: `${baseF}${accented ? "ó" : "o"}`}],
|
[{ p: `${baseP}و`, f: `${baseF}${accented ? "ó" : "o"}` }],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -244,39 +288,39 @@ function inflectEmphasizedYeyUnisex(p: string, f: string): T.UnisexInflections {
|
||||||
const baseF = f.slice(0, -2);
|
const baseF = f.slice(0, -2);
|
||||||
return {
|
return {
|
||||||
masc: [
|
masc: [
|
||||||
[{p, f}],
|
[{ p, f }],
|
||||||
[{p: `${baseP}ي`, f: `${baseF}ée`}],
|
[{ p: `${baseP}ي`, f: `${baseF}ée` }],
|
||||||
[
|
[
|
||||||
{p: `${baseP}یو`, f: `${baseF}iyo`},
|
{ p: `${baseP}یو`, f: `${baseF}iyo` },
|
||||||
{p: `${baseP}و`, f: `${baseF}ó`},
|
{ p: `${baseP}و`, f: `${baseF}ó` },
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
fem: [
|
fem: [
|
||||||
[{p: `${baseP}ۍ`, f: `${baseF}úy`}],
|
[{ p: `${baseP}ۍ`, f: `${baseF}úy` }],
|
||||||
[{p: `${baseP}ۍ`, f: `${baseF}úy`}],
|
[{ p: `${baseP}ۍ`, f: `${baseF}úy` }],
|
||||||
[
|
[
|
||||||
{ p: `${baseP}یو`, f: `${baseF}úyo` },
|
{ p: `${baseP}یو`, f: `${baseF}úyo` },
|
||||||
{ p: `${baseP}و`, f: `${baseF}ó`, },
|
{ p: `${baseP}و`, f: `${baseF}ó` },
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function inflectConsonantEndingUnisex(p: string, f: string): T.UnisexInflections {
|
function inflectConsonantEndingUnisex(
|
||||||
|
p: string,
|
||||||
|
f: string
|
||||||
|
): T.UnisexInflections {
|
||||||
const fSyls = splitUpSyllables(removeAccents(f));
|
const fSyls = splitUpSyllables(removeAccents(f));
|
||||||
const iBase = fSyls.length === 1
|
const iBase =
|
||||||
? makePsString(p, accentFSylsOnNFromEnd(fSyls, 0))
|
fSyls.length === 1
|
||||||
: makePsString(p, f);
|
? makePsString(p, accentFSylsOnNFromEnd(fSyls, 0))
|
||||||
|
: makePsString(p, f);
|
||||||
return {
|
return {
|
||||||
masc: [
|
masc: [[{ p, f }], [{ p, f }], [{ p: `${iBase.p}و`, f: `${iBase.f}o` }]],
|
||||||
[{p, f}],
|
|
||||||
[{p, f}],
|
|
||||||
[{p: `${iBase.p}و`, f: `${iBase.f}o`}],
|
|
||||||
],
|
|
||||||
fem: [
|
fem: [
|
||||||
[{p: `${iBase.p}ه`, f: `${iBase.f}a`}],
|
[{ p: `${iBase.p}ه`, f: `${iBase.f}a` }],
|
||||||
[{p: `${iBase.p}ې`, f: `${iBase.f}e`}],
|
[{ p: `${iBase.p}ې`, f: `${iBase.f}e` }],
|
||||||
[{p: `${iBase.p}و`, f: `${iBase.f}o`}],
|
[{ p: `${iBase.p}و`, f: `${iBase.f}o` }],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -286,11 +330,11 @@ function inflectRegularYeyMasc(p: string, f: string): T.Inflections {
|
||||||
const baseF = f.slice(0, -2);
|
const baseF = f.slice(0, -2);
|
||||||
return {
|
return {
|
||||||
masc: [
|
masc: [
|
||||||
[{p, f}],
|
[{ p, f }],
|
||||||
[{p: `${baseP}ي`, f: `${baseF}ee`}],
|
[{ p: `${baseP}ي`, f: `${baseF}ee` }],
|
||||||
[
|
[
|
||||||
{p: `${baseP}یو`, f: `${baseF}iyo`},
|
{ p: `${baseP}یو`, f: `${baseF}iyo` },
|
||||||
{p: `${baseP}و`, f: `${baseF}o`},
|
{ p: `${baseP}و`, f: `${baseF}o` },
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -301,9 +345,9 @@ function inflectTobMasc(p: string, f: string): T.Inflections {
|
||||||
const baseF = f.slice(0, -3);
|
const baseF = f.slice(0, -3);
|
||||||
return {
|
return {
|
||||||
masc: [
|
masc: [
|
||||||
[{p, f}],
|
[{ p, f }],
|
||||||
[{p: `${baseP}تابه`, f: `${baseF}taabu`}],
|
[{ p: `${baseP}تابه`, f: `${baseF}taabu` }],
|
||||||
[{p: `${baseP}تبو`, f: `${baseF}tabo`}],
|
[{ p: `${baseP}تبو`, f: `${baseF}tabo` }],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -313,39 +357,55 @@ function inflectRegularEmphasizedYeyMasc(p: string, f: string): T.Inflections {
|
||||||
const baseF = f.slice(0, -2);
|
const baseF = f.slice(0, -2);
|
||||||
return {
|
return {
|
||||||
masc: [
|
masc: [
|
||||||
[{p, f}],
|
[{ p, f }],
|
||||||
[{p: `${baseP}ي`, f: `${baseF}ée`}],
|
[{ p: `${baseP}ي`, f: `${baseF}ée` }],
|
||||||
[
|
[
|
||||||
{p: `${baseP}یو`, f: `${baseF}iyo`},
|
{ p: `${baseP}یو`, f: `${baseF}iyo` },
|
||||||
{p: `${baseP}و`, f: `${baseF}o`},
|
{ p: `${baseP}و`, f: `${baseF}o` },
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function inflectIrregularMasc(p: string, f: string, inflections: Array<{p: string, f: string}>): T.Inflections {
|
function inflectIrregularMasc(
|
||||||
|
p: string,
|
||||||
|
f: string,
|
||||||
|
inflections: Array<{ p: string; f: string }>
|
||||||
|
): T.Inflections {
|
||||||
let inf0f = removeAccents(inflections[0].f);
|
let inf0f = removeAccents(inflections[0].f);
|
||||||
const inf0syls = splitUpSyllables(f).length;
|
const inf0syls = splitUpSyllables(f).length;
|
||||||
const inf1f = removeAccents(inflections[1].f);
|
const inf1f = removeAccents(inflections[1].f);
|
||||||
return {
|
return {
|
||||||
masc: [
|
masc: [
|
||||||
[{p, f}],
|
[{ p, f }],
|
||||||
[{p: inflections[0].p, f: `${inf0f.slice(0, -1)}${inf0syls === 1 ? "u" : "ú"}`}],
|
[
|
||||||
[{p: `${inflections[1].p}و`, f: `${inf1f}${inf0syls === 1 ? "o" : "ó"}`}],
|
{
|
||||||
|
p: inflections[0].p,
|
||||||
|
f: `${inf0f.slice(0, -1)}${inf0syls === 1 ? "u" : "ú"}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
p: `${inflections[1].p}و`,
|
||||||
|
f: `${inf1f}${inf0syls === 1 ? "o" : "ó"}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function inflectRegularAFem(p: string, f: string): T.Inflections {
|
function inflectRegularAFem(p: string, f: string): T.Inflections {
|
||||||
const withoutTrailingComma = ["'", "’"].includes(f.slice(-1)) ? f.slice(0, -1) : f;
|
const withoutTrailingComma = ["'", "’"].includes(f.slice(-1))
|
||||||
|
? f.slice(0, -1)
|
||||||
|
: f;
|
||||||
const accentLast = hasAccents(withoutTrailingComma.slice(-1));
|
const accentLast = hasAccents(withoutTrailingComma.slice(-1));
|
||||||
const baseF = withoutTrailingComma.slice(0, -1);
|
const baseF = withoutTrailingComma.slice(0, -1);
|
||||||
const baseP = p.slice(-1) === "ع" ? p : p.slice(0, -1);
|
const baseP = p.slice(-1) === "ع" ? p : p.slice(0, -1);
|
||||||
return {
|
return {
|
||||||
fem: [
|
fem: [
|
||||||
[{p, f}],
|
[{ p, f }],
|
||||||
[{p: `${baseP}ې`, f: `${baseF}${accentLast ? "é" : "e"}`}],
|
[{ p: `${baseP}ې`, f: `${baseF}${accentLast ? "é" : "e"}` }],
|
||||||
[{p: `${baseP}و`, f: `${baseF}${accentLast ? "ó" : "o"}`}],
|
[{ p: `${baseP}و`, f: `${baseF}${accentLast ? "ó" : "o"}` }],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -354,22 +414,21 @@ function inflectRegularAWithHimPEnding(p: string, f: string): T.Inflections {
|
||||||
const baseF = f.slice(0, -1);
|
const baseF = f.slice(0, -1);
|
||||||
return {
|
return {
|
||||||
fem: [
|
fem: [
|
||||||
[{p, f}],
|
[{ p, f }],
|
||||||
[{p: `${p}ې`, f: `${baseF}e`}],
|
[{ p: `${p}ې`, f: `${baseF}e` }],
|
||||||
[{p: `${p}و`, f: `${baseF}o`}],
|
[{ p: `${p}و`, f: `${baseF}o` }],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function inflectRegularInanMissingAFem(p: string, f: string): T.Inflections {
|
function inflectRegularInanMissingAFem(p: string, f: string): T.Inflections {
|
||||||
const fBase = splitUpSyllables(f).length === 1
|
const fBase =
|
||||||
? accentFSylsOnNFromEnd(f, 0)
|
splitUpSyllables(f).length === 1 ? accentFSylsOnNFromEnd(f, 0) : f;
|
||||||
: f;
|
return {
|
||||||
return {
|
|
||||||
fem: [
|
fem: [
|
||||||
[{p, f}],
|
[{ p, f }],
|
||||||
[{p: `${p}ې`, f: `${fBase}e`}],
|
[{ p: `${p}ې`, f: `${fBase}e` }],
|
||||||
[{p: `${p}و`, f: `${fBase}o`}],
|
[{ p: `${p}و`, f: `${fBase}o` }],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -379,9 +438,9 @@ function inflectRegularInanEeFem(p: string, f: string): T.Inflections {
|
||||||
const baseF = f.slice(0, -2);
|
const baseF = f.slice(0, -2);
|
||||||
return {
|
return {
|
||||||
fem: [
|
fem: [
|
||||||
[{p, f}],
|
[{ p, f }],
|
||||||
[{p: `${baseP}ۍ`, f: `${baseF}úy`}],
|
[{ p: `${baseP}ۍ`, f: `${baseF}úy` }],
|
||||||
[{p: `${baseP}یو`, f: `${baseF}úyo`}],
|
[{ p: `${baseP}یو`, f: `${baseF}úyo` }],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -391,26 +450,23 @@ function inflectRegularUyFem(p: string, f: string): T.Inflections {
|
||||||
const baseF = removeAccents(f.slice(0, -2));
|
const baseF = removeAccents(f.slice(0, -2));
|
||||||
return {
|
return {
|
||||||
fem: [
|
fem: [
|
||||||
[{p, f: `${baseF}úy`}],
|
[{ p, f: `${baseF}úy` }],
|
||||||
[{p, f: `${baseF}úy`}],
|
[{ p, f: `${baseF}úy` }],
|
||||||
[
|
[
|
||||||
{p: `${baseP}یو`, f: `${baseF}úyo`},
|
{ p: `${baseP}یو`, f: `${baseF}úyo` },
|
||||||
{p: `${baseP}و`, f: `${baseF}o`},
|
{ p: `${baseP}و`, f: `${baseF}o` },
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function makePashtoPlural(word: T.DictionaryEntryNoFVars): T.PluralInflections | undefined {
|
function makePashtoPlural(
|
||||||
|
word: T.DictionaryEntryNoFVars
|
||||||
|
): T.PluralInflections | undefined {
|
||||||
if (!(word.ppp && word.ppf)) return undefined;
|
if (!(word.ppp && word.ppf)) return undefined;
|
||||||
const base = splitPsByVarients(
|
const base = splitPsByVarients(makePsString(word.ppp, word.ppf));
|
||||||
makePsString(word.ppp, word.ppf)
|
|
||||||
);
|
|
||||||
function getBaseAndO(): T.PluralInflectionSet {
|
function getBaseAndO(): T.PluralInflectionSet {
|
||||||
return [
|
return [base, base.flatMap(addOEnding) as T.ArrayOneOrMore<T.PsString>];
|
||||||
base,
|
|
||||||
base.flatMap(addOEnding) as T.ArrayOneOrMore<T.PsString>,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
if (word.c?.includes("n. m.")) {
|
if (word.c?.includes("n. m.")) {
|
||||||
return { masc: getBaseAndO() };
|
return { masc: getBaseAndO() };
|
||||||
|
@ -422,14 +478,14 @@ function makePashtoPlural(word: T.DictionaryEntryNoFVars): T.PluralInflections |
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeBundledPlural(word: T.DictionaryEntryNoFVars): T.PluralInflections | undefined {
|
function makeBundledPlural(
|
||||||
|
word: T.DictionaryEntryNoFVars
|
||||||
|
): T.PluralInflections | undefined {
|
||||||
if (!endsInConsonant(word) || !word.c?.includes("n.")) {
|
if (!endsInConsonant(word) || !word.c?.includes("n.")) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const w = makePsString(word.p, word.f);
|
const w = makePsString(word.p, word.f);
|
||||||
const base = countSyllables(w) === 1
|
const base = countSyllables(w) === 1 ? accentOnNFromEnd(w, 0) : w;
|
||||||
? accentOnNFromEnd(w, 0)
|
|
||||||
: w;
|
|
||||||
return {
|
return {
|
||||||
masc: [
|
masc: [
|
||||||
[concatPsString(base, { p: "ه", f: "a" })],
|
[concatPsString(base, { p: "ه", f: "a" })],
|
||||||
|
@ -438,7 +494,9 @@ function makeBundledPlural(word: T.DictionaryEntryNoFVars): T.PluralInflections
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeArabicPlural(word: T.DictionaryEntryNoFVars): T.PluralInflections | undefined {
|
function makeArabicPlural(
|
||||||
|
word: T.DictionaryEntryNoFVars
|
||||||
|
): T.PluralInflections | undefined {
|
||||||
if (!(word.apf && word.app)) return undefined;
|
if (!(word.apf && word.app)) return undefined;
|
||||||
const w = makePsString(word.app, word.apf);
|
const w = makePsString(word.app, word.apf);
|
||||||
const plural = splitPsByVarients(w);
|
const plural = splitPsByVarients(w);
|
||||||
|
@ -456,39 +514,55 @@ function makeArabicPlural(word: T.DictionaryEntryNoFVars): T.PluralInflections |
|
||||||
return { masc: value };
|
return { masc: value };
|
||||||
}
|
}
|
||||||
|
|
||||||
function makePlural(w: T.DictionaryEntryNoFVars): { plural: T.PluralInflections, bundledPlural?: T.PluralInflections } | { arabicPlural: T.PluralInflections, bundledPlural?: T.PluralInflections } | undefined {
|
function makePlural(
|
||||||
function addSecondInf(plur: T.ArrayOneOrMore<T.PsString> | T.PsString): T.PluralInflectionSet {
|
w: T.DictionaryEntryNoFVars
|
||||||
|
):
|
||||||
|
| { plural: T.PluralInflections; bundledPlural?: T.PluralInflections }
|
||||||
|
| { arabicPlural: T.PluralInflections; bundledPlural?: T.PluralInflections }
|
||||||
|
| undefined {
|
||||||
|
function addSecondInf(
|
||||||
|
plur: T.ArrayOneOrMore<T.PsString> | T.PsString
|
||||||
|
): T.PluralInflectionSet {
|
||||||
if (!Array.isArray(plur)) {
|
if (!Array.isArray(plur)) {
|
||||||
return addSecondInf([plur]);
|
return addSecondInf([plur]);
|
||||||
}
|
}
|
||||||
return [
|
return [plur, plur.flatMap(addOEnding) as T.ArrayOneOrMore<T.PsString>];
|
||||||
plur,
|
|
||||||
plur.flatMap(addOEnding) as T.ArrayOneOrMore<T.PsString>,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
if (w.c && w.c.includes("pl.")) {
|
if (w.c && w.c.includes("pl.")) {
|
||||||
const plural = addSecondInf(makePsString(w.p, w.f));
|
const plural = addSecondInf(makePsString(w.p, w.f));
|
||||||
// Typescript being dumb and not letting me do a typed variable for the key
|
// Typescript being dumb and not letting me do a typed variable for the key
|
||||||
// could try refactoring with an updated TypeScript dependency
|
// could try refactoring with an updated TypeScript dependency
|
||||||
if (w.c.includes("n. m.")) return { plural: { masc: plural }};
|
if (w.c.includes("n. m.")) return { plural: { masc: plural } };
|
||||||
if (w.c.includes("n. f.")) return { plural: { fem: plural }};
|
if (w.c.includes("n. f.")) return { plural: { fem: plural } };
|
||||||
}
|
}
|
||||||
const arabicPlural = makeArabicPlural(w);
|
const arabicPlural = makeArabicPlural(w);
|
||||||
const pashtoPlural = makePashtoPlural(w);
|
const pashtoPlural = makePashtoPlural(w);
|
||||||
const bundledPlural = makeBundledPlural(w);
|
const bundledPlural = makeBundledPlural(w);
|
||||||
function addMascPluralSuffix(animate?: boolean, shortSquish?: boolean): T.PluralInflectionSet {
|
function addMascPluralSuffix(
|
||||||
|
animate?: boolean,
|
||||||
|
shortSquish?: boolean
|
||||||
|
): T.PluralInflectionSet {
|
||||||
if (shortSquish && (w.infap === undefined || w.infaf === undefined)) {
|
if (shortSquish && (w.infap === undefined || w.infaf === undefined)) {
|
||||||
throw new Error(`no irregular inflection info for ${w.p} - ${w.ts}`);
|
throw new Error(`no irregular inflection info for ${w.p} - ${w.ts}`);
|
||||||
}
|
}
|
||||||
const b = removeAccents(shortSquish
|
const b = removeAccents(
|
||||||
? makePsString((w.infap as string).slice(0, -1), (w.infaf as string).slice(0, -1))
|
shortSquish
|
||||||
: w
|
? makePsString(
|
||||||
|
(w.infap as string).slice(0, -1),
|
||||||
|
(w.infaf as string).slice(0, -1)
|
||||||
|
)
|
||||||
|
: w
|
||||||
);
|
);
|
||||||
const base = endsInShwa(b)
|
const base = endsInShwa(b)
|
||||||
? makePsString(b.p.slice(0, -1), b.f.slice(0, -1))
|
? makePsString(b.p.slice(0, -1), b.f.slice(0, -1))
|
||||||
: b;
|
: b;
|
||||||
return addSecondInf(
|
return addSecondInf(
|
||||||
concatPsString(base, (animate && !shortSquish) ? { p: "ان", f: "áan" } : { p: "ونه", f: "óona" }),
|
concatPsString(
|
||||||
|
base,
|
||||||
|
animate && !shortSquish
|
||||||
|
? { p: "ان", f: "áan" }
|
||||||
|
: { p: "ونه", f: "óona" }
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
function addAnimUnisexPluralSuffix(): T.UnisexSet<T.PluralInflectionSet> {
|
function addAnimUnisexPluralSuffix(): T.UnisexSet<T.PluralInflectionSet> {
|
||||||
|
@ -505,10 +579,14 @@ function makePlural(w: T.DictionaryEntryNoFVars): { plural: T.PluralInflections,
|
||||||
f: b.f.slice(0, -2),
|
f: b.f.slice(0, -2),
|
||||||
};
|
};
|
||||||
const firstInf: T.ArrayOneOrMore<T.PsString> = [
|
const firstInf: T.ArrayOneOrMore<T.PsString> = [
|
||||||
concatPsString(base, { p: "یان", f: "iyáan" }, gender === "fem" ? { p: "ې", f: "e" } : ""),
|
concatPsString(
|
||||||
...gender === "fem"
|
base,
|
||||||
|
{ p: "یان", f: "iyáan" },
|
||||||
|
gender === "fem" ? { p: "ې", f: "e" } : ""
|
||||||
|
),
|
||||||
|
...(gender === "fem"
|
||||||
? [concatPsString(base, { p: "یګانې", f: "eegáane" })]
|
? [concatPsString(base, { p: "یګانې", f: "eegáane" })]
|
||||||
: [],
|
: []),
|
||||||
];
|
];
|
||||||
return [
|
return [
|
||||||
firstInf,
|
firstInf,
|
||||||
|
@ -537,11 +615,12 @@ function makePlural(w: T.DictionaryEntryNoFVars): { plural: T.PluralInflections,
|
||||||
function addLongVowelSuffix(gender: "masc" | "fem"): T.PluralInflectionSet {
|
function addLongVowelSuffix(gender: "masc" | "fem"): T.PluralInflectionSet {
|
||||||
const base = removeEndTick(makePsString(w.p, w.f));
|
const base = removeEndTick(makePsString(w.p, w.f));
|
||||||
const baseWOutAccents = removeAccents(base);
|
const baseWOutAccents = removeAccents(base);
|
||||||
const space = (w.p.slice(-1) === "ع" || w.p.slice(-1) === "ه") ? { p: " ", f: " " } : "";
|
const space =
|
||||||
|
w.p.slice(-1) === "ع" || w.p.slice(-1) === "ه" ? { p: " ", f: " " } : "";
|
||||||
if (gender === "fem") {
|
if (gender === "fem") {
|
||||||
return addSecondInf([
|
return addSecondInf([
|
||||||
concatPsString(base, space, { p: "وې", f: "we" }),
|
concatPsString(base, space, { p: "وې", f: "we" }),
|
||||||
concatPsString(baseWOutAccents, space, { p: "ګانې", f: "gáane" })
|
concatPsString(baseWOutAccents, space, { p: "ګانې", f: "gáane" }),
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
return addSecondInf([
|
return addSecondInf([
|
||||||
|
@ -571,24 +650,32 @@ function makePlural(w: T.DictionaryEntryNoFVars): { plural: T.PluralInflections,
|
||||||
|
|
||||||
const shortSquish = !!w.infap && !w.infap.includes("ا");
|
const shortSquish = !!w.infap && !w.infap.includes("ا");
|
||||||
const anim = w.c?.includes("anim.");
|
const anim = w.c?.includes("anim.");
|
||||||
const type = (w.c?.includes("unisex"))
|
const type = w.c?.includes("unisex")
|
||||||
? "unisex noun"
|
? "unisex noun"
|
||||||
: (w.c?.includes("n. m."))
|
: w.c?.includes("n. m.")
|
||||||
? "masc noun"
|
? "masc noun"
|
||||||
: (w.c?.includes("n. f."))
|
: w.c?.includes("n. f.")
|
||||||
? "fem noun"
|
? "fem noun"
|
||||||
: "other";
|
: "other";
|
||||||
if (pashtoPlural) return {
|
if (pashtoPlural)
|
||||||
plural: pashtoPlural,
|
return {
|
||||||
arabicPlural,
|
plural: pashtoPlural,
|
||||||
};
|
arabicPlural,
|
||||||
|
};
|
||||||
if (type === "unisex noun") {
|
if (type === "unisex noun") {
|
||||||
// doesn't need to be labelled anim - because it's only with animate nouns that you get the unisex - I THINK
|
// doesn't need to be labelled anim - because it's only with animate nouns that you get the unisex - I THINK
|
||||||
if (endsInConsonant(w) && (!w.infap)) {
|
if (endsInConsonant(w) && !w.infap) {
|
||||||
return { arabicPlural, bundledPlural, plural: addAnimUnisexPluralSuffix() };
|
return {
|
||||||
|
arabicPlural,
|
||||||
|
bundledPlural,
|
||||||
|
plural: addAnimUnisexPluralSuffix(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (shortSquish && !anim) {
|
if (shortSquish && !anim) {
|
||||||
return { arabicPlural, plural: { masc: addMascPluralSuffix(anim, shortSquish) }};
|
return {
|
||||||
|
arabicPlural,
|
||||||
|
plural: { masc: addMascPluralSuffix(anim, shortSquish) },
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (endsWith([{ p: "ی", f: "éy" }, { p: "ي" }], w, true)) {
|
if (endsWith([{ p: "ی", f: "éy" }, { p: "ي" }], w, true)) {
|
||||||
return { arabicPlural, plural: addAnimN3UnisexPluralSuffix() };
|
return { arabicPlural, plural: addAnimN3UnisexPluralSuffix() };
|
||||||
|
@ -597,10 +684,10 @@ function makePlural(w: T.DictionaryEntryNoFVars): { plural: T.PluralInflections,
|
||||||
// arabic plurals for the animat ones, right?
|
// arabic plurals for the animat ones, right?
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
type === "masc noun" &&
|
type === "masc noun" &&
|
||||||
(shortSquish || ((endsInConsonant(w) || endsInShwa(w)) && (!w.infap))) &&
|
(shortSquish || ((endsInConsonant(w) || endsInShwa(w)) && !w.infap)) &&
|
||||||
(w.p.slice(-3) !== "توب")
|
w.p.slice(-3) !== "توب"
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
arabicPlural,
|
arabicPlural,
|
||||||
bundledPlural,
|
bundledPlural,
|
||||||
|
@ -609,11 +696,7 @@ function makePlural(w: T.DictionaryEntryNoFVars): { plural: T.PluralInflections,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (
|
if (type === "masc noun" && endsWith({ p: "ی", f: "éy" }, w, true) && anim) {
|
||||||
type === "masc noun" &&
|
|
||||||
endsWith({ p: "ی", f: "éy" }, w, true) &&
|
|
||||||
anim
|
|
||||||
) {
|
|
||||||
const { masc } = addAnimN3UnisexPluralSuffix();
|
const { masc } = addAnimN3UnisexPluralSuffix();
|
||||||
return {
|
return {
|
||||||
arabicPlural,
|
arabicPlural,
|
||||||
|
@ -630,7 +713,7 @@ function makePlural(w: T.DictionaryEntryNoFVars): { plural: T.PluralInflections,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// TODO: What about endings in long ee / animate at inanimate
|
// TODO: What about endings in long ee / animate at inanimate
|
||||||
if (type === "masc noun" && endsInAaOrOo(w) && (!w.infap)) {
|
if (type === "masc noun" && endsInAaOrOo(w) && !w.infap) {
|
||||||
return {
|
return {
|
||||||
arabicPlural,
|
arabicPlural,
|
||||||
plural: {
|
plural: {
|
||||||
|
@ -639,7 +722,7 @@ function makePlural(w: T.DictionaryEntryNoFVars): { plural: T.PluralInflections,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// TODO: What about endings in long ee / animate at inanimate
|
// TODO: What about endings in long ee / animate at inanimate
|
||||||
if (type === "fem noun" && endsInAaOrOo(w) && (!w.infap)) {
|
if (type === "fem noun" && endsInAaOrOo(w) && !w.infap) {
|
||||||
return {
|
return {
|
||||||
arabicPlural,
|
arabicPlural,
|
||||||
plural: {
|
plural: {
|
||||||
|
@ -661,6 +744,8 @@ function makePlural(w: T.DictionaryEntryNoFVars): { plural: T.PluralInflections,
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function inflectYey(ps: T.SingleOrLengthOpts<T.PsString>): T.SingleOrLengthOpts<T.UnisexInflections> {
|
export function inflectYey(
|
||||||
|
ps: T.SingleOrLengthOpts<T.PsString>
|
||||||
|
): T.SingleOrLengthOpts<T.UnisexInflections> {
|
||||||
return fmapSingleOrLengthOpts((x) => inflectRegularYeyUnisex(x.p, x.f), ps);
|
return fmapSingleOrLengthOpts((x) => inflectRegularYeyUnisex(x.p, x.f), ps);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,289 +2,403 @@ import * as T from "../../../types";
|
||||||
import { getLength } from "../p-text-helpers";
|
import { getLength } from "../p-text-helpers";
|
||||||
|
|
||||||
export function makeBlock(block: T.Block["block"], key?: number): T.Block {
|
export function makeBlock(block: T.Block["block"], key?: number): T.Block {
|
||||||
return {
|
return {
|
||||||
key: key === undefined ? Math.random() : key,
|
key: key === undefined ? Math.random() : key,
|
||||||
block,
|
block,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeKid(kid: T.Kid["kid"], key?: number): T.Kid {
|
export function makeKid(kid: T.Kid["kid"], key?: number): T.Kid {
|
||||||
return {
|
return {
|
||||||
key: key === undefined ? Math.random() : key,
|
key: key === undefined ? Math.random() : key,
|
||||||
kid,
|
kid,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSubjectSelection(blocks: T.EPSBlockComplete[] | T.VPSBlockComplete[]): T.SubjectSelectionComplete;
|
export function getSubjectSelection(
|
||||||
export function getSubjectSelection(blocks: T.EPSBlock[] | T.VPSBlock[]): T.SubjectSelection;
|
blocks: T.EPSBlockComplete[] | T.VPSBlockComplete[]
|
||||||
export function getSubjectSelection(blocks: T.EPSBlock[] | T.EPSBlockComplete[] | T.VPSBlockComplete[] | T.VPSBlock[]): T.SubjectSelection | T.SubjectSelectionComplete {
|
): T.SubjectSelectionComplete;
|
||||||
const b = blocks.find(f => f.block?.type === "subjectSelection");
|
export function getSubjectSelection(
|
||||||
if (!b || !b.block || b.block.type !== "subjectSelection") {
|
blocks: T.EPSBlock[] | T.VPSBlock[]
|
||||||
throw new Error("subjectSelection not found in blocks");
|
): T.SubjectSelection;
|
||||||
}
|
export function getSubjectSelection(
|
||||||
return b.block;
|
blocks:
|
||||||
|
| T.EPSBlock[]
|
||||||
|
| T.EPSBlockComplete[]
|
||||||
|
| T.VPSBlockComplete[]
|
||||||
|
| T.VPSBlock[]
|
||||||
|
): T.SubjectSelection | T.SubjectSelectionComplete {
|
||||||
|
const b = blocks.find((f) => f.block?.type === "subjectSelection");
|
||||||
|
if (!b || !b.block || b.block.type !== "subjectSelection") {
|
||||||
|
throw new Error("subjectSelection not found in blocks");
|
||||||
|
}
|
||||||
|
return b.block;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getComplementFromBlocks(blocks: T.Block[][]): T.Rendered<T.ComplementSelection> | T.UnselectedComplementSelection | undefined {
|
export function getComplementFromBlocks(
|
||||||
const b = blocks[0].find(f => f.block.type === "complement");
|
blocks: T.Block[][]
|
||||||
return b?.block as T.Rendered<T.ComplementSelection> | T.UnselectedComplementSelection | undefined;
|
):
|
||||||
|
| T.Rendered<T.ComplementSelection>
|
||||||
|
| T.UnselectedComplementSelection
|
||||||
|
| undefined {
|
||||||
|
const b = blocks[0].find((f) => f.block.type === "complement");
|
||||||
|
return b?.block as
|
||||||
|
| T.Rendered<T.ComplementSelection>
|
||||||
|
| T.UnselectedComplementSelection
|
||||||
|
| undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSubjectSelectionFromBlocks(blocks: T.Block[][]): T.Rendered<T.SubjectSelectionComplete> {
|
export function getSubjectSelectionFromBlocks(
|
||||||
const b = blocks[0].find(f => f.block.type === "subjectSelection");
|
blocks: T.Block[][]
|
||||||
if (!b || b.block.type !== "subjectSelection") {
|
): T.Rendered<T.SubjectSelectionComplete> {
|
||||||
throw new Error("subjectSelection not found in blocks");
|
const b = blocks[0].find((f) => f.block.type === "subjectSelection");
|
||||||
}
|
if (!b || b.block.type !== "subjectSelection") {
|
||||||
return b.block;
|
throw new Error("subjectSelection not found in blocks");
|
||||||
|
}
|
||||||
|
return b.block;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getObjectSelectionFromBlocks(blocks: T.Block[][]): T.Rendered<T.ObjectSelectionComplete> {
|
export function getObjectSelectionFromBlocks(
|
||||||
const b = blocks[0].find(f => f.block.type === "objectSelection");
|
blocks: T.Block[][]
|
||||||
if (!b || b.block.type !== "objectSelection") {
|
): T.Rendered<T.ObjectSelectionComplete> {
|
||||||
throw new Error("objectSelection not found in blocks");
|
const b = blocks[0].find((f) => f.block.type === "objectSelection");
|
||||||
}
|
if (!b || b.block.type !== "objectSelection") {
|
||||||
return b.block;
|
throw new Error("objectSelection not found in blocks");
|
||||||
|
}
|
||||||
|
return b.block;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function includesShrunkenServant(kids?: T.Kid[]): boolean {
|
export function includesShrunkenServant(kids?: T.Kid[]): boolean {
|
||||||
if (!kids) return false;
|
if (!kids) return false;
|
||||||
return kids.some(k => (
|
return kids.some(
|
||||||
k.kid.type === "mini-pronoun" && k.kid.source === "servant"
|
(k) => k.kid.type === "mini-pronoun" && k.kid.source === "servant"
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPredicateSelectionFromBlocks(blocks: T.Block[][]): T.Rendered<T.PredicateSelectionComplete> {
|
export function getPredicateSelectionFromBlocks(
|
||||||
const b = blocks[0].find(f => f.block.type === "predicateSelection");
|
blocks: T.Block[][]
|
||||||
if (!b || b.block.type !== "predicateSelection") {
|
): T.Rendered<T.PredicateSelectionComplete> {
|
||||||
throw new Error("predicateSelection not found in blocks");
|
const b = blocks[0].find((f) => f.block.type === "predicateSelection");
|
||||||
}
|
if (!b || b.block.type !== "predicateSelection") {
|
||||||
return b.block;
|
throw new Error("predicateSelection not found in blocks");
|
||||||
|
}
|
||||||
|
return b.block;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAPsFromBlocks(blocks: T.Block[][]): T.Rendered<T.APSelection>[] {
|
export function getAPsFromBlocks(
|
||||||
return blocks[0].filter(b => b.block.type === "AP").map(b => b.block) as T.Rendered<T.APSelection>[];
|
blocks: T.Block[][]
|
||||||
|
): T.Rendered<T.APSelection>[] {
|
||||||
|
return blocks[0]
|
||||||
|
.filter((b) => b.block.type === "AP")
|
||||||
|
.map((b) => b.block) as T.Rendered<T.APSelection>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getObjectSelection(blocks: T.VPSBlockComplete[]): T.ObjectSelectionComplete;
|
export function getObjectSelection(
|
||||||
|
blocks: T.VPSBlockComplete[]
|
||||||
|
): T.ObjectSelectionComplete;
|
||||||
export function getObjectSelection(blocks: T.VPSBlock[]): T.ObjectSelection;
|
export function getObjectSelection(blocks: T.VPSBlock[]): T.ObjectSelection;
|
||||||
export function getObjectSelection(blocks: T.VPSBlock[] | T.VPSBlockComplete[]): T.ObjectSelection | T.ObjectSelectionComplete {
|
export function getObjectSelection(
|
||||||
const b = blocks.find(f => f.block?.type === "objectSelection");
|
blocks: T.VPSBlock[] | T.VPSBlockComplete[]
|
||||||
if (!b || !b.block || b.block.type !== "objectSelection") {
|
): T.ObjectSelection | T.ObjectSelectionComplete {
|
||||||
throw new Error("objectSelection not found in blocks");
|
const b = blocks.find((f) => f.block?.type === "objectSelection");
|
||||||
}
|
if (!b || !b.block || b.block.type !== "objectSelection") {
|
||||||
return b.block;
|
throw new Error("objectSelection not found in blocks");
|
||||||
|
}
|
||||||
|
return b.block;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeEPSBlocks(): T.EPSBlock[] {
|
export function makeEPSBlocks(): T.EPSBlock[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
key: Math.random(),
|
key: Math.random(),
|
||||||
block: {
|
block: {
|
||||||
type: "subjectSelection",
|
|
||||||
selection: undefined,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function makeAPBlock(): { key: number, block: undefined } {
|
|
||||||
return {
|
|
||||||
key: Math.random(),
|
|
||||||
block: undefined,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function makeSubjectSelection(selection: T.SubjectSelection | T.NPSelection | T.NPSelection["selection"] | undefined): T.SubjectSelection {
|
|
||||||
if (!selection) {
|
|
||||||
return {
|
|
||||||
type: "subjectSelection",
|
|
||||||
selection: undefined,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (selection.type === "subjectSelection") {
|
|
||||||
return selection;
|
|
||||||
}
|
|
||||||
if (selection.type === "NP") {
|
|
||||||
return {
|
|
||||||
type: "subjectSelection",
|
|
||||||
selection,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
type: "subjectSelection",
|
type: "subjectSelection",
|
||||||
selection: {
|
selection: undefined,
|
||||||
type: "NP",
|
},
|
||||||
selection,
|
},
|
||||||
}
|
];
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeObjectSelection(selection: T.ObjectSelection | T.ObjectNP | T.NPSelection | T.NPSelection["selection"] | undefined): T.ObjectSelection {
|
export function makeAPBlock(): { key: number; block: undefined } {
|
||||||
if (!selection) {
|
return {
|
||||||
return {
|
key: Math.random(),
|
||||||
type: "objectSelection",
|
block: undefined,
|
||||||
selection: undefined,
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (typeof selection !== "object") {
|
export function makeSubjectSelection(
|
||||||
return {
|
selection:
|
||||||
type: "objectSelection",
|
| T.SubjectSelection
|
||||||
selection,
|
| T.NPSelection
|
||||||
};
|
| T.NPSelection["selection"]
|
||||||
}
|
| undefined
|
||||||
if (selection.type === "objectSelection") {
|
): T.SubjectSelection {
|
||||||
return selection;
|
if (!selection) {
|
||||||
}
|
|
||||||
if (selection.type === "NP") {
|
|
||||||
return {
|
|
||||||
type: "objectSelection",
|
|
||||||
selection,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
type: "objectSelection",
|
type: "subjectSelection",
|
||||||
selection: {
|
selection: undefined,
|
||||||
type: "NP",
|
|
||||||
selection,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
if (selection.type === "subjectSelection") {
|
||||||
|
return selection;
|
||||||
|
}
|
||||||
|
if (selection.type === "NP") {
|
||||||
|
return {
|
||||||
|
type: "subjectSelection",
|
||||||
|
selection,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: "subjectSelection",
|
||||||
|
selection: {
|
||||||
|
type: "NP",
|
||||||
|
selection,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EPSBlocksAreComplete(blocks: T.EPSBlock[]): blocks is T.EPSBlockComplete[] {
|
export function makeObjectSelection(
|
||||||
if (blocks.some(block => block.block === undefined)) {
|
selection:
|
||||||
return false;
|
| T.ObjectSelection
|
||||||
}
|
| T.ObjectNP
|
||||||
const subject = getSubjectSelection(blocks);
|
| T.NPSelection
|
||||||
return !!subject.selection;
|
| T.NPSelection["selection"]
|
||||||
|
| undefined
|
||||||
|
): T.ObjectSelection {
|
||||||
|
if (!selection) {
|
||||||
|
return {
|
||||||
|
type: "objectSelection",
|
||||||
|
selection: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (typeof selection !== "object") {
|
||||||
|
return {
|
||||||
|
type: "objectSelection",
|
||||||
|
selection,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (selection.type === "objectSelection") {
|
||||||
|
return selection;
|
||||||
|
}
|
||||||
|
if (selection.type === "NP") {
|
||||||
|
return {
|
||||||
|
type: "objectSelection",
|
||||||
|
selection,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: "objectSelection",
|
||||||
|
selection: {
|
||||||
|
type: "NP",
|
||||||
|
selection,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VPSBlocksAreComplete(blocks: T.VPSBlock[]): blocks is T.VPSBlockComplete[] {
|
export function EPSBlocksAreComplete(
|
||||||
if (blocks.some(block => block.block === undefined)) {
|
blocks: T.EPSBlock[]
|
||||||
return false;
|
): blocks is T.EPSBlockComplete[] {
|
||||||
}
|
if (blocks.some((block) => block.block === undefined)) {
|
||||||
const subject = getSubjectSelection(blocks);
|
return false;
|
||||||
if (!subject.selection) return false;
|
}
|
||||||
const object = getObjectSelection(blocks);
|
const subject = getSubjectSelection(blocks);
|
||||||
if (!object.selection) return false;
|
return !!subject.selection;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function adjustSubjectSelection(blocks: T.EPSBlock[], subject: T.SubjectSelection | T.NPSelection | undefined): T.EPSBlock[];
|
export function VPSBlocksAreComplete(
|
||||||
export function adjustSubjectSelection(blocks: T.VPSBlock[], subject: T.SubjectSelection | T.NPSelection | undefined): T.VPSBlock[];
|
blocks: T.VPSBlock[]
|
||||||
export function adjustSubjectSelection(blocks: T.VPSBlock[] | T.EPSBlock[], subject: T.SubjectSelection | T.NPSelection | undefined): T.VPSBlock[] | T.EPSBlock[] {
|
): blocks is T.VPSBlockComplete[] {
|
||||||
const nb = [...blocks];
|
if (blocks.some((block) => block.block === undefined)) {
|
||||||
const i = nb.findIndex(b => b.block && b.block.type === "subjectSelection");
|
return false;
|
||||||
if (i === -1) {
|
}
|
||||||
throw new Error("couldn't find subjectSelection to modify");
|
const subject = getSubjectSelection(blocks);
|
||||||
}
|
if (!subject.selection) return false;
|
||||||
nb[i].block = subject?.type === "subjectSelection" ? subject : makeSubjectSelection(subject);
|
const object = getObjectSelection(blocks);
|
||||||
return nb;
|
if (!object.selection) return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function adjustObjectSelection(blocks: Readonly<T.VPSBlock[]>, object: T.ObjectSelectionComplete | T.NPSelection | T.VerbObject | T.ObjectSelectionComplete): T.VPSBlockComplete[];
|
export function adjustSubjectSelection(
|
||||||
export function adjustObjectSelection(blocks: Readonly<T.VPSBlock[]>, object: T.ObjectSelection | T.NPSelection | T.VerbObject | T.ObjectSelection | undefined): T.EPSBlock[];
|
blocks: T.EPSBlock[],
|
||||||
export function adjustObjectSelection(blocks: Readonly<T.VPSBlock[]>, object: T.ObjectSelection | T.ObjectSelectionComplete | T.VerbObject | T.NPSelection | undefined): T.VPSBlock[] | T.VPSBlockComplete[] {
|
subject: T.SubjectSelection | T.NPSelection | undefined
|
||||||
const nb = [...blocks];
|
): T.EPSBlock[];
|
||||||
const i = nb.findIndex(b => b.block && b.block.type === "objectSelection");
|
export function adjustSubjectSelection(
|
||||||
if (i === -1) {
|
blocks: T.VPSBlock[],
|
||||||
throw new Error("couldn't find objectSelection to modify");
|
subject: T.SubjectSelection | T.NPSelection | undefined
|
||||||
}
|
): T.VPSBlock[];
|
||||||
nb[i].block = typeof object === "object" && object?.type === "objectSelection"
|
export function adjustSubjectSelection(
|
||||||
? object
|
blocks: T.VPSBlock[] | T.EPSBlock[],
|
||||||
: makeObjectSelection(object);
|
subject: T.SubjectSelection | T.NPSelection | undefined
|
||||||
return nb;
|
): T.VPSBlock[] | T.EPSBlock[] {
|
||||||
|
const nb = [...blocks];
|
||||||
|
const i = nb.findIndex((b) => b.block && b.block.type === "subjectSelection");
|
||||||
|
if (i === -1) {
|
||||||
|
throw new Error("couldn't find subjectSelection to modify");
|
||||||
|
}
|
||||||
|
nb[i].block =
|
||||||
|
subject?.type === "subjectSelection"
|
||||||
|
? subject
|
||||||
|
: makeSubjectSelection(subject);
|
||||||
|
return nb;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shiftBlock<B extends T.VPSBlock[] | T.EPSBlock[]>(blocks: B, index: number, direction: "back" | "forward"): B {
|
export function adjustObjectSelection(
|
||||||
const newIndex = index + (direction === "forward"
|
blocks: Readonly<T.VPSBlock[]>,
|
||||||
? 1 // (isNoObject(blocks[index + 1].block) ? 2 : 1)
|
object:
|
||||||
: -1 // (isNoObject(blocks[index - 1].block) ? -2 : -2)
|
| T.ObjectSelectionComplete
|
||||||
);
|
| T.NPSelection
|
||||||
return arrayMove(blocks, index, newIndex) as B;
|
| T.VerbObject
|
||||||
|
| T.ObjectSelectionComplete
|
||||||
|
): T.VPSBlockComplete[];
|
||||||
|
export function adjustObjectSelection(
|
||||||
|
blocks: Readonly<T.VPSBlock[]>,
|
||||||
|
object:
|
||||||
|
| T.ObjectSelection
|
||||||
|
| T.NPSelection
|
||||||
|
| T.VerbObject
|
||||||
|
| T.ObjectSelection
|
||||||
|
| undefined
|
||||||
|
): T.EPSBlock[];
|
||||||
|
export function adjustObjectSelection(
|
||||||
|
blocks: Readonly<T.VPSBlock[]>,
|
||||||
|
object:
|
||||||
|
| T.ObjectSelection
|
||||||
|
| T.ObjectSelectionComplete
|
||||||
|
| T.VerbObject
|
||||||
|
| T.NPSelection
|
||||||
|
| undefined
|
||||||
|
): T.VPSBlock[] | T.VPSBlockComplete[] {
|
||||||
|
const nb = [...blocks];
|
||||||
|
const i = nb.findIndex((b) => b.block && b.block.type === "objectSelection");
|
||||||
|
if (i === -1) {
|
||||||
|
throw new Error("couldn't find objectSelection to modify");
|
||||||
|
}
|
||||||
|
nb[i].block =
|
||||||
|
typeof object === "object" && object?.type === "objectSelection"
|
||||||
|
? object
|
||||||
|
: makeObjectSelection(object);
|
||||||
|
return nb;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function insertNewAP<B extends T.VPSBlock[] | T.EPSBlock[]>(blocks: B): B {
|
export function moveObjectToEnd(
|
||||||
return [makeAPBlock(), ...blocks] as B;
|
blocks: T.VPSBlockComplete[]
|
||||||
|
): T.VPSBlockComplete[] {
|
||||||
|
const i = blocks.findIndex(
|
||||||
|
(b) => b.block && b.block.type === "objectSelection"
|
||||||
|
);
|
||||||
|
if (i === -1) {
|
||||||
|
throw new Error("couldn't find objectSelection to move");
|
||||||
|
}
|
||||||
|
if (i === blocks.length - 1) {
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
return arrayMove(blocks, i, blocks.length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setAP<B extends T.VPSBlock[] | T.EPSBlock[]>(blocks: B, index: number, AP: T.APSelection | undefined): B {
|
export function shiftBlock<B extends T.VPSBlock[] | T.EPSBlock[]>(
|
||||||
const nBlocks = [...blocks] as B;
|
blocks: B,
|
||||||
nBlocks[index].block = AP;
|
index: number,
|
||||||
return nBlocks;
|
direction: "back" | "forward"
|
||||||
|
): B {
|
||||||
|
const newIndex =
|
||||||
|
index +
|
||||||
|
(direction === "forward"
|
||||||
|
? 1 // (isNoObject(blocks[index + 1].block) ? 2 : 1)
|
||||||
|
: -1); // (isNoObject(blocks[index - 1].block) ? -2 : -2)
|
||||||
|
return arrayMove(blocks, index, newIndex) as B;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeAP<B extends T.VPSBlock[] | T.EPSBlock[]>(blocks: B, index: number): B {
|
export function insertNewAP<B extends T.VPSBlock[] | T.EPSBlock[]>(
|
||||||
const nBlocks = [...blocks] as B;
|
blocks: B
|
||||||
nBlocks.splice(index, 1);
|
): B {
|
||||||
return nBlocks;
|
return [makeAPBlock(), ...blocks] as B;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isNoObject(b: T.VPSBlock["block"] | T.EPSBlock["block"]): b is { type: "objectSelection", selection: "none" } {
|
export function setAP<B extends T.VPSBlock[] | T.EPSBlock[]>(
|
||||||
return !!(
|
blocks: B,
|
||||||
b
|
index: number,
|
||||||
&&
|
AP: T.APSelection | undefined
|
||||||
(b.type === "objectSelection" && b.selection === "none")
|
): B {
|
||||||
);
|
const nBlocks = [...blocks] as B;
|
||||||
|
nBlocks[index].block = AP;
|
||||||
|
return nBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function specifyEquativeLength(blocksWVars: T.Block[][], length: "long" | "short"): T.Block[][] {
|
export function removeAP<B extends T.VPSBlock[] | T.EPSBlock[]>(
|
||||||
function specify(blocks: T.Block[]): T.Block[] {
|
blocks: B,
|
||||||
const i = blocks.findIndex(b => b.block.type === "equative");
|
index: number
|
||||||
if (i === -1) throw new Error("equative block not found in EPRendered");
|
): B {
|
||||||
const eq = blocks[i];
|
const nBlocks = [...blocks] as B;
|
||||||
if (eq.block.type !== "equative") throw new Error("error searching for equative block");
|
nBlocks.splice(index, 1);
|
||||||
const adjusted = [...blocks];
|
return nBlocks;
|
||||||
adjusted[i] = {
|
}
|
||||||
...eq,
|
|
||||||
block: {
|
export function isNoObject(
|
||||||
...eq.block,
|
b: T.VPSBlock["block"] | T.EPSBlock["block"]
|
||||||
equative: {
|
): b is { type: "objectSelection"; selection: "none" } {
|
||||||
...eq.block.equative,
|
return !!(b && b.type === "objectSelection" && b.selection === "none");
|
||||||
ps: getLength(eq.block.equative.ps, length),
|
}
|
||||||
},
|
|
||||||
},
|
export function specifyEquativeLength(
|
||||||
};
|
blocksWVars: T.Block[][],
|
||||||
return adjusted;
|
length: "long" | "short"
|
||||||
}
|
): T.Block[][] {
|
||||||
return blocksWVars.map(specify);
|
function specify(blocks: T.Block[]): T.Block[] {
|
||||||
|
const i = blocks.findIndex((b) => b.block.type === "equative");
|
||||||
|
if (i === -1) throw new Error("equative block not found in EPRendered");
|
||||||
|
const eq = blocks[i];
|
||||||
|
if (eq.block.type !== "equative")
|
||||||
|
throw new Error("error searching for equative block");
|
||||||
|
const adjusted = [...blocks];
|
||||||
|
adjusted[i] = {
|
||||||
|
...eq,
|
||||||
|
block: {
|
||||||
|
...eq.block,
|
||||||
|
equative: {
|
||||||
|
...eq.block.equative,
|
||||||
|
ps: getLength(eq.block.equative.ps, length),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return adjusted;
|
||||||
|
}
|
||||||
|
return blocksWVars.map(specify);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isRenderedVerbB({ block }: T.Block): boolean {
|
export function isRenderedVerbB({ block }: T.Block): boolean {
|
||||||
if (block.type === "equative") {
|
if (block.type === "equative") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (block.type === "VB") {
|
if (block.type === "VB") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (block.type === "PH") {
|
if (block.type === "PH") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (block.type === "NComp") {
|
if (block.type === "NComp") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (block.type === "welded") {
|
if (block.type === "welded") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (block.type === "complement") {
|
if (block.type === "complement") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasEquativeWithLengths(blocks: T.Block[][]): boolean {
|
export function hasEquativeWithLengths(blocks: T.Block[][]): boolean {
|
||||||
const equative = blocks[0].find(x => x.block.type === "equative");
|
const equative = blocks[0].find((x) => x.block.type === "equative");
|
||||||
if (!equative) throw new Error("equative not found in blocks");
|
if (!equative) throw new Error("equative not found in blocks");
|
||||||
if (equative.block.type !== "equative") throw new Error("error finding equative in blocks");
|
if (equative.block.type !== "equative")
|
||||||
return "long" in equative.block.equative.ps;
|
throw new Error("error finding equative in blocks");
|
||||||
|
return "long" in equative.block.equative.ps;
|
||||||
}
|
}
|
||||||
|
|
||||||
function arrayMove<X>(ar: X[], old_index: number, new_index: number): X[] {
|
function arrayMove<X>(ar: X[], old_index: number, new_index: number): X[] {
|
||||||
const arr = [...ar];
|
const arr = [...ar];
|
||||||
const new_i = (new_index >= arr.length)
|
const new_i =
|
||||||
? (arr.length - 1)
|
new_index >= arr.length ? arr.length - 1 : new_index < 0 ? 0 : new_index;
|
||||||
: (new_index < 0)
|
arr.splice(new_i, 0, arr.splice(old_index, 1)[0]);
|
||||||
? 0
|
return arr;
|
||||||
: new_index;
|
}
|
||||||
arr.splice(new_i, 0, arr.splice(old_index, 1)[0]);
|
|
||||||
return arr;
|
|
||||||
};
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ import {
|
||||||
specifyEquativeLength,
|
specifyEquativeLength,
|
||||||
} from "./blocks-utils";
|
} from "./blocks-utils";
|
||||||
import { blank, kidsBlank } from "../misc-helpers";
|
import { blank, kidsBlank } from "../misc-helpers";
|
||||||
|
import { monoidPsStringWVars } from "../fp-ps";
|
||||||
|
import { concatAll } from "fp-ts/lib/Monoid";
|
||||||
|
|
||||||
type BlankoutOptions = {
|
type BlankoutOptions = {
|
||||||
equative?: boolean;
|
equative?: boolean;
|
||||||
|
@ -215,64 +217,66 @@ export function combineIntoText(
|
||||||
subjectPerson: T.Person,
|
subjectPerson: T.Person,
|
||||||
blankOut?: BlankoutOptions
|
blankOut?: BlankoutOptions
|
||||||
): T.PsString[] {
|
): T.PsString[] {
|
||||||
function removeDoubleBlanks(x: T.PsString): T.PsString {
|
return piecesWVars
|
||||||
return {
|
.map((pieces) => {
|
||||||
p: x.p.replace(blank.p + blank.p, blank.p),
|
const psVarsBlocks = getPsVarsBlocks(
|
||||||
f: x.f.replace(blank.f + blank.f, blank.f),
|
applyBlankOut(pieces, blankOut),
|
||||||
};
|
subjectPerson
|
||||||
}
|
);
|
||||||
function combine(pieces: (T.Block | T.Kid | T.PsString)[]): T.PsString[] {
|
return concatAll(monoidPsStringWVars)(psVarsBlocks);
|
||||||
const first = pieces[0];
|
})
|
||||||
const next = pieces[1];
|
.flat();
|
||||||
const rest = pieces.slice(1);
|
}
|
||||||
// better to do map-reduce
|
|
||||||
// map the blocks into monoids [T.PsString] (with appropriate space blocks) and then concat them all together
|
function getPsVarsBlocks(
|
||||||
const firstPs =
|
pieces: (T.Block | T.Kid | T.PsString)[],
|
||||||
"p" in first
|
subjectPerson: T.Person
|
||||||
? [first]
|
): T.PsString[][] {
|
||||||
: (blankOut?.equative &&
|
const space = [{ p: " ", f: " " }];
|
||||||
"block" in first &&
|
const phToCliticNegSpace = [{ p: "", f: "-" }];
|
||||||
first.block.type === "equative") ||
|
const endIndex = pieces.length - 1;
|
||||||
(blankOut?.verb && "block" in first && isRenderedVerbB(first)) ||
|
return pieces.reduce<T.PsString[][]>((acc, x, i) => {
|
||||||
(blankOut?.predicate &&
|
const next = pieces[i + 1];
|
||||||
"block" in first &&
|
if ("p" in x) {
|
||||||
first.block.type === "predicateSelection")
|
return [...acc, [x]];
|
||||||
? [blank]
|
|
||||||
: blankOut?.ba && "kid" in first && first.kid.type === "ba"
|
|
||||||
? [kidsBlank]
|
|
||||||
: blankOut?.negative &&
|
|
||||||
"block" in first &&
|
|
||||||
first.block.type === "negative"
|
|
||||||
? [{ p: "", f: "" }]
|
|
||||||
: getPsFromPiece(first, subjectPerson);
|
|
||||||
if (!rest.length) {
|
|
||||||
return firstPs;
|
|
||||||
}
|
}
|
||||||
return combine(rest)
|
const ps = getPsFromPiece(x, subjectPerson);
|
||||||
.flatMap((r) =>
|
return [
|
||||||
firstPs.map((fPs) =>
|
...acc,
|
||||||
concatPsString(
|
ps,
|
||||||
fPs,
|
...(i === endIndex
|
||||||
// TODO: this spacing is a mess and not accurate
|
? []
|
||||||
!("p" in first) &&
|
: "block" in x && x.block.type === "PH"
|
||||||
"block" in first &&
|
? "kid" in next || ("block" in next && next.block.type === "negative")
|
||||||
first.block.type === "PH" &&
|
? [phToCliticNegSpace]
|
||||||
!("p" in next) &&
|
: []
|
||||||
(("block" in next &&
|
: [space]),
|
||||||
(isRenderedVerbB(next) || next.block.type === "negative")) ||
|
];
|
||||||
("kid" in next && next.kid.type === "mini-pronoun"))
|
}, []);
|
||||||
? ("block" in next && next.block.type === "negative") ||
|
}
|
||||||
("kid" in next && next.kid.type === "mini-pronoun")
|
function applyBlankOut(
|
||||||
? { p: "", f: " " }
|
pieces: (T.Block | T.Kid | T.PsString)[],
|
||||||
: ""
|
blankOut: BlankoutOptions | undefined
|
||||||
: " ",
|
): (T.Block | T.Kid | T.PsString)[] {
|
||||||
r
|
if (!blankOut) return pieces;
|
||||||
)
|
return pieces.map((x) => {
|
||||||
)
|
if (
|
||||||
)
|
(blankOut.equative && "block" in x && x.block.type === "equative") ||
|
||||||
.map(removeDoubleBlanks);
|
(blankOut.verb && "block" in x && isRenderedVerbB(x)) ||
|
||||||
}
|
(blankOut?.predicate &&
|
||||||
return piecesWVars.flatMap(combine);
|
"block" in x &&
|
||||||
|
x.block.type === "predicateSelection")
|
||||||
|
) {
|
||||||
|
return blank;
|
||||||
|
}
|
||||||
|
if (blankOut?.ba && "kid" in x && x.kid.type === "ba") {
|
||||||
|
return kidsBlank;
|
||||||
|
}
|
||||||
|
if (blankOut?.negative && "block" in x && x.block.type === "negative") {
|
||||||
|
return { p: "", f: "" };
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPsFromPiece(
|
function getPsFromPiece(
|
||||||
|
|
|
@ -1,52 +1,63 @@
|
||||||
import {
|
import {
|
||||||
isPluralNounEntry,
|
isPluralNounEntry,
|
||||||
isMascNounEntry,
|
isMascNounEntry,
|
||||||
isUnisexNounEntry,
|
isUnisexNounEntry,
|
||||||
} from "../type-predicates";
|
} from "../type-predicates";
|
||||||
import * as T from "../../../types";
|
import * as T from "../../../types";
|
||||||
|
|
||||||
export function makeAdverbSelection(entry: T.AdverbEntry): T.AdverbSelection {
|
export function makeAdverbSelection(entry: T.AdverbEntry): T.AdverbSelection {
|
||||||
return {
|
return {
|
||||||
type: "adverb",
|
type: "adverb",
|
||||||
entry: entry,
|
entry: entry,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeLocativeAdverbSelection(entry: T.LocativeAdverbEntry): T.LocativeAdverbSelection {
|
export function makeLocativeAdverbSelection(
|
||||||
return {
|
entry: T.LocativeAdverbEntry
|
||||||
type: "loc. adv.",
|
): T.LocativeAdverbSelection {
|
||||||
entry: entry,
|
return {
|
||||||
};
|
type: "loc. adv.",
|
||||||
|
entry: entry,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeAdjectiveSelection(entry: T.AdjectiveEntry): T.AdjectiveSelection {
|
export function makeAdjectiveSelection(
|
||||||
return {
|
entry: T.AdjectiveEntry
|
||||||
type: "adjective",
|
): T.AdjectiveSelection {
|
||||||
entry: entry,
|
return {
|
||||||
sandwich: undefined,
|
type: "adjective",
|
||||||
};
|
entry: entry,
|
||||||
|
sandwich: undefined,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeParticipleSelection(verb: T.VerbEntry): T.ParticipleSelection {
|
export function makeParticipleSelection(
|
||||||
return {
|
verb: T.VerbEntry
|
||||||
type: "participle",
|
): T.ParticipleSelection {
|
||||||
verb,
|
return {
|
||||||
possesor: undefined,
|
type: "participle",
|
||||||
};
|
verb,
|
||||||
|
possesor: undefined,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeNounSelection(entry: T.NounEntry, old: T.NounSelection | undefined, dynamicComplement?: true): T.NounSelection {
|
export function makeNounSelection(
|
||||||
const number = isPluralNounEntry(entry) ? "plural" : "singular";
|
entry: T.NounEntry,
|
||||||
return {
|
old: T.NounSelection | undefined,
|
||||||
type: "noun",
|
complementType?: "dynamic" | "generative stative"
|
||||||
entry,
|
): T.NounSelection {
|
||||||
gender: isMascNounEntry(entry) ? "masc" : "fem",
|
const number = isPluralNounEntry(entry) ? "plural" : "singular";
|
||||||
genderCanChange: isUnisexNounEntry(entry),
|
return {
|
||||||
number,
|
type: "noun",
|
||||||
numberCanChange: number === "singular",
|
entry,
|
||||||
adjectives: (!dynamicComplement && old) ? old.adjectives : [],
|
gender: isMascNounEntry(entry) ? "masc" : "fem",
|
||||||
possesor: !dynamicComplement ? old?.possesor : undefined,
|
genderCanChange: isUnisexNounEntry(entry),
|
||||||
dynamicComplement,
|
number,
|
||||||
demonstrative: undefined,
|
numberCanChange: number === "singular",
|
||||||
};
|
adjectives: !complementType && old ? old.adjectives : [],
|
||||||
}
|
possesor: !complementType ? old?.possesor : undefined,
|
||||||
|
dynamicComplement: complementType === "dynamic",
|
||||||
|
genStativeComplement: complementType === "generative stative",
|
||||||
|
demonstrative: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as T from "../../../types";
|
import * as T from "../../../types";
|
||||||
import { mapVerbRenderedOutput } from "../fmaps";
|
import { mapVerbRenderedOutput } from "../fp-ps";
|
||||||
import { removeAccents } from "../accent-helpers";
|
import { removeAccents } from "../accent-helpers";
|
||||||
import { getPersonFromNP, isPastTense } from "./vp-tools";
|
import { getPersonFromNP, isPastTense } from "./vp-tools";
|
||||||
import { isImperativeTense, isPattern4Entry } from "../type-predicates";
|
import { isImperativeTense, isPattern4Entry } from "../type-predicates";
|
||||||
|
@ -19,6 +19,7 @@ import {
|
||||||
getMiniPronounPs,
|
getMiniPronounPs,
|
||||||
} from "./render-common";
|
} from "./render-common";
|
||||||
import { renderComplementSelection } from "./render-complement";
|
import { renderComplementSelection } from "./render-complement";
|
||||||
|
import { statVerb } from "../new-verb-engine/roots-and-stems";
|
||||||
|
|
||||||
export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
|
export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
|
||||||
const subject = getSubjectSelection(VP.blocks).selection;
|
const subject = getSubjectSelection(VP.blocks).selection;
|
||||||
|
@ -45,8 +46,18 @@ export function renderVP(VP: T.VPSelectionComplete): T.VPRendered {
|
||||||
king,
|
king,
|
||||||
complementPerson,
|
complementPerson,
|
||||||
});
|
});
|
||||||
|
// TODO: for dynamic -
|
||||||
const { vbs, hasBa } = renderVerb({
|
const { vbs, hasBa } = renderVerb({
|
||||||
verb: VP.verb.verb,
|
verb:
|
||||||
|
VP.verb.isCompound === "generative stative"
|
||||||
|
? statVerb[
|
||||||
|
VP.verb.transitivity === "intransitive"
|
||||||
|
? "intransitive"
|
||||||
|
: "transitive"
|
||||||
|
]
|
||||||
|
: VP.verb.dynAuxVerb
|
||||||
|
? VP.verb.dynAuxVerb
|
||||||
|
: VP.verb.verb,
|
||||||
tense: VP.verb.tense,
|
tense: VP.verb.tense,
|
||||||
subject: subjectPerson,
|
subject: subjectPerson,
|
||||||
object: objectPerson,
|
object: objectPerson,
|
||||||
|
@ -128,7 +139,6 @@ export function insertNegative(
|
||||||
if (!negative) {
|
if (!negative) {
|
||||||
return [blocks.flat().map(makeBlock)];
|
return [blocks.flat().map(makeBlock)];
|
||||||
}
|
}
|
||||||
const blocksA = blocks.flat().map(makeBlock);
|
|
||||||
const blocksNoAccentA = mapVerbRenderedOutput(removeAccents, blocks)
|
const blocksNoAccentA = mapVerbRenderedOutput(removeAccents, blocks)
|
||||||
.flat()
|
.flat()
|
||||||
.map(makeBlock);
|
.map(makeBlock);
|
||||||
|
@ -138,13 +148,13 @@ export function insertNegative(
|
||||||
// swapped ending with negative for ability and perfect verb forms
|
// swapped ending with negative for ability and perfect verb forms
|
||||||
if (nonStandPerfectiveSplit) {
|
if (nonStandPerfectiveSplit) {
|
||||||
return [
|
return [
|
||||||
insertFromEnd(swapEndingBlocks(blocksA), neg, 2),
|
insertFromEnd(swapEndingBlocks(blocksNoAccentA), neg, 2),
|
||||||
insertFromEnd(swapEndingBlocks(blocksA, 2), neg, 3),
|
insertFromEnd(swapEndingBlocks(blocksNoAccentA, 2), neg, 3),
|
||||||
insertFromEnd(blocksNoAccentA, neg, 1),
|
insertFromEnd(blocksNoAccentA, neg, 1),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
insertFromEnd(swapEndingBlocks(blocksA), neg, 2),
|
insertFromEnd(swapEndingBlocks(blocksNoAccentA), neg, 2),
|
||||||
insertFromEnd(blocksNoAccentA, neg, 1),
|
insertFromEnd(blocksNoAccentA, neg, 1),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -280,8 +290,9 @@ function whatsAdjustable(
|
||||||
VP: T.VPSelectionComplete
|
VP: T.VPSelectionComplete
|
||||||
): "both" | "king" | "servant" {
|
): "both" | "king" | "servant" {
|
||||||
// TODO: intransitive dynamic compounds?
|
// TODO: intransitive dynamic compounds?
|
||||||
return VP.verb.isCompound === "dynamic" &&
|
return VP.verb.isCompound === "dynamic" ||
|
||||||
VP.verb.transitivity === "transitive"
|
(VP.verb.isCompound === "generative stative" &&
|
||||||
|
VP.verb.transitivity === "transitive")
|
||||||
? isPastTense(VP.verb.tense)
|
? isPastTense(VP.verb.tense)
|
||||||
? "servant"
|
? "servant"
|
||||||
: "king"
|
: "king"
|
||||||
|
|
|
@ -1,131 +1,186 @@
|
||||||
import {
|
import { makeNounSelection } from "./make-selections";
|
||||||
makeNounSelection,
|
|
||||||
} from "./make-selections";
|
|
||||||
import * as T from "../../../types";
|
import * as T from "../../../types";
|
||||||
import { getVerbInfo } from "../verb-info";
|
import { getVerbInfo } from "../verb-info";
|
||||||
import {
|
import {
|
||||||
adjustObjectSelection,
|
adjustObjectSelection,
|
||||||
getObjectSelection,
|
getObjectSelection,
|
||||||
getSubjectSelection,
|
getSubjectSelection,
|
||||||
makeObjectSelection,
|
makeObjectSelection,
|
||||||
makeSubjectSelection,
|
makeSubjectSelection,
|
||||||
|
moveObjectToEnd,
|
||||||
} from "./blocks-utils";
|
} from "./blocks-utils";
|
||||||
|
|
||||||
export function makeVPSelectionState(
|
export function makeVPSelectionState(
|
||||||
verb: T.VerbEntry,
|
verb: T.VerbEntry,
|
||||||
os?: T.VPSelectionState,
|
os?: T.VPSelectionState
|
||||||
): T.VPSelectionState {
|
): T.VPSelectionState {
|
||||||
const info = getVerbInfo(verb.entry, verb.complement);
|
const info = getVerbInfo(verb.entry, verb.complement);
|
||||||
const subject = (os?.verb.voice === "passive" && info.type === "dynamic compound")
|
const subject =
|
||||||
? makeNounSelection(info.objComplement.entry as T.NounEntry, undefined, true)
|
os?.verb.voice === "passive" && info.type === "dynamic compound"
|
||||||
: (os?.blocks ? getSubjectSelection(os.blocks).selection : undefined);
|
? makeNounSelection(
|
||||||
function getTransObjFromos() {
|
info.objComplement.entry as T.NounEntry,
|
||||||
const osObj = os ? getObjectSelection(os.blocks).selection : undefined;
|
undefined,
|
||||||
if (
|
"dynamic"
|
||||||
!os ||
|
)
|
||||||
osObj === "none" ||
|
: os?.blocks
|
||||||
typeof osObj === "number" ||
|
? getSubjectSelection(os.blocks).selection
|
||||||
os.verb.isCompound === "dynamic" ||
|
: undefined;
|
||||||
(osObj?.selection.type === "noun" && osObj.selection.dynamicComplement)
|
function getTransObjFromos() {
|
||||||
) return undefined;
|
const osObj = os ? getObjectSelection(os.blocks).selection : undefined;
|
||||||
return osObj;
|
if (
|
||||||
}
|
!os ||
|
||||||
const transitivity: T.Transitivity = "grammaticallyTransitive" in info
|
osObj === "none" ||
|
||||||
? "transitive"
|
typeof osObj === "number" ||
|
||||||
: info.transitivity;
|
os.verb.isCompound === "dynamic" ||
|
||||||
const object = (transitivity === "grammatically transitive")
|
(osObj?.selection.type === "noun" &&
|
||||||
? T.Person.ThirdPlurMale
|
(osObj.selection.dynamicComplement ||
|
||||||
: (info.type === "dynamic compound" && os?.verb.voice !== "passive")
|
osObj.selection.genStativeComplement))
|
||||||
? makeNounSelection(info.objComplement.entry as T.NounEntry, undefined, true)
|
)
|
||||||
: (transitivity === "transitive" && os?.verb.voice !== "passive")
|
return undefined;
|
||||||
? getTransObjFromos()
|
return osObj;
|
||||||
: "none";
|
}
|
||||||
const isCompound = ("stative" in info || info.type === "stative compound")
|
const transitivity: T.Transitivity =
|
||||||
? "stative"
|
"grammaticallyTransitive" in info ? "transitive" : info.transitivity;
|
||||||
: info.type === "dynamic compound"
|
const object =
|
||||||
? "dynamic"
|
transitivity === "grammatically transitive"
|
||||||
: false;
|
? T.Person.ThirdPlurMale
|
||||||
// TODO: here and below in the changeStatDyn function ... allow for entries with complement
|
: (info.type === "dynamic compound" ||
|
||||||
const dynAuxVerb: T.VerbEntry | undefined = isCompound !== "dynamic"
|
info.type === "generative stative compound") &&
|
||||||
? undefined
|
os?.verb.voice !== "passive"
|
||||||
: info.type === "dynamic compound"
|
? makeNounSelection(
|
||||||
? { entry: info.auxVerb } as T.VerbEntry
|
info.objComplement.entry as T.NounEntry,
|
||||||
: "dynamic" in info
|
undefined,
|
||||||
? { entry: info.dynamic.auxVerb } as T.VerbEntry
|
info.type === "dynamic compound" ? "dynamic" : "generative stative"
|
||||||
: undefined;
|
)
|
||||||
const blocks = [
|
: info.type === "dynamic or generative stative compound" &&
|
||||||
{ key: Math.random(), block: makeSubjectSelection(subject) },
|
os?.verb.voice !== "passive"
|
||||||
{ key: Math.random(), block: makeObjectSelection(object) },
|
? makeNounSelection(
|
||||||
];
|
info.dynamic.objComplement.entry as T.NounEntry,
|
||||||
return {
|
undefined,
|
||||||
blocks,
|
"generative stative"
|
||||||
verb: {
|
)
|
||||||
type: "verb",
|
: transitivity === "transitive" && os?.verb.voice !== "passive"
|
||||||
verb: verb,
|
? getTransObjFromos()
|
||||||
dynAuxVerb,
|
: "none";
|
||||||
verbTense: os ? os.verb.verbTense : "presentVerb",
|
const isCompound =
|
||||||
perfectTense: os ? os.verb.perfectTense : "presentPerfect",
|
"stative" in info && info.type === "dynamic or generative stative compound"
|
||||||
imperativeTense: os ? os.verb.imperativeTense : "imperfectiveImperative",
|
? "generative stative"
|
||||||
tenseCategory: os ? os.verb.tenseCategory : "basic",
|
: "stative" in info || info.type === "stative compound"
|
||||||
transitivity,
|
? "stative"
|
||||||
isCompound,
|
: info.type === "dynamic compound"
|
||||||
voice: transitivity === "transitive"
|
? "dynamic"
|
||||||
? (os?.verb.voice || "active")
|
: false;
|
||||||
: "active",
|
// TODO: here and below in the changeStatDyn function ... allow for entries with complement
|
||||||
negative: os ? os.verb.negative : false,
|
const dynAuxVerb: T.VerbEntry | undefined =
|
||||||
canChangeTransitivity: "grammaticallyTransitive" in info,
|
isCompound !== "dynamic"
|
||||||
canChangeVoice: transitivity === "transitive",
|
? undefined
|
||||||
canChangeStatDyn: "stative" in info,
|
: info.type === "dynamic compound"
|
||||||
},
|
? ({ entry: info.auxVerb } as T.VerbEntry)
|
||||||
externalComplement: takesExternalComplement(verb)
|
: "dynamic" in info
|
||||||
? { type: "complement", selection: { type: "unselected" }}
|
? ({ entry: info.dynamic.auxVerb } as T.VerbEntry)
|
||||||
: undefined,
|
: undefined;
|
||||||
form: (os && info.type !== "dynamic compound")
|
const blocks = [
|
||||||
? os.form
|
{ key: Math.random(), block: makeSubjectSelection(subject) },
|
||||||
: { removeKing: false, shrinkServant: false },
|
{ key: Math.random(), block: makeObjectSelection(object) },
|
||||||
};
|
];
|
||||||
|
return {
|
||||||
|
blocks,
|
||||||
|
verb: {
|
||||||
|
type: "verb",
|
||||||
|
verb: verb,
|
||||||
|
dynAuxVerb,
|
||||||
|
verbTense: os ? os.verb.verbTense : "presentVerb",
|
||||||
|
perfectTense: os ? os.verb.perfectTense : "presentPerfect",
|
||||||
|
imperativeTense: os ? os.verb.imperativeTense : "imperfectiveImperative",
|
||||||
|
tenseCategory: os ? os.verb.tenseCategory : "basic",
|
||||||
|
transitivity,
|
||||||
|
isCompound,
|
||||||
|
voice:
|
||||||
|
transitivity === "transitive" ? os?.verb.voice || "active" : "active",
|
||||||
|
negative: os ? os.verb.negative : false,
|
||||||
|
canChangeTransitivity: "grammaticallyTransitive" in info,
|
||||||
|
canChangeVoice: transitivity === "transitive",
|
||||||
|
canChangeStatDyn: "stative" in info,
|
||||||
|
},
|
||||||
|
externalComplement: takesExternalComplement(verb)
|
||||||
|
? { type: "complement", selection: { type: "unselected" } }
|
||||||
|
: undefined,
|
||||||
|
form:
|
||||||
|
os && info.type !== "dynamic compound"
|
||||||
|
? os.form
|
||||||
|
: { removeKing: false, shrinkServant: false },
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function takesExternalComplement(v: T.VerbEntry): boolean {
|
function takesExternalComplement(v: T.VerbEntry): boolean {
|
||||||
if (v.entry.p === "کول" && v.entry.e.includes("to make")) {
|
if (v.entry.p === "کول" && v.entry.e.includes("to make")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (v.entry.p === "کېدل" && v.entry.e.includes("to become")) {
|
if (v.entry.p === "کېدل" && v.entry.e.includes("to become")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function changeStatDyn(v: T.VPSelectionState, s: "dynamic" | "stative"): T.VPSelectionState {
|
export function changeStatDyn(
|
||||||
const info = getVerbInfo(v.verb.verb.entry, v.verb.verb.complement);
|
v: T.VPSelectionState,
|
||||||
if (!("stative" in info)) {
|
s: "dynamic" | "stative"
|
||||||
return v;
|
): T.VPSelectionState {
|
||||||
}
|
const info = getVerbInfo(v.verb.verb.entry, v.verb.verb.complement);
|
||||||
return {
|
if (!("stative" in info)) {
|
||||||
...v,
|
return v;
|
||||||
blocks: adjustObjectSelection(
|
}
|
||||||
v.blocks,
|
const newBlocks = adjustObjectSelection(
|
||||||
s === "dynamic"
|
v.blocks,
|
||||||
? { type: "NP", selection: makeNounSelection(info.dynamic.objComplement.entry as T.NounEntry, undefined, true) }
|
s === "dynamic" ||
|
||||||
: undefined,
|
(s === "stative" &&
|
||||||
),
|
info.type === "dynamic or generative stative compound")
|
||||||
verb: {
|
? {
|
||||||
...v.verb,
|
type: "NP",
|
||||||
isCompound: s,
|
selection: makeNounSelection(
|
||||||
dynAuxVerb: s === "dynamic"
|
info.dynamic.objComplement.entry as T.NounEntry,
|
||||||
? { entry: info.dynamic.auxVerb } as T.VerbEntry
|
undefined,
|
||||||
: undefined,
|
s === "dynamic" ? "dynamic" : "generative stative"
|
||||||
},
|
),
|
||||||
};
|
}
|
||||||
|
: undefined
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...v,
|
||||||
|
blocks:
|
||||||
|
s === "stative" && info.type === "dynamic or generative stative compound"
|
||||||
|
? moveObjectToEnd(newBlocks)
|
||||||
|
: newBlocks,
|
||||||
|
verb: {
|
||||||
|
...v.verb,
|
||||||
|
isCompound:
|
||||||
|
info.type === "dynamic or generative stative compound" &&
|
||||||
|
s === "stative"
|
||||||
|
? "generative stative"
|
||||||
|
: s,
|
||||||
|
dynAuxVerb:
|
||||||
|
s === "dynamic"
|
||||||
|
? ({ entry: info.dynamic.auxVerb } as T.VerbEntry)
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function changeTransitivity(v: T.VPSelectionState, transitivity: "transitive" | "grammatically transitive"): T.VPSelectionState {
|
export function changeTransitivity(
|
||||||
return {
|
v: T.VPSelectionState,
|
||||||
...v,
|
transitivity: "transitive" | "grammatically transitive"
|
||||||
blocks: adjustObjectSelection(v.blocks, transitivity === "grammatically transitive" ? T.Person.ThirdPlurMale : undefined),
|
): T.VPSelectionState {
|
||||||
verb: {
|
return {
|
||||||
...v.verb,
|
...v,
|
||||||
transitivity,
|
blocks: adjustObjectSelection(
|
||||||
},
|
v.blocks,
|
||||||
};
|
transitivity === "grammatically transitive"
|
||||||
|
? T.Person.ThirdPlurMale
|
||||||
|
: undefined
|
||||||
|
),
|
||||||
|
verb: {
|
||||||
|
...v.verb,
|
||||||
|
transitivity,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,12 +132,14 @@ export function isInvalidSubjObjCombo(subj: T.Person, obj: T.Person): boolean {
|
||||||
// throw new Error("unknown tense");
|
// throw new Error("unknown tense");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
export function getPersonFromNP(np: T.NPSelection): T.Person;
|
|
||||||
export function getPersonFromNP(
|
export function getPersonFromNP(
|
||||||
np: T.NPSelection | T.ObjectNP
|
np: T.NPSelection | T.Rendered<T.NPSelection>
|
||||||
|
): T.Person;
|
||||||
|
export function getPersonFromNP(
|
||||||
|
np: T.NPSelection | T.Rendered<T.NPSelection> | T.ObjectNP
|
||||||
): T.Person | undefined;
|
): T.Person | undefined;
|
||||||
export function getPersonFromNP(
|
export function getPersonFromNP(
|
||||||
np: T.NPSelection | T.ObjectNP
|
np: T.NPSelection | T.Rendered<T.NPSelection> | T.ObjectNP
|
||||||
): T.Person | undefined {
|
): T.Person | undefined {
|
||||||
if (np === "none") {
|
if (np === "none") {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -693,7 +693,7 @@ export type VPRendered = {
|
||||||
servant: "subject" | "object" | undefined;
|
servant: "subject" | "object" | undefined;
|
||||||
isPast: boolean;
|
isPast: boolean;
|
||||||
isTransitive: boolean;
|
isTransitive: boolean;
|
||||||
isCompound: "stative" | "dynamic" | false;
|
isCompound: "stative" | "dynamic" | "generative stative" | false;
|
||||||
blocks: Block[][];
|
blocks: Block[][];
|
||||||
kids: Kid[];
|
kids: Kid[];
|
||||||
englishBase?: string[];
|
englishBase?: string[];
|
||||||
|
@ -811,7 +811,7 @@ export type VerbSelection = {
|
||||||
transitivity: Transitivity;
|
transitivity: Transitivity;
|
||||||
canChangeTransitivity: boolean;
|
canChangeTransitivity: boolean;
|
||||||
canChangeStatDyn: boolean;
|
canChangeStatDyn: boolean;
|
||||||
isCompound: "stative" | "dynamic" | false;
|
isCompound: "stative" | "dynamic" | "generative stative" | false;
|
||||||
voice: Voice;
|
voice: Voice;
|
||||||
canChangeVoice: boolean;
|
canChangeVoice: boolean;
|
||||||
negative: boolean;
|
negative: boolean;
|
||||||
|
@ -867,6 +867,7 @@ export type NounSelection = {
|
||||||
number: NounNumber;
|
number: NounNumber;
|
||||||
numberCanChange: boolean;
|
numberCanChange: boolean;
|
||||||
dynamicComplement?: boolean;
|
dynamicComplement?: boolean;
|
||||||
|
genStativeComplement?: boolean;
|
||||||
adjectives: AdjectiveSelection[];
|
adjectives: AdjectiveSelection[];
|
||||||
possesor: undefined | PossesorSelection;
|
possesor: undefined | PossesorSelection;
|
||||||
demonstrative: undefined | DemonstrativeSelection;
|
demonstrative: undefined | DemonstrativeSelection;
|
||||||
|
@ -1199,7 +1200,6 @@ export type MiniPronoun = {
|
||||||
export type RenderVerbOutput = {
|
export type RenderVerbOutput = {
|
||||||
hasBa: boolean;
|
hasBa: boolean;
|
||||||
vbs: VerbRenderedOutput;
|
vbs: VerbRenderedOutput;
|
||||||
objComp: Rendered<NPSelection> | undefined;
|
|
||||||
};
|
};
|
||||||
export type VerbRenderedOutput = [[VHead] | [], [VB, VBE] | [VBE]];
|
export type VerbRenderedOutput = [[VHead] | [], [VB, VBE] | [VBE]];
|
||||||
export type RootsStemsOutput = [[VHead] | [], [VB, VBA] | [VBA]]; // or perfect / equative
|
export type RootsStemsOutput = [[VHead] | [], [VB, VBA] | [VBA]]; // or perfect / equative
|
||||||
|
|
|
@ -7,136 +7,138 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
1527816643, // استعفا کول - to resign, to quit (a job or position)
|
1527818320, // جارو کول - to sweep
|
||||||
1527817823, // اصرار کول - to insist, persist, demand
|
1658796089458, // استري کول - to iron
|
||||||
1591002320547, // امر کول - to order, command
|
1527816643, // استعفا کول - to resign, to quit (a job or position)
|
||||||
1527821339, // انتظار کول - to wait
|
1527817823, // اصرار کول - to insist, persist, demand
|
||||||
1527817226, // اندازه لګول - to guess, to estimate
|
1591002320547, // امر کول - to order, command
|
||||||
1527812167, // انکار کول - to deny, to renounce, to not recognize
|
1527821339, // انتظار کول - to wait
|
||||||
1527812598, // ایمان راوړل - to beileve, have faith (du chaa baande / د چا باندې)
|
1527817226, // اندازه لګول - to guess, to estimate
|
||||||
1527812002, // برخه اخستل - to take part in, to participate, to join in
|
1527812167, // انکار کول - to deny, to renounce, to not recognize
|
||||||
1527813489, // پرهېز کول - to abstain, fast
|
1527812598, // ایمان راوړل - to beileve, have faith (du chaa baande / د چا باندې)
|
||||||
1577390517316, // پرېکړه کول - to decide
|
1527812002, // برخه اخستل - to take part in, to participate, to join in
|
||||||
1527820710, // پناه اړول - to take/seek refuge
|
1527813489, // پرهېز کول - to abstain, fast
|
||||||
1527817312, // پوښتنه کول - to ask
|
1577390517316, // پرېکړه کول - to decide
|
||||||
1527818188, // پیروي کول - to follow, obey (usually a religious teacher or leader)
|
1527820710, // پناه اړول - to take/seek refuge
|
||||||
1527811863, // تاوان رسول - to harm, damage
|
1527817312, // پوښتنه کول - to ask
|
||||||
1527816383, // تپوس کول - to ask, to question, to request
|
1527818188, // پیروي کول - to follow, obey (usually a religious teacher or leader)
|
||||||
1527822770, // ترپکې وهل - to stamp (feet), to tread, to tap one’s foot
|
1527811863, // تاوان رسول - to harm, damage
|
||||||
1527821587, // ترحم کول - to feel pity, to have sympathy, to feel sorry for someone
|
1527816383, // تپوس کول - to ask, to question, to request
|
||||||
1527818390, // تشریف راوړل - to come (when speaking about someone w/ respect)
|
1527822770, // ترپکې وهل - to stamp (feet), to tread, to tap one’s foot
|
||||||
1527818391, // تشریف وړل - to go (when speaking about someone w/ respect)
|
1527821587, // ترحم کول - to feel pity, to have sympathy, to feel sorry for someone
|
||||||
1527814726, // تصمیم نیول - to make a decision
|
1527818390, // تشریف راوړل - to come (when speaking about someone w/ respect)
|
||||||
1579394718033, // تصور کول - to imagine, suppose
|
1527818391, // تشریف وړل - to go (when speaking about someone w/ respect)
|
||||||
1527815968, // تکیه کول - to rely on, to depend on
|
1527814726, // تصمیم نیول - to make a decision
|
||||||
1592303372377, // تلاوت کول - to read (relgious, usually the Quran)
|
1579394718033, // تصور کول - to imagine, suppose
|
||||||
1577551342853, // تمرکز کول - to concentrate, focus (په يوه شي باندې)
|
1527815968, // تکیه کول - to rely on, to depend on
|
||||||
1527815351, // توبه ایستل - to repent
|
1592303372377, // تلاوت کول - to read (relgious, usually the Quran)
|
||||||
1586452103064, // توجه کول - to pay attention to, to consider
|
1577551342853, // تمرکز کول - to concentrate, focus (په يوه شي باندې)
|
||||||
1527816822, // توکل کول - to count on, hope for, depend on
|
1527815351, // توبه ایستل - to repent
|
||||||
1527812186, // تیاري نیول - to prepare
|
1586452103064, // توجه کول - to pay attention to, to consider
|
||||||
1527814870, // ټوپونه وهل - to jump
|
1527816822, // توکل کول - to count on, hope for, depend on
|
||||||
1527815355, // ټوکې کول - to joke, tease, make fun of
|
1527812186, // تیاري نیول - to prepare
|
||||||
1527815867, // ټینګار کول - to emphasize, to insist
|
1527814870, // ټوپونه وهل - to jump
|
||||||
1527822741, // جیټکه خوړل - to be jolted, surprised
|
1527815355, // ټوکې کول - to joke, tease, make fun of
|
||||||
1527814864, // ځان وژل - to commit suicide
|
1527815867, // ټینګار کول - to emphasize, to insist
|
||||||
1527819607, // چرت وهل - to think about something, reflect on something, worry about something
|
1527822741, // جیټکه خوړل - to be jolted, surprised
|
||||||
1527821070, // چکر وهل - to stroll, walk around
|
1527814864, // ځان وژل - to commit suicide
|
||||||
1577812269585, // چمچه ګیري کول - to suck up to, to flatter
|
1527819607, // چرت وهل - to think about something, reflect on something, worry about something
|
||||||
1573768865232, // چنې وهل - to barter, bargain (for a price)
|
1527821070, // چکر وهل - to stroll, walk around
|
||||||
1527822814, // حسد کول - to be envious, to be jealous
|
1577812269585, // چمچه ګیري کول - to suck up to, to flatter
|
||||||
1527823161, // حفاظت کول - to protect, guard
|
1573768865232, // چنې وهل - to barter, bargain (for a price)
|
||||||
1527821042, // حمایه کول - to support, aid, protect, back
|
1527822814, // حسد کول - to be envious, to be jealous
|
||||||
1527818810, // حیا کول - to be bashful, modest, observing of Islamic rules of modesty
|
1527823161, // حفاظت کول - to protect, guard
|
||||||
1577823792516, // خدمت کول - to serve (د چا خدمت کول)
|
1527821042, // حمایه کول - to support, aid, protect, back
|
||||||
1588858155947, // خېز وهل - to jump, leap, bob up and down
|
1527818810, // حیا کول - to be bashful, modest, observing of Islamic rules of modesty
|
||||||
1589024311021, // دافع کول - to defend (د ځان دفاع کول - to defend oneself)
|
1577823792516, // خدمت کول - to serve (د چا خدمت کول)
|
||||||
1527816916, // دفاع کول - to defend, protect
|
1588858155947, // خېز وهل - to jump, leap, bob up and down
|
||||||
1527820291, // ډغره وهل - to challenge, invite to engage in a contest, confront, provoke
|
1589024311021, // دافع کول - to defend (د ځان دفاع کول - to defend oneself)
|
||||||
1527813125, // ذکر کول - to mention, refernce, remark, refer to
|
1527816916, // دفاع کول - to defend, protect
|
||||||
1527813937, // روژه نیول - to fast
|
1527820291, // ډغره وهل - to challenge, invite to engage in a contest, confront, provoke
|
||||||
1591804639647, // روغه کول - to reconcile, to make peace
|
1527813125, // ذکر کول - to mention, refernce, remark, refer to
|
||||||
1527813212, // زاري کول - to plea, ask, request, beg
|
1527813937, // روژه نیول - to fast
|
||||||
1584529741244, // زړه ساتل - to hold back and not say what you're really thinking
|
1591804639647, // روغه کول - to reconcile, to make peace
|
||||||
1575128717139, // زړه وهل - to feel hesitancy about some action or thing (د دې کار څخه زړه وهي); to satiate
|
1527813212, // زاري کول - to plea, ask, request, beg
|
||||||
1527813319, // زنګ وهل - to ring, phone, call (Afghanistan)
|
1584529741244, // زړه ساتل - to hold back and not say what you're really thinking
|
||||||
1527822368, // زیاتي کول - to do injustice, oppression (to someone) (د چا سرس زياتي کول)
|
1575128717139, // زړه وهل - to feel hesitancy about some action or thing (د دې کار څخه زړه وهي); to satiate
|
||||||
1527819178, // زیان رسول - to damage, to cause harm
|
1527813319, // زنګ وهل - to ring, phone, call (Afghanistan)
|
||||||
1594129207239, // سا اخستل - to breathe
|
1527822368, // زیاتي کول - to do injustice, oppression (to someone) (د چا سرس زياتي کول)
|
||||||
1594129204513, // سا اخیستل - to breathe
|
1527819178, // زیان رسول - to damage, to cause harm
|
||||||
1527815309, // سبق وایل - to study, go to school
|
1594129207239, // سا اخستل - to breathe
|
||||||
1527814102, // ست کول - to invite, to make an offer out of politeness (د ډوډۍ ست مې ورته وکړ)
|
1594129204513, // سا اخیستل - to breathe
|
||||||
1527818975, // سترګه وهل - to wink, to blink
|
1527815309, // سبق وایل - to study, go to school
|
||||||
1578326320888, // سجده لګول - to bowing down to the ground, to prostrating (in religion)
|
1527814102, // ست کول - to invite, to make an offer out of politeness (د ډوډۍ ست مې ورته وکړ)
|
||||||
1527816152, // سر ټکول - complain, gripe
|
1527818975, // سترګه وهل - to wink, to blink
|
||||||
1527816463, // سوله کول - to make peace, to reconcile
|
1578326320888, // سجده لګول - to bowing down to the ground, to prostrating (in religion)
|
||||||
1527818094, // سیل کول - to stroll through, go on a walk or tour through, to see, watch, examine, survey, visit, tour
|
1527816152, // سر ټکول - complain, gripe
|
||||||
1527814855, // شپېلۍ وهل - to play the flute, fife, reed, to whistle
|
1527816463, // سوله کول - to make peace, to reconcile
|
||||||
1527819033, // شکایت کول - to complain, to express a grievance
|
1527818094, // سیل کول - to stroll through, go on a walk or tour through, to see, watch, examine, survey, visit, tour
|
||||||
1577817988469, // شکست خوړل - to be defeated, to experience defeat
|
1527814855, // شپېلۍ وهل - to play the flute, fife, reed, to whistle
|
||||||
1527819185, // صبر کول - to be patient, to bear up and endure under difficult or painful circumstances
|
1527819033, // شکایت کول - to complain, to express a grievance
|
||||||
1527814887, // صفت کول - to praise; admire, glorify
|
1577817988469, // شکست خوړل - to be defeated, to experience defeat
|
||||||
1527818217, // طرفداري کول - to support, adhere to, pick a side, stand up for something or someone
|
1527819185, // صبر کول - to be patient, to bear up and endure under difficult or painful circumstances
|
||||||
1571946107980, // ظلم کول - to be cruel to, to oppress, to do voilence against, to persecute (د چا باندې ظلم کول)
|
1527814887, // صفت کول - to praise; admire, glorify
|
||||||
1581610643511, // عبادت کول - to worship, pray
|
1527818217, // طرفداري کول - to support, adhere to, pick a side, stand up for something or someone
|
||||||
1527811674, // عمل کول - to act, to put into practice; to do something addicting (like smoking), to do out of habit
|
1571946107980, // ظلم کول - to be cruel to, to oppress, to do voilence against, to persecute (د چا باندې ظلم کول)
|
||||||
1581610659810, // غچ اخیستل - to take revenge
|
1581610643511, // عبادت کول - to worship, pray
|
||||||
1527818401, // غرض کول - to interfere, to meddle, to step in
|
1527811674, // عمل کول - to act, to put into practice; to do something addicting (like smoking), to do out of habit
|
||||||
1592303194144, // غږ کول - to call out, to say something, make a sound
|
1581610659810, // غچ اخیستل - to take revenge
|
||||||
1578607689918, // غلا کول - to steal
|
1527818401, // غرض کول - to interfere, to meddle, to step in
|
||||||
1527818341, // غمرازي کول - to share in someone’s sorrow, to show sympathy or give condolences
|
1592303194144, // غږ کول - to call out, to say something, make a sound
|
||||||
1527818425, // غوټه اچول - to tie, fasten, hitch
|
1578607689918, // غلا کول - to steal
|
||||||
1527818422, // غوټه وهل - to dive, dip, go into water
|
1527818341, // غمرازي کول - to share in someone’s sorrow, to show sympathy or give condolences
|
||||||
1527812633, // غوږ نیول - to listen
|
1527818425, // غوټه اچول - to tie, fasten, hitch
|
||||||
1527816328, // غیبت کول - to gossip
|
1527818422, // غوټه وهل - to dive, dip, go into water
|
||||||
1588784260692, // فال اچول - to do fortune telling, divination
|
1527812633, // غوږ نیول - to listen
|
||||||
1527812607, // فکر کول - to think
|
1527816328, // غیبت کول - to gossip
|
||||||
1527822096, // قدم وهل - to take a step, to walk
|
1588784260692, // فال اچول - to do fortune telling, divination
|
||||||
1588152878869, // قرباني کول - to make a sacrifice
|
1527812607, // فکر کول - to think
|
||||||
1527817624, // قسم خوړل - to take an oath, vow, to swear
|
1527822096, // قدم وهل - to take a step, to walk
|
||||||
1527812732, // کار کول - to work
|
1588152878869, // قرباني کول - to make a sacrifice
|
||||||
1527811600, // کوشش کول - to try, to attempt, to put in effort
|
1527817624, // قسم خوړل - to take an oath, vow, to swear
|
||||||
1527819661, // ګپ لګول - to talk, converse; to joke
|
1527812732, // کار کول - to work
|
||||||
1527814357, // ګډون کول - to participate, join, be involved
|
1527811600, // کوشش کول - to try, to attempt, to put in effort
|
||||||
1582146016627, // ګذاره کول - to get by, make ends meet, deal with something, handle or get some task done (with difficulty or not quite in the ideal way), to bear with, to be tolerant or forgiving
|
1527819661, // ګپ لګول - to talk, converse; to joke
|
||||||
1527819872, // ګمان کول - to think, to suppose
|
1527814357, // ګډون کول - to participate, join, be involved
|
||||||
1579034883717, // لاړې تېرول - to spit ?? (other fluids too??)
|
1582146016627, // ګذاره کول - to get by, make ends meet, deal with something, handle or get some task done (with difficulty or not quite in the ideal way), to bear with, to be tolerant or forgiving
|
||||||
1527817357, // لاس وړل - to touch
|
1527819872, // ګمان کول - to think, to suppose
|
||||||
1527818937, // لامبو وهل - to swim, bathe
|
1579034883717, // لاړې تېرول - to spit ?? (other fluids too??)
|
||||||
1527813950, // لحاظ کول - to be considerate of, pay attention to someone or something, to be polite, to show deference or respect to someone
|
1527817357, // لاس وړل - to touch
|
||||||
1527813888, // لغته وهل - to kick
|
1527818937, // لامبو وهل - to swim, bathe
|
||||||
1527822099, // لمس کول - to touch, motivate, instigate
|
1527813950, // لحاظ کول - to be considerate of, pay attention to someone or something, to be polite, to show deference or respect to someone
|
||||||
1588760636420, // لوظ کول - to promise, give one's word
|
1527813888, // لغته وهل - to kick
|
||||||
1527819089, // ماته خوړل - to be defeated, beaten by someone
|
1527822099, // لمس کول - to touch, motivate, instigate
|
||||||
1527817361, // مخ اړول - to turn (one’s face), to face, (when turning from someone or people) to neglect, (when turning to someone or people) to pay attention to
|
1588760636420, // لوظ کول - to promise, give one's word
|
||||||
1527812934, // مخه نیول - to prevent, hold back
|
1527819089, // ماته خوړل - to be defeated, beaten by someone
|
||||||
1588161314887, // مرسته کول - to help, assist
|
1527817361, // مخ اړول - to turn (one’s face), to face, (when turning from someone or people) to neglect, (when turning to someone or people) to pay attention to
|
||||||
1527817165, // مزدوري کول - to do labour, to work
|
1527812934, // مخه نیول - to prevent, hold back
|
||||||
1609162269829, // مزې کول - to be enjoyable, to have good taste (the thing that gives enjoyment/taste "does maza"), to have fun
|
1588161314887, // مرسته کول - to help, assist
|
||||||
1579295606403, // ملاتړ کول - to support (ie. a political party etc.)
|
1527817165, // مزدوري کول - to do labour, to work
|
||||||
1589031340746, // موټر چلول - to drive a car
|
1609162269829, // مزې کول - to be enjoyable, to have good taste (the thing that gives enjoyment/taste "does maza"), to have fun
|
||||||
1527812902, // مینه کول - to love
|
1579295606403, // ملاتړ کول - to support (ie. a political party etc.)
|
||||||
1527817369, // ناره وهل - to cry out, to yell, to yell a chant or slogan
|
1589031340746, // موټر چلول - to drive a car
|
||||||
1527819687, // نارې کول - to cry out, shout (ناره)
|
1527812902, // مینه کول - to love
|
||||||
1527821254, // نافرماني کول - to disobey, to not comply, to rebel
|
1527817369, // ناره وهل - to cry out, to yell, to yell a chant or slogan
|
||||||
1527817709, // نجات موندل - to be saved, to find salvation
|
1527819687, // نارې کول - to cry out, shout (ناره)
|
||||||
1527823208, // نفرت کول - to hate, abhor
|
1527821254, // نافرماني کول - to disobey, to not comply, to rebel
|
||||||
1527811827, // نفس ایستل - breath in, inhale; kill
|
1527817709, // نجات موندل - to be saved, to find salvation
|
||||||
1579459605988, // نقصان کول - to suffer loss
|
1527823208, // نفرت کول - to hate, abhor
|
||||||
1527815991, // ننداره کول - to behold, to spectate, to watch, to take in
|
1527811827, // نفس ایستل - breath in, inhale; kill
|
||||||
1527823707, // نیالګی کېنول - to plant a sapling, young tree
|
1579459605988, // نقصان کول - to suffer loss
|
||||||
1527811729, // نیوکه کول - to criticize
|
1527815991, // ننداره کول - to behold, to spectate, to watch, to take in
|
||||||
1527823733, // هجرت کول - to migrate, resettle
|
1527823707, // نیالګی کېنول - to plant a sapling, young tree
|
||||||
1527820620, // هجوم کول - to swarm, rush, attack
|
1527811729, // نیوکه کول - to criticize
|
||||||
1527811599, // هڅه کول - to try, to attempt, to put in effort
|
1527823733, // هجرت کول - to migrate, resettle
|
||||||
1604431102462, // هدایت کول - to guide, show the true path, give revelation leading to truth
|
1527820620, // هجوم کول - to swarm, rush, attack
|
||||||
1527818092, // همکاري کول - to collaborate, to work together, to aid/help
|
1527811599, // هڅه کول - to try, to attempt, to put in effort
|
||||||
1527816106, // وده کول - to grow, develop, improve, rise
|
1604431102462, // هدایت کول - to guide, show the true path, give revelation leading to truth
|
||||||
1579723460957, // ورزش کول - to de exercise, athletics
|
1527818092, // همکاري کول - to collaborate, to work together, to aid/help
|
||||||
1527814910, // وعده کول - to promise
|
1527816106, // وده کول - to grow, develop, improve, rise
|
||||||
1527816263, // وفا کول - to be faithful, to keep one's promise
|
1579723460957, // ورزش کول - to de exercise, athletics
|
||||||
1609162463793, // واده کول - to marry, get married
|
1527814910, // وعده کول - to promise
|
||||||
1609599425410, // دعا کول - to pray
|
1527816263, // وفا کول - to be faithful, to keep one's promise
|
||||||
1527812939, // منډې وهل - to run
|
1609162463793, // واده کول - to marry, get married
|
||||||
1614602054303, // بدله اخیستل - to take revenge
|
1609599425410, // دعا کول - to pray
|
||||||
]
|
1527812939, // منډې وهل - to run
|
||||||
|
1614602054303, // بدله اخیستل - to take revenge
|
||||||
|
];
|
||||||
|
|
|
@ -7,80 +7,81 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
1658537998960, // لېونی کول
|
1608137130992, // چیغه کول
|
||||||
1527812403, // بچ کول - to save, protect, guard, spare, rescue, economize
|
1658537998960, // لېونی کول
|
||||||
1577299232429, // بدلول - to change, to adapt, exchange, replace
|
1527812403, // بچ کول - to save, protect, guard, spare, rescue, economize
|
||||||
1527815728, // بلدول - to familiarize with, to acquaint, orient, to train
|
1577299232429, // بدلول - to change, to adapt, exchange, replace
|
||||||
1527821309, // بندول - to close, block, stop
|
1527815728, // بلدول - to familiarize with, to acquaint, orient, to train
|
||||||
1527821309, // بندول - to close, barricade, cut off, restrain, hold back
|
1527821309, // بندول - to close, block, stop
|
||||||
1527815843, // بېلول - to separate
|
1527821309, // بندول - to close, barricade, cut off, restrain, hold back
|
||||||
1588073727998, // پاکول - to clean, cleanse, purify
|
1527815843, // بېلول - to separate
|
||||||
1527812010, // پخلا کول - to reconcile, to bring to an agreement
|
1588073727998, // پاکول - to clean, cleanse, purify
|
||||||
1527820144, // پستول - to soften, knead, pulverize, dig over again
|
1527812010, // پخلا کول - to reconcile, to bring to an agreement
|
||||||
1584689306281, // پستول - to make soft, tender, gentle, loosened
|
1527820144, // پستول - to soften, knead, pulverize, dig over again
|
||||||
1583269391864, // پورته کول - to raise up, lift up, bring up
|
1584689306281, // پستول - to make soft, tender, gentle, loosened
|
||||||
1577394118297, // پوهول - to make understand (to bring someone to the state of understanding)
|
1583269391864, // پورته کول - to raise up, lift up, bring up
|
||||||
1571859113828, // پخول - to cook
|
1577394118297, // پوهول - to make understand (to bring someone to the state of understanding)
|
||||||
1527812385, // پیدا کول - to find, birth, create
|
1571859113828, // پخول - to cook
|
||||||
1581189437955, // پېش کول - to bring forward, present, deliver
|
1527812385, // پیدا کول - to find, birth, create
|
||||||
1527820021, // پېښول - to cause, provoke, bring on
|
1581189437955, // پېش کول - to bring forward, present, deliver
|
||||||
1591872434020, // پیلول - to start, begin
|
1527820021, // پېښول - to cause, provoke, bring on
|
||||||
1527815323, // تاوول - to turn, to twist (active, causative), to rotate (causative) to wrap up, wind up
|
1591872434020, // پیلول - to start, begin
|
||||||
1527812388, // تباه کول - to destroy, ruin
|
1527815323, // تاوول - to turn, to twist (active, causative), to rotate (causative) to wrap up, wind up
|
||||||
1580754885011, // ترکول - to abandon, leave, refuse
|
1527812388, // تباه کول - to destroy, ruin
|
||||||
1527821357, // تصدیق کول - to confirm, affirm, attest
|
1580754885011, // ترکول - to abandon, leave, refuse
|
||||||
1577501129214, // تکرار کول - to repeat
|
1527821357, // تصدیق کول - to confirm, affirm, attest
|
||||||
1527822697, // تولول - to weigh
|
1577501129214, // تکرار کول - to repeat
|
||||||
1579908304357, // تولول - to balance
|
1527822697, // تولول - to weigh
|
||||||
1579644522321, // تویول - to pour, shed, spill, scatter, knock down (fruit)
|
1579908304357, // تولول - to balance
|
||||||
1527815731, // ټولول - to gather, collect
|
1579644522321, // تویول - to pour, shed, spill, scatter, knock down (fruit)
|
||||||
1589019863017, // ټیک کول - to correct, make right
|
1527815731, // ټولول - to gather, collect
|
||||||
1527816201, // ثبتول - to enter, save, record, register
|
1589019863017, // ټیک کول - to correct, make right
|
||||||
1527821167, // جارول - to clean (with a brush), to warp (textiles); to sacrifice
|
1527816201, // ثبتول - to enter, save, record, register
|
||||||
1527816945, // جوتول - to make clear, evident, apparent, explained, established
|
1527821167, // جارول - to clean (with a brush), to warp (textiles); to sacrifice
|
||||||
1527816947, // جوتول - to harness, hitch up
|
1527816945, // جوتول - to make clear, evident, apparent, explained, established
|
||||||
1527812712, // جوړول - to make, form, build, mend, fix
|
1527816947, // جوتول - to harness, hitch up
|
||||||
1527817455, // ځایول - to place, put, accommodate, make room for, to make fit
|
1527812712, // جوړول - to make, form, build, mend, fix
|
||||||
1527815074, // چاپول - to print, publish
|
1527817455, // ځایول - to place, put, accommodate, make room for, to make fit
|
||||||
1527811693, // چاغول - to fatten up, to fatten, to make stout, plump
|
1527815074, // چاپول - to print, publish
|
||||||
1527816239, // خبرول - to inform, communicate, make known, notify
|
1527811693, // چاغول - to fatten up, to fatten, to make stout, plump
|
||||||
1527811395, // خپرول - to spread, disperse, open, unfold, publicize, distribute
|
1527816239, // خبرول - to inform, communicate, make known, notify
|
||||||
1527812222, // ختمول - to finish, complete, end, use up, destroy, kill
|
1527811395, // خپرول - to spread, disperse, open, unfold, publicize, distribute
|
||||||
1527814183, // خرڅول - to sell, to spend, (fig.) to betray
|
1527812222, // ختمول - to finish, complete, end, use up, destroy, kill
|
||||||
1577898915919, // خفه کول - to make sad, to grieve, to annoy; to choke, to make suffocate
|
1527814183, // خرڅول - to sell, to spend, (fig.) to betray
|
||||||
1592303701516, // خوږول - to sweeten, to make sweet, to delight, to give pleasure
|
1577898915919, // خفه کول - to make sad, to grieve, to annoy; to choke, to make suffocate
|
||||||
1527814174, // خوږول - to cause hurt, pain
|
1592303701516, // خوږول - to sweeten, to make sweet, to delight, to give pleasure
|
||||||
1527812811, // خوښول - to like, to choose, to select; to make happy
|
1527814174, // خوږول - to cause hurt, pain
|
||||||
1527813502, // درنول - to make heavier; to make serious, respectable, reliable
|
1527812811, // خوښول - to like, to choose, to select; to make happy
|
||||||
1527811432, // دفن کول - to bury
|
1527813502, // درنول - to make heavier; to make serious, respectable, reliable
|
||||||
1527813665, // ډکول - to fill
|
1527811432, // دفن کول - to bury
|
||||||
1527817258, // ډوبول - to cause to drown, to make sing, to submerge
|
1527813665, // ډکول - to fill
|
||||||
1527823503, // ډېرول - to increase, make more
|
1527817258, // ډوبول - to cause to drown, to make sing, to submerge
|
||||||
1527818347, // راپورته کول - to raise up
|
1527823503, // ډېرول - to increase, make more
|
||||||
1527823277, // رنګول - to paint, color
|
1527818347, // راپورته کول - to raise up
|
||||||
1527813179, // ړنګول - to destroy, wreck, ruin, demolish, mess up, liquidate, disband
|
1527823277, // رنګول - to paint, color
|
||||||
1591033078746, // ستړی کول - to make tired, wear out
|
1527813179, // ړنګول - to destroy, wreck, ruin, demolish, mess up, liquidate, disband
|
||||||
1527813065, // ستنول - to return, to give back; to delay someone or something, to direct, to turn, to fix on
|
1591033078746, // ستړی کول - to make tired, wear out
|
||||||
1527811949, // شریکول - to make a participant or involved, to share, to bring someone or something in, to include
|
1527813065, // ستنول - to return, to give back; to delay someone or something, to direct, to turn, to fix on
|
||||||
1589883890933, // شړمول - to attach loosely, to cause to be loose, lazy, flabby
|
1527811949, // شریکول - to make a participant or involved, to share, to bring someone or something in, to include
|
||||||
1527814493, // غرقول - to sink, plunge, submerge, immerse
|
1589883890933, // شړمول - to attach loosely, to cause to be loose, lazy, flabby
|
||||||
1527823133, // غلطول - confuse, mix up, make a mistake; to go wrong, to stray from; to deceive, to lead into error; to distract, to be distracted
|
1527814493, // غرقول - to sink, plunge, submerge, immerse
|
||||||
1527823366, // قبلول - to accept, to approve
|
1527823133, // غلطول - confuse, mix up, make a mistake; to go wrong, to stray from; to deceive, to lead into error; to distract, to be distracted
|
||||||
1527820386, // کلکول - to make firm, hard solid, to fasten, to secure, to lock, to staunchly defend
|
1527823366, // قبلول - to accept, to approve
|
||||||
1527814819, // ګرمول - to warm, to heat up, to heat
|
1527820386, // کلکول - to make firm, hard solid, to fasten, to secure, to lock, to staunchly defend
|
||||||
1579034597012, // ګیرول - to seize, catch, trap, confine, imprison, beseige, make stuck
|
1527814819, // ګرمول - to warm, to heat up, to heat
|
||||||
1588152253147, // لرې کول - to remove, put far away
|
1579034597012, // ګیرول - to seize, catch, trap, confine, imprison, beseige, make stuck
|
||||||
1527817121, // لندول - to make wet, moisten, to make damp, to soak
|
1588152253147, // لرې کول - to remove, put far away
|
||||||
1527817118, // لنډول - to shorten, to make short, abbreviate
|
1527817121, // لندول - to make wet, moisten, to make damp, to soak
|
||||||
1527814350, // لویول - to raise, bring up (children)
|
1527817118, // لنډول - to shorten, to make short, abbreviate
|
||||||
1527816012, // ماتول - to break, split, defeat
|
1527814350, // لویول - to raise, bring up (children)
|
||||||
1579387733916, // مینول - to cause to fall in love, to make to fall in love
|
1527816012, // ماتول - to break, split, defeat
|
||||||
1527817762, // هېرول - to forget
|
1579387733916, // مینول - to cause to fall in love, to make to fall in love
|
||||||
1589640176788, // ورکول - to lose/make lost, to misplace, to make dissapear, get rid off
|
1527817762, // هېرول - to forget
|
||||||
1527812004, // وقفول - to devote, dedicate, give, donate
|
1589640176788, // ورکول - to lose/make lost, to misplace, to make dissapear, get rid off
|
||||||
1579724723019, // ویدول - to put to sleep
|
1527812004, // وقفول - to devote, dedicate, give, donate
|
||||||
1579822065104, // ویښول - to wake up, to make awake, to make alert
|
1579724723019, // ویدول - to put to sleep
|
||||||
1527816559, // یادول - to remember, to recall, to think on, to call
|
1579822065104, // ویښول - to wake up, to make awake, to make alert
|
||||||
1527813556, // یو ځای کول - to gather, bring together
|
1527816559, // یادول - to remember, to recall, to think on, to call
|
||||||
1527815444, // زده کول - to learn, to teach
|
1527813556, // یو ځای کول - to gather, bring together
|
||||||
]
|
1527815444, // زده کول - to learn, to teach
|
||||||
|
];
|
||||||
|
|
|
@ -5427,7 +5427,7 @@ forwarded@0.2.0:
|
||||||
|
|
||||||
fp-ts@^2.16.0:
|
fp-ts@^2.16.0:
|
||||||
version "2.16.0"
|
version "2.16.0"
|
||||||
resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.16.0.tgz#64e03314dfc1c7ce5e975d3496ac14bc3eb7f92e"
|
resolved "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.0.tgz"
|
||||||
integrity sha512-bLq+KgbiXdTEoT1zcARrWEpa5z6A/8b7PcDW7Gef3NSisQ+VS7ll2Xbf1E+xsgik0rWub/8u0qP/iTTjj+PhxQ==
|
integrity sha512-bLq+KgbiXdTEoT1zcARrWEpa5z6A/8b7PcDW7Gef3NSisQ+VS7ll2Xbf1E+xsgik0rWub/8u0qP/iTTjj+PhxQ==
|
||||||
|
|
||||||
fragment-cache@^0.2.1:
|
fragment-cache@^0.2.1:
|
||||||
|
@ -9544,11 +9544,6 @@ react-lifecycles-compat@^3.0.4:
|
||||||
resolved "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz"
|
resolved "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz"
|
||||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||||
|
|
||||||
react-media-hook@^0.5.0:
|
|
||||||
version "0.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-media-hook/-/react-media-hook-0.5.0.tgz#f830231f31ea80049f8cbaf8058da90ab71e7150"
|
|
||||||
integrity sha512-OupDgOSCjUUWPiXq3HMoRwpsQry4cGf4vKzh2E984Xtm4I01ZFbq8JwCG/RPqXB9h0qxgzoYLbABC+LIZH8deQ==
|
|
||||||
|
|
||||||
react-overlays@^5.1.1:
|
react-overlays@^5.1.1:
|
||||||
version "5.1.1"
|
version "5.1.1"
|
||||||
resolved "https://registry.npmjs.org/react-overlays/-/react-overlays-5.1.1.tgz"
|
resolved "https://registry.npmjs.org/react-overlays/-/react-overlays-5.1.1.tgz"
|
||||||
|
|
Loading…
Reference in New Issue