From 9efcdf944109ceeced9f7d2ea6fe5bca6a7f75d9 Mon Sep 17 00:00:00 2001 From: undefined Date: Sat, 18 Jul 2020 13:10:04 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E4=B8=80PostJudge=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.js | 1 + hydro/handler/judge.ts | 74 ++++++++++++------- hydro/handler/manage.ts | 12 +-- hydro/handler/problem.ts | 9 ++- hydro/handler/record.ts | 22 ++++-- hydro/interface.ts | 24 ++++++ hydro/script/rating.ts | 12 +-- hydro/service/server.ts | 2 + ui/pages/judge_playground.page.js | 118 ------------------------------ 9 files changed, 108 insertions(+), 166 deletions(-) delete mode 100644 ui/pages/judge_playground.page.js diff --git a/.eslintrc.js b/.eslintrc.js index 22a72819d..59dfb06e8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -33,6 +33,7 @@ module.exports = { 'no-return-await': 'off', 'no-underscore-dangle': 'off', 'no-unused-vars': 'off', + 'prefer-destructuring': 'off', }, settings: { 'import/parsers': { diff --git a/hydro/handler/judge.ts b/hydro/handler/judge.ts index 73e8cda3d..74615ad1c 100644 --- a/hydro/handler/judge.ts +++ b/hydro/handler/judge.ts @@ -1,6 +1,7 @@ import yaml from 'js-yaml'; import { ObjectID } from 'mongodb'; import { parseTimeMS, parseMemoryMB } from '../utils'; +import { JudgeResultBody, Rdoc } from '../interface'; import * as record from '../model/record'; import * as problem from '../model/problem'; import * as builtin from '../model/builtin'; @@ -12,12 +13,31 @@ import { Route, Handler, Connection, ConnectionHandler, Types, param, } from '../service/server'; -async function _postJudge(rdoc) { +interface _PostJudgeBody { + status: number, + domainId: string, + uid: number, + _id: ObjectID, + pid: number, + score: number, + rejudged: boolean, +} + +interface PostJudgeBodyContest extends _PostJudgeBody { + tid: ObjectID, + ttype: number, +} + +type PostJudgeBody = _PostJudgeBody | PostJudgeBodyContest; + +function _isWithContest(v: PostJudgeBody): v is PostJudgeBodyContest { + return !!((v as PostJudgeBodyContest).tid); +} + +async function _postJudge(rdoc: PostJudgeBody) { const accept = rdoc.status === builtin.STATUS.STATUS_ACCEPTED; - bus.publish('record_change', rdoc); - if (rdoc.type === 'run') return; const tasks = []; - if (rdoc.tid) { + if (_isWithContest(rdoc)) { tasks.push( contest.updateStatus( rdoc.domainId, rdoc.tid, rdoc.uid, @@ -36,7 +56,7 @@ async function _postJudge(rdoc) { await Promise.all(tasks); } -export async function next(body) { +export async function next(body: JudgeResultBody) { if (body.rid) body.rid = new ObjectID(body.rid); if (body.tid) body.tid = new ObjectID(body.tid); let rdoc = await record.get(body.domainId, body.rid); @@ -44,56 +64,56 @@ export async function next(body) { const $push: any = {}; if (body.case) { const c: any = {}; - c.memory = body.case.memory_kb || body.case.memory; - c.time = body.case.time_ms || body.case.time; - c.judgeText = body.case.judge_text || body.case.judgeText || body.case.message; + c.memory = body.case.memory; + c.time = body.case.time; + c.message = body.case.message; c.status = body.case.status; rdoc.testCases.push(c); $push.testCases = c; } - if (body.judge_text || body.message) { - rdoc.judgeTexts.push(body.judge_text || body.message); - $push.judgeTexts = body.judge_text || body.message; + if (body.message) { + rdoc.judgeTexts.push(body.message); + $push.judgeTexts = body.message; } - if (body.compiler_text) { - rdoc.compilerTexts.push(body.compiler_text); - $push.compilerTexts = body.compiler_text; + if (body.compilerText) { + rdoc.compilerTexts.push(body.compilerText); + $push.compilerTexts = body.compilerText; } if (body.status) $set.status = body.status; if (body.score) $set.score = body.score; - if (body.time_ms) $set.time = body.time_ms || body.time; - if (body.memory_kb) $set.memory = body.memory_kb || body.memory; + if (body.time) $set.time = body.time; + if (body.memory) $set.memory = body.memory; if (body.progress) $set.progress = body.progress; rdoc = await record.update(body.domainId, body.rid, $set, $push); - bus.publish('record_change', rdoc); + bus.publish('record_change', { rdoc, $set, $push }); } -export async function end(body) { +export async function end(body: JudgeResultBody) { if (body.rid) body.rid = new ObjectID(body.rid); if (body.tid) body.tid = new ObjectID(body.tid); let rdoc = await record.get(body.domainId, body.rid); const $set: any = {}; const $push: any = {}; const $unset = { progress: '' }; - if (body.judge_text) { - rdoc.judgeTexts.push(body.judge_text); - $push.judgeTexts = body.judge_text; + if (body.message) { + rdoc.judgeTexts.push(body.message); + $push.judgeTexts = body.message; } - if (body.compiler_text) { - rdoc.compilerTexts.push(body.compiler_text); - $push.compilerTexts = body.compiler_text; + if (body.compilerText) { + rdoc.compilerTexts.push(body.compilerText); + $push.compilerTexts = body.compilerText; } if (body.status) $set.status = body.status; if (body.score) $set.score = body.score; if (body.stdout) $set.stdout = body.stdout; if (body.stderr) $set.stderr = body.stderr; - if (body.time_ms) $set.time = body.time_ms; - if (body.memory_kb) $set.memory = body.memory_kb; + if (body.time) $set.time = body.time; + if (body.memory) $set.memory = body.memory; $set.judgeAt = new Date(); $set.judger = body.judger; rdoc = await record.update(body.domainId, body.rid, $set, $push, $unset); await _postJudge(rdoc); - rdoc = await record.update(body.domainId, body.rid, $set, $push); + bus.publish('record_change', { rdoc }); // trigger a full update } class PretestHandler extends Handler { diff --git a/hydro/handler/manage.ts b/hydro/handler/manage.ts index 7657a2f6f..65c9e1e37 100644 --- a/hydro/handler/manage.ts +++ b/hydro/handler/manage.ts @@ -128,10 +128,10 @@ class SystemScriptHandler extends SystemHandler { domainId, rid, status: STATUS.STATUS_ACCEPTED, - judge_text: ret.toString(), + message: ret.toString(), judger: 1, - time_ms: time, - memory_kb: 0, + time, + memory: 0, }); }) .catch((err: Error) => { @@ -140,10 +140,10 @@ class SystemScriptHandler extends SystemHandler { domainId, rid, status: STATUS.STATUS_SYSTEM_ERROR, - judge_text: `${err}\n${err.stack}`, + message: `${err}\n${err.stack}`, judger: 1, - time_ms: time, - memory_kb: 0, + time, + memory: 0, }); }); }, 300); diff --git a/hydro/handler/problem.ts b/hydro/handler/problem.ts index 5a3efbd94..224ce5123 100644 --- a/hydro/handler/problem.ts +++ b/hydro/handler/problem.ts @@ -254,6 +254,7 @@ class ProblemPretestConnectionHandler extends ConnectionHandler { @param('pid', Types.String) async prepare(domainId: string, pid: string) { const pdoc = await problem.get(domainId, pid); + if (pdoc.hidden) this.checkPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN); if (!pdoc) throw new ProblemNotFoundError(domainId, pid); this.pid = pdoc.docId.toString(); this.domainId = domainId; @@ -261,12 +262,18 @@ class ProblemPretestConnectionHandler extends ConnectionHandler { } async onRecordChange(data) { - const rdoc: Rdoc = data.value; + const rdoc: Rdoc = data.value.rdoc; if ( rdoc.uid !== this.user._id || rdoc.pid.toString() !== this.pid || rdoc.domainId !== this.domainId ) return; + rdoc.compilerTexts = []; + rdoc.judgeTexts = []; + // @ts-ignore + rdoc.testCases = rdoc.testCases.map((c) => ({ + status: c.status, + })); if (rdoc.tid) return; this.send({ rdoc }); } diff --git a/hydro/handler/record.ts b/hydro/handler/record.ts index 2e50f51f0..766d40a49 100644 --- a/hydro/handler/record.ts +++ b/hydro/handler/record.ts @@ -11,6 +11,7 @@ import * as bus from '../service/bus'; import { Route, Handler, Connection, ConnectionHandler, Types, param, } from '../service/server'; +import { Rdoc } from '../interface'; const RecordHandler = contest.ContestHandlerMixin(Handler); @@ -117,8 +118,9 @@ class RecordMainConnectionHandler extends RecordConnectionHandler { async message(msg) { if (msg.rids instanceof Array) { + const rids = msg.rids.map((id: string) => new ObjectID(id)); const rdocs = await record.getMulti( - this.domainId, { _id: { $in: msg.rids.map((id) => new ObjectID(id)) } }, + this.domainId, { _id: { $in: rids } }, ).toArray(); for (const rdoc of rdocs) { this.onRecordChange({ value: rdoc }); @@ -131,7 +133,7 @@ class RecordMainConnectionHandler extends RecordConnectionHandler { } async onRecordChange(data) { - const rdoc = data.value; + const rdoc: Rdoc = data.value.rdoc; if (rdoc.tid && rdoc.tid.toString() !== this.tid) return; // eslint-disable-next-line prefer-const let [udoc, pdoc] = await Promise.all([ @@ -139,7 +141,7 @@ class RecordMainConnectionHandler extends RecordConnectionHandler { problem.get(this.domainId, rdoc.pid, null, false), ]); if (pdoc && pdoc.hidden && !this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) pdoc = null; - this.send({ html: await this.renderHTML('record_main_tr.html', { rdoc, udoc, pdoc }) }); + else this.send({ html: await this.renderHTML('record_main_tr.html', { rdoc, udoc, pdoc }) }); } } @@ -160,12 +162,16 @@ class RecordDetailConnectionHandler extends contest.ContestHandlerMixin(Connecti } async onRecordChange(data) { - const rdoc = data.value; + const rdoc: Rdoc = data.value.rdoc; + const { $set, $push } = data.value; if (rdoc._id.toString() !== this.rid) return; - this.send({ - status_html: await this.renderHTML('record_detail_status.html', { rdoc }), - summary_html: await this.renderHTML('record_detail_summary.html', { rdoc }), - }); + if ($set) this.send({ $set, $push }); + else { + this.send({ + status_html: await this.renderHTML('record_detail_status.html', { rdoc }), + summary_html: await this.renderHTML('record_detail_summary.html', { rdoc }), + }); + } } async cleanup() { diff --git a/hydro/interface.ts b/hydro/interface.ts index b64c0491b..23ee129ef 100644 --- a/hydro/interface.ts +++ b/hydro/interface.ts @@ -199,6 +199,30 @@ export interface Script { validate: any, } +export interface JudgeResultBody { + domainId: string, + rid: ObjectID, + judger?: number, + tid?: ObjectID, + progress?: number + case?: { + status: number, + time: number, + memory: number, + message?: string, + }, + status?: number, + score?: number, + time?: number, + memory?: number, + message?: string, + compilerText?: string, + + // For pretest + stdout?: string, + stderr?: string, +} + declare global { namespace NodeJS { interface Global { diff --git a/hydro/script/rating.ts b/hydro/script/rating.ts index 97bb1d957..c003e1f52 100644 --- a/hydro/script/rating.ts +++ b/hydro/script/rating.ts @@ -64,9 +64,9 @@ async function runContest(...arg: Array) { await report({ case: { status: STATUS.STATUS_ACCEPTED, - judgeText: `Contest ${tdoc.title} finished`, - time_ms: new Date().getTime() - start, - memory_kb: 0, + message: `Contest ${tdoc.title} finished`, + time: new Date().getTime() - start, + memory: 0, score: 0, }, }); @@ -115,9 +115,9 @@ export async function run({ domainId }, report: Function) { await report({ case: { status: STATUS.STATUS_ACCEPTED, - judgeText: `Domain ${domains[i]._id} finished`, - time_ms: new Date().getTime() - start, - memory_kb: 0, + message: `Domain ${domains[i]._id} finished`, + time: new Date().getTime() - start, + memory: 0, score: 0, }, progress: Math.floor(((parseInt(i, 10) + 1) / domains.length) * 100), diff --git a/hydro/service/server.ts b/hydro/service/server.ts index e5360cf5e..94e747194 100644 --- a/hydro/service/server.ts +++ b/hydro/service/server.ts @@ -700,6 +700,8 @@ export class ConnectionHandler { this.conn.close(code.toString(), reason); } + async message(message: any) { } // eslint-disable-line + onerror(err: HydroError) { console.error(err); this.send({ diff --git a/ui/pages/judge_playground.page.js b/ui/pages/judge_playground.page.js deleted file mode 100644 index 35c6ca191..000000000 --- a/ui/pages/judge_playground.page.js +++ /dev/null @@ -1,118 +0,0 @@ -import { NamedPage } from 'vj/misc/PageLoader'; - -import * as recordEnum from 'vj/constant/record'; - -const page = new NamedPage('judge_playground', async () => { - const { default: SockJs } = await import('../components/socket'); - - const sock = new SockJs(`/judge/consume-conn?token=${UiContext.token}`); - sock.onopen = () => { - const div = $('
').appendTo('#messages'); - $('

Connection opened.

') - .appendTo(div); - }; - - sock.onmessage = (message) => { - const msg = JSON.parse(message.data); - const div = $('
').appendTo('#messages'); - $('

Record

') - .appendTo(div); - const body = $('
').text(message.data).appendTo(div); - - const send = (key, packet) => { - const data = { - ...packet, - key, - tag: msg.tag, - }; - sock.send(JSON.stringify(data)); - }; - - $('