proper caching and sending of test results
This commit is contained in:
parent
82a29978a1
commit
db6ba08c1a
|
@ -7,10 +7,13 @@ import "./timer.css";
|
||||||
import {
|
import {
|
||||||
getPercentageDone,
|
getPercentageDone,
|
||||||
} from "../lib/game-utils";
|
} from "../lib/game-utils";
|
||||||
|
import {
|
||||||
|
saveResult,
|
||||||
|
postSavedResults,
|
||||||
|
} from "../lib/game-results";
|
||||||
import {
|
import {
|
||||||
AT,
|
AT,
|
||||||
getTimestamp,
|
getTimestamp,
|
||||||
postTestResults,
|
|
||||||
} from "@lingdocs/lingdocs-main";
|
} from "@lingdocs/lingdocs-main";
|
||||||
import {
|
import {
|
||||||
Types as T,
|
Types as T,
|
||||||
|
@ -27,7 +30,7 @@ function GameCore<T>({ questions, Display, timeLimit, Instructions, studyLink, i
|
||||||
}) {
|
}) {
|
||||||
// TODO: report pass with id to user info
|
// TODO: report pass with id to user info
|
||||||
const rewardRef = useRef<RewardElement | null>(null);
|
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 [finish, setFinish] = useState<null | "pass" | "fail" | "time out">(null);
|
||||||
const [current, setCurrent] = useState<Current<T> | undefined>(undefined);
|
const [current, setCurrent] = useState<Current<T> | undefined>(undefined);
|
||||||
const [questionBox, setQuestionBox] = useState<QuestionGenerator<T>>(questions());
|
const [questionBox, setQuestionBox] = useState<QuestionGenerator<T>>(questions());
|
||||||
|
@ -47,6 +50,24 @@ function GameCore<T>({ questions, Display, timeLimit, Instructions, studyLink, i
|
||||||
if (next.done) handleFinish();
|
if (next.done) handleFinish();
|
||||||
else setCurrent(next.value);
|
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() {
|
function handleFinish() {
|
||||||
setFinish("pass");
|
setFinish("pass");
|
||||||
rewardRef.current?.rewardMe();
|
rewardRef.current?.rewardMe();
|
||||||
|
@ -56,14 +77,7 @@ function GameCore<T>({ questions, Display, timeLimit, Instructions, studyLink, i
|
||||||
time: getTimestamp(),
|
time: getTimestamp(),
|
||||||
id,
|
id,
|
||||||
};
|
};
|
||||||
console.log("will post result", JSON.stringify(result));
|
handleResult(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);
|
|
||||||
}
|
}
|
||||||
function handleQuit() {
|
function handleQuit() {
|
||||||
setFinish(null);
|
setFinish(null);
|
||||||
|
|
|
@ -2,39 +2,34 @@ import React from "react";
|
||||||
import GenderGame from "./sub-cores/GenderGame";
|
import GenderGame from "./sub-cores/GenderGame";
|
||||||
import UnisexNounGame from "./sub-cores/UnisexNounGame";
|
import UnisexNounGame from "./sub-cores/UnisexNounGame";
|
||||||
|
|
||||||
const unisexNounsId = "unisex-nouns-1";
|
function makeGameRecord(title: string, id: string, game: (id: string) => (() => JSX.Element)): GameRecord {
|
||||||
const nounGender1Id = "gender-nouns-1";
|
return {
|
||||||
const nounGender2Id = "gender-nouns-2";
|
title,
|
||||||
|
id,
|
||||||
export const unisexNounGame: GameRecord = {
|
Game: game(id),
|
||||||
title: "Changing genders on unisex nouns",
|
}
|
||||||
id: unisexNounsId,
|
|
||||||
Game: function() {
|
|
||||||
// TODO: Why won't this.id word here??!
|
|
||||||
return <UnisexNounGame id={unisexNounsId} />;
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const nounGenderGame1: GameRecord = {
|
export const nounGenderGame1 = makeGameRecord(
|
||||||
title: "Identify Noun Genders - Level 1",
|
"Identify Noun Genders - Level 1",
|
||||||
id: nounGender1Id,
|
"gender-nouns-1",
|
||||||
Game: function() {
|
(id) => () => <GenderGame id={id} level={1} />,
|
||||||
return <GenderGame id={nounGender1Id} level={1} />;
|
);
|
||||||
},
|
export const nounGenderGame2 = makeGameRecord(
|
||||||
}
|
"Identify Noun Genders - Level 2",
|
||||||
|
"gender-nouns-2",
|
||||||
export const nounGenderGame2: GameRecord = {
|
(id) => () => <GenderGame id={id} level={2} />,
|
||||||
title: "Identify Noun Genders - Level 1",
|
);
|
||||||
id: nounGender2Id,
|
export const unisexNounGame = makeGameRecord(
|
||||||
Game: function() {
|
"Changing genders on unisex nouns",
|
||||||
return <GenderGame id={nounGender2Id} level={2} />;
|
"unisex-nouns-1",
|
||||||
},
|
(id) => () => <UnisexNounGame id={id} />,
|
||||||
}
|
);
|
||||||
|
|
||||||
const games: GameRecord[] = [
|
const games: GameRecord[] = [
|
||||||
unisexNounGame,
|
|
||||||
nounGenderGame1,
|
nounGenderGame1,
|
||||||
nounGenderGame2,
|
nounGenderGame2,
|
||||||
|
unisexNounGame,
|
||||||
];
|
];
|
||||||
|
|
||||||
export default games;
|
export default games;
|
||||||
|
|
|
@ -48,7 +48,7 @@ const exceptions: Record<string, CategorySet> = {
|
||||||
}
|
}
|
||||||
// consonantFem: words.filter((w) => w.category === "consonant-fem"),
|
// consonantFem: words.filter((w) => w.category === "consonant-fem"),
|
||||||
|
|
||||||
const amount = 40;
|
const amount = 35;
|
||||||
|
|
||||||
export default function({level, id}: { level: 1 | 2, id: string}) {
|
export default function({level, id}: { level: 1 | 2, id: string}) {
|
||||||
function* questions () {
|
function* questions () {
|
||||||
|
@ -105,7 +105,7 @@ export default function({level, id}: { level: 1 | 2, id: string}) {
|
||||||
questions={questions}
|
questions={questions}
|
||||||
id={id}
|
id={id}
|
||||||
Display={Display}
|
Display={Display}
|
||||||
timeLimit={level === 1 ? 65 : 85}
|
timeLimit={level === 1 ? 50 : 70}
|
||||||
Instructions={Instructions}
|
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,
|
userObjIsEqual,
|
||||||
} from "@lingdocs/lingdocs-main";
|
} from "@lingdocs/lingdocs-main";
|
||||||
import { CronJob } from "cron";
|
import { CronJob } from "cron";
|
||||||
|
import { postSavedResults } from "./lib/game-results";
|
||||||
|
|
||||||
const UserContext = createContext<
|
const UserContext = createContext<
|
||||||
{
|
{
|
||||||
|
@ -35,6 +36,9 @@ function UserProvider({ children }: any) {
|
||||||
|
|
||||||
const checkUserCronJob = new CronJob("1/30 * * * * *", () => {
|
const checkUserCronJob = new CronJob("1/30 * * * * *", () => {
|
||||||
pullUser();
|
pullUser();
|
||||||
|
if (value) {
|
||||||
|
postSavedResults(value.userId);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
Loading…
Reference in New Issue