Files
OJ2/packages/contract/src/classroom.ts
yuetsh 8c00cdc947 feat(阶段3): oj 侧端点铺开(基线提交,未经评审)
由外部 agent (Codex) 在本会话额度中断期间完成。原样提交作为基线,
后续修复单独成 commit,便于区分与回退。

覆盖 oj 侧 65 个端点,新增 9 组路由(account/achievement/ai/classroom/
content/contest/flowchart/problemset/site)与对应 Zod 契约。

已核验:tsc --noEmit 退出码 0;API 可启动;/api/problems 返回真实数据;
judge 与 flowchart worker 均 ready。
未核验:权限边界与数据泄露,评审进行中。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 01:25:36 -06:00

65 lines
1.7 KiB
TypeScript

import { z } from "zod"
export const classRankItemSchema = z.object({
className: z.string(),
userCount: z.number().int(),
totalAc: z.number().int(),
totalSubmission: z.number().int(),
avgAc: z.number(),
acRate: z.number(),
rank: z.number().int(),
})
export const classUserRankItemSchema = z.object({
userId: z.number().int(),
username: z.string(),
acceptedNumber: z.number().int(),
submissionNumber: z.number().int(),
rank: z.number().int(),
})
export const classUserRankSchema = z.object({
className: z.string(),
myRank: z.number().int(),
total: z.number().int(),
ranks: z.array(classUserRankItemSchema),
})
export const classComparisonSchema = z.object({
className: z.string(),
userCount: z.number().int(),
totalAc: z.number().int(),
totalSubmission: z.number().int(),
avgAc: z.number(),
medianAc: z.number(),
q1Ac: z.number(),
q3Ac: z.number(),
iqr: z.number(),
stdDev: z.number(),
top10Avg: z.number(),
middle80Avg: z.number(),
bottom10Avg: z.number(),
excellentRate: z.number(),
passRate: z.number(),
activeRate: z.number(),
acRate: z.number(),
compositeScore: z.number(),
recentTotalAc: z.number().int().optional(),
recentTotalSubmission: z.number().int().optional(),
recentAvgAc: z.number().optional(),
recentMedianAc: z.number().optional(),
recentTop10Avg: z.number().optional(),
recentActiveCount: z.number().int().optional(),
})
export const classComparisonRequestSchema = z.object({
classNames: z.array(z.string()).min(1),
startTime: z.string().optional(),
endTime: z.string().optional(),
})
export const classComparisonResponseSchema = z.object({
comparisons: z.array(classComparisonSchema),
hasTimeRange: z.boolean(),
})