修复导入qdoj题目数据出错

This commit is contained in:
Himit_ZH 2021-06-15 19:31:14 +08:00
parent bf6fdaae26
commit 30f6022403
5 changed files with 93 additions and 37 deletions

View File

@ -8,8 +8,8 @@
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="api" />
<module name="DataBackup" />
<module name="JudgeServer" />
<module name="DataBackup" />
</profile>
</annotationProcessing>
</component>

View File

@ -414,7 +414,7 @@ public class FileController {
@GetMapping("/download-contest-ac-submission")
@RequiresAuthentication
@RequiresRoles(value = {"root", "admin","problem_admin"}, logical = Logical.OR)
@RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
public void downloadContestACSubmission(@RequestParam("cid") Long cid,
@RequestParam(value = "excludeAdmin", defaultValue = "false") Boolean excludeAdmin,
HttpServletRequest request,
@ -427,7 +427,7 @@ public class FileController {
UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo");
boolean isRoot = SecurityUtils.getSubject().hasRole("root");
// 除非是root 其它管理员只能下载自己的比赛ac记录
if (!userRolesVo.getUid().equals(contest.getUid())&&!isRoot){
if (!userRolesVo.getUid().equals(contest.getUid()) && !isRoot) {
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
@ -460,7 +460,7 @@ public class FileController {
.isNotNull(!isACM, "score") // OI模式取得分不为null的
.between("submit_time", contest.getStartTime(), contest.getEndTime())
.ne(excludeAdmin, "uid", contest.getUid()) // 排除比赛创建者和root
.ne(excludeAdmin, "username","root")
.ne(excludeAdmin, "username", "root")
.orderByDesc("submit_time");
List<Judge> judgeList = judgeService.list(judgeQueryWrapper);
@ -645,7 +645,7 @@ public class FileController {
@RequestMapping(value = "/upload-md-file", method = RequestMethod.POST)
@RequiresAuthentication
@ResponseBody
@RequiresRoles(value = {"root", "admin","problem_admin"}, logical = Logical.OR)
@RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
public CommonResult uploadMd(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
if (file == null) {
return CommonResult.errorResponse("上传的文件不能为空!");
@ -844,7 +844,6 @@ public class FileController {
for (ProblemDto problemDto : problemDtos) {
problemService.adminAddProblem(problemDto);
}
FileUtil.del(fileDir);
return CommonResult.successResponse(null, "导入题目成功");
}
@ -979,7 +978,6 @@ public class FileController {
for (ProblemDto problemDto : problemDtos) {
problemService.adminAddProblem(problemDto);
}
FileUtil.del(fileDir);
return CommonResult.successResponse(null, "导入题目成功");
}
@ -988,10 +986,17 @@ public class FileController {
QDOJProblemDto qdojProblemDto = new QDOJProblemDto();
List<String> tags = (List<String>) problemJson.get("tags");
qdojProblemDto.setTags(tags.stream().map(UnicodeUtil::toString).collect(Collectors.toList()));
qdojProblemDto.setLanguages(Arrays.asList("C", "C++", "Java", "Python3", "Python2", "Golang", "C#"));
JSONObject spj = problemJson.getJSONObject("spj");
qdojProblemDto.setIsSpj(spj != null);
qdojProblemDto.setLanguages(Arrays.asList("C", "C With O2", "C++", "C++ With O2", "Java", "Python3", "Python2", "Golang", "C#"));
Object spj = problemJson.getObj("spj");
boolean isSpj = !JSONUtil.isNull(spj);
qdojProblemDto.setIsSpj(isSpj);
Problem problem = new Problem();
if (isSpj) {
JSONObject spjJson = JSONUtil.parseObj(spj);
problem.setSpjCode(spjJson.getStr("code"))
.setSpjLanguage(spjJson.getStr("language"));
}
problem.setAuth(1)
.setIsUploadCase(true)
.setSource(problemJson.getStr("source", null))
@ -1009,11 +1014,6 @@ public class FileController {
.setTimeLimit(problemJson.getInt("time_limit"))
.setMemoryLimit(problemJson.getInt("memory_limit"));
if (qdojProblemDto.getIsSpj() && spj != null) {
problem.setSpjCode(spj.getStr("code"))
.setSpjLanguage(spj.getStr("language"));
}
JSONArray samples = problemJson.getJSONArray("samples");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < samples.size(); i++) {

View File

@ -451,7 +451,7 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
jsonObject.set("inputName", problemCase.getInput());
jsonObject.set("outputName", problemCase.getOutput());
// 读取输出文件
FileReader readFile = new FileReader(testCasesDir + "/" + problemCase.getOutput(), CharsetUtil.UTF_8);
FileReader readFile = new FileReader(testCasesDir + File.separator + problemCase.getOutput(), CharsetUtil.UTF_8);
String output = readFile.readString().replaceAll("\r\n", "\n");
// spj是根据特判程序输出判断结果所以无需初始化测试数据
@ -485,6 +485,7 @@ public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, Problem> impl
List<ProblemCase> problemCaseList) {
JSONObject result = new JSONObject();
System.out.println(isSpj);
result.set("isSpj", isSpj);
result.set("version", version);
result.set("testCasesSize", problemCaseList.size());

View File

@ -55,7 +55,7 @@ public class JudgeStrategy {
// 对用户源代码进行编译 获取tmpfs中的fileId
userFileId = Compiler.compile(Constants.CompileConfig.getCompilerByLanguage(judge.getLanguage()), judge.getCode(), judge.getLanguage());
// 测试数据文件所在文件夹
String testCasesDir = Constants.JudgeDir.TEST_CASE_DIR.getContent() + "/problem_" + problem.getId();
String testCasesDir = Constants.JudgeDir.TEST_CASE_DIR.getContent() +File.separator+"problem_" + problem.getId();
// 从文件中加载测试数据json
JSONObject testCasesInfo = problemTestCaseUtils.loadTestCaseInfo(problem.getId(), testCasesDir, problem.getCaseVersion(), !StringUtils.isEmpty(problem.getSpjCode()));
JSONArray testcaseList = (JSONArray) testCasesInfo.get("testCases");

View File

@ -16,6 +16,7 @@ import top.hcode.hoj.pojo.entity.ProblemCase;
import top.hcode.hoj.service.impl.ProblemCaseServiceImpl;
import top.hcode.hoj.util.Constants;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.LinkedList;
@ -32,7 +33,7 @@ public class ProblemTestCaseUtils {
@Autowired
ProblemCaseServiceImpl problemCaseService;
// 初始化测试数据写成json文件
// 本地无文件初始化测试数据写成json文件
public JSONObject initTestCase(List<HashMap<String, Object>> testCases,
Long problemId,
String version,
@ -86,30 +87,77 @@ public class ProblemTestCaseUtils {
((JSONArray) result.get("testCases")).put(index, jsonObject);
}
FileWriter infoFile = new FileWriter(testCasesDir + "/info", CharsetUtil.UTF_8);
FileWriter infoFile = new FileWriter(testCasesDir + File.separator + "info", CharsetUtil.UTF_8);
// 写入记录文件
infoFile.write(JSONUtil.toJsonStr(result));
return result;
}
// 本地有文件进行数据初始化 生成json文件
public JSONObject initLocalTestCase(Boolean isSpj,
String version,
String testCasesDir,
List<ProblemCase> problemCaseList) {
JSONObject result = new JSONObject();
result.set("isSpj", isSpj);
result.set("version", version);
result.set("testCasesSize", problemCaseList.size());
result.set("testCases", new JSONArray());
for (ProblemCase problemCase : problemCaseList) {
JSONObject jsonObject = new JSONObject();
jsonObject.set("caseId", null);
jsonObject.set("score", problemCase.getScore());
jsonObject.set("inputName", problemCase.getInput());
jsonObject.set("outputName", problemCase.getOutput());
// 读取输出文件
FileReader readFile = new FileReader(testCasesDir + File.separator + problemCase.getOutput(), CharsetUtil.UTF_8);
String output = readFile.readString().replaceAll("\r\n", "\n");
// spj是根据特判程序输出判断结果所以无需初始化测试数据
if (!isSpj) {
// 原数据MD5
jsonObject.set("outputMd5", DigestUtils.md5DigestAsHex(output.getBytes()));
// 原数据大小
jsonObject.set("outputSize", output.getBytes().length);
// 去掉全部空格的MD5用来判断pe
jsonObject.set("allStrippedOutputMd5", DigestUtils.md5DigestAsHex(output.replaceAll("\\s+", "").getBytes()));
// 默认去掉文末空格的MD5
jsonObject.set("EOFStrippedOutputMd5", DigestUtils.md5DigestAsHex(rtrim(output).getBytes()));
}
((JSONArray) result.get("testCases")).put(jsonObject);
}
FileWriter infoFile = new FileWriter(testCasesDir + File.separator + "info", CharsetUtil.UTF_8);
// 写入记录文件
infoFile.write(JSONUtil.toJsonStr(result));
return result;
}
// 获取指定题目的info数据
public JSONObject loadTestCaseInfo(Long problemId, String testCasesDir, String version, Boolean isSpj) throws SystemError, UnsupportedEncodingException {
if (FileUtil.exist(testCasesDir + "/info")) {
FileReader fileReader = new FileReader(testCasesDir + "/info", CharsetUtil.UTF_8);
if (FileUtil.exist(testCasesDir + File.separator + "info")) {
FileReader fileReader = new FileReader(testCasesDir + File.separator + "info", CharsetUtil.UTF_8);
String infoStr = fileReader.readString();
JSONObject testcaseInfo = JSONUtil.parseObj(infoStr);
// 测试样例被改动需要重新生成
if (!testcaseInfo.getStr("version", null).equals(version)) {
return tryInitTestCaseInfo(problemId, version, isSpj);
return tryInitTestCaseInfo(testCasesDir, problemId, version, isSpj);
}
return testcaseInfo;
} else {
return tryInitTestCaseInfo(problemId, version, isSpj);
return tryInitTestCaseInfo(testCasesDir, problemId, version, isSpj);
}
}
// 若没有测试数据则尝试从数据库获取并且初始化到本地如果数据库中该题目测试数据为空rsync同步也出了问题则直接判系统错误
public JSONObject tryInitTestCaseInfo(Long problemId, String version, Boolean isSpj) throws SystemError, UnsupportedEncodingException {
public JSONObject tryInitTestCaseInfo(String testCasesDir, Long problemId, String version, Boolean isSpj) throws SystemError, UnsupportedEncodingException {
QueryWrapper<ProblemCase> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("pid", problemId);
List<ProblemCase> problemCases = problemCaseService.list(queryWrapper);
@ -117,23 +165,30 @@ public class ProblemTestCaseUtils {
if (problemCases.size() == 0) { // 数据库也为空的话
throw new SystemError("problemID:[" + problemId + "] test case has not found.", null, null);
}
// 可能zip上传记录的是文件名这是也是说明文件丢失了
// 可能是zip上传记录的是文件名
if (problemCases.get(0).getInput().endsWith(".in") && (problemCases.get(0).getOutput().endsWith(".out") ||
problemCases.get(0).getOutput().endsWith(".ans"))) {
throw new SystemError("problemID:[" + problemId + "] test case has not found.", null, null);
}
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());
tmp.put("caseId", problemCase.getId());
tmp.put("score", problemCase.getScore());
testCases.add(tmp);
}
if (FileUtil.isEmpty(new File(testCasesDir))) { //如果本地对应文件夹也为空说明文件丢失了
throw new SystemError("problemID:[" + problemId + "] test case has not found.", null, null);
} else {
return initLocalTestCase(isSpj, version, testCasesDir, problemCases);
}
} else {
return initTestCase(testCases, problemId, version, isSpj);
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());
tmp.put("caseId", problemCase.getId());
tmp.put("score", problemCase.getScore());
testCases.add(tmp);
}
return initTestCase(testCases, problemId, version, isSpj);
}
}
// 去除末尾的空白符