diff --git a/packages/common/types.ts b/packages/common/types.ts index 094a7f666..bcbbc65cc 100644 --- a/packages/common/types.ts +++ b/packages/common/types.ts @@ -81,24 +81,28 @@ export interface JudgeMeta { type?: string; } -export interface RecordPayload { - domainId: string; - pid: number; - uid: number; - lang: string; - code: string; +export interface RecordJudgeInfo { score: number; memory: number; time: number; judgeTexts: (string | JudgeMessage)[]; compilerTexts: string[]; testCases: Required[]; - rejudged: boolean; - source?: string; /** judge uid */ judger: number; judgeAt: Date; status: number; + subtasks?: Record; +} + +export interface RecordPayload extends RecordJudgeInfo { + domainId: string; + pid: number; + uid: number; + lang: string; + code: string; + rejudged: boolean; + source?: string; progress?: number; /** pretest */ input?: string; @@ -108,7 +112,6 @@ export interface RecordPayload { contest?: string; files?: Record - subtasks?: Record; } export interface JudgeRequest extends Omit { diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 1326504fc..08d31abaf 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -4,7 +4,7 @@ import type fs from 'fs'; import type { Dictionary, NumericDictionary } from 'lodash'; import type { Binary, FindCursor, ObjectId } from 'mongodb'; import type { - FileInfo, RecordPayload, + FileInfo, RecordJudgeInfo, RecordPayload, } from '@hydrooj/common/types'; import type { Context } from './context'; import type { DocStatusType } from './model/document'; @@ -224,6 +224,11 @@ export type RecordDoc = { _id: ObjectId; }; +export interface RecordHistoryDoc extends RecordJudgeInfo { + _id: ObjectId; + rid: ObjectId; +} + export interface RecordStatDoc { _id: ObjectId; domainId: string; @@ -545,6 +550,7 @@ declare module './service/db' { 'domain.user': any; 'record': RecordDoc; 'record.stat': RecordStatDoc; + 'record.history': RecordHistoryDoc; 'document': any; 'document.status': StatusDocBase & { [K in keyof DocStatusType]: { docType: K } & DocStatusType[K]; diff --git a/packages/hydrooj/src/model/record.ts b/packages/hydrooj/src/model/record.ts index c5e987890..4953ea02c 100644 --- a/packages/hydrooj/src/model/record.ts +++ b/packages/hydrooj/src/model/record.ts @@ -1,5 +1,5 @@ /* eslint-disable object-curly-newline */ -import { sum } from 'lodash'; +import { pick, sum } from 'lodash'; import moment from 'moment-timezone'; import { Filter, FindOptions, MatchKeysAndValues, @@ -20,6 +20,7 @@ import task from './task'; export default class RecordModel { static coll = db.collection('record'); static collStat = db.collection('record.stat'); + static collHistory = db.collection('record.history'); static PROJECTION_LIST: (keyof RecordDoc)[] = [ '_id', 'score', 'time', 'memory', 'lang', 'uid', 'pid', 'rejudged', 'progress', 'domainId', @@ -233,6 +234,7 @@ export default class RecordModel { } static async reset(domainId: string, rid: MaybeArray, isRejudge: boolean) { + const rids = rid instanceof Array ? rid : [rid]; const upd: any = { score: 0, status: STATUS.STATUS_WAITING, @@ -246,8 +248,19 @@ export default class RecordModel { judger: null, }; if (isRejudge) upd.rejudged = true; - await RecordModel.collStat.deleteMany(rid instanceof Array ? { _id: { $in: rid } } : { _id: rid }); - await task.deleteMany(rid instanceof Array ? { rid: { $in: rid } } : { rid }); + const [rdocs] = await Promise.all([ + RecordModel.coll.find({ _id: { $in: rids } }).toArray(), + RecordModel.collStat.deleteMany({ _id: { $in: rids } }), + task.deleteMany({ rid: { $in: rids } }), + ]); + await RecordModel.collHistory.insertMany(rdocs.map((rdoc) => ({ + ...pick(rdoc, [ + 'compilerTexts', 'judgeTexts', 'testCases', 'subtasks', + 'score', 'time', 'memory', 'status', 'judgeAt', 'judger', + ]), + rid: rdoc._id, + _id: new ObjectId(), + }))); return RecordModel.update(domainId, rid, upd); }