加入判题机(测试版)
This commit is contained in:
parent
6e3b576ed1
commit
abcc15f16a
|
@ -2,6 +2,7 @@
|
|||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="true" />
|
||||
<profile name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
|
|
|
@ -11,6 +11,22 @@
|
|||
<artifactId>DataBackup</artifactId>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<!-- 指定该Main Class为全局的唯一入口 -->
|
||||
<mainClass>top.hcode.hoj.DataBackupApplication</mainClass>
|
||||
<layout>ZIP</layout>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
|
|
|
@ -18,4 +18,9 @@ public class CloudHandler implements ToJudgeService {
|
|||
public CommonResult submitProblemJudge(Judge judge) {
|
||||
return CommonResult.errorResponse("判题机系统出错,提交进入重判队列,请等待管理员处理!", CommonResult.STATUS_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult initTestCase(Long pid, Boolean isSpj) {
|
||||
return CommonResult.errorResponse("判题机评测数据初始化失败!", CommonResult.STATUS_ERROR);
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.*;
|
|||
import top.hcode.hoj.common.result.CommonResult;
|
||||
import top.hcode.hoj.pojo.dto.ProblemDto;
|
||||
import top.hcode.hoj.pojo.entity.*;
|
||||
import top.hcode.hoj.service.ToJudgeService;
|
||||
import top.hcode.hoj.service.impl.*;
|
||||
|
||||
|
||||
|
@ -37,6 +38,9 @@ public class AdminProblemController {
|
|||
@Autowired
|
||||
private ProblemCaseServiceImpl problemCaseService;
|
||||
|
||||
@Autowired
|
||||
private ToJudgeService toJudgeService;
|
||||
|
||||
@GetMapping("/get-problem-list")
|
||||
public CommonResult getProblemList(@RequestParam(value = "limit", required = false) Integer limit,
|
||||
@RequestParam(value = "currentPage", required = false) Integer currentPage,
|
||||
|
@ -88,6 +92,8 @@ public class AdminProblemController {
|
|||
@PostMapping("")
|
||||
public CommonResult addProblem(@RequestBody ProblemDto problemDto){
|
||||
boolean result = problemService.adminAddProblem(problemDto);
|
||||
toJudgeService.initTestCase(problemDto.getProblem().getId(),
|
||||
!StringUtils.isEmpty(problemDto.getProblem().getSpjCode()));
|
||||
if (result) { // 添加成功
|
||||
return CommonResult.successResponse(null,"添加成功!");
|
||||
} else {
|
||||
|
@ -100,6 +106,8 @@ public class AdminProblemController {
|
|||
@Transactional
|
||||
public CommonResult updateProblem(@RequestBody ProblemDto problemDto){
|
||||
boolean result = problemService.adminUpdateProblem(problemDto);
|
||||
toJudgeService.initTestCase(problemDto.getProblem().getId(),
|
||||
!StringUtils.isEmpty(problemDto.getProblem().getSpjCode()));
|
||||
if (result) { // 更新成功
|
||||
return CommonResult.successResponse(null,"修改成功!");
|
||||
} else {
|
||||
|
|
|
@ -4,8 +4,10 @@ package top.hcode.hoj.service;
|
|||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import top.hcode.hoj.common.exception.CloudHandler;
|
||||
import top.hcode.hoj.common.result.CommonResult;
|
||||
import top.hcode.hoj.pojo.entity.Judge;
|
||||
|
@ -20,5 +22,7 @@ public interface ToJudgeService {
|
|||
@PostMapping(value = "/judge")
|
||||
public CommonResult submitProblemJudge(@RequestBody Judge judge);
|
||||
|
||||
@GetMapping("/init-test-case")
|
||||
public CommonResult initTestCase(@RequestParam("pid")Long pid, @RequestParam("isSpj")Boolean isSpj);
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import top.hcode.hoj.utils.JsoupUtils;
|
|||
import top.hcode.hoj.utils.RedisUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
|
@ -89,6 +90,13 @@ public class DataBackupApplicationTests {
|
|||
|
||||
// List<AnnouncementVo> contestAnnouncement = announcementService.getContestAnnouncement(1L);
|
||||
// System.out.println(contestAnnouncement.size());
|
||||
String test = "{1}....{2}";
|
||||
String command = "/usr/bin/java -cp {1} -XX:MaxRAM={2}k -Djava.security.manager -Dfile.encoding=UTF-8 -Djava.security.policy==/etc/java_policy -Djava.awt.headless=true Main";
|
||||
String exePath = "/judge/run/32/1.exe";
|
||||
String exeDir = "/judge/run/32";
|
||||
int maxMemory = 1024*10;
|
||||
List<String> commandList = Arrays.asList(MessageFormat.format(command, exePath, exeDir, (maxMemory / 1024)).split(" "));
|
||||
System.out.println(commandList);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,25 @@
|
|||
FROM registry.docker-cn.com/library/ubuntu:16.04
|
||||
|
||||
COPY *.jar /app.jar
|
||||
|
||||
RUN sed -i s@/archive.ubuntu.com/@/mirror.tuna.tsinghua.edu.cn/@g /etc/apt/sources.list
|
||||
RUN apt-get clean
|
||||
RUN apt-get update
|
||||
|
||||
RUN buildDeps='software-properties-common git libtool cmake python-dev python3-pip python-pip libseccomp-dev' && \
|
||||
apt-get update && apt-get install -y python python3 python-pkg-resources python3-pkg-resources gcc g++ $buildDeps && \
|
||||
add-apt-repository ppa:openjdk-r/ppa && apt-get update && apt-get install -y openjdk-8-jdk && \
|
||||
cd /tmp && git clone -b newnew --depth 1 https://github.com/QingdaoU/Judger && cd Judger && \
|
||||
mkdir build && cd build && cmake .. && make && make install && \
|
||||
apt-get purge -y --auto-remove $buildDeps && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/* && \
|
||||
useradd -u 12001 compiler && useradd -u 12002 code && useradd -u 12003 spj && usermod -a -G spj
|
||||
|
||||
RUN rm -rf /judge/* && \
|
||||
mkdir -p /judge/run /judge/spj /judge/test_case
|
||||
|
||||
CMD ["--server.port=8010"]
|
||||
|
||||
EXPOSE 8010
|
||||
|
||||
ENTRYPOINT ["java", "-jar", "/app.jar"]
|
|
@ -9,15 +9,33 @@
|
|||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>JudgeServer</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<!-- 指定该Main Class为全局的唯一入口 -->
|
||||
<mainClass>top.hcode.hoj.JudgeServerApplication</mainClass>
|
||||
<layout>ZIP</layout>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
@ -68,6 +86,7 @@
|
|||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.3.3</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -1,20 +1,21 @@
|
|||
package top.hcode.hoj.controller;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import top.hcode.hoj.common.CommonResult;
|
||||
import top.hcode.hoj.pojo.entity.Contest;
|
||||
import top.hcode.hoj.pojo.entity.Judge;
|
||||
import top.hcode.hoj.pojo.entity.UserAcproblem;
|
||||
import top.hcode.hoj.judger.JudgeStrategy;
|
||||
import top.hcode.hoj.pojo.entity.*;
|
||||
import top.hcode.hoj.service.impl.*;
|
||||
import top.hcode.hoj.util.Constants;
|
||||
import top.hcode.hoj.util.IpUtils;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @Author: Himit_ZH
|
||||
|
@ -24,9 +25,13 @@ import java.util.concurrent.TimeUnit;
|
|||
@RestController
|
||||
@Slf4j
|
||||
public class JudgeController {
|
||||
|
||||
@Autowired
|
||||
private JudgeServiceImpl judgeService;
|
||||
|
||||
@Autowired
|
||||
private ProblemServiceImpl problemService;
|
||||
|
||||
@Autowired
|
||||
private ProblemCountServiceImpl problemCountService;
|
||||
|
||||
|
@ -42,6 +47,9 @@ public class JudgeController {
|
|||
@Autowired
|
||||
private ContestServiceImpl contestService;
|
||||
|
||||
@Autowired
|
||||
private ProblemCaseServiceImpl problemCase;
|
||||
|
||||
@PostMapping(value = "/judge") // 待定,到时再添加服务熔断兜底方法
|
||||
public CommonResult submitProblemJudge(@RequestBody Judge judge) {
|
||||
|
||||
|
@ -55,57 +63,65 @@ public class JudgeController {
|
|||
if (!updateResult) { // 出错并不影响主要业务逻辑,可以稍微记录一下即可。
|
||||
log.error("修改Judge表失效----->{}", "修改提交评判为评测队列出错");
|
||||
}
|
||||
/*
|
||||
* 先空着,此部分调用判题机进行测评,所以先返回成功~
|
||||
*/
|
||||
// 线程沉睡,模仿判题过程消耗时间
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(3);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// 进行判题操作
|
||||
Problem problem = problemService.getById(judge.getPid());
|
||||
|
||||
Judge finalJudge = judgeService.Judge(problem, judge);
|
||||
|
||||
// 直接默认为通过,且说明该题已被评测过
|
||||
judge.setStatus(Constants.Judge.STATUS_ACCEPTED.getStatus())
|
||||
.setTime(1)
|
||||
.setMemory(1);
|
||||
// 更新该次提交
|
||||
judgeService.updateById(judge);
|
||||
judgeService.updateById(finalJudge);
|
||||
|
||||
if (judge.getCid() == 0) { // 非比赛提交
|
||||
if (finalJudge.getCid() == 0) { // 非比赛提交
|
||||
|
||||
// 如果是AC,就更新user_acproblem表,
|
||||
if (judge.getStatus().intValue() == Constants.Judge.STATUS_ACCEPTED.getStatus()) {
|
||||
if (finalJudge.getStatus().intValue() == Constants.Judge.STATUS_ACCEPTED.getStatus()) {
|
||||
userAcproblemService.saveOrUpdate(new UserAcproblem()
|
||||
.setPid(judge.getPid())
|
||||
.setUid(judge.getUid())
|
||||
.setSubmitId(judge.getSubmitId())
|
||||
.setPid(finalJudge.getPid())
|
||||
.setUid(finalJudge.getUid())
|
||||
.setSubmitId(finalJudge.getSubmitId())
|
||||
);
|
||||
}
|
||||
// 比赛的提交不纳入,更新该提交对应题目的数据
|
||||
problemCountService.updateCount(Constants.Judge.STATUS_ACCEPTED.getStatus(), judge);
|
||||
problemCountService.updateCount(Constants.Judge.STATUS_ACCEPTED.getStatus(), finalJudge);
|
||||
|
||||
|
||||
// 如果是非比赛提交,且为OI题目的提交,需要判断是否更新用户得分
|
||||
if (judge.getScore() != null) {
|
||||
userRecordService.updateRecord(judge);
|
||||
if (finalJudge.getScore() != null) {
|
||||
userRecordService.updateRecord(finalJudge);
|
||||
}
|
||||
|
||||
} else { //如果是比赛提交
|
||||
|
||||
Contest contest = contestService.getById(judge.getCid());
|
||||
Contest contest = contestService.getById(finalJudge.getCid());
|
||||
if (contest == null) {
|
||||
log.error("判题机出错----------->{}", "该比赛不存在");
|
||||
return CommonResult.errorResponse("该比赛不存在");
|
||||
}
|
||||
// 每个提交都得记录到contest_record里面,同时需要判断是否为比赛前的提交
|
||||
if (contest.getStatus().intValue() == Constants.Contest.STATUS_RUNNING.getCode()) {
|
||||
contestRecordService.UpdateContestRecord(judge);
|
||||
contestRecordService.UpdateContestRecord(finalJudge);
|
||||
}
|
||||
|
||||
}
|
||||
return CommonResult.successResponse(judge, "判题机评测完成!");
|
||||
return CommonResult.successResponse(finalJudge, "判题机评测完成!");
|
||||
}
|
||||
|
||||
@GetMapping("/init-test-case")
|
||||
public CommonResult initTestCase(@RequestParam("pid")Long pid,@RequestParam("isSpj")Boolean isSpj){
|
||||
|
||||
QueryWrapper<ProblemCase> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("pid", pid);
|
||||
List<ProblemCase> problemCases = problemCase.list(queryWrapper);
|
||||
|
||||
List<HashMap<String,Object>> testCases = new LinkedList<>();
|
||||
for (ProblemCase problemCase:problemCases){
|
||||
HashMap<String,Object> tmp = new HashMap<>();
|
||||
tmp.put("input", problemCase.getInput());
|
||||
tmp.put("output", problemCase.getOutput());
|
||||
testCases.add(tmp);
|
||||
}
|
||||
JudgeStrategy.initTestCase(testCases,pid,isSpj);
|
||||
return CommonResult.successResponse(null, "初始化评测数据到判题机成功!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package top.hcode.hoj.dao;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import top.hcode.hoj.pojo.entity.Problem;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author Himit_ZH
|
||||
* @since 2020-10-23
|
||||
*/
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface ProblemMapper extends BaseMapper<Problem> {
|
||||
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
package top.hcode.hoj.judger;
|
||||
|
||||
import cn.hutool.core.io.file.FileWriter;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import top.hcode.hoj.pojo.entity.Judge;
|
||||
import top.hcode.hoj.pojo.entity.Problem;
|
||||
import top.hcode.hoj.util.Constants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @Author: Himit_ZH
|
||||
* @Date: 2021/1/22 21:13
|
||||
* @Description:
|
||||
*/
|
||||
@Slf4j
|
||||
public class JudgeC extends JudgeStrategy {
|
||||
|
||||
private String code;
|
||||
|
||||
private Problem problem;
|
||||
|
||||
private Long submitId;
|
||||
|
||||
public JudgeC(Problem problem, Judge judge) {
|
||||
super(problem,judge.getSubmitId());
|
||||
this.submitId = judge.getSubmitId();
|
||||
this.code = judge.getCode();
|
||||
this.problem = problem;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HashMap<String, Object> judge() {
|
||||
// 该提交对应的文件夹路径
|
||||
String fileDir = Constants.Compiler.WORKPLACE.getContent() + "/" + submitId;
|
||||
// 将代码写入文件
|
||||
String srcFilePath = fileDir + "/" + Constants.CompileConfig.C.getSrcName();
|
||||
FileWriter fileWriter = new FileWriter(srcFilePath, CharsetUtil.UTF_8);
|
||||
fileWriter.write(code);
|
||||
// 编译指令
|
||||
String command = Constants.CompileConfig.C.getCommand();
|
||||
// 输出exe文件路径
|
||||
String exePath = fileDir+"/"+Constants.CompileConfig.C.getExeName();
|
||||
|
||||
String spjCompileResult = checkOrCompileSpj(problem.getSpjCode(), problem.getSpjLanguage());
|
||||
|
||||
// 如果该题是需要特别判题的,但是该特别判题程序不存在或编译时产生异常,则此次判题直接判系统错误。
|
||||
if (!spjCompileResult.equals("success")){
|
||||
HashMap<String,Object> result = new HashMap<>();
|
||||
result.put("code", Constants.Judge.STATUS_SYSTEM_ERROR.getStatus());
|
||||
result.put("msg", spjCompileResult);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 编译的一些时间空间参数等
|
||||
Long maxCpuTime = Constants.CompileConfig.C.getMaxCpuTime();
|
||||
Long maxRealTime = Constants.CompileConfig.C.getMaxRealTime();
|
||||
Long maxMemory = Constants.CompileConfig.C.getMaxMemory();
|
||||
List<String> envs = Constants.RunConfig.C.getEnvs();
|
||||
|
||||
// 运行的一些指令参数,环境配置等
|
||||
String runCommand = Constants.RunConfig.C.getCommand();
|
||||
List<String> runEnvs = Constants.RunConfig.C.getEnvs();
|
||||
String runSeccompRule = Constants.RunConfig.C.getSeccompRule();
|
||||
Integer memoryLimitCheckOnly = Constants.RunConfig.C.getMemoryLimitCheckOnly();
|
||||
|
||||
// 特别判题的参数
|
||||
String spjRunSeccompRule = null;
|
||||
if (problem.getSpjLanguage().equals("C")) {
|
||||
spjRunSeccompRule = Constants.RunConfig.SPJ_C.getSeccompRule();
|
||||
}else if(problem.getSpjLanguage().equals("C++")){
|
||||
spjRunSeccompRule = Constants.RunConfig.SPJ_CPP.getSeccompRule();
|
||||
}
|
||||
|
||||
// 调用安全沙盒进行编译操作
|
||||
HashMap<String, Object> result = compile(srcFilePath, fileDir, command, exePath, maxCpuTime,maxRealTime,maxMemory,envs);
|
||||
if (!(Boolean) result.get("result")){ // 编译失败
|
||||
// {msg:error,code:STATUS_COMPILE_ERROR}
|
||||
result.remove("result");
|
||||
return result;
|
||||
}else{
|
||||
// 编译成功,则进行每个测试点进行测试
|
||||
List<JSONObject> testCaseResultList = judgeAllCase(exePath, fileDir, (long) problem.getTimeLimit(), problem.getTimeLimit() * 3L,
|
||||
problem.getMemoryLimit()*1024*1024L, runCommand, runEnvs, runSeccompRule, spjRunSeccompRule, memoryLimitCheckOnly);
|
||||
// 获取判题结果
|
||||
return getJudgeInfo(testCaseResultList, problem.getType() == 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package top.hcode.hoj.judger;
|
||||
|
||||
import cn.hutool.core.io.file.FileReader;
|
||||
import cn.hutool.core.io.file.FileWriter;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.StringUtils;
|
||||
import top.hcode.hoj.pojo.entity.Judge;
|
||||
import top.hcode.hoj.pojo.entity.Problem;
|
||||
import top.hcode.hoj.util.Constants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: Himit_ZH
|
||||
* @Date: 2021/1/22 21:14
|
||||
* @Description:
|
||||
*/
|
||||
@Slf4j
|
||||
public class JudgeCPP extends JudgeStrategy{
|
||||
|
||||
private String code;
|
||||
|
||||
private Problem problem;
|
||||
|
||||
private Long submitId;
|
||||
|
||||
public JudgeCPP(Problem problem, Judge judge) {
|
||||
super(problem,judge.getSubmitId());
|
||||
this.submitId = judge.getSubmitId();
|
||||
this.code = judge.getCode();
|
||||
this.problem = problem;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HashMap<String, Object> judge() {
|
||||
// 该提交对应的文件夹路径
|
||||
String fileDir = Constants.Compiler.WORKPLACE.getContent() + "/" + submitId;
|
||||
// 将代码写入文件
|
||||
String srcFilePath = fileDir + "/" + Constants.CompileConfig.CPP.getSrcName();
|
||||
FileWriter fileWriter = new FileWriter(srcFilePath, CharsetUtil.UTF_8);
|
||||
fileWriter.write(code);
|
||||
// 编译指令
|
||||
String command = Constants.CompileConfig.CPP.getCommand();
|
||||
// 输出exe文件路径
|
||||
String exePath = fileDir+"/"+Constants.CompileConfig.CPP.getExeName();
|
||||
|
||||
String spjCompileResult = checkOrCompileSpj(problem.getSpjCode(), problem.getSpjLanguage());
|
||||
|
||||
// 如果该题是需要特别判题的,但是该特别判题程序不存在或编译时产生异常,则此次判题直接判系统错误。
|
||||
if (!spjCompileResult.equals("success")){
|
||||
HashMap<String,Object> result = new HashMap<>();
|
||||
result.put("code", Constants.Judge.STATUS_SYSTEM_ERROR.getStatus());
|
||||
result.put("msg", spjCompileResult);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 编译的一些时间空间参数等
|
||||
Long maxCpuTime = Constants.CompileConfig.CPP.getMaxCpuTime();
|
||||
Long maxRealTime = Constants.CompileConfig.CPP.getMaxRealTime();
|
||||
Long maxMemory = Constants.CompileConfig.CPP.getMaxMemory();
|
||||
List<String> envs = Constants.RunConfig.CPP.getEnvs();
|
||||
|
||||
// 运行的一些指令参数,环境配置等
|
||||
String runCommand = Constants.RunConfig.CPP.getCommand();
|
||||
List<String> runEnvs = Constants.RunConfig.CPP.getEnvs();
|
||||
String runSeccompRule = Constants.RunConfig.CPP.getSeccompRule();
|
||||
Integer memoryLimitCheckOnly = Constants.RunConfig.CPP.getMemoryLimitCheckOnly();
|
||||
|
||||
// 特别判题的参数,如果并非特别判题则为null即可
|
||||
String spjRunSeccompRule = null;
|
||||
if (problem.getSpjLanguage().equals("C")) {
|
||||
spjRunSeccompRule = Constants.RunConfig.SPJ_C.getSeccompRule();
|
||||
}else if(problem.getSpjLanguage().equals("C++")){
|
||||
spjRunSeccompRule = Constants.RunConfig.SPJ_CPP.getSeccompRule();
|
||||
}
|
||||
|
||||
// 调用安全沙盒进行编译操作
|
||||
HashMap<String, Object> result = compile(srcFilePath, fileDir, command, exePath, maxCpuTime,maxRealTime,maxMemory,envs);
|
||||
if (!(Boolean) result.get("result")){ // 编译失败
|
||||
// {msg:error,code:STATUS_COMPILE_ERROR}
|
||||
result.remove("result");
|
||||
}else{
|
||||
// 编译成功,则进行每个测试点进行测试
|
||||
List<JSONObject> testCaseResultList = judgeAllCase(exePath, fileDir, (long) problem.getTimeLimit(), problem.getTimeLimit() * 3L,
|
||||
problem.getMemoryLimit()*1024*1024L, runCommand, runEnvs, runSeccompRule, spjRunSeccompRule, memoryLimitCheckOnly);
|
||||
// 获取判题结果
|
||||
return getJudgeInfo(testCaseResultList, problem.getType() == 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package top.hcode.hoj.judger;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @Author: Himit_ZH
|
||||
* @Date: 2021/1/22 21:16
|
||||
* @Description:
|
||||
*/
|
||||
public class JudgeContext {
|
||||
|
||||
private JudgeStrategy judgeStrategy;
|
||||
|
||||
public JudgeContext(JudgeStrategy judgeStrategy) {
|
||||
this.judgeStrategy = judgeStrategy;
|
||||
}
|
||||
|
||||
// 判题的上下文接口
|
||||
public HashMap<String, Object> judge() {
|
||||
return judgeStrategy.judge();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package top.hcode.hoj.judger;
|
||||
|
||||
import cn.hutool.core.io.file.FileWriter;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import top.hcode.hoj.pojo.entity.Judge;
|
||||
import top.hcode.hoj.pojo.entity.Problem;
|
||||
import top.hcode.hoj.util.Constants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: Himit_ZH
|
||||
* @Date: 2021/1/22 21:15
|
||||
* @Description:
|
||||
*/
|
||||
public class JudgeJava extends JudgeStrategy {
|
||||
private String code;
|
||||
|
||||
private Problem problem;
|
||||
|
||||
private Long submitId;
|
||||
|
||||
public JudgeJava(Problem problem, Judge judge) {
|
||||
super(problem,judge.getSubmitId());
|
||||
this.submitId = judge.getSubmitId();
|
||||
this.code = judge.getCode();
|
||||
this.problem = problem;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HashMap<String, Object> judge() {
|
||||
// 该提交对应的文件夹路径
|
||||
String fileDir = Constants.Compiler.WORKPLACE.getContent() + "/" + submitId;
|
||||
// 将代码写入文件
|
||||
String srcFilePath = fileDir + "/" + Constants.CompileConfig.JAVA.getSrcName();
|
||||
FileWriter fileWriter = new FileWriter(srcFilePath, CharsetUtil.UTF_8);
|
||||
fileWriter.write(code);
|
||||
// 编译指令
|
||||
String command = Constants.CompileConfig.JAVA.getCommand();
|
||||
// 输出exe文件路径
|
||||
String exePath = fileDir+"/"+Constants.CompileConfig.JAVA.getExeName();
|
||||
|
||||
String spjCompileResult = checkOrCompileSpj(problem.getSpjCode(), problem.getSpjLanguage());
|
||||
|
||||
// 如果该题是需要特别判题的,但是该特别判题程序不存在或编译时产生异常,则此次判题直接判系统错误。
|
||||
if (!spjCompileResult.equals("success")){
|
||||
HashMap<String,Object> result = new HashMap<>();
|
||||
result.put("code", Constants.Judge.STATUS_SYSTEM_ERROR.getStatus());
|
||||
result.put("msg", spjCompileResult);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 编译的一些时间空间参数等
|
||||
Long maxCpuTime = Constants.CompileConfig.JAVA.getMaxCpuTime();
|
||||
Long maxRealTime = Constants.CompileConfig.JAVA.getMaxRealTime();
|
||||
Long maxMemory = Constants.CompileConfig.JAVA.getMaxMemory();
|
||||
List<String> envs = Constants.RunConfig.JAVA.getEnvs();
|
||||
|
||||
// 运行的一些指令参数,环境配置等
|
||||
String runCommand = Constants.RunConfig.JAVA.getCommand();
|
||||
List<String> runEnvs = Constants.RunConfig.JAVA.getEnvs();
|
||||
String runSeccompRule = Constants.RunConfig.JAVA.getSeccompRule();
|
||||
Integer memoryLimitCheckOnly = Constants.RunConfig.JAVA.getMemoryLimitCheckOnly();
|
||||
|
||||
// 特别判题的参数,如果并非特别判题则为null即可
|
||||
String spjRunSeccompRule = null;
|
||||
if (problem.getSpjLanguage().equals("C")) {
|
||||
spjRunSeccompRule = Constants.RunConfig.SPJ_C.getSeccompRule();
|
||||
}else if(problem.getSpjLanguage().equals("C++")){
|
||||
spjRunSeccompRule = Constants.RunConfig.SPJ_CPP.getSeccompRule();
|
||||
}
|
||||
|
||||
// 调用安全沙盒进行编译操作
|
||||
HashMap<String, Object> result = compile(srcFilePath, fileDir, command, exePath, maxCpuTime,maxRealTime,maxMemory,envs);
|
||||
if (!(Boolean) result.get("result")){ // 编译失败
|
||||
// {msg:error,code:STATUS_COMPILE_ERROR}
|
||||
result.remove("result");
|
||||
}else{
|
||||
// 编译成功,则进行每个测试点进行测试
|
||||
List<JSONObject> testCaseResultList = judgeAllCase(exePath, fileDir, (long) problem.getTimeLimit(), problem.getTimeLimit() * 3L,
|
||||
problem.getMemoryLimit()*1024*1024L, runCommand, runEnvs, runSeccompRule, spjRunSeccompRule, memoryLimitCheckOnly);
|
||||
// 获取判题结果
|
||||
return getJudgeInfo(testCaseResultList, problem.getType() == 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package top.hcode.hoj.judger;
|
||||
|
||||
|
||||
import cn.hutool.core.io.file.FileWriter;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import top.hcode.hoj.pojo.entity.Judge;
|
||||
import top.hcode.hoj.pojo.entity.Problem;
|
||||
import top.hcode.hoj.util.Constants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: Himit_ZH
|
||||
* @Date: 2021/1/22 21:15
|
||||
* @Description:
|
||||
*/
|
||||
public class JudgePython2 extends JudgeStrategy {
|
||||
|
||||
private String code;
|
||||
|
||||
private Problem problem;
|
||||
|
||||
private Long submitId;
|
||||
|
||||
public JudgePython2(Problem problem, Judge judge) {
|
||||
super(problem,judge.getSubmitId());
|
||||
this.submitId = judge.getSubmitId();
|
||||
this.code = judge.getCode();
|
||||
this.problem = problem;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HashMap<String, Object> judge() {
|
||||
// 该提交对应的文件夹路径
|
||||
String fileDir = Constants.Compiler.WORKPLACE.getContent() + "/" + submitId;
|
||||
// 将代码写入文件
|
||||
String srcFilePath = fileDir + "/" + Constants.CompileConfig.PYTHON2.getSrcName();
|
||||
FileWriter fileWriter = new FileWriter(srcFilePath, CharsetUtil.UTF_8);
|
||||
fileWriter.write(code);
|
||||
// 编译指令
|
||||
String command = Constants.CompileConfig.PYTHON2.getCommand();
|
||||
// 输出exe文件路径
|
||||
String exePath = fileDir+"/"+Constants.CompileConfig.PYTHON2.getExeName();
|
||||
|
||||
String spjCompileResult = checkOrCompileSpj(problem.getSpjCode(), problem.getSpjLanguage());
|
||||
|
||||
// 如果该题是需要特别判题的,但是该特别判题程序不存在或编译时产生异常,则此次判题直接判系统错误。
|
||||
if (!spjCompileResult.equals("success")){
|
||||
HashMap<String,Object> result = new HashMap<>();
|
||||
result.put("code", Constants.Judge.STATUS_SYSTEM_ERROR.getStatus());
|
||||
result.put("msg", spjCompileResult);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 编译的一些时间空间参数等
|
||||
Long maxCpuTime = Constants.CompileConfig.PYTHON2.getMaxCpuTime();
|
||||
Long maxRealTime = Constants.CompileConfig.PYTHON2.getMaxRealTime();
|
||||
Long maxMemory = Constants.CompileConfig.PYTHON2.getMaxMemory();
|
||||
List<String> envs = Constants.RunConfig.PYTHON2.getEnvs();
|
||||
|
||||
// 运行的一些指令参数,环境配置等
|
||||
String runCommand = Constants.RunConfig.PYTHON2.getCommand();
|
||||
List<String> runEnvs = Constants.RunConfig.PYTHON2.getEnvs();
|
||||
String runSeccompRule = Constants.RunConfig.PYTHON2.getSeccompRule();
|
||||
Integer memoryLimitCheckOnly = Constants.RunConfig.PYTHON2.getMemoryLimitCheckOnly();
|
||||
|
||||
// 特别判题的参数,如果并非特别判题则为null即可
|
||||
String spjRunSeccompRule = null;
|
||||
if (problem.getSpjLanguage().equals("C")) {
|
||||
spjRunSeccompRule = Constants.RunConfig.SPJ_C.getSeccompRule();
|
||||
}else if(problem.getSpjLanguage().equals("C++")){
|
||||
spjRunSeccompRule = Constants.RunConfig.SPJ_CPP.getSeccompRule();
|
||||
}
|
||||
|
||||
// 调用安全沙盒进行编译操作
|
||||
HashMap<String, Object> result = compile(srcFilePath, fileDir, command, exePath, maxCpuTime,maxRealTime,maxMemory,envs);
|
||||
if (!(Boolean) result.get("result")){ // 编译失败
|
||||
// {msg:error,code:STATUS_COMPILE_ERROR}
|
||||
result.remove("result");
|
||||
}else{
|
||||
// 编译成功,则进行每个测试点进行测试
|
||||
List<JSONObject> testCaseResultList = judgeAllCase(exePath, fileDir, (long) problem.getTimeLimit(), problem.getTimeLimit() * 3L,
|
||||
problem.getMemoryLimit()*1024*1024L, runCommand, runEnvs, runSeccompRule, spjRunSeccompRule, memoryLimitCheckOnly);
|
||||
// 获取判题结果
|
||||
return getJudgeInfo(testCaseResultList, problem.getType() == 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package top.hcode.hoj.judger;
|
||||
|
||||
import cn.hutool.core.io.file.FileWriter;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import top.hcode.hoj.pojo.entity.Judge;
|
||||
import top.hcode.hoj.pojo.entity.Problem;
|
||||
import top.hcode.hoj.util.Constants;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: Himit_ZH
|
||||
* @Date: 2021/1/22 21:15
|
||||
* @Description:
|
||||
*/
|
||||
public class JudgePython3 extends JudgeStrategy {
|
||||
|
||||
private String code;
|
||||
|
||||
private Problem problem;
|
||||
|
||||
private Long submitId;
|
||||
|
||||
public JudgePython3(Problem problem, Judge judge) {
|
||||
super(problem,judge.getSubmitId());
|
||||
this.submitId = judge.getSubmitId();
|
||||
this.code = judge.getCode();
|
||||
this.problem = problem;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HashMap<String, Object> judge() {
|
||||
// 该提交对应的文件夹路径
|
||||
String fileDir = Constants.Compiler.WORKPLACE.getContent() + "/" + submitId;
|
||||
// 将代码写入文件
|
||||
String srcFilePath = fileDir + "/" + Constants.CompileConfig.PYTHON3.getSrcName();
|
||||
FileWriter fileWriter = new FileWriter(srcFilePath, CharsetUtil.UTF_8);
|
||||
fileWriter.write(code);
|
||||
// 编译指令
|
||||
String command = Constants.CompileConfig.PYTHON3.getCommand();
|
||||
// 输出exe文件路径
|
||||
String exePath = fileDir+"/"+Constants.CompileConfig.PYTHON3.getExeName();
|
||||
|
||||
String spjCompileResult = checkOrCompileSpj(problem.getSpjCode(), problem.getSpjLanguage());
|
||||
|
||||
// 如果该题是需要特别判题的,但是该特别判题程序不存在或编译时产生异常,则此次判题直接判系统错误。
|
||||
if (!spjCompileResult.equals("success")){
|
||||
HashMap<String,Object> result = new HashMap<>();
|
||||
result.put("code", Constants.Judge.STATUS_SYSTEM_ERROR.getStatus());
|
||||
result.put("msg", spjCompileResult);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 编译的一些时间空间参数等
|
||||
Long maxCpuTime = Constants.CompileConfig.PYTHON3.getMaxCpuTime();
|
||||
Long maxRealTime = Constants.CompileConfig.PYTHON3.getMaxRealTime();
|
||||
Long maxMemory = Constants.CompileConfig.PYTHON3.getMaxMemory();
|
||||
List<String> envs = Constants.RunConfig.PYTHON3.getEnvs();
|
||||
|
||||
// 运行的一些指令参数,环境配置等
|
||||
String runCommand = Constants.RunConfig.PYTHON3.getCommand();
|
||||
List<String> runEnvs = Constants.RunConfig.PYTHON3.getEnvs();
|
||||
String runSeccompRule = Constants.RunConfig.PYTHON3.getSeccompRule();
|
||||
Integer memoryLimitCheckOnly = Constants.RunConfig.PYTHON3.getMemoryLimitCheckOnly();
|
||||
|
||||
// 特别判题的参数,如果并非特别判题则为null即可
|
||||
String spjRunSeccompRule = null;
|
||||
if (problem.getSpjLanguage().equals("C")) {
|
||||
spjRunSeccompRule = Constants.RunConfig.SPJ_C.getSeccompRule();
|
||||
}else if(problem.getSpjLanguage().equals("C++")){
|
||||
spjRunSeccompRule = Constants.RunConfig.SPJ_CPP.getSeccompRule();
|
||||
}
|
||||
|
||||
// 调用安全沙盒进行编译操作
|
||||
HashMap<String, Object> result = compile(srcFilePath, fileDir, command, exePath, maxCpuTime,maxRealTime,maxMemory,envs);
|
||||
if (!(Boolean) result.get("result")){ // 编译失败
|
||||
// {msg:error,code:STATUS_COMPILE_ERROR}
|
||||
result.remove("result");
|
||||
}else{
|
||||
// 编译成功,则进行每个测试点进行测试
|
||||
List<JSONObject> testCaseResultList = judgeAllCase(exePath, fileDir, (long) problem.getTimeLimit(), problem.getTimeLimit() * 3L,
|
||||
problem.getMemoryLimit()*1024*1024L, runCommand, runEnvs, runSeccompRule, spjRunSeccompRule, memoryLimitCheckOnly);
|
||||
// 获取判题结果
|
||||
return getJudgeInfo(testCaseResultList, problem.getType() == 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,480 @@
|
|||
package top.hcode.hoj.judger;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.file.FileReader;
|
||||
import cn.hutool.core.io.file.FileWriter;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import top.hcode.hoj.pojo.entity.Problem;
|
||||
import top.hcode.hoj.util.Constants;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
public abstract class JudgeStrategy {
|
||||
|
||||
private static final int SPJ_WA = 1;
|
||||
|
||||
private static final int SPJ_AC = 0;
|
||||
|
||||
private static final int SPJ_ERROR = -1;
|
||||
|
||||
private static final int cpuNum = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
private JSONObject testCasesInfo;
|
||||
|
||||
private String testCasesDir;
|
||||
|
||||
private String submissionDir;
|
||||
|
||||
private String spjExePath;
|
||||
|
||||
private String spjExeName;
|
||||
|
||||
private String spjRunCommand;
|
||||
|
||||
private Long problemId;
|
||||
|
||||
public JudgeStrategy(Problem problem, Long submitId) {
|
||||
this.problemId = problem.getId();
|
||||
this.testCasesInfo = loadTestCaseInfo(problemId);
|
||||
this.testCasesDir = Constants.Compiler.TEST_CASE_DIR.getContent() + "/problem_" + problemId;
|
||||
this.submissionDir = Constants.Compiler.WORKPLACE.getContent() + "/" + submitId;
|
||||
if (problem.getSpjLanguage().equals("C")) { //
|
||||
this.spjRunCommand = Constants.RunConfig.SPJ_C.getCommand();
|
||||
String spjExeName = MessageFormat.format(Constants.CompileConfig.SPJ_C.getExeName(), problem.getId());
|
||||
this.spjExeName = spjExeName;
|
||||
this.spjExePath = Constants.Compiler.SPJ_EXE_DIR.getContent() + "/" + MessageFormat.format(spjExeName, problemId);
|
||||
if (!FileUtil.exist(spjExePath)) {
|
||||
this.spjExePath = null;
|
||||
}
|
||||
} else if (problem.getSpjLanguage().equals("C++")) {
|
||||
this.spjRunCommand = Constants.RunConfig.SPJ_CPP.getCommand();
|
||||
String spjExeName = MessageFormat.format(Constants.CompileConfig.SPJ_CPP.getExeName(), problem.getId());
|
||||
this.spjExeName = spjExeName;
|
||||
this.spjExePath = Constants.Compiler.SPJ_EXE_DIR.getContent() + "/" + MessageFormat.format(spjExeName, problemId);
|
||||
if (!FileUtil.exist(spjExePath)) {
|
||||
this.spjExePath = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HashMap<String, Object> compile(String srcPath, String outputDir, String command, String exePath,
|
||||
Long maxCpuTime, Long maxRealTime, Long maxMemory, List<String> envs) {
|
||||
|
||||
// 执行的exe指令路径
|
||||
command = MessageFormat.format(command, srcPath, outputDir, exePath);
|
||||
|
||||
List<String> commandList = Arrays.asList(command.split(" "));
|
||||
|
||||
// 编译后的重定向到文件
|
||||
String outFilePath = outputDir + "/compiler.out";
|
||||
|
||||
// 调用沙盒进行编译
|
||||
JSONObject result = SandboxRun.run(maxCpuTime,
|
||||
maxRealTime,
|
||||
maxMemory,
|
||||
128 * 1024 * 1024L,
|
||||
20 * 1024 * 1024L,
|
||||
Constants.SandBoxStatus.UNLIMITED.getStatus(),
|
||||
commandList.get(0),
|
||||
srcPath,
|
||||
outFilePath,
|
||||
outFilePath,
|
||||
commandList.subList(1, commandList.size()),
|
||||
envs,
|
||||
Constants.Compiler.COMPILE_LOG_PATH.getContent(),
|
||||
null,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
|
||||
System.out.println(result+"\n");
|
||||
|
||||
HashMap<String, Object> data = new HashMap<>();
|
||||
if (result == null) {
|
||||
data.put("result", false);
|
||||
data.put("code", Constants.Judge.STATUS_SYSTEM_ERROR.getStatus());
|
||||
data.put("msg", "Error running security sandbox.");
|
||||
return data;
|
||||
} else if (result.get("result") != Constants.SandBoxStatus.RESULT_SUCCESS.getStatus()) {
|
||||
data.put("result", false);
|
||||
if (FileUtil.exist(outFilePath)) {
|
||||
FileReader fileReader = new FileReader(outFilePath);
|
||||
String error = fileReader.readString();
|
||||
FileUtil.del(outFilePath);
|
||||
if (!StringUtils.isEmpty(error)) {
|
||||
data.put("msg", error);
|
||||
data.put("code", Constants.Judge.STATUS_COMPILE_ERROR.getStatus());
|
||||
return data;
|
||||
}
|
||||
}
|
||||
data.put("msg", MessageFormat.format("Compiler runtime error, info:{0}", result.toString()));
|
||||
data.put("code", Constants.Judge.STATUS_COMPILE_ERROR.getStatus());
|
||||
return data;
|
||||
} else {
|
||||
FileUtil.del(outFilePath);
|
||||
data.put("result", true);
|
||||
data.put("exePath", exePath);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public String checkOrCompileSpj(String spjCode, String spjLanguage) {
|
||||
// 如果是需要特判的题目,则需要检测特批程序是否已经编译,否则进行编译
|
||||
if (!StringUtils.isEmpty(spjCode)) {
|
||||
if (spjLanguage.equals("C")) {
|
||||
String srcName = MessageFormat.format(Constants.CompileConfig.SPJ_C.getSrcName(), problemId);
|
||||
String command = Constants.CompileConfig.SPJ_C.getCommand();
|
||||
Long maxCpuTime = Constants.CompileConfig.SPJ_C.getMaxCpuTime();
|
||||
Long maxRealTime = Constants.CompileConfig.SPJ_C.getMaxRealTime();
|
||||
Long maxMemory = Constants.CompileConfig.SPJ_C.getMaxMemory();
|
||||
|
||||
// 如果不存在该已经编译好的特批程序,则需要再次进行编译
|
||||
if (!FileUtil.exist(Constants.Compiler.SPJ_EXE_DIR.getContent() + "/" + spjExeName)) {
|
||||
String result = compileSpj(spjCode, srcName, spjExeName, command, maxCpuTime, maxRealTime, maxMemory, new LinkedList<String>());
|
||||
if (!result.equals("success")) { // 如果出错,直接在判题结束,报系统错误!
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} else if (spjLanguage.equals("C++")) {
|
||||
|
||||
String srcName = MessageFormat.format(Constants.CompileConfig.SPJ_CPP.getSrcName(), problemId);
|
||||
String command = Constants.CompileConfig.SPJ_CPP.getCommand();
|
||||
Long maxCpuTime = Constants.CompileConfig.SPJ_CPP.getMaxCpuTime();
|
||||
Long maxRealTime = Constants.CompileConfig.SPJ_CPP.getMaxRealTime();
|
||||
Long maxMemory = Constants.CompileConfig.SPJ_CPP.getMaxMemory();
|
||||
|
||||
// 如果不存在该已经编译好的特批程序,则需要再次进行编译
|
||||
if (!FileUtil.exist(Constants.Compiler.SPJ_EXE_DIR.getContent() + "/" + spjExeName)) {
|
||||
String result = compileSpj(spjCode, srcName, spjExeName, command, maxCpuTime, maxRealTime, maxMemory, new LinkedList<String>());
|
||||
if (!result.equals("success")) { // 如果出错,直接在判题结束,报系统错误!
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "success";
|
||||
}
|
||||
|
||||
|
||||
public String compileSpj(String spjCode, String srcName, String exeName, String command, Long maxCpuTime, Long maxRealTime,
|
||||
Long maxMemory, List<String> envs) {
|
||||
String srcPath = Constants.Compiler.SPJ_SRC_DIR.getContent() + "/" + srcName;
|
||||
String exePath = Constants.Compiler.SPJ_EXE_DIR.getContent() + "/" + exeName;
|
||||
if (!FileUtil.exist(srcPath) && !StringUtils.isEmpty(spjCode)) {
|
||||
// 如果不存在,则将特别判题代码写入
|
||||
FileWriter fileWriter = new FileWriter(srcPath);
|
||||
fileWriter.write(spjCode);
|
||||
}
|
||||
// 调用安全沙盒进行编译
|
||||
HashMap<String, Object> compileResult = compile(srcPath, Constants.Compiler.SPJ_EXE_DIR.getContent(), command, exePath, maxCpuTime, maxRealTime, maxMemory, envs);
|
||||
if ((Boolean) compileResult.getOrDefault("result", false)) {
|
||||
return "success";
|
||||
} else {
|
||||
log.error("特殊判题程序的编译异常---------------->{}", (String) compileResult.getOrDefault("msg", "特殊判题程序编译失败!"));
|
||||
return (String) compileResult.getOrDefault("msg", "特殊判题程序编译失败!");
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化测试数据,写成json文件
|
||||
public static void initTestCase(List<HashMap<String, Object>> testCases, Long problemId, Boolean isSpj) {
|
||||
|
||||
JSONObject result = new JSONObject();
|
||||
result.set("isSpj", isSpj);
|
||||
result.set("testCasesSize", testCases.size());
|
||||
result.set("testCases", new JSONArray());
|
||||
|
||||
String testCasesDir = Constants.Compiler.TEST_CASE_DIR.getContent() + "/problem_" + problemId;
|
||||
|
||||
// 无论有没有测试数据,一旦执行该函数,一律清空,重新生成该题目对应的测试数据文件
|
||||
FileUtil.del(testCasesDir);
|
||||
for (int index = 0; index < testCases.size(); index++) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
String inputName = index + ".in";
|
||||
jsonObject.set("inputName", inputName);
|
||||
// 生成对应文件
|
||||
FileWriter fileWriter = new FileWriter(testCasesDir + "/" + inputName, CharsetUtil.UTF_8);
|
||||
// 将该测试数据的输入写入到文件
|
||||
fileWriter.write((String) testCases.get(index).get("input"));
|
||||
|
||||
if (!isSpj) {
|
||||
String outputName = index + ".out";
|
||||
jsonObject.set("outputName", outputName);
|
||||
String outputData = (String) testCases.get(index).get("output");
|
||||
jsonObject.set("outputMd5", DigestUtils.md5DigestAsHex(outputData.getBytes()));
|
||||
jsonObject.set("outputSize", outputData.length());
|
||||
jsonObject.set("strippedOutputMd5", DigestUtils.md5DigestAsHex(outputData.trim().getBytes()));
|
||||
// 生成对应文件
|
||||
FileWriter outFile = new FileWriter(testCasesDir + "/" + outputName, CharsetUtil.UTF_8);
|
||||
outFile.write(outputData);
|
||||
}
|
||||
|
||||
((JSONArray) result.get("testCases")).put(index, jsonObject);
|
||||
}
|
||||
|
||||
FileWriter infoFile = new FileWriter(testCasesDir + "/info", CharsetUtil.UTF_8);
|
||||
// 写入记录文件
|
||||
infoFile.write(JSONUtil.toJsonStr(result));
|
||||
}
|
||||
|
||||
// 获取指定题目的info数据
|
||||
public JSONObject loadTestCaseInfo(Long problemId) {
|
||||
String testCasesDir = Constants.Compiler.TEST_CASE_DIR.getContent() + "/problem_" + problemId;
|
||||
if (FileUtil.exist(testCasesDir + "/info")) {
|
||||
FileReader fileReader = new FileReader(testCasesDir + "/info", CharsetUtil.UTF_8);
|
||||
String infoStr = fileReader.readString();
|
||||
return JSONUtil.parseObj(infoStr);
|
||||
} else {
|
||||
log.error("加载题目测试数据的info文件异常----------------->{}", problemId);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject getTestCasesInfo(int testCaseId) {
|
||||
return (JSONObject) ((JSONArray) testCasesInfo.get("testCases")).get(testCaseId);
|
||||
}
|
||||
|
||||
public Integer specialJudge(String inFilePath, String userOutFilePath, Long maxCpuTime, Long maxMemory, String spjRule) {
|
||||
|
||||
if (spjRunCommand == null || spjExePath == null) {
|
||||
log.error("spj-" + problemId + "---------------->{}", "该题特别判题程序不存在!");
|
||||
return null;
|
||||
}
|
||||
List<String> commandList = Arrays.asList(MessageFormat.format(spjRunCommand, spjExePath, inFilePath, userOutFilePath).split(" "));
|
||||
|
||||
JSONObject runResult = SandboxRun.run(maxCpuTime * 3,
|
||||
maxCpuTime * 9,
|
||||
maxMemory * 3,
|
||||
128 * 1024 * 1024L,
|
||||
1024 * 1024 * 1024L,
|
||||
Constants.SandBoxStatus.UNLIMITED.getStatus(),
|
||||
commandList.get(0),
|
||||
inFilePath,
|
||||
"/tmp/spj.out",
|
||||
"tmp/spj.out",
|
||||
commandList.subList(1, commandList.size()),
|
||||
null,
|
||||
Constants.Compiler.RUN_LOG_PATH.getContent(),
|
||||
spjRule,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
if (runResult == null) {
|
||||
return SPJ_ERROR;
|
||||
} else if (runResult.getInt("result").intValue() == Constants.SandBoxStatus.RESULT_SUCCESS.getStatus() ||
|
||||
(runResult.getInt("result").intValue() == Constants.SandBoxStatus.RESULT_RUNTIME_ERROR.getStatus() &&
|
||||
(runResult.getInt("exit_code") == SPJ_WA || runResult.getInt("exit_code") == SPJ_ERROR) &&
|
||||
runResult.getInt("signal") == 0)) {
|
||||
return runResult.getInt("exit_code");
|
||||
} else {
|
||||
return SPJ_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject judgeOneCase(int testCaseId, Boolean getUserOutput, Boolean isSpj, String exePath, String exeDir,
|
||||
Long maxCpuTime, Long maxRealTime, Long maxMemory, String command, List<String> envs,
|
||||
String seccompRule, String spjRule, Integer memoryLimitCheckOnly) {
|
||||
if (testCasesInfo != null) {
|
||||
JSONObject testCaseInfo = getTestCasesInfo(testCaseId);
|
||||
String inFile = testCasesDir + "/" + testCaseInfo.get("inputName");
|
||||
// 对于当前测试样例,用户程序的控制台输出对应生成的文件
|
||||
String realUserOutputFile = submissionDir + "/" + testCaseId + ".out";
|
||||
|
||||
List<String> commandList = Arrays.asList(MessageFormat.format(command, exePath, exeDir, maxMemory/1024).split(" "));
|
||||
// 调用沙盒环境进行程序运行测试样例
|
||||
JSONObject result = SandboxRun.run(maxCpuTime,
|
||||
maxRealTime,
|
||||
maxMemory,
|
||||
128 * 1024 * 1024L,
|
||||
Math.max(testCasesInfo.getLong("outputSize", 0L) * 2, 1024 * 1024 * 16L),
|
||||
Constants.SandBoxStatus.UNLIMITED.getStatus(),
|
||||
commandList.get(0),
|
||||
inFile,
|
||||
realUserOutputFile,
|
||||
realUserOutputFile,
|
||||
commandList.subList(1, commandList.size()),
|
||||
envs,
|
||||
Constants.Compiler.RUN_LOG_PATH.getContent(),
|
||||
seccompRule,
|
||||
0,
|
||||
0,
|
||||
memoryLimitCheckOnly);
|
||||
|
||||
if (result == null) {
|
||||
result = new JSONObject();
|
||||
result.set("msg", "Error running security sandbox.");
|
||||
result.set("cpu_time", 0L);
|
||||
result.set("memory", 0L);
|
||||
result.set("result", Constants.SandBoxStatus.RESULT_SYSTEM_ERROR.getStatus());
|
||||
return result;
|
||||
}
|
||||
|
||||
result.set("testCaseId", testCaseId);
|
||||
result.set("outputMd5", null);
|
||||
result.set("output", null);
|
||||
if (result.getInt("result").intValue() == Constants.SandBoxStatus.RESULT_SUCCESS.getStatus()) {
|
||||
if (!FileUtil.exist(realUserOutputFile)) {
|
||||
result.set("result", Constants.SandBoxStatus.RESULT_WRONG_ANSWER.getStatus());
|
||||
} else {
|
||||
if (isSpj) { // 特殊判题
|
||||
Integer spjResult = specialJudge(inFile, realUserOutputFile, maxCpuTime, maxMemory, spjRule);
|
||||
if (spjResult == null) {
|
||||
result.set("result", Constants.SandBoxStatus.RESULT_SYSTEM_ERROR.getStatus());
|
||||
result.set("msg", "The special Special judgment code doesn't exist.");
|
||||
} else if (spjResult == SPJ_WA) {
|
||||
result.set("result", Constants.SandBoxStatus.RESULT_WRONG_ANSWER.getStatus());
|
||||
} else if (spjResult == SPJ_ERROR) {
|
||||
result.set("result", Constants.SandBoxStatus.RESULT_SYSTEM_ERROR.getStatus());
|
||||
result.set("msg", "There's something wrong with the special Special judging.");
|
||||
}
|
||||
} else {
|
||||
// 与原测试数据输出的md5进行对比
|
||||
HashMap<String, Object> data = compareOutput(testCaseId, realUserOutputFile);
|
||||
result.set("outputMd5",data.get("outputMd5"));
|
||||
if (!(Boolean) data.get("result")) {
|
||||
result.set("result", Constants.SandBoxStatus.RESULT_WRONG_ANSWER.getStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getUserOutput) { // 如果需要获取用户对于该题目的输出
|
||||
FileReader fileReader = new FileReader(realUserOutputFile);
|
||||
result.set("output", fileReader.readString());
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
log.error("题号为:" + problemId + "的评测数据出错--------------->{}", "测试数据的统计数据info为空");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<JSONObject> judgeAllCase(String exePath, String exeDir, Long maxCpuTime, Long maxRealTime, Long maxMemory, String command, List<String> envs,
|
||||
String seccompRule, String spjRule, Integer memoryLimitCheckOnly) {
|
||||
// 使用线程池开启多线程测试每一测试输入数据
|
||||
ExecutorService threadPool = new ThreadPoolExecutor(
|
||||
cpuNum, // 核心线程数
|
||||
cpuNum * 2, // 最大线程数。最多几个线程并发。
|
||||
3,//当线程无任务时,几秒后结束该线程
|
||||
TimeUnit.SECONDS,// 结束线程时间单位
|
||||
new LinkedBlockingDeque<>(200), //阻塞队列,限制等候线程数
|
||||
Executors.defaultThreadFactory(),
|
||||
new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,也不会抛出异常!
|
||||
|
||||
List<FutureTask<JSONObject>> futureTasks = new ArrayList<>();
|
||||
JSONArray testcaseList = (JSONArray) testCasesInfo.get("testCases");
|
||||
Boolean isSpj = testCasesInfo.getBool("isSpj");
|
||||
for (int index = 0; index < testcaseList.size(); index++) {
|
||||
// 将每个需要测试的线程任务加入任务列表中
|
||||
final int testCaseId = index;
|
||||
futureTasks.add(new FutureTask<>(new Callable<JSONObject>() {
|
||||
@Override
|
||||
public JSONObject call() throws Exception {
|
||||
return judgeOneCase(testCaseId, false, isSpj, exePath, exeDir, maxCpuTime, maxRealTime,
|
||||
maxMemory, command, envs, seccompRule, spjRule, memoryLimitCheckOnly);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// 提交到线程池进行执行
|
||||
for (FutureTask<JSONObject> futureTask : futureTasks) {
|
||||
threadPool.submit(futureTask);
|
||||
}
|
||||
// 所有任务执行完成且等待队列中也无任务关闭线程池
|
||||
if (!threadPool.isShutdown()) {
|
||||
threadPool.shutdown();
|
||||
}
|
||||
// 阻塞主线程, 直至线程池关闭
|
||||
try {
|
||||
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
log.error("判题线程池异常--------------->{}", e.getMessage());
|
||||
}
|
||||
List<JSONObject> result = new LinkedList<>();
|
||||
|
||||
// 获取线程返回结果
|
||||
for (int i = 0; i < futureTasks.size(); i++) {
|
||||
try {
|
||||
JSONObject tmp = futureTasks.get(i).get();
|
||||
result.add(tmp);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 根据评测结果与用户程序跑出的字符串MD5进行对比
|
||||
public HashMap<String, Object> compareOutput(int testCaseId, String userOutputFile) {
|
||||
|
||||
FileReader fileReader = new FileReader(userOutputFile, CharsetUtil.UTF_8);
|
||||
String code = fileReader.readString();
|
||||
String outputMd5 = DigestUtils.md5DigestAsHex(code.trim().getBytes());
|
||||
HashMap<String, Object> result = new HashMap<>();
|
||||
if (outputMd5.equals(getTestCasesInfo(testCaseId).getStr("strippedOutputMd5"))) {
|
||||
result.put("result", true);
|
||||
} else {
|
||||
result.put("result", false);
|
||||
}
|
||||
result.put("outputMd5", outputMd5);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 获取判题的运行时间,运行空间,OI得分
|
||||
public HashMap<String, Object> computeResultInfo(List<JSONObject> testCaseResultList, Boolean isACM, Integer errorCaseNum) {
|
||||
HashMap<String, Object> result = new HashMap<>();
|
||||
// 用时和内存占用保存为多个测试点中最长的
|
||||
testCaseResultList.stream().max(Comparator.comparing(t -> t.getLong("cpu_time")))
|
||||
.ifPresent(t -> result.put("time", t.getLong("cpu_time")));
|
||||
|
||||
testCaseResultList.stream().max(Comparator.comparing(t -> t.getLong("memory")))
|
||||
.ifPresent(t -> result.put("memory", t.getLong("memory")));
|
||||
|
||||
// OI题目计算得分
|
||||
if (!isACM) {
|
||||
// 现在默认得分规则为 通过测试点数/总测试点数*100
|
||||
int score = 0;
|
||||
score = (testCaseResultList.size() - errorCaseNum) / testCaseResultList.size() * 100;
|
||||
result.put("score", score);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// 进行最终测试结果的判断(除编译失败外的评测状态码和时间,空间,OI题目的得分)
|
||||
public HashMap<String, Object> getJudgeInfo(List<JSONObject> testCaseResultList, Boolean isACM) {
|
||||
|
||||
|
||||
// 过滤出结果不是AC的测试点结果
|
||||
List<JSONObject> errorTestCaseList = testCaseResultList.stream()
|
||||
.filter(jsonObject -> jsonObject.getInt("result").intValue() != Constants.SandBoxStatus.RESULT_SUCCESS.getStatus())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 获取判题的运行时间,运行空间,OI得分
|
||||
HashMap<String, Object> result = computeResultInfo(testCaseResultList, isACM, errorTestCaseList.size());
|
||||
|
||||
// 如果该题为ACM类型的题目,多个测试点全部正确则AC,否则取第一个错误的测试点的状态
|
||||
// 如果该题为OI类型的题目, 若多个测试点全部正确则AC,若全部错误则取第一个错误测试点状态,否则为部分正确
|
||||
if (errorTestCaseList.size() == 0) { // 全部测试点正确,则为AC
|
||||
result.put("code", Constants.Judge.STATUS_ACCEPTED.getStatus());
|
||||
} else if (isACM || errorTestCaseList.size() == testCaseResultList.size()) {
|
||||
result.put("code", errorTestCaseList.get(0).getInt("result"));
|
||||
} else {
|
||||
result.put("code", Constants.Judge.STATUS_PARTIAL_ACCEPTED.getStatus());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public abstract HashMap<String, Object> judge();
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package top.hcode.hoj.judger;
|
||||
|
||||
import cn.hutool.core.io.file.FileReader;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.StringUtils;
|
||||
import top.hcode.hoj.util.Constants;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: Himit_ZH
|
||||
* @Date: 2021/1/23 13:44
|
||||
* @Description:
|
||||
*/
|
||||
@Slf4j
|
||||
public final class SandboxRun {
|
||||
|
||||
public static JSONObject run(Long maxCpuTime, Long maxRealTime, Long maxMemory, Long maxStack, Long maxOutputSize,
|
||||
Integer maxProcessNumber, String exePath, String inputPath, String outputPath,
|
||||
String errorPath, List<String> args, List<String> envs, String logPath,
|
||||
String seccompRuleName, Integer uid, Integer gid, Integer memoryLimitCheckOnly) {
|
||||
|
||||
StringBuffer sb = new StringBuffer(Constants.Compiler.JUDGER_LIB_PATH.getContent());
|
||||
|
||||
if (args != null) {
|
||||
for (String arg : args) {
|
||||
sb.append(" --args=" + arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (envs != null) {
|
||||
for (String env : envs) {
|
||||
sb.append(" --env=" + env);
|
||||
}
|
||||
}
|
||||
|
||||
sb.append(" --max_cpu_time=" + maxCpuTime);
|
||||
sb.append(" --max_real_time=" + maxRealTime);
|
||||
sb.append(" --max_memory=" + maxMemory);
|
||||
sb.append(" --max_stack=" + maxStack);
|
||||
sb.append(" --max_output_size=" + maxOutputSize);
|
||||
sb.append(" --max_process_number=" + maxProcessNumber);
|
||||
sb.append(" --uid=" + uid);
|
||||
sb.append(" --gid=" + gid);
|
||||
sb.append(" --memory_limit_check_only=0");
|
||||
|
||||
sb.append(" --exe_path=" + exePath);
|
||||
sb.append(" --input_path=" + inputPath);
|
||||
sb.append(" --output_path=" + outputPath);
|
||||
sb.append(" --error_path=" + errorPath);
|
||||
sb.append(" --log_path=" + logPath);
|
||||
|
||||
if (seccompRuleName != null) {
|
||||
sb.append(" --seccomp_rule=" + seccompRuleName);
|
||||
}
|
||||
|
||||
Process process = null;
|
||||
BufferedReader bufIn = null;
|
||||
BufferedReader bufError = null;
|
||||
try {
|
||||
String execution = sb.toString();
|
||||
process = Runtime.getRuntime().exec(execution);
|
||||
process.waitFor();
|
||||
// 获取命令执行结果, 有两个结果: 正常的输出 和 错误的输出(PS: 子进程的输出就是主进程的输入)
|
||||
bufIn = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
|
||||
bufError = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
|
||||
|
||||
// 读取输出
|
||||
String line = null;
|
||||
StringBuffer out = new StringBuffer();
|
||||
StringBuffer errorTmp = new StringBuffer();
|
||||
|
||||
while ((line = bufIn.readLine()) != null) {
|
||||
out.append(line).append('\n');
|
||||
}
|
||||
|
||||
while ((line = bufError.readLine()) != null) {
|
||||
errorTmp.append(line).append('\n');
|
||||
}
|
||||
|
||||
String error = errorTmp.toString();
|
||||
|
||||
if (!StringUtils.isEmpty(error)) { // 如果错误输出不为空的话
|
||||
log.error("调用沙盒运行程序时出错--------------------->{}", error);
|
||||
}
|
||||
JSONObject jsonObject = JSONUtil.parseObj(out.toString());
|
||||
return jsonObject;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("调用沙盒运行程序时出错--------------------->{}", e);
|
||||
} finally {
|
||||
if (process != null) {
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -2,6 +2,7 @@ package top.hcode.hoj.service;
|
|||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import top.hcode.hoj.pojo.entity.Judge;
|
||||
import top.hcode.hoj.pojo.entity.Problem;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -14,4 +15,5 @@ import top.hcode.hoj.pojo.entity.Judge;
|
|||
*/
|
||||
public interface JudgeService extends IService<Judge> {
|
||||
String test();
|
||||
Judge Judge(Problem problem, Judge judge);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package top.hcode.hoj.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import top.hcode.hoj.pojo.entity.Problem;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author Himit_ZH
|
||||
* @since 2020-10-23
|
||||
*/
|
||||
|
||||
public interface ProblemService extends IService<Problem> {
|
||||
|
||||
}
|
|
@ -4,8 +4,13 @@ package top.hcode.hoj.service.impl;
|
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.hcode.hoj.dao.JudgeMapper;
|
||||
import top.hcode.hoj.judger.*;
|
||||
import top.hcode.hoj.pojo.entity.Judge;
|
||||
import top.hcode.hoj.pojo.entity.Problem;
|
||||
import top.hcode.hoj.service.JudgeService;
|
||||
import top.hcode.hoj.util.Constants;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
@ -21,4 +26,51 @@ public class JudgeServiceImpl extends ServiceImpl<JudgeMapper, Judge> implements
|
|||
public String test() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Judge Judge(Problem problem, Judge judge) {
|
||||
|
||||
JudgeStrategy needJudge = getJudge(problem, judge);
|
||||
if (needJudge == null) {
|
||||
judge.setErrorMessage("Unknown Language!");
|
||||
judge.setStatus(Constants.Judge.STATUS_COMPILE_ERROR.getStatus());
|
||||
return judge;
|
||||
}
|
||||
|
||||
JudgeContext judgeContext = new JudgeContext(needJudge);
|
||||
HashMap<String, Object> result = judgeContext.judge();
|
||||
if (result.get("code") == Constants.Judge.STATUS_COMPILE_ERROR.getStatus() ||
|
||||
result.get("code") == Constants.Judge.STATUS_SYSTEM_ERROR.getStatus()) {
|
||||
judge.setStatus(Constants.Judge.STATUS_COMPILE_ERROR.getStatus());
|
||||
judge.setErrorMessage((String) result.get("msg"));
|
||||
} else {
|
||||
judge.setStatus((Integer) result.get("code"));
|
||||
Long memory = (Long)result.get("memory"); // 单位为long类型的b
|
||||
judge.setMemory(memory.intValue());
|
||||
Long time = (Long)result.get("time");
|
||||
judge.setTime(time.intValue());
|
||||
if (problem.getType() == 0) {
|
||||
judge.setScore((Integer) result.getOrDefault("score", 0));
|
||||
}
|
||||
}
|
||||
return judge;
|
||||
}
|
||||
|
||||
public JudgeStrategy getJudge(Problem problem, Judge judge) {
|
||||
switch (judge.getLanguage()) {
|
||||
case "C":
|
||||
return new JudgeC(problem, judge);
|
||||
case "C++":
|
||||
return new JudgeCPP(problem, judge);
|
||||
case "Python3":
|
||||
return new JudgePython3(problem, judge);
|
||||
case "Python2":
|
||||
return new JudgePython2(problem, judge);
|
||||
case "Java":
|
||||
return new JudgeJava(problem, judge);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,12 +33,6 @@ public class ProblemCountServiceImpl extends ServiceImpl<ProblemCountMapper, Pro
|
|||
@Autowired
|
||||
private ProblemCountMapper problemCountMapper;
|
||||
|
||||
@Autowired
|
||||
private UserRecordServiceImpl userRecordService;
|
||||
|
||||
@Autowired
|
||||
private JudgeServiceImpl judgeService;
|
||||
|
||||
// 默认的事务隔离等级可重复读会产生幻读,读不到新的version数据,所以需要更换等级为读已提交
|
||||
@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
|
||||
@Async
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package top.hcode.hoj.service.impl;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.hcode.hoj.dao.ProblemMapper;
|
||||
import top.hcode.hoj.pojo.entity.Problem;
|
||||
import top.hcode.hoj.service.ProblemService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author Himit_ZH
|
||||
* @since 2020-10-23
|
||||
*/
|
||||
@Service
|
||||
public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> implements ProblemService {
|
||||
|
||||
}
|
|
@ -1,5 +1,9 @@
|
|||
package top.hcode.hoj.util;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: Himit_ZH
|
||||
* @Date: 2021/1/1 13:00
|
||||
|
@ -10,22 +14,22 @@ public class Constants {
|
|||
* @Description 提交评测结果的状态码
|
||||
* @Since 2021/1/1
|
||||
*/
|
||||
public enum Judge{
|
||||
STATUS_NOT_SUBMITTED (-10,"Not Submitted"),
|
||||
STATUS_PRESENTATION_ERROR (-3,"Presentation Error"),
|
||||
STATUS_COMPILE_ERROR (-2,"Compile Error"),
|
||||
STATUS_WRONG_ANSWER (-1,"Wrong Answer"),
|
||||
STATUS_ACCEPTED (0,"Accepted"),
|
||||
STATUS_CPU_TIME_LIMIT_EXCEEDED (1,"CPU Time Limit Exceeded"),
|
||||
STATUS_REAL_TIME_LIMIT_EXCEEDED (2,"Real Time Limit Exceeded"),
|
||||
STATUS_MEMORY_LIMIT_EXCEEDED (3,"Memory Limit Exceeded"),
|
||||
STATUS_RUNTIME_ERROR (4,"Runtime Error"),
|
||||
STATUS_SYSTEM_ERROR (5,"System Error"),
|
||||
STATUS_PENDING (6,"Pending"),
|
||||
STATUS_JUDGING (7,"Judging"),
|
||||
STATUS_PARTIAL_ACCEPTED (8,"Partial Accepted"),
|
||||
STATUS_SUBMITTING (9,"Submitting"),
|
||||
STATUS_NULL (10,"No Status");
|
||||
public enum Judge {
|
||||
STATUS_NOT_SUBMITTED(-10, "Not Submitted"),
|
||||
STATUS_PRESENTATION_ERROR(-3, "Presentation Error"),
|
||||
STATUS_COMPILE_ERROR(-2, "Compile Error"),
|
||||
STATUS_WRONG_ANSWER(-1, "Wrong Answer"),
|
||||
STATUS_ACCEPTED(0, "Accepted"),
|
||||
STATUS_CPU_TIME_LIMIT_EXCEEDED(1, "CPU Time Limit Exceeded"),
|
||||
STATUS_REAL_TIME_LIMIT_EXCEEDED(2, "Real Time Limit Exceeded"),
|
||||
STATUS_MEMORY_LIMIT_EXCEEDED(3, "Memory Limit Exceeded"),
|
||||
STATUS_RUNTIME_ERROR(4, "Runtime Error"),
|
||||
STATUS_SYSTEM_ERROR(5, "System Error"),
|
||||
STATUS_PENDING(6, "Pending"),
|
||||
STATUS_JUDGING(7, "Judging"),
|
||||
STATUS_PARTIAL_ACCEPTED(8, "Partial Accepted"),
|
||||
STATUS_SUBMITTING(9, "Submitting"),
|
||||
STATUS_NULL(10, "No Status");
|
||||
|
||||
private final Integer status;
|
||||
private final String name;
|
||||
|
@ -43,9 +47,9 @@ public class Constants {
|
|||
return name;
|
||||
}
|
||||
|
||||
public static Judge getTypeByStatus(int status){
|
||||
for (Judge judge:Judge.values()){
|
||||
if (judge.getStatus()==status){
|
||||
public static Judge getTypeByStatus(int status) {
|
||||
for (Judge judge : Judge.values()) {
|
||||
if (judge.getStatus() == status) {
|
||||
return judge;
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +57,180 @@ public class Constants {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public enum SandBoxStatus {
|
||||
UNLIMITED(-1),
|
||||
VERSION(0x020101),
|
||||
|
||||
RESULT_SUCCESS (0),
|
||||
RESULT_WRONG_ANSWER (-1),
|
||||
RESULT_CPU_TIME_LIMIT_EXCEEDED (1),
|
||||
RESULT_REAL_TIME_LIMIT_EXCEEDED (2),
|
||||
RESULT_MEMORY_LIMIT_EXCEEDED (3),
|
||||
RESULT_RUNTIME_ERROR (4),
|
||||
RESULT_SYSTEM_ERROR (5),
|
||||
|
||||
ERROR_INVALID_CONFIG (-1),
|
||||
ERROR_FORK_FAILED (-2),
|
||||
ERROR_PTHREAD_FAILED (-3),
|
||||
ERROR_WAIT_FAILED (-4),
|
||||
ERROR_ROOT_REQUIRED (-5),
|
||||
ERROR_LOAD_SECCOMP_FAILED (-6),
|
||||
ERROR_SETRLIMIT_FAILED (-7),
|
||||
ERROR_DUP2_FAILED (-8),
|
||||
ERROR_SETUID_FAILED (-9),
|
||||
ERROR_EXECVE_FAILED (-10),
|
||||
ERROR_SPJ_ERROR (-11);
|
||||
|
||||
private Integer status;
|
||||
SandBoxStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Compiler {
|
||||
|
||||
WORKPLACE("/judge/run"),
|
||||
|
||||
JUDGER_LIB_PATH("/usr/lib/judger/libjudger.so"),
|
||||
|
||||
COMPILE_LOG_PATH("/log/compiler.log"),
|
||||
|
||||
RUN_LOG_PATH("/log/judger.log"),
|
||||
|
||||
TEST_CASE_DIR("/judge/test_case"),
|
||||
|
||||
SPJ_SRC_DIR("/judge/spj"),
|
||||
|
||||
SPJ_EXE_DIR("/judge/spj");
|
||||
|
||||
private String content;
|
||||
|
||||
Compiler(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
public enum CompileConfig {
|
||||
C("main.c", "main", 3000L, 10000L, 256 * 1024 * 1024L, "/usr/bin/gcc -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c11 {0} -lm -o {1}"),
|
||||
|
||||
CPP("main.cpp", "main", 10000L, 20000L, 1024 * 1024 * 1024L, "/usr/bin/g++ -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c++14 {0} -lm -o {1}"),
|
||||
|
||||
JAVA("Main.java", "Main", 5000L, 10000L, -1L, "/usr/bin/javac {0} -d {1} -encoding UTF8"),
|
||||
|
||||
PYTHON2("main.py", "main.pyc", 3000L, 10000L, 128 * 1024 * 1024L, "/usr/bin/python -m py_compile {0}"),
|
||||
|
||||
PYTHON3("main.py", "__pycache__/main.cpython-36.pyc", 3000L, 10000L, 128 * 1024 * 1024L, "/usr/bin/python3 -m py_compile {0}"),
|
||||
|
||||
SPJ_C("spj-{0}.c","spj-{0}",3000L,5000L,1024*1024*1024L,"/usr/bin/gcc -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c99 {0} -lm -o {1}"),
|
||||
|
||||
SPJ_CPP("spj-{0}.cpp","spj-{0}",10000L,20000L,1024*1024*1024L,"/usr/bin/g++ -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c++14 {0} -lm -o {1}");
|
||||
|
||||
|
||||
private String srcName;
|
||||
private String exeName;
|
||||
private Long maxCpuTime;
|
||||
private Long maxRealTime;
|
||||
private Long maxMemory;
|
||||
private String command;
|
||||
|
||||
CompileConfig(String srcName, String exeName, Long maxCpuTime, Long maxRealTime, Long maxMemory, String command) {
|
||||
this.srcName = srcName;
|
||||
this.exeName = exeName;
|
||||
this.maxCpuTime = maxCpuTime;
|
||||
this.maxRealTime = maxRealTime;
|
||||
this.maxMemory = maxMemory;
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public String getSrcName() {
|
||||
return srcName;
|
||||
}
|
||||
|
||||
public String getExeName() {
|
||||
return exeName;
|
||||
}
|
||||
|
||||
public Long getMaxCpuTime() {
|
||||
return maxCpuTime;
|
||||
}
|
||||
|
||||
public Long getMaxRealTime() {
|
||||
return maxRealTime;
|
||||
}
|
||||
|
||||
public Long getMaxMemory() {
|
||||
return maxMemory;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static List<String> defaultEnv = Arrays.asList("LANG=en_US.UTF-8",
|
||||
"LANGUAGE=en_US:en", "LC_ALL=en_US.UTF-8");
|
||||
|
||||
public static List<String> python3Env = Arrays.asList("LANG=en_US.UTF-8",
|
||||
"LANGUAGE=en_US:en", "LC_ALL=en_US.UTF-8", "PYTHONIOENCODING=utf-8");
|
||||
|
||||
public enum RunConfig {
|
||||
C("{0}", "c_cpp", defaultEnv, 0),
|
||||
|
||||
CPP("{0}", "c_cpp", defaultEnv, 0),
|
||||
|
||||
JAVA("/usr/bin/java -cp {1} -Djava.security.manager " +
|
||||
"-Dfile.encoding=UTF-8 -Djava.security.policy==policy -Djava.awt.headless=true Main",
|
||||
null, defaultEnv, 1),
|
||||
|
||||
PYTHON2("/usr/bin/python {0}", "general", defaultEnv, 0),
|
||||
|
||||
|
||||
PYTHON3("/usr/bin/python3 {0}", "general", python3Env, 0),
|
||||
|
||||
SPJ_C("{0} {1} {2}","c_cpp",null,0),
|
||||
|
||||
SPJ_CPP("{0} {1} {2}","c_cpp",null,0);
|
||||
|
||||
private String command;
|
||||
private String seccompRule;
|
||||
private List<String> envs;
|
||||
private Integer memoryLimitCheckOnly;
|
||||
|
||||
RunConfig(String command, String seccompRule, List<String> envs, Integer memoryLimitCheckOnly) {
|
||||
this.command = command;
|
||||
this.seccompRule = seccompRule;
|
||||
this.envs = envs;
|
||||
this.memoryLimitCheckOnly = memoryLimitCheckOnly;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public String getSeccompRule() {
|
||||
return seccompRule;
|
||||
}
|
||||
|
||||
public List<String> getEnvs() {
|
||||
return envs;
|
||||
}
|
||||
|
||||
public Integer getMemoryLimitCheckOnly() {
|
||||
return memoryLimitCheckOnly;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Description 比赛相关的常量
|
||||
* @Since 2021/1/7
|
||||
|
@ -61,17 +239,17 @@ public class Constants {
|
|||
TYPE_ACM(0, "ACM"),
|
||||
TYPE_OI(1, "OI"),
|
||||
|
||||
STATUS_SCHEDULED(-1,"Scheduled"),
|
||||
STATUS_RUNNING(0,"Running"),
|
||||
STATUS_ENDED(1,"Ended"),
|
||||
STATUS_SCHEDULED(-1, "Scheduled"),
|
||||
STATUS_RUNNING(0, "Running"),
|
||||
STATUS_ENDED(1, "Ended"),
|
||||
|
||||
AUTH_PUBLIC(0,"Public"),
|
||||
AUTH_PRIVATE(1,"Private"),
|
||||
AUTH_PROTECT(2,"Protect"),
|
||||
AUTH_PUBLIC(0, "Public"),
|
||||
AUTH_PRIVATE(1, "Private"),
|
||||
AUTH_PROTECT(2, "Protect"),
|
||||
|
||||
RECORD_NOT_AC_PENALTY(-1,"未AC通过算罚时"),
|
||||
RECORD_NOT_AC_NOT_PENALTY(0,"未AC通过不罚时"),
|
||||
RECORD_AC(1,"AC通过");
|
||||
RECORD_NOT_AC_PENALTY(-1, "未AC通过算罚时"),
|
||||
RECORD_NOT_AC_NOT_PENALTY(0, "未AC通过不罚时"),
|
||||
RECORD_AC(1, "AC通过");
|
||||
|
||||
private final Integer code;
|
||||
private final String name;
|
||||
|
@ -89,4 +267,6 @@ public class Constants {
|
|||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
#Generated by Maven
|
||||
#Tue Jan 26 15:57:01 CST 2021
|
||||
version=1.0-SNAPSHOT
|
||||
groupId=top.hcode
|
||||
artifactId=JudgeServer
|
|
@ -0,0 +1,54 @@
|
|||
top\hcode\hoj\judger\JudgeStrategy.class
|
||||
top\hcode\hoj\JudgeServerApplication.class
|
||||
top\hcode\hoj\service\impl\SystemConfigServiceImpl.class
|
||||
top\hcode\hoj\common\CommonResult.class
|
||||
top\hcode\hoj\dao\ProblemMapper.class
|
||||
top\hcode\hoj\judger\JudgePython2.class
|
||||
top\hcode\hoj\util\Constants$SandBoxStatus.class
|
||||
top\hcode\hoj\config\AsyncTaskConfig.class
|
||||
top\hcode\hoj\dao\JudgeCaseMapper.class
|
||||
top\hcode\hoj\dao\UserRecordMapper.class
|
||||
top\hcode\hoj\service\impl\ProblemCountServiceImpl.class
|
||||
top\hcode\hoj\service\impl\UserAcproblemServiceImpl.class
|
||||
top\hcode\hoj\controller\JudgeController.class
|
||||
top\hcode\hoj\judger\JudgeJava.class
|
||||
top\hcode\hoj\dao\ProblemCountMapper.class
|
||||
top\hcode\hoj\service\impl\ProblemCaseServiceImpl.class
|
||||
top\hcode\hoj\util\Constants$RunConfig.class
|
||||
top\hcode\hoj\dao\ContestMapper.class
|
||||
top\hcode\hoj\judger\JudgeContext.class
|
||||
top\hcode\hoj\service\ProblemCountService.class
|
||||
top\hcode\hoj\judger\JudgeCPP.class
|
||||
top\hcode\hoj\util\Constants$Compiler.class
|
||||
top\hcode\hoj\config\MyMetaObjectConfig.class
|
||||
top\hcode\hoj\service\impl\JudgeCaseServiceImpl.class
|
||||
top\hcode\hoj\service\SystemConfigService.class
|
||||
top\hcode\hoj\service\impl\JudgeServiceImpl.class
|
||||
top\hcode\hoj\service\ContestRecordService.class
|
||||
top\hcode\hoj\config\MybatisPlusConfig.class
|
||||
top\hcode\hoj\controller\SystemConfigController.class
|
||||
top\hcode\hoj\judger\JudgePython3.class
|
||||
top\hcode\hoj\service\impl\ContestServiceImpl.class
|
||||
top\hcode\hoj\service\ProblemService.class
|
||||
top\hcode\hoj\dao\ContestRecordMapper.class
|
||||
top\hcode\hoj\service\impl\ContestRecordServiceImpl.class
|
||||
top\hcode\hoj\service\JudgeCaseService.class
|
||||
top\hcode\hoj\dao\UserAcproblemMapper.class
|
||||
top\hcode\hoj\util\Constants$CompileConfig.class
|
||||
top\hcode\hoj\util\IpUtils.class
|
||||
top\hcode\hoj\service\ContestService.class
|
||||
top\hcode\hoj\service\impl\ProblemCountServiceImpl$1.class
|
||||
top\hcode\hoj\service\UserRecordService.class
|
||||
top\hcode\hoj\util\Constants$Contest.class
|
||||
top\hcode\hoj\service\impl\ProblemServiceImpl.class
|
||||
top\hcode\hoj\judger\JudgeStrategy$1.class
|
||||
top\hcode\hoj\service\UserAcproblemService.class
|
||||
top\hcode\hoj\dao\ProblemCaseMapper.class
|
||||
top\hcode\hoj\service\impl\UserRecordServiceImpl.class
|
||||
top\hcode\hoj\judger\SandboxRun.class
|
||||
top\hcode\hoj\service\ProblemCaseService.class
|
||||
top\hcode\hoj\dao\JudgeMapper.class
|
||||
top\hcode\hoj\judger\JudgeC.class
|
||||
top\hcode\hoj\service\JudgeService.class
|
||||
top\hcode\hoj\util\Constants.class
|
||||
top\hcode\hoj\util\Constants$Judge.class
|
|
@ -0,0 +1,46 @@
|
|||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\judger\JudgePython2.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\dao\ContestRecordMapper.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\JudgeServerApplication.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\UserAcproblemService.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\dao\ProblemMapper.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\dao\ProblemCountMapper.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\config\AsyncTaskConfig.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\impl\SystemConfigServiceImpl.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\judger\SandboxRun.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\dao\JudgeCaseMapper.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\common\CommonResult.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\JudgeService.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\dao\UserRecordMapper.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\impl\UserRecordServiceImpl.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\ProblemCountService.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\ProblemService.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\UserRecordService.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\impl\ProblemCountServiceImpl.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\judger\JudgeJava.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\impl\JudgeServiceImpl.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\controller\SystemConfigController.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\judger\JudgeC.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\judger\JudgeStrategy.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\judger\JudgeCPP.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\dao\ProblemCaseMapper.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\impl\ContestRecordServiceImpl.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\ContestRecordService.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\impl\ContestServiceImpl.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\judger\JudgePython3.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\util\IpUtils.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\dao\JudgeMapper.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\impl\ProblemServiceImpl.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\util\Constants.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\impl\UserAcproblemServiceImpl.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\SystemConfigService.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\ContestService.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\dao\UserAcproblemMapper.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\impl\ProblemCaseServiceImpl.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\ProblemCaseService.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\config\MybatisPlusConfig.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\judger\JudgeContext.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\config\MyMetaObjectConfig.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\impl\JudgeCaseServiceImpl.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\controller\JudgeController.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\dao\ContestMapper.java
|
||||
E:\code\Gitee\hoj\hoj-springboot\JudgeServer\src\main\java\top\hcode\hoj\service\JudgeCaseService.java
|
|
@ -24,14 +24,21 @@
|
|||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests> <!--默认关掉单元测试 -->
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<!--版本控制-->
|
||||
<properties>
|
||||
<project.bulid.sourceEncoding>UTF-8</project.bulid.sourceEncoding>
|
||||
<maven.compiler.sourse>1.8</maven.compiler.sourse>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven.compiler.sourse>8</maven.compiler.sourse>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<junit.version>4.12</junit.version>
|
||||
<lombok.version>1.16.10</lombok.version>
|
||||
<log4j.version>1.2.17</log4j.version>
|
||||
|
|
Loading…
Reference in New Issue