use of top.hcode.hoj.pojo.entity.judge.Judge in project HOJ by HimitZH.
the class RejudgeServiceImpl method rejudgeContestProblem.
@Override
@Transactional(rollbackFor = Exception.class)
public CommonResult rejudgeContestProblem(Long cid, Long pid) {
QueryWrapper<Judge> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("cid", cid).eq("pid", pid);
List<Judge> rejudgeList = judgeService.list(queryWrapper);
if (rejudgeList.size() == 0) {
return CommonResult.errorResponse("当前该题目无提交,不可重判!");
}
List<Long> submitIdList = new LinkedList<>();
HashMap<Long, Integer> idMapStatus = new HashMap<>();
// 全部设置默认值
for (Judge judge : rejudgeList) {
idMapStatus.put(judge.getSubmitId(), judge.getStatus());
// 开始进入判题队列
judge.setStatus(Constants.Judge.STATUS_PENDING.getStatus());
judge.setVersion(judge.getVersion() + 1);
judge.setJudger("").setTime(null).setMemory(null).setErrorMessage(null).setOiRankScore(null).setScore(null);
submitIdList.add(judge.getSubmitId());
}
boolean resetJudgeResult = judgeService.updateBatchById(rejudgeList);
// 清除每个提交对应的测试点结果
QueryWrapper<JudgeCase> judgeCaseQueryWrapper = new QueryWrapper<>();
judgeCaseQueryWrapper.in("submit_id", submitIdList);
judgeCaseService.remove(judgeCaseQueryWrapper);
// 将对应比赛记录设置成默认值
UpdateWrapper<ContestRecord> updateWrapper = new UpdateWrapper<>();
updateWrapper.in("submit_id", submitIdList).setSql("status=null,score=null");
boolean resetContestRecordResult = contestRecordService.update(updateWrapper);
if (resetContestRecordResult && resetJudgeResult) {
// 调用重判服务
Problem problem = problemService.getById(pid);
if (problem.getIsRemote()) {
// 如果是远程oj判题
for (Judge judge : rejudgeList) {
// 进入重判队列,等待调用判题服务
remoteJudgeDispatcher.sendTask(judge, judgeToken, problem.getProblemId(), judge.getCid() != 0, isHasSubmitIdRemoteRejudge(judge.getVjudgeSubmitId(), idMapStatus.get(judge.getSubmitId())));
}
} else {
for (Judge judge : rejudgeList) {
// 进入重判队列,等待调用判题服务
judgeDispatcher.sendTask(judge, judgeToken, judge.getCid() != 0);
}
}
return CommonResult.successResponse(null, "重判成功!该题目对应的全部提交已进入判题队列!");
} else {
return CommonResult.errorResponse("重判失败!请重新尝试!");
}
}
use of top.hcode.hoj.pojo.entity.judge.Judge in project HOJ by HimitZH.
the class RejudgeServiceImpl method rejudge.
@Override
@Transactional(rollbackFor = Exception.class)
public CommonResult rejudge(Long submitId) {
Judge judge = judgeService.getById(submitId);
boolean isContestSubmission = judge.getCid() != 0;
boolean resetContestRecordResult = true;
// 如果是非比赛题目
if (!isContestSubmission) {
// 如果该题已经是AC通过状态,更新该题目的用户ac做题表 user_acproblem
if (judge.getStatus().intValue() == Constants.Judge.STATUS_ACCEPTED.getStatus().intValue()) {
QueryWrapper<UserAcproblem> userAcproblemQueryWrapper = new QueryWrapper<>();
userAcproblemQueryWrapper.eq("submit_id", judge.getSubmitId());
userAcproblemService.remove(userAcproblemQueryWrapper);
}
} else {
// 将对应比赛记录设置成默认值
UpdateWrapper<ContestRecord> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("submit_id", submitId).setSql("status=null,score=null");
resetContestRecordResult = contestRecordService.update(updateWrapper);
}
// 清除该提交对应的测试点结果
QueryWrapper<JudgeCase> judgeCaseQueryWrapper = new QueryWrapper<>();
judgeCaseQueryWrapper.eq("submit_id", submitId);
judgeCaseService.remove(judgeCaseQueryWrapper);
boolean hasSubmitIdRemoteRejudge = isHasSubmitIdRemoteRejudge(judge.getVjudgeSubmitId(), judge.getStatus());
// 设置默认值
// 开始进入判题队列
judge.setStatus(Constants.Judge.STATUS_PENDING.getStatus());
judge.setVersion(judge.getVersion() + 1);
judge.setJudger("").setTime(null).setMemory(null).setErrorMessage(null).setOiRankScore(null).setScore(null);
boolean result = judgeService.updateById(judge);
if (result && resetContestRecordResult) {
// 调用判题服务
Problem problem = problemService.getById(judge.getPid());
if (problem.getIsRemote()) {
// 如果是远程oj判题
remoteJudgeDispatcher.sendTask(judge, judgeToken, problem.getProblemId(), isContestSubmission, hasSubmitIdRemoteRejudge);
} else {
judgeDispatcher.sendTask(judge, judgeToken, isContestSubmission);
}
return CommonResult.successResponse(judge, "重判成功!该提交已进入判题队列!");
} else {
return CommonResult.successResponse(judge, "重判失败!请重新尝试!");
}
}
use of top.hcode.hoj.pojo.entity.judge.Judge in project HOJ by HimitZH.
the class ContestFileController method downloadContestACSubmission.
@GetMapping("/download-contest-ac-submission")
@RequiresAuthentication
@RequiresRoles(value = { "root", "admin", "problem_admin" }, logical = Logical.OR)
public void downloadContestACSubmission(@RequestParam("cid") Long cid, @RequestParam(value = "excludeAdmin", defaultValue = "false") Boolean excludeAdmin, @RequestParam(value = "splitType", defaultValue = "user") String splitType, HttpServletRequest request, HttpServletResponse response) {
Contest contest = contestService.getById(cid);
// 获取当前登录的用户
HttpSession session = request.getSession();
UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo");
boolean isRoot = SecurityUtils.getSubject().hasRole("root");
// 除非是root 其它管理员只能下载自己的比赛ac记录
if (!userRolesVo.getUid().equals(contest.getUid()) && !isRoot) {
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Map<String, Object> map = new HashMap<>();
map.put("status", CommonResult.STATUS_FORBIDDEN);
map.put("msg", "对不起,你无权限下载!");
map.put("data", null);
try {
response.getWriter().println(JSONUtil.toJsonStr(map));
} catch (IOException ioException) {
ioException.printStackTrace();
}
return;
}
boolean isACM = contest.getType().intValue() == Constants.Contest.TYPE_ACM.getCode();
QueryWrapper<ContestProblem> contestProblemQueryWrapper = new QueryWrapper<>();
contestProblemQueryWrapper.eq("cid", contest.getId());
List<ContestProblem> contestProblemList = contestProblemService.list(contestProblemQueryWrapper);
List<UserInfo> superAdminList = contestRecordService.getSuperAdminList();
List<String> superAdminUsernameList = superAdminList.stream().map(UserInfo::getUsername).collect(Collectors.toList());
QueryWrapper<Judge> judgeQueryWrapper = new QueryWrapper<>();
judgeQueryWrapper.eq("cid", cid).eq(isACM, "status", Constants.Judge.STATUS_ACCEPTED.getStatus()).isNotNull(!isACM, // OI模式取得分不为null的
"score").between("submit_time", contest.getStartTime(), contest.getEndTime()).ne(excludeAdmin, "uid", // 排除比赛创建者和root
contest.getUid()).notIn(excludeAdmin && superAdminUsernameList.size() > 0, "username", superAdminUsernameList).orderByDesc("submit_time");
List<Judge> judgeList = judgeService.list(judgeQueryWrapper);
// 打包文件的临时路径 -> username为文件夹名字
String tmpFilesDir = Constants.File.CONTEST_AC_SUBMISSION_TMP_FOLDER.getPath() + File.separator + IdUtil.fastSimpleUUID();
FileUtil.mkdir(tmpFilesDir);
HashMap<String, Boolean> recordMap = new HashMap<>();
if ("user".equals(splitType)) {
/**
* 以用户来分割提交的代码
*/
List<String> usernameList = judgeList.stream().filter(// 根据用户名过滤唯一
distinctByKey(Judge::getUsername)).map(Judge::getUsername).collect(// 映射出用户名列表
Collectors.toList());
HashMap<Long, String> cpIdMap = new HashMap<>();
for (ContestProblem contestProblem : contestProblemList) {
cpIdMap.put(contestProblem.getId(), contestProblem.getDisplayId());
}
for (String username : usernameList) {
// 对于每个用户生成对应的文件夹
String userDir = tmpFilesDir + File.separator + username;
FileUtil.mkdir(userDir);
// 如果是ACM模式,则所有提交代码都要生成,如果同一题多次提交AC,加上提交时间秒后缀 ---> A_(666666).c
// 如果是OI模式就生成最近一次提交即可,且带上分数 ---> A_(666666)_100.c
List<Judge> userSubmissionList = judgeList.stream().filter(// 过滤出对应用户的提交
judge -> judge.getUsername().equals(username)).sorted(// 根据提交时间进行降序
Comparator.comparing(Judge::getSubmitTime).reversed()).collect(Collectors.toList());
for (Judge judge : userSubmissionList) {
String filePath = userDir + File.separator + cpIdMap.getOrDefault(judge.getCpid(), "null");
// OI模式只取最后一次提交
if (!isACM) {
String key = judge.getUsername() + "_" + judge.getPid();
if (!recordMap.containsKey(key)) {
filePath += "_" + judge.getScore() + "_(" + threadLocalTime.get().format(judge.getSubmitTime()) + ")." + languageToFileSuffix(judge.getLanguage().toLowerCase());
FileWriter fileWriter = new FileWriter(filePath);
fileWriter.write(judge.getCode());
recordMap.put(key, true);
}
} else {
filePath += "_(" + threadLocalTime.get().format(judge.getSubmitTime()) + ")." + languageToFileSuffix(judge.getLanguage().toLowerCase());
FileWriter fileWriter = new FileWriter(filePath);
fileWriter.write(judge.getCode());
}
}
}
} else if ("problem".equals(splitType)) {
for (ContestProblem contestProblem : contestProblemList) {
// 对于每题目生成对应的文件夹
String problemDir = tmpFilesDir + File.separator + contestProblem.getDisplayId();
FileUtil.mkdir(problemDir);
// 如果是ACM模式,则所有提交代码都要生成,如果同一题多次提交AC,加上提交时间秒后缀 ---> username_(666666).c
// 如果是OI模式就生成最近一次提交即可,且带上分数 ---> username_(666666)_100.c
List<Judge> problemSubmissionList = judgeList.stream().filter(// 过滤出对应题目的提交
judge -> judge.getPid().equals(contestProblem.getPid())).sorted(// 根据提交时间进行降序
Comparator.comparing(Judge::getSubmitTime).reversed()).collect(Collectors.toList());
for (Judge judge : problemSubmissionList) {
String filePath = problemDir + File.separator + judge.getUsername();
if (!isACM) {
String key = judge.getUsername() + "_" + contestProblem.getDisplayId();
// OI模式只取最后一次提交
if (!recordMap.containsKey(key)) {
filePath += "_" + judge.getScore() + "_(" + threadLocalTime.get().format(judge.getSubmitTime()) + ")." + languageToFileSuffix(judge.getLanguage().toLowerCase());
FileWriter fileWriter = new FileWriter(filePath);
fileWriter.write(judge.getCode());
recordMap.put(key, true);
}
} else {
filePath += "_(" + threadLocalTime.get().format(judge.getSubmitTime()) + ")." + languageToFileSuffix(judge.getLanguage().toLowerCase());
FileWriter fileWriter = new FileWriter(filePath);
fileWriter.write(judge.getCode());
}
}
}
}
String zipFileName = "contest_" + contest.getId() + "_" + System.currentTimeMillis() + ".zip";
String zipPath = Constants.File.CONTEST_AC_SUBMISSION_TMP_FOLDER.getPath() + File.separator + zipFileName;
ZipUtil.zip(tmpFilesDir, zipPath);
// 将zip变成io流返回给前端
FileReader zipFileReader = new FileReader(zipPath);
// 放到缓冲流里面
BufferedInputStream bins = new BufferedInputStream(zipFileReader.getInputStream());
// 获取文件输出IO流
OutputStream outs = null;
BufferedOutputStream bouts = null;
try {
outs = response.getOutputStream();
bouts = new BufferedOutputStream(outs);
response.setContentType("application/x-download");
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(zipFileName, "UTF-8"));
int bytesRead = 0;
byte[] buffer = new byte[1024 * 10];
// 开始向网络传输文件流
while ((bytesRead = bins.read(buffer, 0, 1024 * 10)) != -1) {
bouts.write(buffer, 0, bytesRead);
}
// 刷新缓存
bouts.flush();
} catch (IOException e) {
log.error("下载比赛AC提交代码的压缩文件异常------------>", e);
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Map<String, Object> map = new HashMap<>();
map.put("status", CommonResult.STATUS_ERROR);
map.put("msg", "下载文件失败,请重新尝试!");
map.put("data", null);
try {
response.getWriter().println(JSONUtil.toJsonStr(map));
} catch (IOException ioException) {
ioException.printStackTrace();
}
} finally {
try {
bins.close();
if (outs != null) {
outs.close();
}
if (bouts != null) {
bouts.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
FileUtil.del(tmpFilesDir);
FileUtil.del(zipPath);
}
use of top.hcode.hoj.pojo.entity.judge.Judge in project HOJ by HimitZH.
the class JudgeController method updateSubmission.
/**
* @MethodName updateSubmission
* @Params * @param null
* @Description 修改单个提交详情的分享权限
* @Return CommonResult
* @Since 2021/1/2
*/
@PutMapping("/submission")
@RequiresAuthentication
public CommonResult updateSubmission(@RequestBody Judge judge, HttpServletRequest request) {
// 需要获取一下该token对应用户的数据
HttpSession session = request.getSession();
UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo");
if (!userRolesVo.getUid().equals(judge.getUid())) {
// 判断该提交是否为当前用户的
return CommonResult.errorResponse("对不起,您不能修改他人的代码分享权限!");
}
Judge judgeInfo = judgeService.getById(judge.getSubmitId());
if (judgeInfo.getCid() != 0) {
// 如果是比赛提交,不可分享!
return CommonResult.errorResponse("对不起,您不能分享比赛题目的提交代码!");
}
judgeInfo.setShare(judge.getShare());
boolean result = judgeService.updateById(judgeInfo);
if (result) {
if (judge.getShare()) {
return CommonResult.successResponse(null, "设置代码公开成功!");
} else {
return CommonResult.successResponse(null, "设置代码隐藏成功!");
}
} else {
return CommonResult.errorResponse("修改代码权限失败!");
}
}
use of top.hcode.hoj.pojo.entity.judge.Judge in project HOJ by HimitZH.
the class JudgeController method getSubmission.
/**
* @MethodName getSubmission
* @Params * @param null
* @Description 获取单个提交记录的详情
* @Return CommonResult
* @Since 2021/1/2
*/
@GetMapping("/submission")
public CommonResult getSubmission(@RequestParam(value = "submitId", required = true) Long submitId, HttpServletRequest request) {
Judge judge = judgeService.getById(submitId);
if (judge == null) {
return CommonResult.errorResponse("此提交数据不存在!");
}
HttpSession session = request.getSession();
UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo");
// 是否为超级管理员
boolean isRoot = SecurityUtils.getSubject().hasRole("root");
// 清空vj信息
judge.setVjudgeUsername(null);
judge.setVjudgeSubmitId(null);
judge.setVjudgePassword(null);
// 超级管理员与题目管理员有权限查看代码
// 如果不是本人或者并未分享代码,则不可查看
// 当此次提交代码不共享
// 比赛提交只有比赛创建者和root账号可看代码
HashMap<String, Object> result = new HashMap<>();
if (judge.getCid() != 0) {
if (userRolesVo == null) {
return CommonResult.errorResponse("请先登录!", CommonResult.STATUS_ACCESS_DENIED);
}
Contest contest = contestService.getById(judge.getCid());
if (!isRoot && !userRolesVo.getUid().equals(contest.getUid())) {
// 如果是比赛,那么还需要判断是否为封榜,比赛管理员和超级管理员可以有权限查看(ACM题目除外)
if (contest.getType().intValue() == Constants.Contest.TYPE_OI.getCode() && contestService.isSealRank(userRolesVo.getUid(), contest, true, false)) {
result.put("submission", new Judge().setStatus(Constants.Judge.STATUS_SUBMITTED_UNKNOWN_RESULT.getStatus()));
return CommonResult.successResponse(result, "获取提交数据成功!");
}
// 不是本人的话不能查看代码、时间,空间,长度
if (!userRolesVo.getUid().equals(judge.getUid())) {
judge.setCode(null);
// 如果还在比赛时间,不是本人不能查看时间,空间,长度,错误提示信息
if (contest.getStatus().intValue() == Constants.Contest.STATUS_RUNNING.getCode()) {
judge.setTime(null);
judge.setMemory(null);
judge.setLength(null);
judge.setErrorMessage("The contest is in progress. You are not allowed to view other people's error information.");
}
}
}
} else {
// 是否为题目管理员
boolean admin = SecurityUtils.getSubject().hasRole("problem_admin");
if (!judge.getShare() && !isRoot && !admin) {
if (userRolesVo != null) {
// 需要判断是否为当前登陆用户自己的提交代码
if (!judge.getUid().equals(userRolesVo.getUid())) {
judge.setCode(null);
}
} else {
// 不是登陆状态,就直接无权限查看代码
judge.setCode(null);
}
}
}
Problem problem = problemService.getById(judge.getPid());
// 只允许用户查看ce错误,sf错误,se错误信息提示
if (judge.getStatus().intValue() != Constants.Judge.STATUS_COMPILE_ERROR.getStatus() && judge.getStatus().intValue() != Constants.Judge.STATUS_SYSTEM_ERROR.getStatus() && judge.getStatus().intValue() != Constants.Judge.STATUS_SUBMITTED_FAILED.getStatus()) {
judge.setErrorMessage("The error message does not support viewing.");
}
result.put("submission", judge);
result.put("codeShare", problem.getCodeShare());
return CommonResult.successResponse(result, "获取提交数据成功!");
}
Aggregations