"use client" import type { HomeworkAssignmentQuestionAnalytics } from "@/modules/homework/types" import { ScrollArea } from "@/shared/components/ui/scroll-area" const isRecord = (v: unknown): v is Record => typeof v === "object" && v !== null const getOptions = (content: unknown): Array<{ id: string; text: string }> => { if (!isRecord(content)) return [] const raw = content.options if (!Array.isArray(raw)) return [] const out: Array<{ id: string; text: string }> = [] for (const item of raw) { if (!isRecord(item)) continue const id = typeof item.id === "string" ? item.id : "" const text = typeof item.text === "string" ? item.text : "" if (!id || !text) continue out.push({ id, text }) } return out } const safeInlineJson = (v: unknown) => { try { const s = JSON.stringify(v) if (typeof s === "string" && s.length > 180) return `${s.slice(0, 180)}…` return s ?? String(v) } catch { return String(v) } } const formatAnswer = (answerContent: unknown, question: HomeworkAssignmentQuestionAnalytics | null) => { if (isRecord(answerContent) && "answer" in answerContent) answerContent = answerContent.answer if (answerContent === null || answerContent === undefined) return "未作答" const options = getOptions(question?.questionContent ?? null) const optionTextById = new Map(options.map((o) => [o.id, o.text] as const)) if (typeof answerContent === "boolean") return answerContent ? "True" : "False" if (typeof answerContent === "string") return optionTextById.get(answerContent) ?? answerContent if (Array.isArray(answerContent)) { const parts = answerContent .map((x) => (typeof x === "string" ? optionTextById.get(x) ?? x : x)) .map((x) => (typeof x === "string" ? x : safeInlineJson(x))) return parts.join(", ") } return safeInlineJson(answerContent) } const clamp01 = (v: number) => Math.max(0, Math.min(1, v)) function ErrorRatePieChart({ errorRate }: { errorRate: number }) { const pct = clamp01(errorRate) * 100 const r = 15.91549430918954 const dashA = pct const dashB = 100 - pct const showError = pct > 0 return ( {showError ? ( ) : null} {pct.toFixed(0)}% ) } export function HomeworkAssignmentQuestionErrorDetailPanel({ selected, gradedSampleCount, }: { selected: HomeworkAssignmentQuestionAnalytics | null gradedSampleCount: number }) { const wrongAnswers = selected?.wrongAnswers ?? [] const errorCount = selected?.errorCount ?? 0 const errorRate = selected?.errorRate ?? 0 return (
Error Analysis
{selected ? ( <>
Question Q{selected.questionId.slice(-4)}
Errors {errorCount} / {gradedSampleCount}
Wrong Answers ({wrongAnswers.length})
{wrongAnswers.length === 0 ? (
No wrong answers recorded.
) : (
{wrongAnswers.map((wa, i) => (
Student Answer {wa.count ?? 1} student{(wa.count ?? 1) > 1 ? "s" : ""}
{formatAnswer(wa.answerContent, selected)}
))}
)}
) : (

Select a question from the left

to view error analysis

)}
) }