-
-
Notifications
You must be signed in to change notification settings - Fork 422
core&ui: support bulk rejudge task #998
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
178c1cd
16a4d42
d1098b0
39cc430
f30f12e
4c120db
56897bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,14 +1,21 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| 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'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { Time } from '@hydrooj/utils'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||||
| CannotEditSuperAdminError, NotLaunchedByPM2Error, UserNotFoundError, ValidationError, | ||||||||||||||||||||||||||||||||||||||||||||||
| CannotEditSuperAdminError, ContestNotFoundError, NotLaunchedByPM2Error, ProblemNotFoundError, | ||||||||||||||||||||||||||||||||||||||||||||||
| RecordNotFoundError, UserNotFoundError, ValidationError, | ||||||||||||||||||||||||||||||||||||||||||||||
| } from '../error'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { RecordDoc } from '../interface'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { Logger } from '../logger'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { PRIV, STATUS } from '../model/builtin'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { NORMAL_STATUS, PRIV, STATUS } from '../model/builtin'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import * as contest from '../model/contest'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import domain from '../model/domain'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import problem from '../model/problem'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import record from '../model/record'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import * as setting from '../model/setting'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import * as system from '../model/system'; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -357,6 +364,124 @@ class SystemUserPrivHandler extends SystemHandler { | |||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| class SystemRejudgeHandler extends SystemHandler { | ||||||||||||||||||||||||||||||||||||||||||||||
| async get() { | ||||||||||||||||||||||||||||||||||||||||||||||
| this.response.body = { | ||||||||||||||||||||||||||||||||||||||||||||||
| rrdocs: await record.getMultiRejudgeTask(undefined, {}), | ||||||||||||||||||||||||||||||||||||||||||||||
| apply: true, | ||||||||||||||||||||||||||||||||||||||||||||||
| status: NORMAL_STATUS.filter((i: STATUS) => ![STATUS.STATUS_COMPILE_ERROR, STATUS.STATUS_ACCEPTED].includes(i)).join(','), | ||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||
| this.response.template = 'manage_rejudge.html'; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| @param('uidOrName', Types.UidOrName, true) | ||||||||||||||||||||||||||||||||||||||||||||||
| @param('pid', Types.ProblemId, true) | ||||||||||||||||||||||||||||||||||||||||||||||
| @param('tid', Types.ObjectId, true) | ||||||||||||||||||||||||||||||||||||||||||||||
| @param('langs', Types.CommaSeperatedArray, true) | ||||||||||||||||||||||||||||||||||||||||||||||
| @param('beginAtDate', Types.Date, true) | ||||||||||||||||||||||||||||||||||||||||||||||
| @param('beginAtTime', Types.Time, true) | ||||||||||||||||||||||||||||||||||||||||||||||
| @param('endAtDate', Types.Date, true) | ||||||||||||||||||||||||||||||||||||||||||||||
| @param('endAtTime', Types.Time, true) | ||||||||||||||||||||||||||||||||||||||||||||||
| @param('status', Types.CommaSeperatedArray, true) | ||||||||||||||||||||||||||||||||||||||||||||||
| @param('type', Types.Range(['preview', 'rejudge'])) | ||||||||||||||||||||||||||||||||||||||||||||||
| @param('high_priority', Types.Boolean) | ||||||||||||||||||||||||||||||||||||||||||||||
| @param('apply', Types.Boolean) | ||||||||||||||||||||||||||||||||||||||||||||||
| async post( | ||||||||||||||||||||||||||||||||||||||||||||||
| domainId: string, uidOrName?: string, pid?: string | number, tid?: ObjectId, | ||||||||||||||||||||||||||||||||||||||||||||||
| langs: string[] = [], beginAtDate?: string, beginAtTime?: string, endAtDate?: string, | ||||||||||||||||||||||||||||||||||||||||||||||
| endAtTime?: string, status: string[] = [], _type = 'rejudge', highPriority = false, _apply = false, | ||||||||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const q: Filter<RecordDoc> = {}; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (uidOrName) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const udoc = await user.getById(domainId, +uidOrName) | ||||||||||||||||||||||||||||||||||||||||||||||
| || await user.getByUname(domainId, uidOrName) | ||||||||||||||||||||||||||||||||||||||||||||||
| || await user.getByEmail(domainId, uidOrName); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (udoc) q.uid = udoc._id; | ||||||||||||||||||||||||||||||||||||||||||||||
| else throw new UserNotFoundError(uidOrName); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| if (tid) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const tdoc = await contest.get(domainId, tid); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!tdoc) throw new ContestNotFoundError(domainId, tid); | ||||||||||||||||||||||||||||||||||||||||||||||
| q.contest = tdoc._id; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| if (pid) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const pdoc = await problem.get(domainId, pid); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (pdoc) q.pid = pdoc.docId; | ||||||||||||||||||||||||||||||||||||||||||||||
| else throw new ProblemNotFoundError(domainId, pid); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| if (langs.length) q.lang = { $in: langs.filter((i) => setting.langs[i]) }; | ||||||||||||||||||||||||||||||||||||||||||||||
| let beginAt = null; | ||||||||||||||||||||||||||||||||||||||||||||||
| let endAt = null; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (beginAtDate) { | ||||||||||||||||||||||||||||||||||||||||||||||
| beginAt = moment(`${beginAtDate} ${beginAtTime || '00:00'}`); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!beginAt.isValid()) throw new ValidationError('beginAtDate', 'beginAtTime'); | ||||||||||||||||||||||||||||||||||||||||||||||
| q._id ||= {}; | ||||||||||||||||||||||||||||||||||||||||||||||
| q._id = { ...q._id, $gte: Time.getObjectID(beginAt) }; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| if (endAtDate) { | ||||||||||||||||||||||||||||||||||||||||||||||
| endAt = moment(`${endAtDate} ${endAtTime || '23:59'}`); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!endAt.isValid()) throw new ValidationError('endAtDate', 'endAtTime'); | ||||||||||||||||||||||||||||||||||||||||||||||
| q._id ||= {}; | ||||||||||||||||||||||||||||||||||||||||||||||
| q._id = { ...q._id, $lte: Time.getObjectID(endAt) }; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| if (beginAt && endAt && beginAt.isSameOrAfter(endAt)) throw new ValidationError('duration'); | ||||||||||||||||||||||||||||||||||||||||||||||
| const rdocs = await record.getMulti(domainId, q).project({ _id: 1, contest: 1 }).toArray(); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (_type === 'preview') { | ||||||||||||||||||||||||||||||||||||||||||||||
| this.response.body = { | ||||||||||||||||||||||||||||||||||||||||||||||
| uidOrName, | ||||||||||||||||||||||||||||||||||||||||||||||
| pid, | ||||||||||||||||||||||||||||||||||||||||||||||
| tid, | ||||||||||||||||||||||||||||||||||||||||||||||
| langs: langs.join(','), | ||||||||||||||||||||||||||||||||||||||||||||||
| beginAtDate, | ||||||||||||||||||||||||||||||||||||||||||||||
| beginAtTime, | ||||||||||||||||||||||||||||||||||||||||||||||
| endAtDate, | ||||||||||||||||||||||||||||||||||||||||||||||
| endAtTime, | ||||||||||||||||||||||||||||||||||||||||||||||
| status: status.join(','), | ||||||||||||||||||||||||||||||||||||||||||||||
| highPriority, | ||||||||||||||||||||||||||||||||||||||||||||||
| apply: _apply, | ||||||||||||||||||||||||||||||||||||||||||||||
| recordLength: rdocs.length, | ||||||||||||||||||||||||||||||||||||||||||||||
| rrdocs: await record.getMultiRejudgeTask(undefined, {}), | ||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use consistent variable naming Same issue as above - maintain consistent naming convention. - rrdocs: await record.getMultiRejudgeTask(undefined, {}),
+ tasks: await record.getMultiRejudgeTask(undefined, {}),📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||
| this.response.template = 'manage_rejudge.html'; | ||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| const rid = await record.addRejudgeTask(domainId, { | ||||||||||||||||||||||||||||||||||||||||||||||
| owner: this.user._id, | ||||||||||||||||||||||||||||||||||||||||||||||
| apply: _apply, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+448
to
+451
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add count field when creating rejudge task The rejudge task should include a count of records to be rejudged. const rid = await record.addRejudgeTask(domainId, {
owner: this.user._id,
apply: _apply,
+ count: rdocs.length,
});📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
| 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(), | ||||||||||||||||||||||||||||||||||||||||||||||
| }))); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+453
to
+463
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix conditional logic for history insertion The current logic creates history records when NOT applying ( The history insertion should happen before rejudging to preserve the original state: - 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(),
- })));
- }
+ // Always preserve history before rejudging
+ 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(),
+ })));
+
+ if (_apply) await record.reset(domainId, rdocs.map((rdoc) => rdoc._id), true);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
| await Promise.all([ | ||||||||||||||||||||||||||||||||||||||||||||||
| record.judge(domainId, rdocs.filter((i) => i.contest).map((i) => i._id), priority, { detail: false }, | ||||||||||||||||||||||||||||||||||||||||||||||
| { rejudge: _apply ? true : 'controlled' }), | ||||||||||||||||||||||||||||||||||||||||||||||
| record.judge(domainId, rdocs.filter((i) => !i.contest).map((i) => i._id), priority, {}, | ||||||||||||||||||||||||||||||||||||||||||||||
| { rejudge: _apply ? true : 'controlled' }), | ||||||||||||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||||||||||||
| this.response.redirect = this.url('manage_rejudge_detail', { rid }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| class SystemRejudgeDetailHandler extends SystemHandler { | ||||||||||||||||||||||||||||||||||||||||||||||
| @param('rid', Types.ObjectId) | ||||||||||||||||||||||||||||||||||||||||||||||
| async get(domainId: string, rid: ObjectId) { | ||||||||||||||||||||||||||||||||||||||||||||||
| 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, rdocs }; | ||||||||||||||||||||||||||||||||||||||||||||||
| this.response.template = 'manage_rejudge_detail.html'; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| export const inject = ['config', 'check']; | ||||||||||||||||||||||||||||||||||||||||||||||
| export async function apply(ctx) { | ||||||||||||||||||||||||||||||||||||||||||||||
| ctx.Route('manage', '/manage', SystemMainHandler); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -366,5 +491,7 @@ export async function apply(ctx) { | |||||||||||||||||||||||||||||||||||||||||||||
| ctx.Route('manage_config', '/manage/config', SystemConfigHandler); | ||||||||||||||||||||||||||||||||||||||||||||||
| ctx.Route('manage_user_import', '/manage/userimport', SystemUserImportHandler); | ||||||||||||||||||||||||||||||||||||||||||||||
| ctx.Route('manage_user_priv', '/manage/userpriv', SystemUserPrivHandler); | ||||||||||||||||||||||||||||||||||||||||||||||
| ctx.Route('manage_rejudge', '/manage/rejudge', SystemRejudgeHandler); | ||||||||||||||||||||||||||||||||||||||||||||||
| ctx.Route('manage_rejudge_detail', '/manage/rejudge/:rid', SystemRejudgeDetailHandler); | ||||||||||||||||||||||||||||||||||||||||||||||
| ctx.Connection('manage_check', '/manage/check-conn', SystemCheckConnHandler); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,11 +8,12 @@ import { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ProblemConfigFile } from '@hydrooj/common'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Context } from '../context'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ProblemNotFoundError } from '../error'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { JudgeMeta, RecordDoc } from '../interface'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { JudgeMeta, RecordDoc, RecordRejudgeDoc } from '../interface'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -21,6 +22,7 @@ export default class RecordModel { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static coll = db.collection('record'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static collStat = db.collection('record.stat'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static collHistory = db.collection('record.history'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static collRejudge = db.collection('record.rejudge'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static PROJECTION_LIST: (keyof RecordDoc)[] = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '_id', 'score', 'time', 'memory', 'lang', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'uid', 'pid', 'rejudged', 'progress', 'domainId', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -280,6 +282,30 @@ export default class RecordModel { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const rdoc of rdocs) r[rdoc._id.toHexString()] = rdoc; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return r; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static async getMultiRejudgeTask(domainId: string | undefined, query: Filter<RecordRejudgeDoc>) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return document.getMulti(domainId, document.TYPE_REJUDGE, query).toArray(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static async getRejudgeTask(domainId: string, _id: ObjectId) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return document.get(domainId, document.TYPE_REJUDGE, _id); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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, newStatus: number, newScore: number, newRev) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add type annotation for the newRev parameter - static async pushRejudgeResult(rrid: ObjectId, newStatus: number, newScore: number, newRev) {
+ static async pushRejudgeResult(rrid: ObjectId, newStatus: number, newScore: number, newRev: ObjectId) {📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await RecordModel.collRejudge.updateOne({ _id: rrid }, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $set: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newStatus, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newScore, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newRev, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| upsert: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+298
to
+308
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Method name doesn't reflect its actual behavior The method name Consider renaming the method to better reflect its behavior: - static async pushRejudgeResult(rrid: ObjectId, newStatus: number, newScore: number, newRev: ObjectId) {
+ static async upsertRejudgeResult(rrid: ObjectId, newStatus: number, newScore: number, newRev: ObjectId) {📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export async function apply(ctx: Context) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -327,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; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,24 @@ | ||||||||||||||||||||||||
| import { STATUS_TEXTS } from '@hydrooj/common'; | ||||||||||||||||||||||||
| import $ from 'jquery'; | ||||||||||||||||||||||||
| import CustomSelectAutoComplete from 'vj/components/autocomplete/CustomSelectAutoComplete'; | ||||||||||||||||||||||||
| import ProblemSelectAutoComplete from 'vj/components/autocomplete/ProblemSelectAutoComplete'; | ||||||||||||||||||||||||
| import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete'; | ||||||||||||||||||||||||
| import { NamedPage } from 'vj/misc/Page'; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const page = new NamedPage('manage_rejudge', async () => { | ||||||||||||||||||||||||
| UserSelectAutoComplete.getOrConstruct($('[name="uidOrName"]'), { | ||||||||||||||||||||||||
| clearDefaultValue: false, | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
| ProblemSelectAutoComplete.getOrConstruct($('[name="pid"]'), { | ||||||||||||||||||||||||
| clearDefaultValue: false, | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
| const prefixes = new Set(Object.keys(window.LANGS).filter((i) => i.includes('.')).map((i) => i.split('.')[0])); | ||||||||||||||||||||||||
| const langs = Object.keys(window.LANGS).filter((i) => !prefixes.has(i)).map((i) => ( | ||||||||||||||||||||||||
| { name: `${i.includes('.') ? `${window.LANGS[i.split('.')[0]].display}/` : ''}${window.LANGS[i].display}`, _id: i } | ||||||||||||||||||||||||
| )); | ||||||||||||||||||||||||
|
Comment on lines
+15
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Review the language filtering logic The current logic filters out base languages (like 'cpp') if any variant (like 'cpp.11') exists. This could lead to missing language options in the dropdown. Consider this alternative approach to include all languages properly: - const prefixes = new Set(Object.keys(window.LANGS).filter((i) => i.includes('.')).map((i) => i.split('.')[0]));
- const langs = Object.keys(window.LANGS).filter((i) => !prefixes.has(i)).map((i) => (
- { name: `${i.includes('.') ? `${window.LANGS[i.split('.')[0]].display}/` : ''}${window.LANGS[i].display}`, _id: i }
- ));
+ const langs = Object.keys(window.LANGS).map((i) => {
+ const parts = i.split('.');
+ const displayName = parts.length > 1
+ ? `${window.LANGS[parts[0]].display}/${window.LANGS[i].display}`
+ : window.LANGS[i].display;
+ return { name: displayName, _id: i };
+ });📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| CustomSelectAutoComplete.getOrConstruct($('[name=lang]'), { multi: true, data: langs }); | ||||||||||||||||||||||||
| const statuses = Object.entries(STATUS_TEXTS).map(([i, j]) => ({ name: j, _id: i })); | ||||||||||||||||||||||||
| CustomSelectAutoComplete.getOrConstruct($('[name=status]'), { multi: true, data: statuses }); | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| export default page; | ||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use consistent variable naming for rejudge task documents
The variable name
rrdocssuggests "rejudge result documents" but it's actually storing rejudge task documents.📝 Committable suggestion
🤖 Prompt for AI Agents