t123yh
7 years ago
1 changed files with 0 additions and 106 deletions
@ -1,106 +0,0 @@ |
|||||||
import { TestData, StandardJudgeParameter, SubtaskJudge, TestcaseJudge, SubtaskScoringType } from '../interfaces'; |
|
||||||
import { SubtaskResult, TestcaseDetails, TaskStatus, TestcaseResult, JudgeResult } from '../../interfaces'; |
|
||||||
import { globalConfig as Cfg } from '../config'; |
|
||||||
import winston = require('winston'); |
|
||||||
import _ = require('lodash'); |
|
||||||
|
|
||||||
const globalFullScore = 100; |
|
||||||
function calculateSubtaskScore(scoring: SubtaskScoringType, scores: number[]): number { |
|
||||||
if (scoring === SubtaskScoringType.Minimum) { |
|
||||||
return _.min(scores); |
|
||||||
} else if (scoring === SubtaskScoringType.Multiple) { |
|
||||||
return _.reduce(scores, |
|
||||||
(res, cur) => res * cur, 1); |
|
||||||
} else if (scoring === SubtaskScoringType.Summation) { |
|
||||||
return _.sum(scores) / scores.length; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export async function processJudgement( |
|
||||||
subtasks: SubtaskJudge[], |
|
||||||
reportProgress: (r: SubtaskResult[]) => Promise<void>, |
|
||||||
judgeTestcase: (curCase: TestcaseJudge, started: () => Promise<void>) => Promise<TestcaseDetails>, |
|
||||||
): Promise<SubtaskResult[]> { |
|
||||||
const results: SubtaskResult[] = subtasks.map(t => ({ |
|
||||||
cases: t.cases.map(j => ({ |
|
||||||
status: TaskStatus.Waiting |
|
||||||
})), |
|
||||||
status: TaskStatus.Waiting |
|
||||||
})); |
|
||||||
winston.debug(`Totally ${results.length} subtasks.`); |
|
||||||
|
|
||||||
const judgeTasks: Promise<void>[] = []; |
|
||||||
for (let subtaskIndex = 0; subtaskIndex < subtasks.length; subtaskIndex++) { |
|
||||||
const currentResult = results[subtaskIndex]; |
|
||||||
const currentTask = subtasks[subtaskIndex]; |
|
||||||
|
|
||||||
judgeTasks.push((async () => { |
|
||||||
// Type minimum is skippable, run one by one
|
|
||||||
if (currentTask.type !== SubtaskScoringType.Summation) { |
|
||||||
let skipped: boolean = true; |
|
||||||
for (let index = 0; index < currentTask.cases.length; index++) { |
|
||||||
const currentTaskResult = currentResult.cases[index]; |
|
||||||
if (skipped) { |
|
||||||
currentTaskResult.status = TaskStatus.Skipped; |
|
||||||
} else { |
|
||||||
winston.verbose(`Judging ${subtaskIndex}, case ${index}.`); |
|
||||||
let score = 0; |
|
||||||
try { |
|
||||||
const taskJudge = await judgeTestcase(currentTask.cases[index], async () => { |
|
||||||
currentTaskResult.status = TaskStatus.Running; |
|
||||||
currentResult.status = TaskStatus.Running; |
|
||||||
await reportProgress(results); |
|
||||||
}); |
|
||||||
currentTaskResult.status = TaskStatus.Done; |
|
||||||
currentTaskResult.result = taskJudge; |
|
||||||
score = taskJudge.scoringRate; |
|
||||||
} catch (err) { |
|
||||||
currentTaskResult.status = TaskStatus.Failed; |
|
||||||
currentTaskResult.errorMessage = err.toString(); |
|
||||||
winston.warn(`Task runner error: ${err.toString()} (subtask ${subtaskIndex}, case ${index})`); |
|
||||||
} |
|
||||||
if (score === 0) { |
|
||||||
winston.debug(`Subtask ${subtaskIndex}, case ${index}: zero, skipping the rest.`); |
|
||||||
skipped = true; |
|
||||||
} |
|
||||||
await reportProgress(results); |
|
||||||
} |
|
||||||
} |
|
||||||
} else { |
|
||||||
// Non skippable, run all immediately
|
|
||||||
const caseTasks: Promise<void>[] = []; |
|
||||||
for (let index = 0; index < currentTask.cases.length; index++) { |
|
||||||
caseTasks.push((async () => { |
|
||||||
const currentTaskResult = currentResult.cases[index]; |
|
||||||
winston.verbose(`Judging ${subtaskIndex}, case ${index}.`); |
|
||||||
try { |
|
||||||
currentTaskResult.result = await judgeTestcase(currentTask.cases[index], async () => { |
|
||||||
currentTaskResult.status = TaskStatus.Running; |
|
||||||
currentResult.status = TaskStatus.Running; |
|
||||||
await reportProgress(results); |
|
||||||
}); |
|
||||||
currentTaskResult.status = TaskStatus.Done; |
|
||||||
} catch (err) { |
|
||||||
currentTaskResult.status = TaskStatus.Failed; |
|
||||||
currentTaskResult.errorMessage = err.toString(); |
|
||||||
winston.warn(`Task runner error: ${err.toString()} (subtask ${subtaskIndex}, case ${index})`); |
|
||||||
} |
|
||||||
await reportProgress(results); |
|
||||||
})()); |
|
||||||
} |
|
||||||
await Promise.all(caseTasks); |
|
||||||
} |
|
||||||
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 results; |
|
||||||
} |
|
Loading…
Reference in new issue