Browse Source

Fix interaction bugs.

master
t123yh 7 years ago
parent
commit
6062298f46
  1. 1
      src/daemon/judge/index.ts
  2. 8
      src/daemon/judge/interaction.ts
  3. 4
      src/daemon/judge/standard.ts
  4. 4
      src/daemon/judge/submit-answer.ts
  5. 24
      src/runner/judge.ts

1
src/daemon/judge/index.ts

@ -32,6 +32,7 @@ export async function judge(
} }
let judger: JudgerBase; let judger: JudgerBase;
console.log("Task typ: " + task.type);
if (task.type === ProblemType.Standard) { if (task.type === ProblemType.Standard) {
judger = new StandardJudger(testData, task.param as StandardJudgeParameter, task.priority); judger = new StandardJudger(testData, task.param as StandardJudgeParameter, task.priority);
} else if (task.type === ProblemType.AnswerSubmission) { } else if (task.type === ProblemType.AnswerSubmission) {

8
src/daemon/judge/interaction.ts

@ -26,7 +26,7 @@ export class InteractionJudger extends JudgerBase {
async preprocessTestData(): Promise<void> { async preprocessTestData(): Promise<void> {
if (this.testData.interactor != null) { if (this.testData.interactor != null) {
winston.verbose("Compiling special judge."); winston.verbose("Compiling interactor.");
const [interactorExecutableName, interactorResult] = await compile(this.testData.interactor.sourceCode, const [interactorExecutableName, interactorResult] = await compile(this.testData.interactor.sourceCode,
this.testData.interactor.language, null, this.priority); this.testData.interactor.language, null, this.priority);
if (interactorResult.status !== TaskStatus.Done) { if (interactorResult.status !== TaskStatus.Done) {
@ -69,9 +69,9 @@ export class InteractionJudger extends JudgerBase {
// We do not have to create a InteractionRunResult // We do not have to create a InteractionRunResult
const [inputContent, outputContent, runResult]: [string, string, StandardRunResult] = await Promise.all([ const [inputContent, outputContent, runResult]: [string, string, StandardRunResult] = await Promise.all([
readFileLength(pathLib.join(Cfg.testDataDirectory, this.testData.name, curCase.input), Cfg.dataDisplayLimit), readFileLength(curCase.input ? pathLib.join(Cfg.testDataDirectory, this.testData.name, curCase.input) : null, Cfg.dataDisplayLimit),
readFileLength(pathLib.join(Cfg.testDataDirectory, this.testData.name, curCase.output), Cfg.dataDisplayLimit), readFileLength(curCase.output ? pathLib.join(Cfg.testDataDirectory, this.testData.name, curCase.output) : null, Cfg.dataDisplayLimit),
runTask({ type: RPCTaskType.RunStandard, task: task }, this.priority, started) runTask({ type: RPCTaskType.RunInteraction, task: task }, this.priority, started)
]) as any; ]) as any;
return { return {

4
src/daemon/judge/standard.ts

@ -70,8 +70,8 @@ export class StandardJudger extends JudgerBase {
}; };
const [inputContent, outputContent, runResult]: [string, string, StandardRunResult] = await Promise.all([ const [inputContent, outputContent, runResult]: [string, string, StandardRunResult] = await Promise.all([
readFileLength(pathLib.join(Cfg.testDataDirectory, this.testData.name, curCase.input), Cfg.dataDisplayLimit), readFileLength(curCase.input ? pathLib.join(Cfg.testDataDirectory, this.testData.name, curCase.input) : null, Cfg.dataDisplayLimit),
readFileLength(pathLib.join(Cfg.testDataDirectory, this.testData.name, curCase.output), Cfg.dataDisplayLimit), readFileLength(curCase.output ? pathLib.join(Cfg.testDataDirectory, this.testData.name, curCase.output) : null, Cfg.dataDisplayLimit),
runTask({ type: RPCTaskType.RunStandard, task: task }, this.priority, started) runTask({ type: RPCTaskType.RunStandard, task: task }, this.priority, started)
]) as any; ]) as any;

4
src/daemon/judge/submit-answer.ts

@ -77,8 +77,8 @@ export class AnswerSubmissionJudger extends JudgerBase {
} }
const [inputContent, outputContent, runResult]: [string, string, AnswerSubmissionRunResult] = await Promise.all([ const [inputContent, outputContent, runResult]: [string, string, AnswerSubmissionRunResult] = await Promise.all([
readFileLength(pathLib.join(Cfg.testDataDirectory, this.testData.name, curCase.input), Cfg.dataDisplayLimit), readFileLength(curCase.input ? pathLib.join(Cfg.testDataDirectory, this.testData.name, curCase.input) : null, Cfg.dataDisplayLimit),
readFileLength(pathLib.join(Cfg.testDataDirectory, this.testData.name, curCase.output), Cfg.dataDisplayLimit), readFileLength(curCase.output ? pathLib.join(Cfg.testDataDirectory, this.testData.name, curCase.output) : null, Cfg.dataDisplayLimit),
runTask({ type: RPCTaskType.RunSubmitAnswer, task: task }, this.priority, started) runTask({ type: RPCTaskType.RunSubmitAnswer, task: task }, this.priority, started)
]) as any; ]) as any;

24
src/runner/judge.ts

@ -1,8 +1,9 @@
import pathLib = require('path'); import pathLib = require('path');
import randomString = require('randomstring'); import randomString = require('randomstring');
import util = require('util');
import fse = require('fs-extra'); import fse = require('fs-extra');
import winston = require('winston'); import winston = require('winston');
import syspipe = require('syspipe'); const syspipe = require('syspipe');
import { SandboxStatus } from 'simple-sandbox/lib/interfaces'; import { SandboxStatus } from 'simple-sandbox/lib/interfaces';
import { TestcaseResultType, StandardRunTask, StandardRunResult, InteractionRunTask, AnswerSubmissionRunTask, AnswerSubmissionRunResult } from '../interfaces'; import { TestcaseResultType, StandardRunTask, StandardRunResult, InteractionRunTask, AnswerSubmissionRunTask, AnswerSubmissionRunResult } from '../interfaces';
@ -285,7 +286,7 @@ export async function judgeInteraction(task: InteractionRunTask)
winston.debug("Fetching user binary..."); winston.debug("Fetching user binary...");
const [userBinaryDirectory, userLanguage, userCode] = await fetchBinary(task.userExecutableName); const [userBinaryDirectory, userLanguage, userCode] = await fetchBinary(task.userExecutableName);
winston.debug("Fetching interactor binary..."); winston.debug("Fetching interactor binary...");
const [interactorBinaryDirectory, interactorLanguage] = await fetchBinary(task.userExecutableName); const [interactorBinaryDirectory, interactorLanguage] = await fetchBinary(task.interactorExecutableName);
pipe1 = syspipe.pipe(), pipe1 = syspipe.pipe(),
pipe2 = syspipe.pipe(); pipe2 = syspipe.pipe();
@ -311,8 +312,6 @@ export async function judgeInteraction(task: InteractionRunTask)
const [interactorResult, runResult] = await Promise.all([interactorTaskPromise const [interactorResult, runResult] = await Promise.all([interactorTaskPromise
.then((result) => { stopUser(); return result; }, (err) => { stopUser(); return Promise.reject(err); }), userProgramTaskPromise]); .then((result) => { stopUser(); return result; }, (err) => { stopUser(); return Promise.reject(err); }), userProgramTaskPromise]);
const userError = await readFileLength(pathLib.join(workingDir, tempErrFile), Cfg.stderrDisplayLimit);
const time = Math.round(runResult.result.time / 1e6), const time = Math.round(runResult.result.time / 1e6),
memory = runResult.result.memory / 1024; memory = runResult.result.memory / 1024;
@ -327,6 +326,7 @@ export async function judgeInteraction(task: InteractionRunTask)
message = `Killed: ${signals[runResult.result.code]}`; message = `Killed: ${signals[runResult.result.code]}`;
status = TestcaseResultType.RuntimeError; status = TestcaseResultType.RuntimeError;
} else if (runResult.result.status !== SandboxStatus.OK) { } else if (runResult.result.status !== SandboxStatus.OK) {
message = "Warning: corrupt sandbox result " + util.inspect(runResult.result);
status = TestcaseResultType.RuntimeError; status = TestcaseResultType.RuntimeError;
} else { } else {
message = `Exited with return code ${runResult.result.code}`; message = `Exited with return code ${runResult.result.code}`;
@ -344,7 +344,7 @@ export async function judgeInteraction(task: InteractionRunTask)
time: time, time: time,
memory: time, memory: time,
userOutput: null, userOutput: null,
userError: userError, userError: await readFileLength(pathLib.join(workingDir, tempErrFile), Cfg.stderrDisplayLimit),
spjMessage: await readFileLength(pathLib.join(spjWorkingDir, tempErrFile), Cfg.stderrDisplayLimit) spjMessage: await readFileLength(pathLib.join(spjWorkingDir, tempErrFile), Cfg.stderrDisplayLimit)
}; };
@ -352,21 +352,23 @@ export async function judgeInteraction(task: InteractionRunTask)
let score = 0; let score = 0;
if (status == null) { if (status == null) {
const scoreString = await tryReadFile(spjWorkingDir + '/score.txt'); const scoreString = await tryReadFile(spjWorkingDir + '/score.txt');
let score = Number(scoreString); const rawScore = Number(scoreString);
if ((!scoreString) || isNaN(score)) { if ((!scoreString) || isNaN(rawScore)) {
score = null;
status = TestcaseResultType.JudgementFailed; status = TestcaseResultType.JudgementFailed;
message = `Interactor returned a non-number score ${scoreString}`; message = `Interactor returned a non-number score ${scoreString}`;
} else if (score === -1) { } else if (score === -1) {
score = 0;
status = TestcaseResultType.InvalidInteraction; status = TestcaseResultType.InvalidInteraction;
} else { } else {
score = score; score = rawScore;
status = getStatusByScore(score); status = getStatusByScore(rawScore);
} }
} }
winston.debug(`Interaction problem judge succeeded, score = ${score}`);
return Object.assign(partialResult, { return Object.assign(partialResult, {
result: status, result: status,
scoringRate: score / spjFullScore scoringRate: score / spjFullScore,
systemMessage: message
}); });
} finally { } finally {
const closePipe = async (p) => { const closePipe = async (p) => {

Loading…
Cancel
Save