Files

109 lines
2.9 KiB
TypeScript

import { create } from "zustand";
import {
generateSession,
gradeAnswer,
} from "@/lib/engine/parenthesis-sign";
import type { ParenthesisTermCount } from "@/lib/engine/parenthesis-sign";
import type {
GradeResult,
ParenthesisSignProblem,
UserAnswer,
} from "@/lib/engine/types";
export interface GameSession {
problems: ParenthesisSignProblem[];
currentIndex: number;
results: (GradeResult | null)[];
termCount: ParenthesisTermCount;
}
export type ProblemCount = 5 | 10;
export type MaxTermCount = ParenthesisTermCount;
interface GameState {
session: GameSession | null;
selectedProblemCount: ProblemCount;
selectedMaxTermCount: MaxTermCount;
setProblemCount: (count: ProblemCount) => void;
setMaxTermCount: (count: MaxTermCount) => void;
initSession: (count?: ProblemCount, maxTermCount?: MaxTermCount) => void;
submitAnswer: (answer: UserAnswer) => void;
nextProblem: () => void;
resetSession: () => void;
}
const DEFAULT_SESSION_COUNT: ProblemCount = 10;
const DEFAULT_MAX_TERM_COUNT: MaxTermCount = 2;
function createSession(
count: ProblemCount = DEFAULT_SESSION_COUNT,
maxTermCount: MaxTermCount = DEFAULT_MAX_TERM_COUNT,
): GameSession {
const problems = generateSession(count, maxTermCount);
return {
problems,
currentIndex: 0,
results: problems.map(() => null),
termCount: maxTermCount,
};
}
export const useGameStore = create<GameState>((set, get) => ({
session: null,
selectedProblemCount: DEFAULT_SESSION_COUNT,
selectedMaxTermCount: DEFAULT_MAX_TERM_COUNT,
setProblemCount: (count) => {
set({ selectedProblemCount: count });
},
setMaxTermCount: (count) => {
set({ selectedMaxTermCount: count });
},
initSession: (count, maxTermCount) => {
const selectedProblemCount = count ?? get().selectedProblemCount;
const selectedMaxTermCount = maxTermCount ?? get().selectedMaxTermCount;
set({ session: createSession(selectedProblemCount, selectedMaxTermCount) });
},
submitAnswer: (answer) => {
const { session } = get();
if (!session || session.currentIndex >= session.problems.length) return;
if (session.results[session.currentIndex] !== null) return;
const problem = session.problems[session.currentIndex];
const result = gradeAnswer(problem, answer);
const results = [...session.results];
results[session.currentIndex] = result;
set({
session: {
...session,
results,
},
});
},
nextProblem: () => {
const { session } = get();
if (!session || session.currentIndex >= session.problems.length) return;
if (session.results[session.currentIndex] === null) return;
set({
session: {
...session,
currentIndex: session.currentIndex + 1,
},
});
},
resetSession: () => {
set({
session: createSession(
get().selectedProblemCount,
get().selectedMaxTermCount,
),
});
},
}));