diff --git a/packages/hydrooj/src/handler/judge.ts b/packages/hydrooj/src/handler/judge.ts index fc93790bf..fd8da0c91 100644 --- a/packages/hydrooj/src/handler/judge.ts +++ b/packages/hydrooj/src/handler/judge.ts @@ -98,48 +98,48 @@ export async function postJudge(rdoc: RecordDoc) { const pdoc = (accept && updated) ? await problem.inc(rdoc.domainId, rdoc.pid, 'nAccept', 1) : await problem.get(rdoc.domainId, rdoc.pid, undefined, true); - if (pdoc) { - if (isNormalSubmission) { - await Promise.all([ - problem.inc(pdoc.domainId, pdoc.docId, `stats.${builtin.STATUS_SHORT_TEXTS[rdoc.status]}`, 1), - problem.inc(pdoc.domainId, pdoc.docId, `stats.s${Math.floor(rdoc.score)}`, 1), - ]); - } - if (rdoc.status === STATUS.STATUS_HACK_SUCCESSFUL) { - try { - const config = yaml.load(pdoc.config as string) as ProblemConfigFile; - assert(config.subtasks instanceof Array); - const file = await storage.get(`submission/${rdoc.files.hack.split('#')[0]}`); - assert(file); - const hackSubtask = config.subtasks[config.subtasks.length - 1]; - hackSubtask.cases ||= []; - const input = `hack-${rdoc._id}-${hackSubtask.cases.length + 1}.in`; - hackSubtask.cases.push({ input, output: '/dev/null' }); - await Promise.all([ - problem.addTestdata(rdoc.domainId, rdoc.pid, input, file), - problem.addTestdata(rdoc.domainId, rdoc.pid, 'config.yaml', Buffer.from(yaml.dump(config))), - ]); - // trigger rejudge - const rdocs = await record.getMulti(rdoc.domainId, { - pid: rdoc.pid, - status: STATUS.STATUS_ACCEPTED, - contest: { $nin: [record.RECORD_GENERATE, record.RECORD_PRETEST] }, - }).project({ _id: 1, contest: 1 }).toArray(); - const priority = await record.submissionPriority(rdoc.uid, -5000 - rdocs.length * 5 - 50); - await record.judge(rdoc.domainId, rdocs.map((r) => r._id), priority, {}, { hackRejudge: input }); - } catch (e) { - next({ - rid: rdoc._id, - domainId: rdoc.domainId, - key: 'next', - message: { message: 'Unable to apply hack: {0}', params: [e.message] }, - }); - } - } + if (pdoc && isNormalSubmission) { + await Promise.all([ + problem.inc(pdoc.domainId, pdoc.docId, `stats.${builtin.STATUS_SHORT_TEXTS[rdoc.status]}`, 1), + problem.inc(pdoc.domainId, pdoc.docId, `stats.s${Math.floor(rdoc.score)}`, 1), + ]); } - await bus.parallel('record/judge', rdoc, updated); + await bus.parallel('record/judge', rdoc, updated, pdoc); } +bus.on('record/judge', async (rdoc, updated, pdoc) => { + if (!pdoc || rdoc.status !== STATUS.STATUS_HACK_SUCCESSFUL) return; + try { + const config = yaml.load(pdoc.config as string) as ProblemConfigFile; + assert(config.subtasks instanceof Array); + const file = await storage.get(`submission/${rdoc.files.hack.split('#')[0]}`); + assert(file); + const hackSubtask = config.subtasks[config.subtasks.length - 1]; + hackSubtask.cases ||= []; + const input = `hack-${rdoc._id}-${hackSubtask.cases.length + 1}.in`; + hackSubtask.cases.push({ input, output: '/dev/null' }); + await Promise.all([ + problem.addTestdata(rdoc.domainId, rdoc.pid, input, file), + problem.addTestdata(rdoc.domainId, rdoc.pid, 'config.yaml', Buffer.from(yaml.dump(config))), + ]); + // trigger rejudge + const rdocs = await record.getMulti(rdoc.domainId, { + pid: rdoc.pid, + status: STATUS.STATUS_ACCEPTED, + contest: { $nin: [record.RECORD_GENERATE, record.RECORD_PRETEST] }, + }).project({ _id: 1, contest: 1 }).toArray(); + const priority = await record.submissionPriority(rdoc.uid, -5000 - rdocs.length * 5 - 50); + await record.judge(rdoc.domainId, rdocs.map((r) => r._id), priority, {}, { hackRejudge: input }); + } catch (e) { + next({ + rid: rdoc._id, + domainId: rdoc.domainId, + key: 'next', + message: { message: 'Unable to apply hack: {0}', params: [e.message] }, + }); + } +}); + export async function end(body: Partial) { body.rid = new ObjectId(body.rid); // TODO remove this const { $set, $push } = processPayload(body); diff --git a/packages/hydrooj/src/service/bus.ts b/packages/hydrooj/src/service/bus.ts index 25e5f442d..114e9105d 100644 --- a/packages/hydrooj/src/service/bus.ts +++ b/packages/hydrooj/src/service/bus.ts @@ -104,7 +104,7 @@ export interface EventMap extends LifecycleEvents, HandlerEvents { 'training/get': (tdoc: TrainingDoc, handler: any) => VoidReturn 'record/change': (rdoc: RecordDoc, $set?: any, $push?: any, body?: any) => void - 'record/judge': (rdoc: RecordDoc, updated: boolean) => VoidReturn + 'record/judge': (rdoc: RecordDoc, updated: boolean, pdoc?: ProblemDoc) => VoidReturn } /* eslint-enable @typescript-eslint/naming-convention */