fixed speed
This commit is contained in:
parent
7561dd5279
commit
a9e17553b0
|
@ -24,7 +24,8 @@ function Sidebar({ content, navOpen, setNavOpen, pathname }) {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<aside className={classNames(
|
<aside
|
||||||
|
className={classNames(
|
||||||
"side-nav col-3 col-lg-2 p-0 bg-light",
|
"side-nav col-3 col-lg-2 p-0 bg-light",
|
||||||
{ "side-nav-closed": !navOpen }
|
{ "side-nav-closed": !navOpen }
|
||||||
)}>
|
)}>
|
||||||
|
|
|
@ -1,144 +1,188 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import { comparePs } from "../../lib/game-utils";
|
||||||
comparePs,
|
|
||||||
} from "../../lib/game-utils";
|
|
||||||
import genderColors from "../../lib/gender-colors";
|
import genderColors from "../../lib/gender-colors";
|
||||||
import GameCore from "../GameCore";
|
import GameCore from "../GameCore";
|
||||||
import {
|
import {
|
||||||
Types as T,
|
Types as T,
|
||||||
Examples,
|
Examples,
|
||||||
defaultTextOptions as opts,
|
defaultTextOptions as opts,
|
||||||
inflectWord,
|
inflectWord,
|
||||||
firstVariation,
|
firstVariation,
|
||||||
typePredicates as tp,
|
typePredicates as tp,
|
||||||
randFromArray,
|
randFromArray,
|
||||||
} from "@lingdocs/ps-react";
|
} from "@lingdocs/ps-react";
|
||||||
import { nouns } from "../../words/words";
|
import { nouns } from "../../words/words";
|
||||||
import { intoPatterns } from "../../lib/categorize";
|
import { intoPatterns } from "../../lib/categorize";
|
||||||
|
|
||||||
const unisexNouns = nouns.filter(tp.isUnisexNounEntry);
|
const unisexNouns = nouns.filter(tp.isUnisexNounEntry);
|
||||||
type NType = "pattern1" | "pattern2" | "pattern3" | "pattern4" | "pattern5" | "other";
|
type NType =
|
||||||
|
| "pattern1"
|
||||||
|
| "pattern2"
|
||||||
|
| "pattern3"
|
||||||
|
| "pattern4"
|
||||||
|
| "pattern5"
|
||||||
|
| "other";
|
||||||
// TODO: make pattern types as overlay types
|
// TODO: make pattern types as overlay types
|
||||||
const types = intoPatterns(unisexNouns);
|
const types = intoPatterns(unisexNouns);
|
||||||
const genders: T.Gender[] = ["masc", "fem"];
|
const genders: T.Gender[] = ["masc", "fem"];
|
||||||
|
|
||||||
const amount = 20;
|
const amount = 14;
|
||||||
|
|
||||||
type Question = { entry: T.DictionaryEntry, gender: T.Gender };
|
type Question = { entry: T.DictionaryEntry; gender: T.Gender };
|
||||||
|
|
||||||
export default function UnisexNounGame({ id, link, inChapter }: { inChapter: boolean, id: string, link: string }) {
|
export default function UnisexNounGame({
|
||||||
let pool = { ...types };
|
id,
|
||||||
function getQuestion(): Question {
|
link,
|
||||||
const keys = Object.keys(types) as NType[];
|
inChapter,
|
||||||
let type: NType
|
}: {
|
||||||
do {
|
inChapter: boolean;
|
||||||
type = randFromArray(keys);
|
id: string;
|
||||||
} while (!pool[type].length);
|
link: string;
|
||||||
const entry = randFromArray<T.UnisexNounEntry>(
|
}) {
|
||||||
// @ts-ignore
|
let pool = { ...types };
|
||||||
pool[type]
|
function getQuestion(): Question {
|
||||||
);
|
const keys = Object.keys(types) as NType[];
|
||||||
const gender = randFromArray(genders) as T.Gender;
|
let type: NType;
|
||||||
// @ts-ignore
|
do {
|
||||||
pool[type] = pool[type].filter((x) => x.ts !== entry.ts);
|
type = randFromArray(keys);
|
||||||
return {
|
} while (!pool[type].length);
|
||||||
entry,
|
const entry = randFromArray<T.UnisexNounEntry>(
|
||||||
gender,
|
// @ts-ignore
|
||||||
};
|
pool[type]
|
||||||
|
);
|
||||||
|
const gender = randFromArray(genders) as T.Gender;
|
||||||
|
// @ts-ignore
|
||||||
|
pool[type] = pool[type].filter((x) => x.ts !== entry.ts);
|
||||||
|
return {
|
||||||
|
entry,
|
||||||
|
gender,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function Display({ question, callback }: QuestionDisplayProps<Question>) {
|
||||||
|
const [answer, setAnswer] = useState<string>("");
|
||||||
|
const infOut = inflectWord(question.entry);
|
||||||
|
if (!infOut) return <div>WORD ERROR</div>;
|
||||||
|
const { inflections } = infOut;
|
||||||
|
if (!inflections) return <div>WORD ERROR</div>;
|
||||||
|
const givenGender = question.gender === "masc" ? "masculine" : "feminine";
|
||||||
|
const requiredGender = question.gender === "fem" ? "masculine" : "feminine";
|
||||||
|
if (!("masc" in inflections) || !("fem" in inflections)) {
|
||||||
|
return <div>WORD ERROR</div>;
|
||||||
}
|
}
|
||||||
|
if (!inflections.masc || !inflections.fem) {
|
||||||
|
return <div>WORD ERROR</div>;
|
||||||
|
}
|
||||||
|
const handleInput = ({
|
||||||
|
target: { value },
|
||||||
|
}: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setAnswer(value);
|
||||||
|
};
|
||||||
|
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
// @ts-ignore
|
||||||
|
const correctAnswer = inflections[flipGender(question.gender)][0];
|
||||||
|
const correct = comparePs(answer, correctAnswer);
|
||||||
|
if (correct) {
|
||||||
|
setAnswer("");
|
||||||
|
}
|
||||||
|
callback(correct);
|
||||||
|
};
|
||||||
|
|
||||||
function Display({ question, callback }: QuestionDisplayProps<Question>) {
|
return (
|
||||||
const [answer, setAnswer] = useState<string>("");
|
<div>
|
||||||
const infOut = inflectWord(question.entry);
|
<div
|
||||||
if (!infOut) return <div>WORD ERROR</div>;
|
className="pt-2 pb-1 mb-2"
|
||||||
const { inflections } = infOut;
|
style={{
|
||||||
if (!inflections) return <div>WORD ERROR</div>;
|
maxWidth: "300px",
|
||||||
const givenGender = question.gender === "masc" ? "masculine" : "feminine";
|
margin: "0 auto",
|
||||||
const requiredGender = question.gender === "fem" ? "masculine" : "feminine";
|
backgroundColor:
|
||||||
if (!("masc" in inflections ) || !("fem" in inflections)) {
|
genderColors[question.gender === "masc" ? "m" : "f"],
|
||||||
return <div>WORD ERROR</div>;
|
}}
|
||||||
}
|
>
|
||||||
if (!inflections.masc || !inflections.fem) {
|
<Examples opts={opts}>
|
||||||
return <div>WORD ERROR</div>;
|
{[
|
||||||
}
|
{
|
||||||
const handleInput = ({ target: { value }}: React.ChangeEvent<HTMLInputElement>) => {
|
...inflections[question.gender][0][0],
|
||||||
setAnswer(value);
|
e: firstVariation(question.entry.e),
|
||||||
}
|
},
|
||||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
]}
|
||||||
e.preventDefault();
|
</Examples>
|
||||||
// @ts-ignore
|
</div>
|
||||||
const correctAnswer = inflections[flipGender(question.gender)][0];
|
<div>
|
||||||
const correct = comparePs(answer, correctAnswer);
|
Is {givenGender}. Make it{" "}
|
||||||
if (correct) {
|
<span
|
||||||
setAnswer("");
|
style={{
|
||||||
}
|
background:
|
||||||
callback(correct);
|
genderColors[requiredGender === "masculine" ? "m" : "f"],
|
||||||
}
|
}}
|
||||||
|
>
|
||||||
return <div>
|
{requiredGender}
|
||||||
<div className="pt-2 pb-1 mb-2" style={{ maxWidth: "300px", margin: "0 auto", backgroundColor: genderColors[question.gender === "masc" ? "m" : "f"]}}>
|
</span>
|
||||||
<Examples opts={opts}>{[
|
.
|
||||||
{
|
</div>
|
||||||
...inflections[question.gender][0][0],
|
<form onSubmit={handleSubmit}>
|
||||||
e: firstVariation(question.entry.e),
|
<div className="my-3" style={{ maxWidth: "200px", margin: "0 auto" }}>
|
||||||
}
|
<input
|
||||||
]}</Examples>
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
autoComplete="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
dir="auto"
|
||||||
|
value={answer}
|
||||||
|
onChange={handleInput}
|
||||||
|
/>
|
||||||
|
<div className="text-muted small mt-3">
|
||||||
|
Type <kbd>Enter</kbd> to check
|
||||||
</div>
|
</div>
|
||||||
<div>Is {givenGender}. Make it <span style={{ background: genderColors[requiredGender === "masculine" ? "m" : "f"]}}>{requiredGender}</span>.</div>
|
</div>
|
||||||
<form onSubmit={handleSubmit}>
|
</form>
|
||||||
<div className="my-3" style={{ maxWidth: "200px", margin: "0 auto" }}>
|
</div>
|
||||||
<input
|
);
|
||||||
type="text"
|
}
|
||||||
className="form-control"
|
|
||||||
autoComplete="off"
|
|
||||||
autoCapitalize="off"
|
|
||||||
spellCheck="false"
|
|
||||||
dir="auto"
|
|
||||||
value={answer}
|
|
||||||
onChange={handleInput}
|
|
||||||
/>
|
|
||||||
<div className="text-muted small mt-3">
|
|
||||||
Type <kbd>Enter</kbd> to check
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div>
|
function Instructions() {
|
||||||
}
|
return (
|
||||||
|
<div>
|
||||||
|
<h5>Change the gender of a given noun</h5>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function Instructions() {
|
function DisplayCorrectAnswer({ question }: { question: Question }) {
|
||||||
return <div>
|
const infOut = inflectWord(question.entry);
|
||||||
<h5>Change the gender of a given noun</h5>
|
if (!infOut) return <div>WORD ERROR</div>;
|
||||||
</div>
|
const { inflections } = infOut;
|
||||||
}
|
// @ts-ignore
|
||||||
|
const correctAnswer = inflections[flipGender(question.gender)][0];
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{correctAnswer.length > 1 && (
|
||||||
|
<div className="text-muted">One of the following:</div>
|
||||||
|
)}
|
||||||
|
{correctAnswer.map((ps: any) => (
|
||||||
|
<Examples opts={opts}>{ps}</Examples>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function DisplayCorrectAnswer({ question }: { question: Question }) {
|
return (
|
||||||
const infOut = inflectWord(question.entry);
|
<GameCore
|
||||||
if (!infOut) return <div>WORD ERROR</div>;
|
inChapter={inChapter}
|
||||||
const { inflections } = infOut;
|
studyLink={link}
|
||||||
// @ts-ignore
|
getQuestion={getQuestion}
|
||||||
const correctAnswer = inflections[flipGender(question.gender)][0];
|
id={id}
|
||||||
return <div>
|
Display={Display}
|
||||||
{correctAnswer.length > 1 && <div className="text-muted">One of the following:</div>}
|
DisplayCorrectAnswer={DisplayCorrectAnswer}
|
||||||
{correctAnswer.map((ps: any) => (
|
amount={amount}
|
||||||
<Examples opts={opts}>{ps}</Examples>
|
timeLimit={175}
|
||||||
))}
|
Instructions={Instructions}
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <GameCore
|
|
||||||
inChapter={inChapter}
|
|
||||||
studyLink={link}
|
|
||||||
getQuestion={getQuestion}
|
|
||||||
id={id}
|
|
||||||
Display={Display}
|
|
||||||
DisplayCorrectAnswer={DisplayCorrectAnswer}
|
|
||||||
amount={amount}
|
|
||||||
timeLimit={130}
|
|
||||||
Instructions={Instructions}
|
|
||||||
/>
|
/>
|
||||||
};
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function flipGender(g: T.Gender): T.Gender {
|
function flipGender(g: T.Gender): T.Gender {
|
||||||
return g === "masc" ? "fem" : "masc";
|
return g === "masc" ? "fem" : "masc";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue