Commit Graph
299 Commits
Author SHA1 Message Date
xuyueandClaude Opus 5.5 b046af4ba0 chore(部署): push 后先过检查再部署;判题机重启那几秒交的题不再变成系统错误;worker 挂了看得出来
Deploy / deploy (push) Canceled after 0s
按外部分析报告(reports/analysis)挑出来做的几条:
- CI 在编完前端之后跑 `bunx vp run verify`,有一项不过就不部署(必须排在编前端之后:
  前端类型检查要的 auto-imports.d.ts / components.d.ts 是 vite build 时才生成的)
- 连不上判题机(连接被拒、解析不到、被重置)时,正式判题等 2/5/10 秒重试,不再当场记成
  系统错误;超时、判题机回错、页面上的运行和自测不重试
- worker 每 10 秒刷一次「还活着」,compose 加 `oj2-api healthcheck --worker`,deploy.sh 起栈后
  也等 worker 健康(docker 不会因 unhealthy 自动重启,只是看得见、部署时拦得住)
- 三套 compose 的容器日志限 10MB × 3
- `/public/%` 这类畸形编码回 404 而不是 500;找不到的接口回统一的 JSON 错误
- 删掉没人用的「停用判题机」接口,契约不再给 task_number / is_disabled(列留在库里)
- 删掉腐化的 apps/web/tests/submitButtonState.test.ts;契约包 zod 范围对齐到 ^4.6.6
- 修几处和实际对不上的注释与文档(表数、编译并发、AST 语言数、deploy.sh 流程、校验处数)

⚠️ 改了 compose 的日志配置,这次部署会把 postgres / redis / 判题机也重建一遍,各停几秒

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 20:59:19 +08:00
xuyueandClaude Opus 5.5 b344bd1dd6 feat(布置作业): 能按知识点点选题目;一个班一天能布置几节课;数据统计认老师布置的课;后台能管布置过的课
Deploy / deploy (push) Canceled after 0s
- 课堂看板「选题」弹框:左边知识点(加必会题),右边搜题号/题名、点选,按点的先后排;
  只列这次作业的语言能交的题(/problems、/problem-tags 加 ?language=)
- 一天多节课:0040 拿掉 class_lesson (class_name, day) 唯一约束,每次布置一行;
  看板「改」只改当前一节,加「新的一节」;这一节布置超过 100 分钟时先问这节课做哪几道题。
  不带 lessonId/newLesson 的老请求照旧改今天最后一节
- 数据统计「一行一节课」:布置过的课以布置为准(题目和顺序照布置、做完按全班算、标「布置」),
  这些提交不再参与推断切段,也不算零散;详情页「做完」注明是这一天/这节课/这段时间
- 后台「课堂作业」:一节一行,改(班级/日子/时刻/语言/题目)、看统计、删除、补一节;
  看板加「布置过的课」入口。题号校验和「做完」口径抽到 services/lesson.ts,三处共用

⚠️ 机房站点要和服务器一起升级:旧代码布置时 ON CONFLICT (class_name, day) 找不到约束会报错

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 20:41:25 +08:00
xuyueandClaude Opus 5.5 179d5fa67d feat(语法要求): 能要求「调用 print() 时必须用 sep 参数」,题目说要用 sep/end 的不再被绕过
Deploy / deploy (push) Canceled after 0s
原来只能数 print 调用几次,写成 print("1-2-3***4") + print() 也算达标。
新加 must_use_keyword(只有 Python),后台「关键字参数」一组里配函数名和参数名。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 22:16:44 +08:00
xuyueandClaude Opus 5.5 37e971b6b4 refactor(判题机): 换成 go-judge,空闲内存从几百 MB 降到 16 MB
原来的 JudgeServer 按核数起 gunicorn worker、每份提交再按核数开进程池,空闲内存跟着核数走
(2 核 52MB、16 核 305MB)。换成 go-judge 后空闲 16MB,同一批提交判题中 80–100MB(原来约 370MB)。

go-judge 只管在沙箱里跑命令,编译、逐点运行、比对输出、定状态码搬到 judge/sandbox.ts,
口径逐条照搬 JudgeServer,出参形状不变。拿生产库真实提交新旧逐点对比:C 2000 份 1989 一致、
C++ 891 份 890 一致、Python 2000 份全一致;不一致的是 system("pause")(现在不再判运行时错误)、
未定义行为、endl 死循环打印(运行时错误变运行超时),见 docker/judge/README.md。

- 判题容器改成 privileged(go-judge 要自己建 cgroup),镜像 oj2-judge-3
- 心跳改由 worker 每 5 秒问判题机 /version 代记,删掉 /api/judge-server/heartbeat
- 前端统一用 stripJudgePath 去掉判题机工作目录(新的 /w/ 和旧的 /judger/run/)
- 提交前编译检查只编译不运行

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 15:03:57 +08:00
xuyueandClaude Opus 5.5 8427475337 chore(清理): 删掉并行试跑、搬库、Python3 别名、旧链接这些过渡期的兼容写法
Deploy / deploy (push) Canceled after 0s
- 部署:JUDGE_STATE_DIR 不再强制设;删掉搬库脚本和只为搬库存在的自检、提醒
- 语言:Python3 / Python2 别名表删掉,normalizeLanguage 改名 parseLanguage
- 旧链接:后台题单详情的跳转、用户列表 -last_login 的转换
- 旧页面:布置作业必须带 language(null = 没选);不再清旧版出题页草稿

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 14:15:04 +08:00
xuyueandClaude Opus 5.5 9e074f3ab8 fix(路由检查): 改成单引号之后 check:routes 一条路由都没查,却照样报「没有遮蔽」
正则只认双引号,全仓换成单引号后匹配数变成 0。现在单双引号都认,查到 197 条。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 14:15:04 +08:00
xuyueandClaude Opus 5.5 6b5ca745bb fix(出题页): 改了挑战点保存,提示「保存好了」其实一条都没存上
出题页发请求时漏了 challenges 这个字段,后端又把「不带」当成「不动原来的」,
所以改动被静默丢掉。现在出题页带上它,接口也改成必须带(null 是清空),
以后再漏传会直接报错,不会再悄悄丢。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 14:15:04 +08:00
xuyueandClaude Opus 5.5 195069450f style(格式化): 改成单引号、一行最长 160,全仓重新格式化
Deploy / deploy (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 13:52:24 +08:00
xuyueandClaude Opus 5.5 36b3cd6b21 feat(结果): 判完之后测试点一格一格亮起来,错的那格写着第几组
Deploy / deploy (push) Canceled after 0s
借小丑牌结算时一张张牌亮起来:结果里每组测试点一个方块,从左往右依次亮,
对的绿、错的红并写组号,不到 1 秒亮完,提示和按钮亮完才出来,全对时亮完再放烟花。
大字和「通过几个」判完马上就有;只播刚交的那条,刷新、看旧提交、系统减少动画都直接全亮。
提交详情多给每组对没对(只有对错,不带数据),比赛照旧不给。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 09:56:32 +08:00
xuyueandClaude Opus 5.5 0faf78ad8f feat(挑战): 做对之后可以加一条写法上的限制再做一遍,判题时记下谁做到了
借小丑牌的赌注档:同一道题加一条限制(「整首歌只用 1 次 print」)再做一遍,
给课上做得快的学生找事做(做完一节课的题,中位要空等 13 分钟)。
判定沿用 AST 规则,挑战配在 problem.challenges,做到的记在 challenge_success;
做对的提交顺手判一遍,挑战没做到也照样算做对。没过的规则带上是第几行。
0039 灌进第一批 56 道常用题的 73 条挑战,api 起来后拿历史上做对的代码补一遍谁已经做到了。
出题页能配挑战、从做对的代码里找候选;课堂看板的格子带上挑战状态。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 08:52:50 +08:00
xuyueandClaude Opus 5.5 b3dca1a271 perf(判题): SQL 题每次判题少等约 50ms,后端起服务快一倍
Deploy / deploy (push) Canceled after 0s
单二进制改用预编译字节码(--bytecode --format=esm)。SQL 判题每题都要起一次子进程,
单核实测从约 120ms 降到约 72ms;serve 起服务约 180ms → 100ms,内存不变,二进制大 8MB。
编译形态在仓库外实跑过:migrate / healthcheck / serve / worker 能起,C 题判对、
AST 规则判出 10、jieba 分词、SQL 子进程的判题与展示都和 dev 形态结果一致。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 09:16:32 +08:00
xuyueandClaude Opus 5.5 eb0309ae35 chore(构建): Bun 锁到 1.4.4,CI 和镜像不再跟 latest;后端类型检查换成 bun check
单二进制把运行时一起打进去,CI 装的是几线上就是几,之前三处都不锁(@types/bun latest、
setup-bun latest、oven/bun:1),1.4.x 每版都有破坏性变更会悄悄上线。
顺带 bunfig 加 minimumReleaseAge = "3d",@types/bun 除外。
后端 typecheck 从 tsc 换成 bun check,1.9s → 0.26s,报错一致。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 09:13:21 +08:00
xuyueandClaude Opus 5.5 a718394284 fix(年度趋势): 默认先打开 25 级,新一届没正式上课前只做过几道题,不再默认停在它上面
Deploy / deploy (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 21:30:11 +08:00
xuyueandClaude Opus 5.5 f7c4af0c01 fix(年度趋势): 刚学一个月的届不再拿去和学了一年多的往届比,两边都只算同样学了这么久时做的
Deploy / deploy (push) Canceled after 0s
以前往届那一侧把所有记录都算进去,25 级比 24 级显示 73% / 82%,
其实 24 级在这些题上近一半是学了半年以上才做的;同期比是 73% / 75%。

现在每个人以自己第一次交题为起点,两边都只算离起点不超过 N 天的人题对,
N = 两届里学得短的那届一半人开始做题到现在的天数。按人不按日历,因为各届
开始做题的时间不一样(25 级第二年才开始)。比哪届改成后端算,接口带 grade / compare。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 21:21:22 +08:00
xuyueandClaude Opus 5.5 e3c0507d41 feat(设置): 能查出并删掉没人用的图片,编辑器里删掉的图和换下来的头像都算
Deploy / deploy (push) Canceled after 0s
编辑器里删图、学生换头像都只改库不删文件,盘上越积越多。设置页加「没人用的图片」,
点「查一下」才扫(要扫整个库,不在进页面时跑),按编辑器插图 / 头像分两组,
缩略图可点开,单张删或整组删(先确认)。

判定宁可多留:扫库里每张表的每个文本列,文件名在哪儿出现过都算在用(老域名、
markdown 写法都认,不分大小写);只看 png/jpg/gif/bmp,目录里的 mp4 不碰;
一天内传的不算(可能还在编辑器里没保存);库里一张图都没提到时什么也不列(多半连错了库);
删之前重新扫一遍。服务器和机房图片目录各一份,要各清各的。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 20:50:02 +08:00
xuyueandClaude Opus 5.5 13843c79a0 fix(登录): 两个标签页同时换 token 时,学生可能过一刻钟被莫名踢下线
Deploy / deploy (push) Canceled after 0s
refresh token 轮换原来是「读出来、查库、写回去」,两个标签页同时换会各自轮换出一张,
后写的冲掉先写的;浏览器里留下的若是被冲掉那张,下次换就被拒。机房走 http 用不了
navigator.locks,前端没法让标签页排队。

- 轮换改成比对再写入(Lua),抢输的重读后走宽限期
- 宽限期里回的是当前那张 refresh token,不再回 null,几个标签页最后落到同一张上
- 响应丢了、前端拿旧的重试,也由同一支接住

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:27:08 +08:00
xuyueandClaude Opus 5.5 793848b06f refactor(登录): 登录态从 Cookie 换成 access token + refresh token
Deploy / deploy (push) Canceled after 0s
- access token 是 15 分钟的 JWT,走 Authorization: Bearer;refresh token 7 天,每次换都轮换
- 退出登录、改密码、禁用账号仍然立刻生效:每个请求核对 Redis 会话和库里新加的 user.token_version
- 在服务器后台改密码 / 禁用,机房那边登着的也会一起下线(原来两边 Redis 分开,管不到)
- WebSocket 握手借子协议带 token;JWT 密钥存在本站 Redis,部署不用加配置
- 去掉 COOKIE_SECURE;上线后所有人要重新登录一次

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:22:52 +08:00
xuyueandClaude Opus 5.5 4be569d978 chore(文档): CLAUDE.md 瘦身,后端专属的坑挪进 apps/api/CLAUDE.md,并改正「推 origin 不部署」的说法
Deploy / deploy (push) Canceled after 0s
- 单二进制、runtime.ts、SQL 自 spawn、路由遮蔽、出参 satisfies、外键与迁移原样搬到
  apps/api/CLAUDE.md,只在动后端文件时加载;根文件留一行指路
- Chrome 105 的 polyfill 审计细节挪到 apps/web/CLAUDE.md
- 删掉 ls 就能看到的仓库结构表,以及 docs/database.md、docker/judge/README.md 已有的重复步骤
- origin 会镜像到 github,平时推 origin 通常也就部署了(CLAUDE.md 与 deploy.md 原来写的是不触发)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 18:18:24 +08:00
xuyueandClaude Opus 5.5 df152f505d feat(课堂看板): 「这节课」写上是哪位老师布置的,别的老师改题也不换人
Deploy / deploy (push) Canceled after 0s
看板题号后面从「09:56 布置」变成「09:56 徐越 布置」,老师首页「今天的课」同样带上名字。
老师写真名(用户名 lwp0201、little 认不出是谁),没填真名的退回用户名。
「改」不再覆盖 created_by,和布置时间一样认第一次布置的人。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 09:56:46 +08:00
xuyueandClaude Opus 5.5 9ae6287fb1 feat(流程图): 没画对也分得出远近——五档说法、完成度条、比上次多对了几组;右栏的图放大
只说「还没画对」,学生改了几次还是这一句,看不出在往前走。等级照旧存 S/A/B/C,
标题换成话:画对了,画得很清楚 / 画对了 / 快画对了 / 对了一部分 / 还没画对;
下面一根完成度条,走对几组亮几段;第二次起没画对时说比上次多(少)对了几组
(详情接口带上同一道题上一次走对了几组)。提交列表右栏的图从 42% 加宽到 62%,
小图也放大填满图框(最多 1.5 倍)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:11:42 +08:00
xuyueandClaude Opus 5.5 d2fc0382ec feat(流程图): 没走对的图,AI 对照答案说出错在哪个框、该怎么改,并把那个框标红
原来只有程序拼出的现象(「输出 a」输出的是 2,应该是 8),指的是出结果的框,
错的根子常在前面,学生和老师都看不出该改哪里。跑完以后再请 AI 看题目、图、
没走对的几组和老师的答案,写「哪里错了 / 可以这样改」两句,指出真正要改的框;
提交列表右栏的图和题目页画布上标红它。等级照旧只由跑出来的结果定,
点评失败或像代码就不要,退回只显示逐组结果。老提交不补。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:52:05 +08:00
xuyueandClaude Opus 5.5 67b13a9345 fix(流程图): 老提交重新评分后四项明细全显示「0 / 0」
Deploy / deploy (push) Canceled after 0s
老办法(四项打总分)的 prompt 只写了 "criteria_details":{},模型换成 deepseek-flash
之后直接给 {"逻辑正确性": 32} 这样的裸数字,详情页读不到 score / max。prompt 里把
四项的形状写全,存之前按 { score, max, comment } 收好(缺满分按 40/30/20/10 补);
0036 把线上已经存进去的 4 条改回来。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:11:35 +08:00
xuyueandClaude Opus 5.5 940895f643 feat(课堂看板): 接口给做对了的格子带上今天每一次代码提交和第几次做对
原来今天最后一次提交只给没做对的格子;现在同一条查询取今天全部,做对了的格子
多带 trail(从早到晚的 id / 结果 / 时间)和 acceptedTry(今天第几次做对,
以前就做对了的为 null)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:09:35 +08:00
xuyueandClaude Opus 5.5 465dbfd42f refactor(后端): 权限判断收到一处,路由文件之间不再互相 import
- services/permissions.ts:「超管或创建者」原来在比赛、题单、比赛题目(4 处)、
  services/contest.ts 各抄一遍,「题目全部权限」在题目和标签两个路由各写一份
- services/submission-filters.ts:提交列表的用户名 / 班级 / 题号筛选,原来
  submission.ts、flowchart.ts 从 submission-statistics.ts 这个路由文件里拿
- services/class-activity.ts:课堂做题记录的口径和「正在上课的班」,原来后台
  conf.ts 从 classroom.ts 路由里拿
- services/problem-tags.ts:标签名去重、按名查标签,原来 tag.ts 从 admin/problem.ts 拿

纯搬家。三种身份(超管 / 老师 / 学生)打了 26 个受影响的接口,改前改后状态码和响应体
逐字节一致,包括「不是自己的比赛 / 题单 / 题目报不存在」那几条。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:53:24 +08:00
xuyueandClaude Opus 5.5 fb11e86151 perf(排名): 一个班同时打开排名、班级对抗、按人数排的题目列表时只查一次库
这几样谁来看都一样,原来每次请求现算:全服全部时间的排名本机 16 核就要 250ms,
服务器两核还要判题。services/cache.ts 进程内缓存 10 秒,同时到达的相同请求等同一个结果:
- 排名榜面的原始数据(「我」排第几、前后一名照旧每次现算):250ms → 6ms
- 班级对抗 / 详情 / PK 共用的这学期数据:40ms → 1ms
- 题目列表按做对、做过人数排序的全表人数:45ms → 20ms
40 个人同时打开全服排名(缓存是冷的)一共 342ms。代价是做对之后最多晚 10 秒上榜。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:47:24 +08:00
xuyueandClaude Opus 5.5 307b0725d0 perf(判题): 判题机上同时跑的程序从最多 8 个压到 4 个,挤的时候不再把不超时的判成超时
原来四道闸各管各的(worker 判题 2、api 试运行 2、提交前编译检查 2、worker 里流程图
评分的试运行又 2),api 和 worker 两个进程互相看不见,峰值 8 个程序压在服务器两个核上;
判题机按墙钟判超时,挤到一定程度会冤枉学生。

judge/slots.ts 在 Redis 里按池数名额(每个站点各数各的):
- 后台池(正式判题、诊断重跑、流程图评分)上限 JUDGE_CONCURRENCY
- 交互池(运行例子、自己输入、生成测试点、编译检查)上限 TRIAL_CONCURRENCY
两池不互相借,正式判题排再长也挤不掉学生的「运行例子」。名额是带到期时间的租约,
进程被杀了到期自动作废;Redis 出错直接放行。正式判题的超时从拿到名额才开始算。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:47:24 +08:00
xuyueandClaude Opus 5.5 55038cc78b fix(判题): 判题机卡住不再让全班一直「等待评分」,重判和同时交对也不再把做对题数算多
Deploy / deploy (push) Canceled after 0s
- 正式判题、样例重跑、运行时错误诊断都加了超时(默认 120 秒,时限放宽的题按比例放宽),
  超时记系统错误、提示是中文;回包和试运行一样边读边数,超过 16MB 就掐断,
  免得一个疯狂打印的错误程序把 worker 撑爆
- 做对题数、中等、困难、一次就对改成在锁里按定义现数:原来逐次 +1,两条挨着判完或重判
  一条做对的提交都会多加,库里 372 人多了 1–4 道。0035 把存量一次订正
- 重判不再给提交次数、凌晨/早起计数 +1,编译错误按前后差值改;「错了几次才对」只数这条之前的
- 已拿到的成就数只 jsonb_set 那一个键,不再整块写回冲掉并发判题刚写的指标

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:15:08 +08:00
xuyueandClaude Opus 5.5 a814776fb9 feat(教程): 改练一练时可以顺手清空学生的作答——改了答案,按旧答案做对的人不再算做对
Deploy / deploy (push) Canceled after 0s
练一练是原地改的,作答记录跟着题走:改了答案或选项,按旧答案做对的人仍然显示做对、
「最后错在 选了 B」说的也是旧选项。编辑框底下多一个「同时清空学生的作答(N 人做过)」,
没人做过时不出现;勾上保存,学生那边这道题回到没做。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 12:28:47 +08:00
xuyueandClaude Opus 5.5 1ebb23cdac feat(自学情况): 看得到配套题做没做——每人一列、每课一个页签、学生明细里逐题列出
Deploy / deploy (push) Canceled after 0s
- 方块格多一列「配套题」:他打开过的那些课挂的题,做对几道 / 一共几道;格子提示里也带上
- 右栏分「练一练 / 配套题」两个页签:每道题读过这课的人里几人做对,点开看谁没交、谁交了没对,
  一键跳到这个人这道题的提交
- 学生明细每课多一段配套题:做对没有、交了几次、最后哪天交的
- 做对不论早晚,读教程之前在课上做对的也算;口径同学生端课文里那个勾(代码 AC 或流程图 A / S)
- 1366 宽下 C 语言 20 课也不用横着滑了:「最后学习」只留日期,几列收窄

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 12:21:34 +08:00
xuyueandClaude Opus 5.5 7839a65f59 feat(自学情况): 每个学生练一练做到哪了——格子分出做了一部分、点名字看逐题明细
- 方块格多一档「做了一部分」:按做对的比例从下往上涨绿,一道没做对的底下压一条橙;
  鼠标停上去是「练一练 3/5,错了 4 次」
- 「练一练」列改成 做对/应做(应做 = 他打开过的课的练一练总数)
- 点学生名字从右边滑出明细:每课一段,逐题写第几次做对、交了几次、最后错在哪;
  手机上返回键关它
- 点开一道练一练,底下多一串「读了这课还没做」的人
- 顺手修:那个弹框七列加起来比弹框宽,「最后作答」被挤没了;改成一列用户名

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 11:40:30 +08:00
xuyueandClaude Opus 5.5 e7b6e27b85 feat(课堂看板): 标出谁在线、谁今天没上过线,请假框里没上线的人分在前面一堆
机房有两人共用一台电脑的,同桌只有一个登着,只看「此刻在不在线」会把旁边的人
当成没来。所以每次记在线时按天再记一笔「今天最后一次上线」:
- 看板「在线」列(原「在写」):开着题的照旧写题号,其余写 在线 / N 分钟前在 / 今天没上线
- 还没交过的人里,今天没上过线的排最前
- 请假框分「今天没上线」「今天上过线」两堆,前一堆可以一键全勾上

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 13:50:59 +08:00
xuyueandClaude Opus 5.5 cff989bf19 perf(提交): 格式化前送判题机编的那一下改成排队,一个班同时交也不会把判题机挤到人人超时
Deploy / deploy (push) Canceled after 0s
格式化前的编译检查不走判题队列,原来来多少份就同时往判题机上压多少份。服务器只有两核,
按两核实测 40 份 C++ 同时压上去,每份都撞 8 秒超时,正式判题也跟着变慢。现在同时最多
2 份,其余排队,8 秒是连排队带编译的总预算,排不上就当编得过、照常格式化。

同样 40 份,现在 5.2 秒全部编完、判断全对;压到 80 份时有 24 份等满 8 秒放弃。上一个提交
之后,编得过的代码只有 1~2% 还会走到这一步,平时基本排不起队。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:24:07 +08:00
xuyueandClaude Opus 5.5 797b41751e perf(提交): 交 C / C++ 不用再干等:编得过的代码不再先送判题机编一遍,全班一起交时不会卡上好几秒
Deploy / deploy (push) Canceled after 0s
提交前的自动格式化原来每次都先在判题机上编一次(防止 clang-format 把编不过的几行并成
一行)。服务器只有两核、还要和判题抢 CPU,按两核实测:40 人同时交 C,这一步中位 1.8 秒、
最慢 2.7 秒;40 人同时交 C++(iostream),全部撞上 8 秒超时。而且等完之后判题还要再编一遍。

现在先跑 clang-format(十几毫秒),只有它真把学生原来分开的两行并成一行时才去判题机编。
大括号挪到上一行、} else 接上不算并行。拿本机库里的真实提交核过:编得过的 C 只有 1.2%、
C++ 2.1% 还会去编;编不过又被并了行的照样拦住、原样返回。

顺带:格式化不再给 #include 排序、不再把超长的 printf 字符串拆成两截(学生看不懂
"……" "……" 这种写法,它们也是误判的主要来源)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:19:48 +08:00
xuyueandClaude Opus 5.5 c8c38553ec feat(首页): 新接口给老师首页列出今天在上课的每个班——这节课的题、几人交过、全做对几人、最后一次交题的时刻
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:53:38 +08:00
xuyueandClaude Opus 5.5 20a6f667d8 refactor(设置): 站点配置去掉从来没人读的网址、简称、页脚三项和 AI 小助手开关
库里 options 表那几行旧值留着,没有代码再读。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:37:35 +08:00
xuyueandClaude Opus 5.5 c33b084788 fix(后台成就): 成就指标的名字改成大白话(「AC 题目数」→「做对的题数」这类)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:32:33 +08:00
xuyueandClaude Opus 5.5 b93d4d83a1 fix(后台公告): 后台公告列表置顶的排在最前,和学生在首页看到的顺序一样
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:21:49 +08:00
xuyueandClaude Opus 5.5 1d406a50e4 feat(后台首页): 首页接口带上全站的数(学生、题目、提交、比赛、题单、自学、这周做题的人)、最近 30 天每天提交、系统错误、在线人数和正在上课的班
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:17:00 +08:00
xuyueandClaude Opus 5.5 09e5e0bfcf feat(后台 AI 报告): 报告列表带上学生是哪个班的
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:11:07 +08:00
xuyueandClaude Opus 5.5 591c7bcab9 feat(后台比赛): 比赛列表带上每场几道题、几人参加,按开始时间排,复制出来的旧比赛不再跑到最前面
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:07:24 +08:00
xuyueandClaude Opus 5.5 ba823ecb7d feat(后台用户): 用户列表能按班级筛、按用户名排、看出几人从没登录;批量建号前能查重名,新班级建好自动加进班级列表
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:56:03 +08:00
xuyueandClaude Opus 5.5 952edbf86f feat(后台题目): 题目列表带上做对 / 做过的人数和「学生看得到 / 藏着的」各几道,能一次放出或藏起好几道题;比赛题目也能按题号搜
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:27:39 +08:00
xuyueandClaude Opus 5.5 573a0f967f feat(举手与协作): 老师能在看板上直接打开学生正在写的代码,同一道题好几个人举手能「讲完了,都放下」,举手面板写着每人错在哪
学生编辑器报「在写哪道题」,看板接口带 editing;新增 peek / dismiss 两条协作消息,
求助记录带这道题最后一次提交(判完新的一次会刷新)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:04:57 +08:00
xuyueandClaude Opus 5.5 5c9d0ca501 feat(课堂看板): 「这节课」那排题号后面写上几点布置的,之后改题不变
Deploy / deploy (push) Canceled after 0s
class_lesson 加 created_at(0034,老数据用 updated_at 回填),「改」只动 updated_at;
清掉再布置算重新开始。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:21:39 +08:00
xuyueandClaude Opus 5.5 0a4f528c44 feat(课堂看板): 看板接口给没做对的格子带上今天最后一次提交,按错法归堆、点开讲错误要用
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:02:50 +08:00
xuyueandClaude Opus 5.5 df76e7f101 feat(提交详情): 单独打开的一条提交改成左边代码、右边为什么错 + 这道题交的每一次
Deploy / deploy (push) Canceled after 0s
- 原来不显示是哪道题、时间只到日、答案错误不说为什么,测试点表 5 行一模一样
- 右边摆题目页那块例子对比(输入 / 正确输出 / 他的输出,差的字标红),编译失败、运行时错误同提交列表右栏的说法,代码里标出那一行
- 「这道题交了 N 次」常驻右栏,← → 一次次翻,看他是怎么改对的;题单藏着的那几次点不进
- 老师:「他的全部提交」和「⋯」(复制两项、重新判题);测试点方块悬停看用时和内存;判题中自己刷新
- 别人的代码、链接不对原来一直转圈,现在说清楚是哪种;自己在题单布置期内的照样看得到是哪道题、什么结果
- 后端详情多给题目名、班级、题单,`?attempts=1` 带上同题的每一次;看不到别人的回 403 而不是 404;提交者本人也拿得到 contestId(比赛里的题号是比赛自己的)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:00:22 +08:00
xuyueandClaude Opus 5.5 4240a451e4 chore(站内信): 消息页、后台空壳页、两个接口和 message 表一起下线
Deploy / deploy (push) Canceled after 0s
历史上一共 6 条站内信(最后一条 2025-06),发信接口两代前端都没接过,后台页面只有一句
「未完待续」,OJ2 顶栏也没有入口。

