move to document

This commit is contained in:
panda committed 2025-05-30 09:57:23 +00:00
1 parent 4c120db8de
commit 56897bf622
5 files changed
+57 -81

No files matched your search

+18 -8
View File
@@ -1,7 +1,7 @@
import { exec } from 'child_process';
import { inspect } from 'util';
import * as yaml from 'js-yaml';
import { omit } from 'lodash';
import { omit, pick } from 'lodash';
import moment from 'moment';
import { Filter, ObjectId } from 'mongodb';
import Schema from 'schemastery';
@@ -367,7 +367,7 @@ class SystemUserPrivHandler extends SystemHandler {
class SystemRejudgeHandler extends SystemHandler {
async get() {
this.response.body = {
rrdocs: await record.getMultiRejudgeTask({}),
rrdocs: await record.getMultiRejudgeTask(undefined, {}),
apply: true,
status: NORMAL_STATUS.filter((i: STATUS) => ![STATUS.STATUS_COMPILE_ERROR, STATUS.STATUS_ACCEPTED].includes(i)).join(','),
};
@@ -440,7 +440,7 @@ class SystemRejudgeHandler extends SystemHandler {
highPriority,
apply: _apply,
recordLength: rdocs.length,
rrdocs: await record.getMultiRejudgeTask({}),
rrdocs: await record.getMultiRejudgeTask(undefined, {}),
};
this.response.template = 'manage_rejudge.html';
return;
@@ -448,10 +448,19 @@ class SystemRejudgeHandler extends SystemHandler {
const rid = await record.addRejudgeTask(domainId, {
owner: this.user._id,
apply: _apply,
rids: rdocs.map((i) => i._id),
});
const priority = await record.submissionPriority(this.user._id, -10000 - rdocs.length * 5 - 50);
await record.reset(domainId, rdocs.map((rdoc) => rdoc._id), true);
const priority = await record.submissionPriority(this.user._id, (highPriority ? 0 : -10000) - rdocs.length * 5 - 50);
if (_apply) await record.reset(domainId, rdocs.map((rdoc) => rdoc._id), true);
else {
await record.collHistory.insertMany(rdocs.map((rdoc) => ({
...pick(rdoc, [
'compilerTexts', 'judgeTexts', 'testCases', 'subtasks',
'score', 'time', 'memory', 'status', 'judgeAt', 'judger',
]),
rid: rdoc._id,
_id: new ObjectId(),
})));
}
await Promise.all([
record.judge(domainId, rdocs.filter((i) => i.contest).map((i) => i._id), priority, { detail: false },
{ rejudge: _apply ? true : 'controlled' }),
@@ -465,9 +474,10 @@ class SystemRejudgeHandler extends SystemHandler {
class SystemRejudgeDetailHandler extends SystemHandler {
@param('rid', Types.ObjectId)
async get(domainId: string, rid: ObjectId) {
const rrdoc = await record.getRejudgeTask(rid);
const rrdoc = await record.getRejudgeTask(domainId, rid);
const rdocs = await record.getMulti(domainId, { _id: { $in: rrdoc.rids } }).toArray();
if (!rrdoc) throw new RecordNotFoundError(domainId, rid);
this.response.body = { rrdoc };
this.response.body = { rrdoc, rdocs };
this.response.template = 'manage_rejudge_detail.html';
}
}
+17 -11
View File
@@ -228,18 +228,24 @@ export interface RecordStatDoc {
lang: string;
}
export interface RecordRejudgeDoc {
_id: ObjectId;
domainId: string;
owner: number;
export interface RecordRejudgeDoc extends Document {
content: string;
docId: ObjectId;
docType: document['TYPE_REJUDGE'];
apply: boolean;
finishAt?: Date;
rids: ObjectId[];
changes?: {
rid: ObjectId;
old: number;
new: number;
}[];
}
export interface RecordRejudgeResultDoc {
_id: ObjectId;
rrid: ObjectId;
rid: ObjectId;
oldRev: ObjectId;
newRev: ObjectId;
oldStatus: number;
newStatus: number;
oldScore: number;
newScore: number;
}
export interface ScoreboardNode {
@@ -548,7 +554,7 @@ declare module './service/db' {
'record': RecordDoc;
'record.stat': RecordStatDoc;
'record.history': RecordHistoryDoc;
'record.rejudge': RecordRejudgeDoc;
'record.rejudge': RecordRejudgeResultDoc;
'document': any;
'document.status': StatusDocBase & {
[K in keyof DocStatusType]: { docType: K } & DocStatusType[K];
+4 -1
View File
@@ -7,7 +7,7 @@ import { Context } from '../context';
import {
Content, ContestClarificationDoc, DiscussionDoc,
DiscussionReplyDoc, ProblemDoc, ProblemStatusDoc,
Tdoc, TrainingDoc,
RecordRejudgeDoc, Tdoc, TrainingDoc,
} from '../interface';
import bus from '../service/bus';
import db from '../service/db';
@@ -29,6 +29,7 @@ export const TYPE_DISCUSSION_REPLY = 22 as const;
export const TYPE_CONTEST = 30 as const;
export const TYPE_CONTEST_CLARIFICATION = 31 as const;
export const TYPE_TRAINING = 40 as const;
export const TYPE_REJUDGE = 50 as const;
export interface DocType {
[TYPE_PROBLEM]: ProblemDoc;
@@ -40,6 +41,7 @@ export interface DocType {
[TYPE_CONTEST]: Tdoc;
[TYPE_CONTEST_CLARIFICATION]: ContestClarificationDoc;
[TYPE_TRAINING]: TrainingDoc;
[TYPE_REJUDGE]: RecordRejudgeDoc;
}
export interface DocStatusType {
@@ -487,5 +489,6 @@ global.Hydro.model.document = {
TYPE_PROBLEM,
TYPE_PROBLEM_LIST,
TYPE_PROBLEM_SOLUTION,
TYPE_REJUDGE,
TYPE_TRAINING,
};
+18 -10
View File
@@ -13,6 +13,7 @@ import db from '../service/db';
import { MaybeArray, NumberKeys } from '../typeutils';
import { ArgMethod, buildProjection, Time } from '../utils';
import { STATUS } from './builtin';
import * as document from './document';
import DomainModel from './domain';
import problem from './problem';
import task from './task';
@@ -282,24 +283,27 @@ export default class RecordModel {
return r;
}
static async getMultiRejudgeTask(query: Filter<RecordRejudgeDoc>) {
return RecordModel.collRejudge.find(query).toArray();
static async getMultiRejudgeTask(domainId: string | undefined, query: Filter<RecordRejudgeDoc>) {
return document.getMulti(domainId, document.TYPE_REJUDGE, query).toArray();
}
static async getRejudgeTask(_id: ObjectId) {
return RecordModel.collRejudge.findOne({ _id });
static async getRejudgeTask(domainId: string, _id: ObjectId) {
return document.get(domainId, document.TYPE_REJUDGE, _id);
}
static async addRejudgeTask(domainId: string, doc: Pick<RecordRejudgeDoc, 'owner' | 'apply' | 'rids' | 'changes'>) {
const res = await RecordModel.collRejudge.insertOne({ _id: new ObjectId(), domainId, ...doc });
return res.insertedId;
static async addRejudgeTask(domainId: string, doc: Partial<RecordRejudgeDoc>) {
return await document.add(domainId, '', doc.owner, document.TYPE_REJUDGE, null, null, null, doc);
}
static async pushRejudgeResult(rrid: ObjectId, result: { rid: ObjectId, old: number, new: number }) {
static async pushRejudgeResult(rrid: ObjectId, newStatus: number, newScore: number, newRev) {
await RecordModel.collRejudge.updateOne({ _id: rrid }, {
$push: {
changes: result,
$set: {
newStatus,
newScore,
newRev,
},
}, {
upsert: true,
});
}
}
@@ -349,6 +353,10 @@ export async function apply(ctx: Context) {
RecordModel.collHistory,
{ key: { rid: 1, _id: -1 }, name: 'basic' },
),
db.ensureIndexes(
RecordModel.collRejudge,
{ key: { domainId: 1, rrid: 1, rid: 1 }, name: 'basic' },
),
]);
}
global.Hydro.model.record = RecordModel;
-51
View File
@@ -1,51 +0,0 @@
import { Filter, ObjectId } from 'mongodb';
import Schema from 'schemastery';
import { Context } from '../context';
import { RecordDoc } from '../interface';
import { STATUS, STATUS_SHORT_TEXTS } from '../model/builtin';
import record from '../model/record';
export const apply = (ctx: Context) => ctx.addScript(
'rejudge', 'rejudge with filter',
Schema.object({
rrid: Schema.string(),
domainId: Schema.string(),
uid: Schema.number(),
pid: Schema.number(),
contest: Schema.string(),
lang: Schema.string(),
status: Schema.number(),
apply: Schema.boolean(),
}),
async (arg, report) => {
const q: Filter<RecordDoc> = { 'files.hack': { $exists: false } };
for (const key of ['domainId', 'uid', 'pid', 'contest', 'lang', 'status']) {
if (arg[key]) q[key] = arg[key];
}
q.contest ||= { $nin: [record.RECORD_GENERATE, record.RECORD_PRETEST] };
q.status ||= { $ne: STATUS.STATUS_CANCELED };
const rdocs = await record.getMulti(arg.domainId, q).project({ _id: 1, contest: 1, status: 1 }).toArray();
const rdict = new Map(rdocs.map((rdoc) => [rdoc._id, rdoc.status]));
report({ message: `Found ${rdocs.length} records` });
ctx.on('record/change', async (rdoc: RecordDoc) => {
if (rdict.has(rdoc._id)) {
rdict.delete(rdoc._id);
report({ message: `Rejudged ${rdoc._id}, ${STATUS_SHORT_TEXTS[rdict.get(rdoc._id)]} -> ${STATUS_SHORT_TEXTS[rdoc.status]}` });
await record.pushRejudgeResult(new ObjectId(arg.rrid), { rid: rdoc._id, old: rdict.get(rdoc._id), new: rdoc.status });
}
});
if (rdocs.length) {
const priority = await record.submissionPriority(1, -10000 - rdocs.length * 5 - 50);
if (arg.apply) {
await record.reset(arg.domainId, rdocs.map((rdoc) => rdoc._id), true);
}
await Promise.all([
record.judge(arg.domainId, rdocs.filter((i) => i.contest).map((i) => i._id),
priority, { detail: false }, { rejudge: arg.apply ? true : 'controlled' }),
record.judge(arg.domainId, rdocs.filter((i) => !i.contest).map((i) => i._id),
priority, {}, { rejudge: arg.apply ? true : 'controlled' }),
]);
}
return true;
},
);