feat(统计): 流程图统计列出「最常见的错」,不再显示新评法下没意义的平均分

新评法(走例子)没有四项分、几乎没有评语,雷达图、各项平均分、词云都拼不出来,
页面上只剩一个等级圆环。改成:
- 「最常见的错」:每张图第一组没走对的原因原样数一下(「『一级果』多输出了一行
  『一级果』2 张」),最多 8 条;全是新数据时放在等级分布旁边,新老混着时顶替词云
- 只有新数据时「每人最好的一次」铺满一行、分几栏
- 去掉「平均分」:新评法的分数只是走对的比例,看它不如看「拿到 A / S」;
  「每人最好的一次」也只写等级
老数据(2026-10 之前)照旧是四项分和词云。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-12 21:31:18 +08:00
1 parent 04c90e3f89
commit b9ece7d38f
3 files changed
+85 -15

No files matched your search

+14 -1
View File
@@ -610,6 +610,7 @@ flowchartRoutes.get("/flowcharts/statistics", requireTeacher, async (c) => {
personCount: roster.length,
completedCount: 0,
wordFrequencies: [],
commonMistakes: [],
// 一条提交都没有时,花名册上的人**全都**是「没做」—— 原来这里写死空数组,
// 于是一节课刚开始、最该点名的时候,教师面板反而一个名字都不给
dataUnaccepted: roster.map((row) => ({
@@ -645,8 +646,16 @@ flowchartRoutes.get("/flowcharts/statistics", requireTeacher, async (c) => {
const pushText = (value: string) => {
if (texts.length < WORDCLOUD_TEXT_LIMIT) texts.push(value)
}
const mistakes = new Map<string, number>()
for (const row of textRows) {
for (const [key, value] of Object.entries(asRecord(row.criteria))) {
const report = asRecord(row.criteria)
if (report.version === 2 && Array.isArray(report.cases)) {
const first = report.cases.map((item) => asRecord(item)).find((item) => item.ok === false)
if (typeof first?.why === "string" && first.why) {
mistakes.set(first.why, (mistakes.get(first.why) ?? 0) + 1)
}
}
for (const [key, value] of Object.entries(report)) {
const detail = asRecord(value)
// 和上面那条聚合同一道闸:分数不是数字的项当没配过,满分和评语也都不收
if (typeof detail.score !== "number") continue
@@ -676,6 +685,10 @@ flowchartRoutes.get("/flowcharts/statistics", requireTeacher, async (c) => {
personCount: roster.length,
completedCount: totals.completedCount,
wordFrequencies: await buildWordFrequencies(texts),
commonMistakes: [...mistakes]
.sort((a, b) => b[1] - a[1])
.slice(0, 8)
.map(([text, n]) => ({ text, count: n })),
dataUnaccepted: roster
.filter((row) => !submitted.has(row.id))
.map((row) => ({