Browse Source

Finish!

master
t123yh 7 years ago
parent
commit
5523af45bd
  1. 13
      package-lock.json
  2. 1
      package.json
  3. 12
      src/daemon-frontend-syzoj/socketio.ts
  4. 8
      src/daemon/judge/judger-base.ts
  5. 1
      src/daemon/judge/standard.ts
  6. 2
      src/daemon/testData.ts
  7. 20
      src/interfaces.ts
  8. 2
      src/judgeResult.ts
  9. 4
      src/runner/compile.ts

13
package-lock.json generated

@ -250,6 +250,14 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz",
"integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=" "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": { "argparse": {
"version": "1.0.9", "version": "1.0.9",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
@ -649,6 +657,11 @@
"has-binary2": "1.0.2" "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": { "escape-html": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",

1
package.json

@ -7,6 +7,7 @@
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"amqplib": "^0.5.1", "amqplib": "^0.5.1",
"ansi-to-html": "^0.6.3",
"bluebird": "^3.5.0", "bluebird": "^3.5.0",
"body-parser": "^1.17.2", "body-parser": "^1.17.2",
"command-line-args": "^4.0.6", "command-line-args": "^4.0.6",

12
src/daemon-frontend-syzoj/socketio.ts

@ -42,6 +42,9 @@ export function initializeSocketIO(s: http.Server) {
let req; let req;
try { try {
req = jwt.verify(reqJwt, Cfg.token); req = jwt.verify(reqJwt, Cfg.token);
if (req.type !== 'detail') {
throw new Error("Request type in token mismatch.");
}
} catch (err) { } catch (err) {
cb({ cb({
ok: false, ok: false,
@ -60,7 +63,7 @@ export function initializeSocketIO(s: http.Server) {
cb({ cb({
ok: true, ok: true,
finished: false, finished: false,
current: currentJudgeList[taskId] current: currentJudgeList[taskId] || { running: false }
}); });
} }
}); });
@ -71,6 +74,9 @@ export function initializeSocketIO(s: http.Server) {
let req; let req;
try { try {
req = jwt.verify(reqJwt, Cfg.token); req = jwt.verify(reqJwt, Cfg.token);
if (req.type !== 'rough') {
throw new Error("Request type in token mismatch.");
}
} catch (err) { } catch (err) {
cb({ cb({
ok: false, ok: false,
@ -110,6 +116,9 @@ export function initializeSocketIO(s: http.Server) {
let req; let req;
try { try {
req = jwt.verify(reqJwt, Cfg.token); req = jwt.verify(reqJwt, Cfg.token);
if (req.type !== 'compile') {
throw new Error("Request type in token mismatch.");
}
} catch (err) { } catch (err) {
cb({ cb({
ok: false, ok: false,
@ -141,7 +150,6 @@ export function initializeSocketIO(s: http.Server) {
}); });
} }
export function createTask(taskId: number) { export function createTask(taskId: number) {
detailProgressNamespace.to(taskId.toString()).emit("start", { taskId: taskId }); detailProgressNamespace.to(taskId.toString()).emit("start", { taskId: taskId });
roughProgressNamespace.to(taskId.toString()).emit("start", { taskId: taskId }); roughProgressNamespace.to(taskId.toString()).emit("start", { taskId: taskId });

8
src/daemon/judge/judger-base.ts

@ -38,7 +38,7 @@ export abstract class JudgerBase {
status: TaskStatus.Waiting status: TaskStatus.Waiting
})); }));
const reportProgress = function () { const reportProgress = function () {
reportProgressResult({ status: TaskStatus.Running, subtasks: results }); reportProgressResult({ subtasks: results });
} }
winston.debug(`Totally ${results.length} subtasks.`); winston.debug(`Totally ${results.length} subtasks.`);
@ -61,7 +61,6 @@ export abstract class JudgerBase {
try { try {
const taskJudge = await this.judgeTestcase(currentTask.cases[index], async () => { const taskJudge = await this.judgeTestcase(currentTask.cases[index], async () => {
currentTaskResult.status = TaskStatus.Running; currentTaskResult.status = TaskStatus.Running;
currentResult.status = TaskStatus.Running;
await reportProgress(); await reportProgress();
}); });
currentTaskResult.status = TaskStatus.Done; currentTaskResult.status = TaskStatus.Done;
@ -89,7 +88,6 @@ export abstract class JudgerBase {
try { try {
currentTaskResult.result = await this.judgeTestcase(currentTask.cases[index], async () => { currentTaskResult.result = await this.judgeTestcase(currentTask.cases[index], async () => {
currentTaskResult.status = TaskStatus.Running; currentTaskResult.status = TaskStatus.Running;
currentResult.status = TaskStatus.Running;
await reportProgress(); await reportProgress();
}); });
currentTaskResult.status = TaskStatus.Done; currentTaskResult.status = TaskStatus.Done;
@ -106,16 +104,14 @@ export abstract class JudgerBase {
if (currentResult.cases.some(c => c.status === TaskStatus.Failed)) { if (currentResult.cases.some(c => c.status === TaskStatus.Failed)) {
// If any testcase has failed, the score is invaild. // If any testcase has failed, the score is invaild.
currentResult.score = NaN; currentResult.score = NaN;
currentResult.status = TaskStatus.Failed;
} else { } else {
currentResult.score = calculateSubtaskScore(currentTask.type, currentResult.cases.map(c => c.result ? c.result.scoringRate : 0)) * currentTask.score; 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`); winston.verbose(`Subtask ${subtaskIndex}, finished`);
})()); })());
} }
await Promise.all(judgeTasks); await Promise.all(judgeTasks);
return { status: TaskStatus.Done, subtasks: results }; return { subtasks: results };
} }
protected abstract judgeTestcase(curCase: TestcaseJudge, started: () => Promise<void>): Promise<TestcaseDetails>; protected abstract judgeTestcase(curCase: TestcaseJudge, started: () => Promise<void>): Promise<TestcaseDetails>;
} }

1
src/daemon/judge/standard.ts

@ -4,7 +4,6 @@ import { globalConfig as Cfg } from '../config';
import { cloneObject, readFileLength } from '../../utils'; import { cloneObject, readFileLength } from '../../utils';
import { compile } from './compile'; import { compile } from './compile';
import { Language, getLanguage } from '../../languages'; import { Language, getLanguage } from '../../languages';
import { processJudgement } from './process'
import { runTask } from '../rmq'; import { runTask } from '../rmq';
import { JudgerBase } from './judger-base'; import { JudgerBase } from './judger-base';

2
src/daemon/testData.ts

@ -81,7 +81,7 @@ export async function readRulesFile(dataName: string): Promise<TestData> {
const dataPath = pathLib.join(Cfg.testDataDirectory, dataName); const dataPath = pathLib.join(Cfg.testDataDirectory, dataName);
let fileContent = await tryReadFile(pathLib.join(dataPath, 'data.yml')); let fileContent = await tryReadFile(pathLib.join(dataPath, 'data.yml'));
if (fileContent != null) { if (fileContent != null) {
return parseYamlContent(yaml.safeLoad(fileContent), dataPath); return parseYamlContent(yaml.safeLoad(fileContent), dataName);
} else { // No data.yml } else { // No data.yml
let spj: Executable = null; let spj: Executable = null;
for (const lang of languages) { for (const lang of languages) {

20
src/interfaces.ts

@ -37,7 +37,6 @@ export interface TestcaseResult {
} }
export interface SubtaskResult { export interface SubtaskResult {
status: TaskStatus;
score?: number; score?: number;
cases: TestcaseResult[]; cases: TestcaseResult[];
} }
@ -53,7 +52,6 @@ export interface CompilationResult {
} }
export interface JudgeResult { export interface JudgeResult {
status: TaskStatus;
subtasks?: SubtaskResult[]; subtasks?: SubtaskResult[];
} }
@ -97,15 +95,15 @@ export enum TaskStatus {
export enum TestcaseResultType { export enum TestcaseResultType {
Accepted = 1, Accepted = 1,
WrongAnswer, WrongAnswer = 2,
PartiallyCorrect, PartiallyCorrect = 3,
MemoryLimitExceeded, MemoryLimitExceeded = 4,
TimeLimitExceeded, TimeLimitExceeded = 5,
OutputLimitExceeded, OutputLimitExceeded = 6,
FileError, // The output file does not exist FileError = 7, // The output file does not exist
RuntimeError, RuntimeError = 8,
JudgementFailed, // Special Judge or Interactor fails JudgementFailed = 9, // Special Judge or Interactor fails
InvalidInteraction InvalidInteraction = 10
} }
export interface FileContent { export interface FileContent {

2
src/judgeResult.ts

@ -61,7 +61,7 @@ export function convertResult(id: number, source: OverallResult): JudgeResultSub
time = forEveryTestcase(c => c.time, _.sum); time = forEveryTestcase(c => c.time, _.sum);
memory = forEveryTestcase(c => c.memory, _.max); 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`); winston.debug(`Some subtasks failed, returning system error`);
statusString = systemError; statusString = systemError;
} else { } else {

4
src/runner/compile.ts

@ -3,6 +3,7 @@ import fse = require('fs-extra');
import randomString = require('randomstring'); import randomString = require('randomstring');
import bluebird = require('bluebird'); import bluebird = require('bluebird');
import getFolderSize = require('get-folder-size'); import getFolderSize = require('get-folder-size');
import AnsiToHtml = require('ansi-to-html');
import { CompileTask, CompilationResult, TaskStatus } from '../interfaces'; import { CompileTask, CompilationResult, TaskStatus } from '../interfaces';
import { globalConfig as Cfg } from './config'; import { globalConfig as Cfg } from './config';
@ -14,6 +15,7 @@ import { readFileLength } from '../utils';
import { pushBinary } from './executable'; import { pushBinary } from './executable';
const getSize: any = bluebird.promisify(getFolderSize); const getSize: any = bluebird.promisify(getFolderSize);
const convert = new AnsiToHtml({ escapeXML: true });
export async function compile(task: CompileTask): Promise<CompilationResult> { export async function compile(task: CompileTask): Promise<CompilationResult> {
const srcDir = pathLib.join(Cfg.workingDirectory, `src`); const srcDir = pathLib.join(Cfg.workingDirectory, `src`);
@ -75,7 +77,7 @@ export async function compile(task: CompileTask): Promise<CompilationResult> {
} else { // If compilation error } else { // If compilation error
return { return {
status: TaskStatus.Failed, 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 { } else {

Loading…
Cancel
Save