Game working alright! 💪
This commit is contained in:
parent
0fb73af58b
commit
dad93bfa14
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@lingdocs/pashto-inflector",
|
||||
"version": "1.9.0",
|
||||
"version": "1.9.1",
|
||||
"author": "lingdocs.com",
|
||||
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
|
||||
"homepage": "https://verbs.lingdocs.com",
|
||||
|
|
16
src/App.css
16
src/App.css
|
@ -10,7 +10,21 @@
|
|||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
}
|
||||
|
||||
|
||||
.answer-feedback {
|
||||
transition: opacity 0.3s ease-in;
|
||||
opacity: 0.8;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
z-index: 99999999;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.hide {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
:root {
|
||||
--secondary: #00c1fc;
|
||||
--primary: #ffda54;
|
||||
|
|
|
@ -68,10 +68,11 @@ export function getRandomTense(type: "basic" | "modal" | "perfect", o?: T.Perfec
|
|||
return tns;
|
||||
}
|
||||
|
||||
function TensePicker({ onChange, vps, mode }: {
|
||||
function TensePicker({ onChange, vps, mode, locked }: {
|
||||
vps: T.VPSelectionState,
|
||||
onChange: (p: T.VPSelectionState) => void,
|
||||
mode: "charts" | "phrases" | "quiz",
|
||||
locked: boolean,
|
||||
}) {
|
||||
function onTenseSelect(o: { value: T.VerbTense | T.PerfectTense } | null) {
|
||||
const value = o?.value ? o.value : undefined;
|
||||
|
@ -179,7 +180,7 @@ function TensePicker({ onChange, vps, mode }: {
|
|||
options={tOptions}
|
||||
{...zIndexProps}
|
||||
/>
|
||||
{vps.verb && <div className="d-flex flex-row justify-content-between align-items-center mt-3 mb-1" style={{ width: "100%" }}>
|
||||
{vps.verb && !locked && <div className="d-flex flex-row justify-content-between align-items-center mt-3 mb-1" style={{ width: "100%" }}>
|
||||
<div className="btn btn-light clickable" onClick={moveTense("back")}>
|
||||
<i className="fas fa-chevron-left" />
|
||||
</div>
|
||||
|
|
|
@ -16,10 +16,13 @@ import { randomSubjObj } from "../../library";
|
|||
import shuffleArray from "../../lib/shuffle-array";
|
||||
import InlinePs from "../InlinePs";
|
||||
import { psStringEquals } from "../../lib/p-text-helpers";
|
||||
import classNames from "classnames";
|
||||
import { randFromArray } from "../../lib/misc-helpers";
|
||||
// import { useReward } from 'react-rewards';
|
||||
|
||||
const kingEmoji = "👑";
|
||||
const servantEmoji = "🙇♂️";
|
||||
const correctEmoji = ["✅", '🤓', "✅", '😊', "🌹", "✅", "✅", "🕺", "💃", '🥳', "👏", "✅", "💯", "😎", "✅", "👍"];
|
||||
|
||||
// TODO: Drill Down text display options
|
||||
|
||||
|
@ -34,6 +37,8 @@ const servantEmoji = "🙇♂️";
|
|||
|
||||
// TODO: error handling on error with rendering etc
|
||||
|
||||
const checkDuration = 400;
|
||||
|
||||
type QuizState = {
|
||||
answer: {
|
||||
ps: T.SingleOrLengthOpts<T.PsString[]>;
|
||||
|
@ -62,18 +67,26 @@ export function VPExplorer(props: {
|
|||
);
|
||||
const [mode, setMode] = useStickyState<"charts" | "phrases" | "quiz">("phrases", "verbExplorerMode");
|
||||
const [quizState, setQuizState] = useState<QuizState | undefined>(undefined);
|
||||
const [showCheck, setShowCheck] = useState<boolean>(false);
|
||||
const [currentCorrectEmoji, setCurrentCorrectEmoji] = useState<string>(randFromArray(correctEmoji));
|
||||
// const { reward } = useReward('rewardId', "emoji", {
|
||||
// emoji: ['🤓', '😊', '🥳', "👏", "💯", "😎", "👍"],
|
||||
// lifetime: 50,
|
||||
// elementCount: 10,
|
||||
// elementSize: 30,
|
||||
// });
|
||||
useEffect(() => {
|
||||
if (mode === "quiz") {
|
||||
handleResetQuiz();
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
setVps(o => {
|
||||
if (mode === "quiz") {
|
||||
return getRandomVPSelection("both")(
|
||||
makeVPSelectionState(props.verb, o)
|
||||
);
|
||||
const { VPS, qs } = makeQuizState(vps);
|
||||
setQuizState(qs);
|
||||
return VPS;
|
||||
}
|
||||
return makeVPSelectionState(props.verb, o);
|
||||
});
|
||||
|
@ -130,8 +143,17 @@ export function VPExplorer(props: {
|
|||
function checkQuizAnswer(a: T.PsString) {
|
||||
if (!quizState) return;
|
||||
if (isInAnswer(a, quizState.answer)) {
|
||||
// reward();
|
||||
handleResetQuiz();
|
||||
setShowCheck(true);
|
||||
setTimeout(() => {
|
||||
handleResetQuiz();
|
||||
}, checkDuration / 2);
|
||||
setTimeout(() => {
|
||||
setShowCheck(false);
|
||||
}, checkDuration);
|
||||
// this sucks, have to do this so the emoji doesn't change in the middle of animation
|
||||
setTimeout(() => {
|
||||
setCurrentCorrectEmoji(randFromArray(correctEmoji));
|
||||
}, checkDuration * 2);
|
||||
} else {
|
||||
setQuizState({
|
||||
...quizState,
|
||||
|
@ -219,6 +241,7 @@ export function VPExplorer(props: {
|
|||
vps={vps}
|
||||
onChange={quizLock(setVps)}
|
||||
mode={mode}
|
||||
locked={!!(mode === "quiz" && quizState)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -228,10 +251,15 @@ export function VPExplorer(props: {
|
|||
{(vps.verb && (mode === "charts")) && <ChartDisplay VS={vps.verb} opts={props.opts} />}
|
||||
<span id="rewardId" />
|
||||
{(mode === "quiz" && quizState) && <div className="text-center">
|
||||
<div style={{ fontSize: "4rem" }} className={classNames("answer-feedback", { hide: !showCheck })}>
|
||||
{currentCorrectEmoji}
|
||||
</div>
|
||||
{quizState.result === "waiting" ? <>
|
||||
<div className="text-muted my-3">Choose a correct answer:</div>
|
||||
{quizState.options.map(o => <div className="pb-3">
|
||||
<div className="btn btn-outline-secondary" onClick={() => checkQuizAnswer(o)}>
|
||||
{quizState.options.map(o => <div className="pb-3" key={o.f}>
|
||||
<div className="btn btn-answer btn-outline-secondary" onClick={() => {
|
||||
checkQuizAnswer(o);
|
||||
}}>
|
||||
<InlinePs opts={props.opts}>{o}</InlinePs>
|
||||
</div>
|
||||
</div>)}
|
||||
|
@ -248,9 +276,6 @@ export function VPExplorer(props: {
|
|||
</div>
|
||||
</div>}
|
||||
</div>}
|
||||
{mode === "quiz" && <div style={{ height: "300px" }}>
|
||||
{/* spacer for blank space while quizzing */}
|
||||
</div>}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
@ -398,7 +423,7 @@ function getRandomVPSelection(mix: MixType = "both") {
|
|||
};
|
||||
return {
|
||||
subject: s,
|
||||
verb: mix === "both" ? randomizeTense(v, false) : v,
|
||||
verb: randomizeTense(v, true),
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -152,6 +152,12 @@ export function randomNumber(minInclusive: number, maxExclusive: number): number
|
|||
return Math.floor(Math.random() * (maxExclusive - minInclusive) + minInclusive);
|
||||
}
|
||||
|
||||
export function randFromArray<M>(arr: M[]): M {
|
||||
return arr[
|
||||
Math.floor(Math.random()*arr.length)
|
||||
];
|
||||
}
|
||||
|
||||
// TODO: deprecate this because we have it in np-tools?
|
||||
/**
|
||||
* Sees if a possiblePerson (for subject/object) is possible, given the other person
|
||||
|
|
Loading…
Reference in New Issue