judge: 将testlib移入vendor

pull/92/head
undefined 4 years ago
parent ec4971d213
commit a0a6f5107f

@ -15,7 +15,9 @@ jobs:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
steps:
- name: Check out
uses: actions/checkout@v1
uses: actions/checkout@v2
with:
submodules: recursive
- name: Set up Node
uses: actions/setup-node@v1
with:

4
.gitmodules vendored

@ -1,3 +1,7 @@
[submodule "customize"]
path = packages/customize
url = https://github.com/hydro-dev/customize.git
[submodule "testlib"]
path = packages/hydrojudge/vendor/testlib
url = https://github.com/MikeMirzayanov/testlib.git

File diff suppressed because it is too large Load Diff

@ -1,7 +1,7 @@
{
"name": "@hydrooj/hydrojudge",
"bin": "bin/hydrojudge.js",
"version": "2.4.18",
"version": "2.4.19",
"os": [
"linux"
],

@ -224,7 +224,9 @@ export async function readYamlCases(folder: string, cfg: Dictionary<any> = {}, a
}
} else throw new FormatError('Invalid user_extra_files config.');
}
if (cfg.cases) {
if (cfg.outputs) {
config.type = 'submit_answer';
} else if (cfg.cases) {
config.subtasks = [{
score: parseInt(cfg.score, 10) || Math.floor(100 / cfg.cases.length),
time_limit_ms: parseTimeMS(cfg.time || '1s'),
@ -264,6 +266,7 @@ export async function readYamlCases(folder: string, cfg: Dictionary<any> = {}, a
config.subtasks = c.subtasks;
config.count = c.count;
}
if (config.type === 'submit_answer' && !cfg.outputs) throw new FormatError('outputs config not found');
return Object.assign(cfg, config);
}
@ -299,9 +302,12 @@ function isValidConfig(config) {
export default async function readCases(folder: string, cfg: Record<string, any> = {}, args) {
const iniConfig = path.resolve(folder, 'config.ini');
const yamlConfig = path.resolve(folder, 'config.yaml');
const ymlConfig = path.resolve(folder, 'config.yml');
let config;
if (fs.existsSync(yamlConfig)) {
config = { ...yaml.load(fs.readFileSync(yamlConfig).toString()) as object, ...cfg };
} else if (fs.existsSync(ymlConfig)) {
config = { ...yaml.load(fs.readFileSync(ymlConfig).toString()) as object, ...cfg };
} else if (fs.existsSync(iniConfig)) {
config = { ...convertIniConfig(fs.readFileSync(iniConfig).toString()), ...cfg };
} else config = cfg;

@ -24,7 +24,7 @@ export async function check(config): Promise<[number, number, string]> {
export async function compileChecker(checkerType: string, checker: string, copyIn: any) {
if (!checkers[checkerType]) throw new SystemError('Unknown checker type {0}.', [checkerType]);
if (checkerType === 'testlib') copyIn['testlib.h'] = { src: resolve(__dirname, '../files/testlib.h') };
if (checkerType === 'testlib') copyIn['testlib.h'] = { src: resolve(__dirname, '../vendor/testlib/testlib.h') };
const file = await fs.readFile(checker);
// TODO cache compiled checker
return await compile(parseFilename(checker).split('.')[1], file.toString(), 'checker', copyIn);

@ -19,7 +19,7 @@ function judgeCase(c) {
return async (ctx, ctxSubtask) => {
ctx.executeInteractor.copyIn.in = c.input ? { src: c.input } : { content: '' };
ctx.executeInteractor.copyIn.out = c.output ? { src: c.output } : { content: '' };
ctx.executeInteractor.copyIn['testlib.h'] = { src: resolve(__dirname, '../../files/testlib.h') };
ctx.executeInteractor.copyIn['testlib.h'] = { src: resolve(__dirname, '../../vendor/testlib/testlib.h') };
const [{ code, time_usage_ms, memory_usage_kb }, resInteractor] = await run([
{
execute: ctx.executeUser.execute.replace(/\$\{name\}/g, 'code'),

@ -1,4 +1,3 @@
import { readFile } from 'fs-extra';
import * as STATUS from '../status';
export async function judge({
@ -6,42 +5,28 @@ export async function judge({
}) {
next({ status: STATUS.STATUS_JUDGING, progress: 0 });
code = code.replace(/\r/g, '');
const expected = (await readFile(config.subtasks[0].cases[0].output)).toString().replace(/\r/g, '');
if (config.subtasks.length === 1) {
const status = code.trim() === expected.trim() ? STATUS.STATUS_ACCEPTED : STATUS.STATUS_WRONG_ANSWER;
const score = status === STATUS.STATUS_ACCEPTED ? config.subtasks[0].score : 0;
next({
status,
progress: 100,
case: {
status, score, time_ms: 0, memory_kb: 0, message: '',
},
});
return end({
status, score, time_ms: 0, memory_kb: 0,
});
}
const outputs = code.split('\n');
let score = 0;
let totalScore = 0;
let totalStatus = 0;
const lines = expected.split('\n');
for (const i in config.subtasks) {
const subtask = config.subtasks[i];
for (const i in config.outputs) {
const c = config.outputs[i];
let status = STATUS.STATUS_WRONG_ANSWER;
if (lines[i].trim() === outputs[i].trim()) {
score += subtask.score;
let score = 0;
if (outputs[i].trim() === (c.output || c[0]).trim()) {
score = c.score || c[1];
status = STATUS.STATUS_ACCEPTED;
}
totalScore += score;
totalStatus = Math.max(status, totalStatus);
next({
status: totalStatus,
process: (100 * config.subtasks.length) / (+i + 1),
progress: (100 * (+i + 1)) / config.outputs.length,
case: {
status, score, time_ms: 0, memory_kb: 0, message: '',
},
}, i + 1);
}, +i + 1);
}
return end({
status: totalStatus, score, time_ms: 0, memory_kb: 0,
status: totalStatus, score: totalScore, time_ms: 0, memory_kb: 0,
});
}

@ -0,0 +1 @@
Subproject commit f5b55f138709e97916f51bdb7a23baed941b5751

@ -31,8 +31,7 @@ export default class MessagePadContainer extends React.PureComponent {
{this.props.panel.map((i, name) => (
<div className="row">
<div className="medium-7 columns form__item end">
{i.type === 'textbox' && this.Textbox(i, name)}
{i.type === 'radio' && this.Radio(i, name)}
{i.choices ? this.Radio(i, name) : this.Textbox(i, name)}
</div>
</div>
))}

Loading…
Cancel
Save