feat(流程图): 流程图画到 A / S 算这道题做完——题单进度、课堂条都认;加入题单之前画的图先藏起来
Deploy / deploy (push) Canceled after 0s

- 流程图评到 A 或 S,记进所有已加入、且包含这道题的题单(和判题那一路同一个口径,不看从哪个
  入口交的),徽章和题单类成就照样推送。原来题单进度只在判代码时记,流程图作业在题单里永远是
  「没做」。流程图提交的 id 进不了 problemset_submission(外键指向代码提交表),所以只写
  progress_detail —— 解锁旧提交的那道闸看的也是它
- 课堂条(/me/class-activity)的 myStatus:流程图 A / S 也算 accepted,评完的非 A/S 算 tried
- 题单防抄闸门补到流程图上:加入题单之前画的图,对本人藏起来(列表 showLink、详情 404、
  current / history 不数它),规则和代码提交同一份(problemSetJoinTimes 挪进 services/problemset)。
  原来加入之前画到 A 的那张图点一下就能载回画布、交上去就是 A
- 新增 GET /problems/:id/flowchart/scores:一次给出自己评完的每一次的分数和等级,外加被藏起来
  的次数(原来 history 一次只给一条,看分数走势得一页一页翻)
- 「A/S 算过关」和按分数定等级收进 flowchart/grade.ts;判题那边的记账 + 通知抽成
  recordSolvedAndNotify,两条路共用

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-09-28 17:56:35 +08:00
1 parent 948e9a734d
commit 3fe3caa944
8 files changed
+280 -145

No files matched your search

+13 -12
View File
@@ -5,6 +5,8 @@ import { config } from "../config"
import { db, schema } from "../db"
import { publishFlowchartUpdate } from "../events"
import { completeChat } from "../services/ai"
import { recordSolvedAndNotify } from "../services/problemset"
import { gradeForScore, isFlowchartPass } from "./grade"
import type { FlowchartJobData } from "./job"
function evaluationPrompt(problem: typeof schema.problem.$inferSelect) {
@@ -16,18 +18,6 @@ function evaluationPrompt(problem: typeof schema.problem.$inferSelect) {
题目:${problem.title}\n${problem.description.slice(0, 2000)}`
}
/**
* 等级一律由分数推出来,不采信模型自报的 grade。
* 提示词里写死了这四档,但模型偶尔会给出 88 分配 S 级这种自相矛盾的结果,
* 甚至直接吐「优秀」;脏值会一路串到等级分布图和「A/S 才展示流程图」的判断里。
*/
function gradeForScore(score: number) {
if (score >= 90) return "S"
if (score >= 80) return "A"
if (score >= 70) return "B"
return "C"
}
function parseEvaluation(value: string) {
const block = value.match(/```(?:json)?\s*([\s\S]*?)```/)?.[1]
const json = block ?? value.match(/\{[\s\S]*\}/)?.[0]
@@ -89,6 +79,17 @@ export async function evaluateFlowchart(
evaluationTime: new Date().toISOString(),
})
.where(eq(schema.flowchartSubmission.id, row.flowchart.id))
// 画到 A / S 算这道题做完,记进所有已加入、且包含这道题的题单 —— 和判题那一路
// 同一个口径(不看是从哪个入口交的)。放在推「评完了」之前:前端收到的时候进度已经
// 落库,1.5 秒后跳回题单页看到的就是新数据。比赛题不进题单
if (isFlowchartPass(result.grade) && row.problem.contestId === null) {
await recordSolvedAndNotify(
row.flowchart.userId,
row.problem.id,
null,
new Date().toISOString(),
)
}
await publishFlowchartUpdate(row.flowchart.userId, {
type: "flowchart_evaluation_completed",
submissionId: row.flowchart.id,