diff --git a/package-lock.json b/package-lock.json index 643b69d..304878a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -250,6 +250,14 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=" }, + "ansi-to-html": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.3.tgz", + "integrity": "sha512-EAhxLited8575DW57wt0csRYUrwjpNErgOPc5KJIyY7YD41AuqBy9CAuWyuQYLPUUtmoPzHYxgFKGPniKpgEig==", + "requires": { + "entities": "1.1.1" + } + }, "argparse": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", @@ -649,6 +657,11 @@ "has-binary2": "1.0.2" } }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", diff --git a/package.json b/package.json index 81323e5..e809108 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "license": "GPL-3.0", "dependencies": { "amqplib": "^0.5.1", + "ansi-to-html": "^0.6.3", "bluebird": "^3.5.0", "body-parser": "^1.17.2", "command-line-args": "^4.0.6", diff --git a/src/daemon-frontend-syzoj/socketio.ts b/src/daemon-frontend-syzoj/socketio.ts index d1fc8ba..3b88125 100644 --- a/src/daemon-frontend-syzoj/socketio.ts +++ b/src/daemon-frontend-syzoj/socketio.ts @@ -42,6 +42,9 @@ export function initializeSocketIO(s: http.Server) { let req; try { req = jwt.verify(reqJwt, Cfg.token); + if (req.type !== 'detail') { + throw new Error("Request type in token mismatch."); + } } catch (err) { cb({ ok: false, @@ -60,7 +63,7 @@ export function initializeSocketIO(s: http.Server) { cb({ ok: true, finished: false, - current: currentJudgeList[taskId] + current: currentJudgeList[taskId] || { running: false } }); } }); @@ -71,6 +74,9 @@ export function initializeSocketIO(s: http.Server) { let req; try { req = jwt.verify(reqJwt, Cfg.token); + if (req.type !== 'rough') { + throw new Error("Request type in token mismatch."); + } } catch (err) { cb({ ok: false, @@ -110,6 +116,9 @@ export function initializeSocketIO(s: http.Server) { let req; try { req = jwt.verify(reqJwt, Cfg.token); + if (req.type !== 'compile') { + throw new Error("Request type in token mismatch."); + } } catch (err) { cb({ ok: false, @@ -141,7 +150,6 @@ export function initializeSocketIO(s: http.Server) { }); } - export function createTask(taskId: number) { detailProgressNamespace.to(taskId.toString()).emit("start", { taskId: taskId }); roughProgressNamespace.to(taskId.toString()).emit("start", { taskId: taskId }); diff --git a/src/daemon/judge/judger-base.ts b/src/daemon/judge/judger-base.ts index 6ccb9b0..97a8a47 100644 --- a/src/daemon/judge/judger-base.ts +++ b/src/daemon/judge/judger-base.ts @@ -38,7 +38,7 @@ export abstract class JudgerBase { status: TaskStatus.Waiting })); const reportProgress = function () { - reportProgressResult({ status: TaskStatus.Running, subtasks: results }); + reportProgressResult({ subtasks: results }); } winston.debug(`Totally ${results.length} subtasks.`); @@ -61,7 +61,6 @@ export abstract class JudgerBase { try { const taskJudge = await this.judgeTestcase(currentTask.cases[index], async () => { currentTaskResult.status = TaskStatus.Running; - currentResult.status = TaskStatus.Running; await reportProgress(); }); currentTaskResult.status = TaskStatus.Done; @@ -89,7 +88,6 @@ export abstract class JudgerBase { try { currentTaskResult.result = await this.judgeTestcase(currentTask.cases[index], async () => { currentTaskResult.status = TaskStatus.Running; - currentResult.status = TaskStatus.Running; await reportProgress(); }); currentTaskResult.status = TaskStatus.Done; @@ -106,16 +104,14 @@ export abstract class JudgerBase { if (currentResult.cases.some(c => c.status === TaskStatus.Failed)) { // If any testcase has failed, the score is invaild. currentResult.score = NaN; - currentResult.status = TaskStatus.Failed; } else { currentResult.score = calculateSubtaskScore(currentTask.type, currentResult.cases.map(c => c.result ? c.result.scoringRate : 0)) * currentTask.score; - currentResult.status = TaskStatus.Done; } winston.verbose(`Subtask ${subtaskIndex}, finished`); })()); } await Promise.all(judgeTasks); - return { status: TaskStatus.Done, subtasks: results }; + return { subtasks: results }; } protected abstract judgeTestcase(curCase: TestcaseJudge, started: () => Promise): Promise; } \ No newline at end of file diff --git a/src/daemon/judge/standard.ts b/src/daemon/judge/standard.ts index 1e389f8..a48dd52 100644 --- a/src/daemon/judge/standard.ts +++ b/src/daemon/judge/standard.ts @@ -4,7 +4,6 @@ import { globalConfig as Cfg } from '../config'; import { cloneObject, readFileLength } from '../../utils'; import { compile } from './compile'; import { Language, getLanguage } from '../../languages'; -import { processJudgement } from './process' import { runTask } from '../rmq'; import { JudgerBase } from './judger-base'; diff --git a/src/daemon/testData.ts b/src/daemon/testData.ts index 5921851..9b13333 100644 --- a/src/daemon/testData.ts +++ b/src/daemon/testData.ts @@ -81,7 +81,7 @@ export async function readRulesFile(dataName: string): Promise { const dataPath = pathLib.join(Cfg.testDataDirectory, dataName); let fileContent = await tryReadFile(pathLib.join(dataPath, 'data.yml')); if (fileContent != null) { - return parseYamlContent(yaml.safeLoad(fileContent), dataPath); + return parseYamlContent(yaml.safeLoad(fileContent), dataName); } else { // No data.yml let spj: Executable = null; for (const lang of languages) { diff --git a/src/interfaces.ts b/src/interfaces.ts index 52e279c..c175d88 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -37,7 +37,6 @@ export interface TestcaseResult { } export interface SubtaskResult { - status: TaskStatus; score?: number; cases: TestcaseResult[]; } @@ -53,7 +52,6 @@ export interface CompilationResult { } export interface JudgeResult { - status: TaskStatus; subtasks?: SubtaskResult[]; } @@ -97,15 +95,15 @@ export enum TaskStatus { export enum TestcaseResultType { Accepted = 1, - WrongAnswer, - PartiallyCorrect, - MemoryLimitExceeded, - TimeLimitExceeded, - OutputLimitExceeded, - FileError, // The output file does not exist - RuntimeError, - JudgementFailed, // Special Judge or Interactor fails - InvalidInteraction + WrongAnswer = 2, + PartiallyCorrect = 3, + MemoryLimitExceeded = 4, + TimeLimitExceeded = 5, + OutputLimitExceeded = 6, + FileError = 7, // The output file does not exist + RuntimeError = 8, + JudgementFailed = 9, // Special Judge or Interactor fails + InvalidInteraction = 10 } export interface FileContent { diff --git a/src/judgeResult.ts b/src/judgeResult.ts index d64feb8..72e6c17 100644 --- a/src/judgeResult.ts +++ b/src/judgeResult.ts @@ -61,7 +61,7 @@ export function convertResult(id: number, source: OverallResult): JudgeResultSub time = forEveryTestcase(c => c.time, _.sum); memory = forEveryTestcase(c => c.memory, _.max); - if (source.judge.subtasks.some(s => s.status === TaskStatus.Failed)) { + if (source.judge.subtasks.some(s => s.cases.some(c => c.status === TaskStatus.Failed))) { winston.debug(`Some subtasks failed, returning system error`); statusString = systemError; } else { diff --git a/src/runner/compile.ts b/src/runner/compile.ts index cbf4754..a8ac17d 100644 --- a/src/runner/compile.ts +++ b/src/runner/compile.ts @@ -3,6 +3,7 @@ import fse = require('fs-extra'); import randomString = require('randomstring'); import bluebird = require('bluebird'); import getFolderSize = require('get-folder-size'); +import AnsiToHtml = require('ansi-to-html'); import { CompileTask, CompilationResult, TaskStatus } from '../interfaces'; import { globalConfig as Cfg } from './config'; @@ -14,6 +15,7 @@ import { readFileLength } from '../utils'; import { pushBinary } from './executable'; const getSize: any = bluebird.promisify(getFolderSize); +const convert = new AnsiToHtml({ escapeXML: true }); export async function compile(task: CompileTask): Promise { const srcDir = pathLib.join(Cfg.workingDirectory, `src`); @@ -75,7 +77,7 @@ export async function compile(task: CompileTask): Promise { } else { // If compilation error return { status: TaskStatus.Failed, - message: await readFileLength(pathLib.join(binDir, compileConfig.messageFile), Cfg.compilerMessageLimit) + message: convert.toHtml(await readFileLength(pathLib.join(binDir, compileConfig.messageFile), Cfg.compilerMessageLimit)) }; } } else {