109 lines
2.9 KiB
TypeScript
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,
|
|
),
|
|
});
|
|
},
|
|
}));
|