괄호 안의 항을 2, 3, 4 항으로 설정하는 기능 추가

This commit is contained in:
2026-05-31 13:40:45 +09:00
parent e148a957ea
commit ac3c939051
21 changed files with 708 additions and 344 deletions
@@ -12,15 +12,18 @@ import KatexRenderer from "@/components/math/KatexRenderer";
import { formatVariableTermLatex } from "@/lib/engine/variable-parenthesis";
import {
useVariableGameStore,
type VariableMaxTermCount,
type VariableProblemCount,
} from "@/store/variableGameStore";
interface VariablePlayClientProps {
problemCount: VariableProblemCount;
maxTermCount: VariableMaxTermCount;
}
export default function VariablePlayClient({
problemCount,
maxTermCount,
}: VariablePlayClientProps) {
const session = useVariableGameStore((state) => state.session);
const selectedProblemCount = useVariableGameStore(
@@ -29,15 +32,21 @@ export default function VariablePlayClient({
const setProblemCount = useVariableGameStore(
(state) => state.setProblemCount,
);
const selectedMaxTermCount = useVariableGameStore(
(state) => state.selectedMaxTermCount,
);
const setMaxTermCount = useVariableGameStore(
(state) => state.setMaxTermCount,
);
const initSession = useVariableGameStore((state) => state.initSession);
const submitAnswer = useVariableGameStore((state) => state.submitAnswer);
const nextProblem = useVariableGameStore((state) => state.nextProblem);
const resetSession = useVariableGameStore((state) => state.resetSession);
const [selectedChoiceIds, setSelectedChoiceIds] = useState<
[string | null, string | null]
>([null, null]);
const [activeTermIndex, setActiveTermIndex] = useState<0 | 1>(0);
const [selectedChoiceIds, setSelectedChoiceIds] = useState<(string | null)[]>(
() => Array.from({ length: maxTermCount }, () => null),
);
const [activeTermIndex, setActiveTermIndex] = useState(0);
const sessionProblemCount = session?.problems.length ?? null;
const currentProblem = session?.problems[session.currentIndex] ?? null;
@@ -45,7 +54,8 @@ export default function VariablePlayClient({
const isComplete = Boolean(
session && session.currentIndex >= session.problems.length,
);
const sessionNeedsInit = sessionProblemCount !== problemCount;
const sessionNeedsInit =
sessionProblemCount !== problemCount || session?.termCount !== maxTermCount;
const correctCount =
session?.results.filter((result) => result?.correct).length ?? 0;
const totalCount = session?.problems.length ?? 0;
@@ -55,40 +65,46 @@ export default function VariablePlayClient({
setProblemCount(problemCount);
}
if (selectedMaxTermCount !== maxTermCount) {
setMaxTermCount(maxTermCount);
}
if (sessionNeedsInit) {
initSession(problemCount);
initSession(problemCount, maxTermCount);
}
}, [
initSession,
maxTermCount,
problemCount,
selectedMaxTermCount,
selectedProblemCount,
sessionProblemCount,
sessionNeedsInit,
setMaxTermCount,
setProblemCount,
]);
useEffect(() => {
setSelectedChoiceIds([null, null]);
setSelectedChoiceIds(
Array.from({ length: currentProblem?.terms.length ?? maxTermCount }, () => null),
);
setActiveTermIndex(0);
}, [currentProblem?.key]);
}, [currentProblem?.key, currentProblem?.terms.length, maxTermCount]);
function handleSelectChoice(termIndex: 0 | 1, choiceId: string) {
const nextSelectedChoiceIds: [string | null, string | null] = [
...selectedChoiceIds,
];
function handleSelectChoice(termIndex: number, choiceId: string) {
const nextSelectedChoiceIds = [...selectedChoiceIds];
nextSelectedChoiceIds[termIndex] = choiceId;
setSelectedChoiceIds(nextSelectedChoiceIds);
if (termIndex === 0) {
setActiveTermIndex(1);
if (termIndex < nextSelectedChoiceIds.length - 1) {
setActiveTermIndex(termIndex + 1);
return;
}
if (currentResult || !currentProblem) return;
if (
nextSelectedChoiceIds[0] === null ||
nextSelectedChoiceIds[1] === null
nextSelectedChoiceIds.some((selectedChoiceId) => selectedChoiceId === null)
) {
return;
}
@@ -140,16 +156,15 @@ export default function VariablePlayClient({
const submitted = currentResult !== null;
const isLastProblem = session.currentIndex === session.problems.length - 1;
const pendingChoiceLabels: [string, string] = [
formatVariableTermLatex(currentProblem.firstTerm),
const pendingChoiceLabels = currentProblem.terms.map((term, index) =>
formatVariableTermLatex({
...currentProblem.secondTerm,
...term,
coefficient:
currentProblem.operator === "-"
? -currentProblem.secondTerm.coefficient
: currentProblem.secondTerm.coefficient,
index > 0 && currentProblem.operators[index - 1] === "-"
? -term.coefficient
: term.coefficient,
}),
];
);
return (
<main className="min-h-screen bg-slate-50 px-6 py-10 text-slate-950">
@@ -173,9 +188,6 @@ export default function VariablePlayClient({
</div>
<div className="rounded-md bg-white px-6 pt-6 pb-4 shadow-sm ring-1 ring-slate-200 sm:p-8">
<p className="mb-4 text-sm font-semibold text-slate-500">
.
</p>
<div className="text-3xl font-semibold text-slate-950 sm:text-4xl">
<KatexRenderer latex={currentProblem.latexBefore} displayMode />
</div>