결과창에 정답, 오답 내용 출력

This commit is contained in:
2026-05-26 18:25:57 +09:00
parent 51a96db269
commit 2427b458dc
4 changed files with 123 additions and 43 deletions
+2
View File
@@ -221,6 +221,8 @@ export default function PlayClient({ problemCount }: PlayClientProps) {
<ScoreSummary <ScoreSummary
correctCount={correctCount} correctCount={correctCount}
totalCount={totalCount} totalCount={totalCount}
problems={session.problems}
results={session.results}
onRestart={resetSession} onRestart={resetSession}
/> />
); );
+64
View File
@@ -0,0 +1,64 @@
"use client";
import type { ReactNode } from "react";
import KatexRenderer from "@/components/math/KatexRenderer";
interface AnswerResultLineProps {
expressionLatex: string;
userAnswerLatex: string;
correctAnswerLatex: string;
correct: boolean;
prefix?: ReactNode;
}
export default function AnswerResultLine({
expressionLatex,
userAnswerLatex,
correctAnswerLatex,
correct,
prefix,
}: AnswerResultLineProps) {
return (
<li
className={`flex flex-wrap items-center gap-x-2 gap-y-1 rounded-md px-4 py-3 text-lg font-semibold ring-1 ring-inset ${
correct
? "bg-emerald-100 text-emerald-950 ring-emerald-200"
: "bg-red-100 text-red-950 ring-red-200"
}`}
>
{prefix}
<KatexRenderer latex={expressionLatex} output="mathml" />
<span aria-hidden="true">=</span>
<span className={correct ? undefined : "text-red-700"}>
<KatexRenderer latex={userAnswerLatex} output="mathml" />
</span>
{correct ? (
<span
aria-label="정답"
role="img"
className="inline-flex h-7 items-center text-2xl leading-none text-emerald-700"
>
</span>
) : (
<>
<span
aria-label="오답"
role="img"
className="mr-2 inline-flex h-7 items-center text-2xl leading-none text-red-700"
>
×
</span>
<span className="text-slate-700">
(
<span className="font-bold">
<KatexRenderer latex={correctAnswerLatex} output="mathml" />
</span>
)
</span>
</>
)}
</li>
);
}
+7 -43
View File
@@ -2,7 +2,7 @@
import { useEffect, useRef } from "react"; import { useEffect, useRef } from "react";
import KatexRenderer from "@/components/math/KatexRenderer"; import AnswerResultLine from "@/components/game/AnswerResultLine";
import type { GradeResult, ParenthesisSignProblem } from "@/lib/engine/types"; import type { GradeResult, ParenthesisSignProblem } from "@/lib/engine/types";
interface FeedbackPanelProps { interface FeedbackPanelProps {
@@ -53,49 +53,13 @@ export default function FeedbackPanel({
</p> </p>
<ul className="mt-5 space-y-3"> <ul className="mt-5 space-y-3">
{feedbackItems.map((item, index) => ( {feedbackItems.map((item, index) => (
<li <AnswerResultLine
key={index} key={index}
className={`flex flex-wrap items-center gap-x-2 gap-y-1 rounded-md px-4 py-3 text-lg font-semibold ring-1 ring-inset ${ expressionLatex={item.formulaLatex}
item.correct userAnswerLatex={`${item.userAnswer}`}
? "bg-emerald-100 text-emerald-950 ring-emerald-200" correctAnswerLatex={`${item.correctAnswer}`}
: "bg-red-100 text-red-950 ring-red-200" correct={item.correct}
}`} />
>
<KatexRenderer latex={item.formulaLatex} output="mathml" />
<span aria-hidden="true">=</span>
<span className={item.correct ? undefined : "text-red-700"}>
<KatexRenderer latex={`${item.userAnswer}`} output="mathml" />
</span>
{item.correct ? (
<span
aria-label="정답"
role="img"
className="inline-flex h-7 items-center text-2xl leading-none text-emerald-700"
>
</span>
) : (
<>
<span
aria-label="오답"
role="img"
className="mr-2 inline-flex h-7 items-center text-2xl leading-none text-red-700"
>
×
</span>
<span className="text-slate-700">
(
<span className="font-bold">
<KatexRenderer
latex={`${item.correctAnswer}`}
output="mathml"
/>
</span>
)
</span>
</>
)}
</li>
))} ))}
</ul> </ul>
<button <button
+50
View File
@@ -3,18 +3,40 @@
import Link from "next/link"; import Link from "next/link";
import { useEffect, useRef } from "react"; import { useEffect, useRef } from "react";
import AnswerResultLine from "@/components/game/AnswerResultLine";
import type { GradeResult, ParenthesisSignProblem } from "@/lib/engine/types";
interface ScoreSummaryProps { interface ScoreSummaryProps {
correctCount: number; correctCount: number;
totalCount: number; totalCount: number;
problems: ParenthesisSignProblem[];
results: (GradeResult | null)[];
onRestart: () => void; onRestart: () => void;
} }
function formatLatexTermPair(first: number, second: number) {
const operator = second < 0 ? "-" : "+";
return `${first} ${operator} ${Math.abs(second)}`;
}
export default function ScoreSummary({ export default function ScoreSummary({
correctCount, correctCount,
totalCount, totalCount,
problems,
results,
onRestart, onRestart,
}: ScoreSummaryProps) { }: ScoreSummaryProps) {
const restartButtonRef = useRef<HTMLButtonElement>(null); const restartButtonRef = useRef<HTMLButtonElement>(null);
const solvedItems = problems
.map((problem, index) => ({
problem,
result: results[index],
}))
.filter(
(item): item is { problem: ParenthesisSignProblem; result: GradeResult } =>
item.result !== null,
);
useEffect(() => { useEffect(() => {
restartButtonRef.current?.focus(); restartButtonRef.current?.focus();
@@ -35,6 +57,34 @@ export default function ScoreSummary({
</p> </p>
</div> </div>
<ol className="space-y-3">
{solvedItems.map(({ problem, result }, index) => {
const userAnswerLatex = formatLatexTermPair(
result.userAnswer[0],
result.userAnswer[1],
);
const correctAnswerLatex = formatLatexTermPair(
result.correctAnswer[0],
result.correctAnswer[1],
);
return (
<AnswerResultLine
key={problem.key}
expressionLatex={problem.latexBefore}
userAnswerLatex={userAnswerLatex}
correctAnswerLatex={correctAnswerLatex}
correct={result.correct}
prefix={
<span className="mr-1 text-sm font-bold text-slate-500">
{index + 1}.
</span>
}
/>
);
})}
</ol>
<div className="flex flex-wrap gap-3"> <div className="flex flex-wrap gap-3">
<button <button
ref={restartButtonRef} ref={restartButtonRef}