proper caching and sending of test results
This commit is contained in:
parent
82a29978a1
commit
db6ba08c1a
|
@ -7,10 +7,13 @@ import "./timer.css";
|
|||
import {
|
||||
getPercentageDone,
|
||||
} from "../lib/game-utils";
|
||||
import {
|
||||
saveResult,
|
||||
postSavedResults,
|
||||
} from "../lib/game-results";
|
||||
import {
|
||||
AT,
|
||||
getTimestamp,
|
||||
postTestResults,
|
||||
} from "@lingdocs/lingdocs-main";
|
||||
import {
|
||||
Types as T,
|
||||
|
@ -27,7 +30,7 @@ function GameCore<T>({ questions, Display, timeLimit, Instructions, studyLink, i
|
|||
}) {
|
||||
// TODO: report pass with id to user info
|
||||
const rewardRef = useRef<RewardElement | null>(null);
|
||||
const { user, pullUser } = useUser();
|
||||
const { user, pullUser, setUser } = useUser();
|
||||
const [finish, setFinish] = useState<null | "pass" | "fail" | "time out">(null);
|
||||
const [current, setCurrent] = useState<Current<T> | undefined>(undefined);
|
||||
const [questionBox, setQuestionBox] = useState<QuestionGenerator<T>>(questions());
|
||||
|
@ -47,6 +50,24 @@ function GameCore<T>({ questions, Display, timeLimit, Instructions, studyLink, i
|
|||
if (next.done) handleFinish();
|
||||
else setCurrent(next.value);
|
||||
}
|
||||
function handleResult(result: AT.TestResult) {
|
||||
// add the test to the user object
|
||||
if (!user) return;
|
||||
setUser((u) => {
|
||||
// pure type safety with the prevUser
|
||||
if (!u) return u;
|
||||
return {
|
||||
...u,
|
||||
tests: [...u.tests, result],
|
||||
};
|
||||
});
|
||||
// save the test result in local storage
|
||||
saveResult(result, user.userId);
|
||||
// try to post the result
|
||||
postSavedResults(user.userId).then((r) => {
|
||||
if (r === "sent") pullUser();
|
||||
}).catch(console.error);
|
||||
}
|
||||
function handleFinish() {
|
||||
setFinish("pass");
|
||||
rewardRef.current?.rewardMe();
|
||||
|
@ -56,14 +77,7 @@ function GameCore<T>({ questions, Display, timeLimit, Instructions, studyLink, i
|
|||
time: getTimestamp(),
|
||||
id,
|
||||
};
|
||||
console.log("will post result", JSON.stringify(result));
|
||||
// TODO: Check not showing up - should show up immediately whether online or not
|
||||
postTestResults([result])
|
||||
.then((res) => {
|
||||
if (res.ok) {
|
||||
pullUser();
|
||||
}
|
||||
}).catch(console.error);
|
||||
handleResult(result);
|
||||
}
|
||||
function handleQuit() {
|
||||
setFinish(null);
|
||||
|
|
|
@ -2,39 +2,34 @@ import React from "react";
|
|||
import GenderGame from "./sub-cores/GenderGame";
|
||||
import UnisexNounGame from "./sub-cores/UnisexNounGame";
|
||||
|
||||
const unisexNounsId = "unisex-nouns-1";
|
||||
const nounGender1Id = "gender-nouns-1";
|
||||
const nounGender2Id = "gender-nouns-2";
|
||||
|
||||
export const unisexNounGame: GameRecord = {
|
||||
title: "Changing genders on unisex nouns",
|
||||
id: unisexNounsId,
|
||||
Game: function() {
|
||||
// TODO: Why won't this.id word here??!
|
||||
return <UnisexNounGame id={unisexNounsId} />;
|
||||
},
|
||||
function makeGameRecord(title: string, id: string, game: (id: string) => (() => JSX.Element)): GameRecord {
|
||||
return {
|
||||
title,
|
||||
id,
|
||||
Game: game(id),
|
||||
}
|
||||
}
|
||||
|
||||
export const nounGenderGame1: GameRecord = {
|
||||
title: "Identify Noun Genders - Level 1",
|
||||
id: nounGender1Id,
|
||||
Game: function() {
|
||||
return <GenderGame id={nounGender1Id} level={1} />;
|
||||
},
|
||||
}
|
||||
|
||||
export const nounGenderGame2: GameRecord = {
|
||||
title: "Identify Noun Genders - Level 1",
|
||||
id: nounGender2Id,
|
||||
Game: function() {
|
||||
return <GenderGame id={nounGender2Id} level={2} />;
|
||||
},
|
||||
}
|
||||
export const nounGenderGame1 = makeGameRecord(
|
||||
"Identify Noun Genders - Level 1",
|
||||
"gender-nouns-1",
|
||||
(id) => () => <GenderGame id={id} level={1} />,
|
||||
);
|
||||
export const nounGenderGame2 = makeGameRecord(
|
||||
"Identify Noun Genders - Level 2",
|
||||
"gender-nouns-2",
|
||||
(id) => () => <GenderGame id={id} level={2} />,
|
||||
);
|
||||
export const unisexNounGame = makeGameRecord(
|
||||
"Changing genders on unisex nouns",
|
||||
"unisex-nouns-1",
|
||||
(id) => () => <UnisexNounGame id={id} />,
|
||||
);
|
||||
|
||||
const games: GameRecord[] = [
|
||||
unisexNounGame,
|
||||
nounGenderGame1,
|
||||
nounGenderGame2,
|
||||
unisexNounGame,
|
||||
];
|
||||
|
||||
export default games;
|
||||
|
|
|
@ -48,7 +48,7 @@ const exceptions: Record<string, CategorySet> = {
|
|||
}
|
||||
// consonantFem: words.filter((w) => w.category === "consonant-fem"),
|
||||
|
||||
const amount = 40;
|
||||
const amount = 35;
|
||||
|
||||
export default function({level, id}: { level: 1 | 2, id: string}) {
|
||||
function* questions () {
|
||||
|
@ -105,7 +105,7 @@ export default function({level, id}: { level: 1 | 2, id: string}) {
|
|||
questions={questions}
|
||||
id={id}
|
||||
Display={Display}
|
||||
timeLimit={level === 1 ? 65 : 85}
|
||||
timeLimit={level === 1 ? 50 : 70}
|
||||
Instructions={Instructions}
|
||||
/>
|
||||
};
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import {
|
||||
AT,
|
||||
postTestResults,
|
||||
} from "@lingdocs/lingdocs-main";
|
||||
|
||||
const fullKey = (uid: AT.UUID) => `test-results-${uid}`;
|
||||
|
||||
export async function postSavedResults(uid: AT.UUID): Promise<"sent" | "unsent" | "none"> {
|
||||
const key = fullKey(uid);
|
||||
const results = getSavedResults(key);
|
||||
if (results.length === 0) return "none";
|
||||
// if the result posting was successful, delete the result from local storage
|
||||
// and pull the user
|
||||
try {
|
||||
const res = await postTestResults(results)
|
||||
if (res.ok) {
|
||||
deleteTestResults(res.tests, key);
|
||||
return "sent";
|
||||
}
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
}
|
||||
return "unsent";
|
||||
}
|
||||
|
||||
export function saveResult(result: AT.TestResult, uid: AT.UUID) {
|
||||
const key = fullKey(uid);
|
||||
const results = getSavedResults(key);
|
||||
localStorage.setItem(key, JSON.stringify([...results, result]));
|
||||
}
|
||||
|
||||
function getSavedResults(key: string): AT.TestResult[] {
|
||||
return JSON.parse(localStorage.getItem(key) || "[]") as AT.TestResult[];
|
||||
}
|
||||
|
||||
function deleteTestResults(results: AT.TestResult[], key: string) {
|
||||
const r = getSavedResults(key);
|
||||
const left = r.filter((rs) => !results.some(x => x.time === rs.time));
|
||||
localStorage.setItem(key, JSON.stringify(left));
|
||||
}
|
|
@ -6,6 +6,7 @@ import {
|
|||
userObjIsEqual,
|
||||
} from "@lingdocs/lingdocs-main";
|
||||
import { CronJob } from "cron";
|
||||
import { postSavedResults } from "./lib/game-results";
|
||||
|
||||
const UserContext = createContext<
|
||||
{
|
||||
|
@ -35,6 +36,9 @@ function UserProvider({ children }: any) {
|
|||
|
||||
const checkUserCronJob = new CronJob("1/30 * * * * *", () => {
|
||||
pullUser();
|
||||
if (value) {
|
||||
postSavedResults(value.userId);
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
|
Loading…
Reference in New Issue