diff --git a/apps/api/src/routes/problem-stats.ts b/apps/api/src/routes/problem-stats.ts index 7a065f4..86fba65 100644 --- a/apps/api/src/routes/problem-stats.ts +++ b/apps/api/src/routes/problem-stats.ts @@ -203,20 +203,26 @@ async function classRows(problemId: number): Promise { - const classSize = - (row.class_name && sizes.find((item) => item.className === row.class_name)?.value) || - row.tried - return { - className: row.class_name, - classSize, - solved: row.solved, - unsolved: row.tried - row.solved, - untouched: Math.max(0, classSize - row.tried), - correctRate: row.judged ? Math.round((row.accepted / row.judged) * 100) : null, - lastTime: row.last_time, - } - }) - .sort((a, b) => b.lastTime.localeCompare(a.lastTime)) + return ( + rows + .map((row) => { + const classSize = + (row.class_name && sizes.find((item) => item.className === row.class_name)?.value) || + row.tried + return { + className: row.class_name, + classSize, + solved: row.solved, + unsolved: row.tried - row.solved, + untouched: Math.max(0, classSize - row.tried), + correctRate: row.judged ? Math.round((row.accepted / row.judged) * 100) : null, + lastTime: row.last_time, + } + }) + // 交过的人多的在前:按最近一次排的话,零星一两个人补做的班会压在全班做过的班上面 + .sort( + (a, b) => + b.solved + b.unsolved - (a.solved + a.unsolved) || b.lastTime.localeCompare(a.lastTime), + ) + ) } diff --git a/apps/web/src/oj/problem/components/ProblemInfo.vue b/apps/web/src/oj/problem/components/ProblemInfo.vue index a926e1f..26fc41b 100644 --- a/apps/web/src/oj/problem/components/ProblemInfo.vue +++ b/apps/web/src/oj/problem/components/ProblemInfo.vue @@ -130,7 +130,7 @@ const stuck = computed(() => { // ---------- 老师:各班的表 ---------- -/** 班多的老题(1001 这种十几个班都做过)先给 6 个,最近做的在前 */ +/** 班多的老题(1001 这种十几个班都做过)先给 6 个,交过的人多的在前 */ const allClasses = ref(false) const shownClasses = computed(() => allClasses.value ? (stats.value?.classes ?? []) : (stats.value?.classes ?? []).slice(0, 6), diff --git a/apps/web/src/oj/statistics/components/ByClass.vue b/apps/web/src/oj/statistics/components/ByClass.vue index 4f9522e..2bbd846 100644 --- a/apps/web/src/oj/statistics/components/ByClass.vue +++ b/apps/web/src/oj/statistics/components/ByClass.vue @@ -30,39 +30,46 @@ const classes = computed(() => { const key = row.className ?? "" groups.set(key, [...(groups.get(key) ?? []), row]) } - return [...groups.entries()] - .map(([className, rows]) => { - let submissions = 0 - let accepted = 0 - let last = "" - let done = 0 - for (const row of rows) { - const solved = new Set( - row.submissions.filter((item) => isAc(item.result)).map((item) => item.problemDisplayId), - ) - if (props.explicit ? need.every((pid) => solved.has(pid)) : solved.size > 0) done++ - // 正确率的分母不算还在判的,和数字行一个口径 - submissions += row.submissions.filter( - (item) => - item.result !== SubmissionStatus.pending && item.result !== SubmissionStatus.judging, - ).length - accepted += row.submissions.filter((item) => isAc(item.result)).length - const lastTime = row.submissions.at(-1)?.createTime ?? "" - if (lastTime > last) last = lastTime - } - const size = props.grid.classSizes[className] ?? rows.length - return { - className, - label: className ? classLabel(className) : "没有班级", - size, - done, - tried: rows.length - done, - none: Math.max(0, size - rows.length), - rate: submissions ? `${Math.round((accepted / submissions) * 100)}%` : "—", - last, - } - }) - .sort((a, b) => b.last.localeCompare(a.last)) + return ( + [...groups.entries()] + .map(([className, rows]) => { + let submissions = 0 + let accepted = 0 + let last = "" + let done = 0 + for (const row of rows) { + const solved = new Set( + row.submissions + .filter((item) => isAc(item.result)) + .map((item) => item.problemDisplayId), + ) + if (props.explicit ? need.every((pid) => solved.has(pid)) : solved.size > 0) done++ + // 正确率的分母不算还在判的,和数字行一个口径 + submissions += row.submissions.filter( + (item) => + item.result !== SubmissionStatus.pending && item.result !== SubmissionStatus.judging, + ).length + accepted += row.submissions.filter((item) => isAc(item.result)).length + const lastTime = row.submissions.at(-1)?.createTime ?? "" + if (lastTime > last) last = lastTime + } + const size = props.grid.classSizes[className] ?? rows.length + return { + className, + label: className ? classLabel(className) : "没有班级", + size, + done, + tried: rows.length - done, + none: Math.max(0, size - rows.length), + rate: submissions ? `${Math.round((accepted / submissions) * 100)}%` : "—", + last, + triedUsers: rows.length, + } + }) + // 交过的人多的在前(和题目页「各班做得怎样」一个顺序):按最近一次排的话, + // 零星一两个人补做的班会压在全班做过的班上面 + .sort((a, b) => b.triedUsers - a.triedUsers || b.last.localeCompare(a.last)) + ) }) diff --git a/packages/contract/src/problem.ts b/packages/contract/src/problem.ts index 0ffe52b..1811c01 100644 --- a/packages/contract/src/problem.ts +++ b/packages/contract/src/problem.ts @@ -474,7 +474,7 @@ export const problemStatsSchema = z.object({ .nullable(), /** * 老师:各班做这道题的情况,和数据统计「按班级汇总」**同一个口径**(只算学生的提交; - * 做完 / 班级人数、交了没对、没交、正确率、最近一次),按最近一次倒序。 + * 做完 / 班级人数、交了没对、没交、正确率、最近一次),交过的人多的在前。 * 两边数字要一模一样 —— 老师从这里点过去,看到的数「变了」就不会再信任何一边。 * 学生、比赛里为 null */