From 039d0c2d4d432c453429b2d7649932ff0ce92038 Mon Sep 17 00:00:00 2001 From: undefined Date: Sat, 25 Nov 2023 08:46:41 +0800 Subject: [PATCH] core: update tdoc type --- packages/hydrooj/src/handler/contest.ts | 4 ++-- packages/hydrooj/src/handler/record.ts | 8 ++++---- packages/hydrooj/src/interface.ts | 24 ++++++++++++---------- packages/hydrooj/src/model/contest.ts | 27 ++++++++++++------------- packages/hydrooj/src/script/rating.ts | 2 +- packages/hydrooj/src/service/bus.ts | 6 +++--- packages/hydrooj/src/typeutils.ts | 1 + 7 files changed, 37 insertions(+), 35 deletions(-) diff --git a/packages/hydrooj/src/handler/contest.ts b/packages/hydrooj/src/handler/contest.ts index 43b1aa04..c74fd3d6 100644 --- a/packages/hydrooj/src/handler/contest.ts +++ b/packages/hydrooj/src/handler/contest.ts @@ -112,7 +112,7 @@ export class ContestListHandler extends Handler { } export class ContestDetailBaseHandler extends Handler { - tdoc?: Tdoc<30>; + tdoc?: Tdoc; tsdoc?: any; @param('tid', Types.ObjectId, true) @@ -172,7 +172,7 @@ export class ContestDetailBaseHandler extends Handler { } export class ContestDetailHandler extends Handler { - tdoc?: Tdoc<30>; + tdoc?: Tdoc; tsdoc?: any; @param('tid', Types.ObjectId) diff --git a/packages/hydrooj/src/handler/record.ts b/packages/hydrooj/src/handler/record.ts index 2784cff0..ab701e43 100644 --- a/packages/hydrooj/src/handler/record.ts +++ b/packages/hydrooj/src/handler/record.ts @@ -25,7 +25,7 @@ import { ContestDetailBaseHandler } from './contest'; import { postJudge } from './judge'; class RecordListHandler extends ContestDetailBaseHandler { - tdoc?: Tdoc<30>; + tdoc?: Tdoc; @param('page', Types.PositiveInt, true) @param('pid', Types.ProblemId, true) @@ -122,7 +122,7 @@ class RecordListHandler extends ContestDetailBaseHandler { class RecordDetailHandler extends ContestDetailBaseHandler { rdoc: RecordDoc; - tdoc?: Tdoc<30>; + tdoc?: Tdoc; @param('rid', Types.ObjectId) async prepare(domainId: string, rid: ObjectId) { @@ -242,7 +242,7 @@ class RecordMainConnectionHandler extends ConnectionHandler { pid: number; status: number; pretest = false; - tdoc: Tdoc<30>; + tdoc: Tdoc; applyProjection = false; @param('tid', Types.ObjectId, true) @@ -334,7 +334,7 @@ class RecordMainConnectionHandler extends ConnectionHandler { class RecordDetailConnectionHandler extends ConnectionHandler { pdoc: ProblemDoc; - tdoc?: Tdoc<30>; + tdoc?: Tdoc; rid: string = ''; disconnectTimeout: NodeJS.Timeout; throttleSend: any; diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index bfd1da3d..c8021da4 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -373,9 +373,9 @@ export interface TrainingNode { pids: number[], } -export interface Tdoc extends Document { +export interface Tdoc extends Document { docId: ObjectId; - docType: docType & number; + docType: document['TYPE_CONTEST']; beginAt: Date; endAt: Date; attend: number; @@ -410,7 +410,8 @@ export interface Tdoc { + docType: document['TYPE_TRAINING'], description: string; pin?: number; dag: TrainingNode[]; @@ -536,24 +537,25 @@ export interface ContestRule { check: (args: any) => any; statusSort: Record; submitAfterAccept: boolean; - showScoreboard: (tdoc: Tdoc<30>, now: Date) => boolean; - showSelfRecord: (tdoc: Tdoc<30>, now: Date) => boolean; - showRecord: (tdoc: Tdoc<30>, now: Date) => boolean; - stat: (this: ContestRule, tdoc: Tdoc<30>, journal: any[]) => ContestStat & T; + showScoreboard: (tdoc: Tdoc, now: Date) => boolean; + showSelfRecord: (tdoc: Tdoc, now: Date) => boolean; + showRecord: (tdoc: Tdoc, now: Date) => boolean; + stat: (this: ContestRule, tdoc: Tdoc, journal: any[]) => ContestStat & T; scoreboardHeader: ( this: ContestRule, config: ScoreboardConfig, _: (s: string) => string, - tdoc: Tdoc<30>, pdict: ProblemDict, + tdoc: Tdoc, pdict: ProblemDict, ) => Promise; scoreboardRow: ( this: ContestRule, config: ScoreboardConfig, _: (s: string) => string, - tdoc: Tdoc<30>, pdict: ProblemDict, udoc: BaseUser, rank: number, tsdoc: ContestStat & T, + tdoc: Tdoc, pdict: ProblemDict, udoc: BaseUser, rank: number, tsdoc: ContestStat & T, meta?: any, ) => Promise; scoreboard: ( this: ContestRule, config: ScoreboardConfig, _: (s: string) => string, - tdoc: Tdoc<30>, pdict: ProblemDict, cursor: FindCursor, + tdoc: Tdoc, pdict: ProblemDict, cursor: FindCursor, ) => Promise<[board: ScoreboardRow[], udict: BaseUserDict]>; - ranked: (tdoc: Tdoc<30>, cursor: FindCursor) => Promise<[number, ContestStat & T][]>; + ranked: (tdoc: Tdoc, cursor: FindCursor) => Promise<[number, ContestStat & T][]>; + applyProjection: (tdoc: Tdoc, rdoc: RecordDoc, user: User) => RecordDoc; } export type ContestRules = Dictionary; diff --git a/packages/hydrooj/src/model/contest.ts b/packages/hydrooj/src/model/contest.ts index f6231309..e4eaec48 100644 --- a/packages/hydrooj/src/model/contest.ts +++ b/packages/hydrooj/src/model/contest.ts @@ -13,6 +13,7 @@ import ranked from '../lib/rank'; import * as bus from '../service/bus'; import db from '../service/db'; import type { Handler } from '../service/server'; +import { Optional } from '../typeutils'; import { PERM, STATUS, STATUS_SHORT_TEXTS } from './builtin'; import * as document from './document'; import problem from './problem'; @@ -69,11 +70,11 @@ export function isExtended(tdoc: Tdoc) { return tdoc.penaltySince.getTime() <= now && now < tdoc.endAt.getTime(); } -function buildContestRule(def: ContestRule): ContestRule; +function buildContestRule(def: Optional, 'applyProjection'>): ContestRule; function buildContestRule(def: Partial>, baseRule: ContestRule): ContestRule; function buildContestRule(def: Partial>, baseRule: ContestRule = {} as any) { const base = baseRule._originalRule || {}; - const funcs = ['scoreboard', 'scoreboardRow', 'scoreboardHeader', 'stat']; + const funcs = ['scoreboard', 'scoreboardRow', 'scoreboardHeader', 'stat', 'applyProjection']; const f = {}; const rule = { ...baseRule, ...def }; for (const key of funcs) { @@ -81,6 +82,7 @@ function buildContestRule(def: Partial>, baseRule: ContestRule rule[key] = f[key].bind(rule); } rule._originalRule = f; + rule.applyProjection ||= (_, rdoc) => rdoc; return rule; } @@ -715,9 +717,6 @@ const homework = buildContestRule({ async ranked(tdoc, cursor) { return await ranked(cursor, (a, b) => a.score === b.score); }, - applyProjection(_, rdoc) { - return rdoc; - }, }); export const RULES: ContestRules = { @@ -733,7 +732,7 @@ function _getStatusJournal(tsdoc) { export async function add( domainId: string, title: string, content: string, owner: number, rule: string, beginAt = new Date(), endAt = new Date(), pids: number[] = [], - rated = false, data: Partial> = {}, + rated = false, data: Partial = {}, ) { if (!RULES[rule]) throw new ValidationError('rule'); if (beginAt >= endAt) throw new ValidationError('beginAt', 'endAt'); @@ -765,7 +764,7 @@ export async function del(domainId: string, tid: ObjectId) { ]); } -export async function get(domainId: string, tid: ObjectId): Promise> { +export async function get(domainId: string, tid: ObjectId): Promise { const tdoc = await document.get(domainId, document.TYPE_CONTEST, tid); if (!tdoc) throw new ContestNotFoundError(tid); return tdoc; @@ -807,7 +806,7 @@ export async function getStatus(domainId: string, tid: ObjectId, uid: number) { } async function _updateStatus( - tdoc: Tdoc<30>, uid: number, rid: ObjectId, pid: number, status: STATUS, score: number, + tdoc: Tdoc, uid: number, rid: ObjectId, pid: number, status: STATUS, score: number, subtasks: Record, ) { const tsdoc = await document.revPushStatus(tdoc.domainId, document.TYPE_CONTEST, tdoc.docId, uid, 'journal', { @@ -902,25 +901,25 @@ export async function unlockScoreboard(domainId: string, tid: ObjectId) { await recalcStatus(domainId, tid); } -export function canViewHiddenScoreboard(this: { user: User }, tdoc: Tdoc<30>) { +export function canViewHiddenScoreboard(this: { user: User }, tdoc: Tdoc) { if (this.user.own(tdoc)) return true; if (tdoc.rule === 'homework') return this.user.hasPerm(PERM.PERM_VIEW_HOMEWORK_HIDDEN_SCOREBOARD); return this.user.hasPerm(PERM.PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD); } -export function canShowRecord(this: { user: User }, tdoc: Tdoc<30>, allowPermOverride = true) { +export function canShowRecord(this: { user: User }, tdoc: Tdoc, allowPermOverride = true) { if (RULES[tdoc.rule].showRecord(tdoc, new Date())) return true; if (allowPermOverride && canViewHiddenScoreboard.call(this, tdoc)) return true; return false; } -export function canShowSelfRecord(this: { user: User }, tdoc: Tdoc<30>, allowPermOverride = true) { +export function canShowSelfRecord(this: { user: User }, tdoc: Tdoc, allowPermOverride = true) { if (RULES[tdoc.rule].showSelfRecord(tdoc, new Date())) return true; if (allowPermOverride && canViewHiddenScoreboard.call(this, tdoc)) return true; return false; } -export function canShowScoreboard(this: { user: User }, tdoc: Tdoc<30>, allowPermOverride = true) { +export function canShowScoreboard(this: { user: User }, tdoc: Tdoc, allowPermOverride = true) { if (RULES[tdoc.rule].showScoreboard(tdoc, new Date())) return true; if (allowPermOverride && canViewHiddenScoreboard.call(this, tdoc)) return true; return false; @@ -928,7 +927,7 @@ export function canShowScoreboard(this: { user: User }, tdoc: Tdoc<30>, allowPer export async function getScoreboard( this: Handler, domainId: string, tid: ObjectId, config: ScoreboardConfig, -): Promise<[Tdoc<30>, ScoreboardRow[], BaseUserDict, ProblemDict]> { +): Promise<[Tdoc, ScoreboardRow[], BaseUserDict, ProblemDict]> { const tdoc = await get(domainId, tid); if (!canShowScoreboard.call(this, tdoc)) throw new ContestScoreboardHiddenError(tid); const tsdocsCursor = getMultiStatus(domainId, { docId: tid }).sort(RULES[tdoc.rule].statusSort); @@ -972,7 +971,7 @@ export function getMultiClarification(domainId: string, tid: ObjectId, owner = 0 ).sort('_id', -1).toArray(); } -export function applyProjection(tdoc: Tdoc<30>, rdoc: RecordDoc, udoc: User) { +export function applyProjection(tdoc: Tdoc, rdoc: RecordDoc, udoc: User) { if (!RULES[tdoc.rule]) return rdoc; return RULES[tdoc.rule].applyProjection(tdoc, rdoc, udoc); } diff --git a/packages/hydrooj/src/script/rating.ts b/packages/hydrooj/src/script/rating.ts index ba8ba0be..60bd95c0 100644 --- a/packages/hydrooj/src/script/rating.ts +++ b/packages/hydrooj/src/script/rating.ts @@ -55,7 +55,7 @@ export const RpTypes: Record = { }, contest: { async run(domainIds, udict, report) { - const contests: Tdoc<30>[] = await contest.getMulti('', { domainId: { $in: domainIds }, rated: true }) + const contests: Tdoc[] = await contest.getMulti('', { domainId: { $in: domainIds }, rated: true }) .limit(10).toArray() as any; if (contests.length) await report({ message: `Found ${contests.length} contests in ${domainIds[0]}` }); for (const tdoc of contests.reverse()) { diff --git a/packages/hydrooj/src/service/bus.ts b/packages/hydrooj/src/service/bus.ts index a7ad75a0..1c478c3d 100644 --- a/packages/hydrooj/src/service/bus.ts +++ b/packages/hydrooj/src/service/bus.ts @@ -91,9 +91,9 @@ export interface EventMap extends LifecycleEvents, HandlerEvents { 'problem/renameAdditionalFile': (domainId: string, docId: number, name: string, newName: string) => VoidReturn 'problem/delAdditionalFile': (domainId: string, docId: number, name: string[]) => VoidReturn - 'contest/before-add': (payload: Partial>) => VoidReturn - 'contest/add': (payload: Partial>, id: ObjectId) => VoidReturn - 'contest/scoreboard': (tdoc: Tdoc<30>, rows: ScoreboardRow[], udict: BaseUserDict, pdict: ProblemDict) => VoidReturn + 'contest/before-add': (payload: Partial) => VoidReturn + 'contest/add': (payload: Partial, id: ObjectId) => VoidReturn + 'contest/scoreboard': (tdoc: Tdoc, rows: ScoreboardRow[], udict: BaseUserDict, pdict: ProblemDict) => VoidReturn 'contest/balloon': (domainId: string, tid: ObjectId, bdoc: ContestBalloonDoc) => VoidReturn 'oplog/log': (type: string, handler: Handler, args: any, data: any) => VoidReturn; diff --git a/packages/hydrooj/src/typeutils.ts b/packages/hydrooj/src/typeutils.ts index 5c1e4473..95893063 100644 --- a/packages/hydrooj/src/typeutils.ts +++ b/packages/hydrooj/src/typeutils.ts @@ -14,3 +14,4 @@ export type Projection = readonly (string & keyof O)[]; export type Omit = Pick>; export type MaybeArray = T | T[]; export type UnionToIntersection = (U extends any ? (arg: U) => void : never) extends ((arg: infer I) => void) ? I : never; +export type Optional = Omit & Partial>;