0033 是 DROP TABLE,部署要显式放行:OJ2_ALLOW_DESTRUCTIVE=1 docker/deploy.sh,
或 CI 手工触发时勾 allow_destructive。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:51:12 +08:00
xuyueandClaude Opus 5.5 85108df9d8 feat(成就): 下架三个拿不到的成就、理顺稀有度和图标;接口多给本班几人有和「本班」卡片
- 0032:下架六边形战士(判题机只剩 3 种语言)、坚持三天/一周(按天算基本拿不到);
  不撞南墙改白银、屡败屡战改黄金;百发百中换 💯、屡败屡战换 💪,不再和别的撞图标;
  代码行数只算做对的、空行不算,并按新口径重算所有人;已经拿到的一个不收回
- 奖杯收藏家只数上架的成就(判题结算、补发重算、0032 存量一起改)
- GET /achievements:每个成就带全站几人有、本班几人有;看自己时带「本班」(最近拿到、成就最多前五、自己第几);
  隐藏成就同一串拿到一档就整串亮出来;连续几周给「现在连着几周」而不是历史最长
- 删掉只有旧成就页在用的 /achievements/summary

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:26:37 +08:00
xuyueandClaude Opus 5.5 cbf5b9d922 feat(个人主页): 后端一个接口给齐主页要的东西:做对的题带题名和日期、四个时间、本班第几、成就,老师和本人多拿知识点和没做对的题
- GET /profiles/:username/overview:同学看拿不到知识点和没做对的题,多一份「你和他」
- DELETE /me/avatar:不用图片,退回名字的字
- 知识点地图抽成 knowledgeMapOf,老师看学生也能用
- 删掉没人用了的 /users/:id/metrics

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:03:37 +08:00
xuyueandClaude Opus 5.5 3ca3b42997 fix(排名): 老师点「本班」不再随手挑个交题最多的班,改成布置过作业的班、上次选的班,都没有就停在全部
Deploy / deploy (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:28:55 +08:00