Search in sources :

Example 1 with Validator

use of com.github.zhanhb.judge.common.Validator in project judge by zjnu-acm.

the class JudgeService method runProcess.

private void runProcess(RunRecord runRecord) throws IOException {
    Path dataPath = judgeConfiguration.getDataDirectory(runRecord.getProblemId());
    Objects.requireNonNull(dataPath, "dataPath");
    Path specialFile = dataPath.resolve(JudgeConfiguration.VALIDATE_FILE_NAME);
    boolean isSpecial = Files.exists(specialFile);
    if (!Files.isDirectory(dataPath)) {
        log.error("{} not exists", dataPath);
        return;
    }
    List<Path[]> files = new ArrayList<>(20);
    try (DirectoryStream<Path> listFiles = Files.newDirectoryStream(dataPath)) {
        log.debug("dataPath = {}", dataPath);
        for (Path inFile : listFiles) {
            String inFileName = inFile.getFileName().toString();
            if (!inFileName.toLowerCase().endsWith(".in")) {
                continue;
            }
            Path outFile = dataPath.resolve(inFileName.substring(0, inFileName.length() - 3) + ".out");
            if (!Files.exists(outFile)) {
                continue;
            }
            // 统计输入,输出文件
            files.add(new Path[] { inFile, outFile });
        }
    }
    int caseNum = files.size();
    log.debug("caseNum = {}", caseNum);
    if (caseNum == 0) {
        log.error("No test cases found for problem({})", runRecord.getProblemId());
        return;
    }
    // 最后通过的个数
    int accept = 0;
    ArrayList<String> details = new ArrayList<>(caseNum << 2);
    String command = runRecord.getLanguage().getExecuteCommand();
    // 建立临时文件
    Path work = judgeConfiguration.getWorkDirectory(runRecord.getSubmissionId());
    command = StringUtils.hasText(command) ? command : work.resolve("Main." + runRecord.getLanguage().getExecutableExtension()).toString();
    long extTime = runRecord.getLanguage().getExtTime();
    long castTimeLimit = runRecord.getTimeLimit() * runRecord.getLanguage().getTimeFactor() + extTime;
    // 内存附加
    long extraMemory = runRecord.getLanguage().getExtMemory();
    long caseMemoryLimit = (runRecord.getMemoryLimit() + extraMemory) * 1024;
    Options[] optionses = new Options[caseNum];
    for (int cas = 0; cas < caseNum; cas++) {
        Path[] entry = files.get(cas);
        Path in = entry[0];
        Path standard = entry[1];
        Path progOutput = work.resolve(standard.getFileName());
        optionses[cas] = Options.builder().timeLimit(// time limit
        castTimeLimit).memoryLimit(// memory in bytes
        caseMemoryLimit).outputLimit(// 16M
        16 * 1024 * 1024).command(command).workDirectory(work).inputFile(in).outputFile(progOutput).standardOutput(standard).errFile(NULL_FILE.toPath()).build();
    }
    String detailMessageStr = null;
    String scorePerCase = new DecimalFormat("0.#").format(100.0 / caseNum);
    final Validator validator = isSpecial ? new SpecialValidator(specialFile.toString(), work) : SimpleValidator.PE_AS_ACCEPTED;
    // 时间
    long time = 0;
    // 内存
    long memory = 0;
    try {
        ExecuteResult[] ers = JudgeBridge.INSTANCE.judge(optionses, false, validator);
        for (ExecuteResult er : ers) {
            long tim1 = Math.max(0, er.getTime() - extTime);
            long mem1 = Math.max(0, er.getMemory() / 1024 - extraMemory);
            String message = er.getMessage();
            boolean success = er.isSuccess();
            time = Math.max(time, tim1);
            memory = Math.max(memory, mem1);
            log.debug("message = {}, time = {}, memory = {}", message, time, memory);
            details.add(String.valueOf(er.getCode().getResult()));
            details.add(success ? scorePerCase : "0");
            details.add(String.valueOf(tim1));
            details.add(String.valueOf(mem1));
            if (success) {
                ++accept;
            }
        }
    } catch (JudgeException | RuntimeException | Error ex) {
        log.error("", ex);
        accept = ResultType.SYSTEM_ERROR;
        detailMessageStr = ex.getMessage();
    }
    log.debug("{}", details);
    int score = accept >= 0 ? (int) Math.round(accept * 100.0 / caseNum) : accept;
    if (score == 0 && accept != 0) {
        ++score;
    } else if (score == ResultType.SCORE_ACCEPT && accept != caseNum) {
        --score;
    }
    submissionMapper.updateResult(runRecord.getSubmissionId(), score, time, memory);
    submissionMapper.saveDetail(runRecord.getSubmissionId(), detailMessageStr != null ? detailMessageStr : details.stream().map(String::valueOf).collect(Collectors.joining(",")));
    updateSubmissionStatus(runRecord);
}
Also used : Path(java.nio.file.Path) Options(com.github.zhanhb.judge.common.Options) DecimalFormat(java.text.DecimalFormat) ArrayList(java.util.ArrayList) SpecialValidator(com.github.zhanhb.judge.win32.SpecialValidator) JudgeException(com.github.zhanhb.judge.common.JudgeException) ExecuteResult(com.github.zhanhb.judge.common.ExecuteResult) SimpleValidator(com.github.zhanhb.judge.common.SimpleValidator) SpecialValidator(com.github.zhanhb.judge.win32.SpecialValidator) Validator(com.github.zhanhb.judge.common.Validator)

Aggregations

ExecuteResult (com.github.zhanhb.judge.common.ExecuteResult)1 JudgeException (com.github.zhanhb.judge.common.JudgeException)1 Options (com.github.zhanhb.judge.common.Options)1 SimpleValidator (com.github.zhanhb.judge.common.SimpleValidator)1 Validator (com.github.zhanhb.judge.common.Validator)1 SpecialValidator (com.github.zhanhb.judge.win32.SpecialValidator)1 Path (java.nio.file.Path)1 DecimalFormat (java.text.DecimalFormat)1 ArrayList (java.util.ArrayList)1