JudgeServiceImpl.java 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package com.example.onlinejudge.judge;
  2. import cn.hutool.json.JSONUtil;
  3. import com.example.onlinejudge.exception.BusinessException;
  4. import com.example.onlinejudge.judge.codesandbox.CodeSandbox;
  5. import com.example.onlinejudge.judge.codesandbox.CodeSandboxFactory;
  6. import com.example.onlinejudge.judge.codesandbox.CodeSandboxProxy;
  7. import com.example.onlinejudge.judge.codesandbox.model.ExecuteCodeRequest;
  8. import com.example.onlinejudge.judge.codesandbox.model.ExecuteCodeResponse;
  9. import com.example.onlinejudge.judge.codesandbox.model.JudgeInfo;
  10. import com.example.onlinejudge.judge.strategy.JudgeContext;
  11. import com.example.onlinejudge.model.dto.question.JudgeCase;
  12. import com.example.onlinejudge.model.entity.Question;
  13. import com.example.onlinejudge.model.entity.QuestionSubmit;
  14. import com.example.onlinejudge.common.result.ResultCode;
  15. import com.example.onlinejudge.model.enums.QuestionSubmitStatusEnum;
  16. import com.example.onlinejudge.service.QuestionService;
  17. import com.example.onlinejudge.service.QuestionSubmitService;
  18. import org.springframework.beans.factory.annotation.Value;
  19. import org.springframework.stereotype.Service;
  20. import javax.annotation.Resource;
  21. import java.util.List;
  22. import java.util.stream.Collectors;
  23. @Service
  24. public class JudgeServiceImpl implements JudgeService{
  25. @Resource
  26. private QuestionService questionService;
  27. @Resource
  28. private QuestionSubmitService questionSubmitService;
  29. @Resource
  30. private JudgeManager judgeManager;
  31. @Value("${codesandbox.type:example}")
  32. private String type;
  33. @Override
  34. public QuestionSubmit doJudge(long questionSubmitId) {
  35. System.out.println("判题服务开始");
  36. System.out.println("questionSubmitId: " + questionSubmitId);
  37. // 1)传入题目的提交 id,获取到对应的题目、提交信息(包含代码、编程语言等)
  38. QuestionSubmit questionSubmit = questionSubmitService.getById(questionSubmitId);
  39. if (questionSubmit == null) {
  40. System.out.println("提交信息不存在");
  41. throw new BusinessException(ResultCode.NOT_FOUND_ERROR, "提交信息不存在");
  42. }
  43. Long questionId = questionSubmit.getQuestionId();
  44. Question question = questionService.getById(questionId);
  45. if (question == null) {
  46. System.out.println("题目不存在");
  47. throw new BusinessException(ResultCode.NOT_FOUND_ERROR, "题目不存在");
  48. }
  49. System.out.println("1结束");
  50. // 2)如果题目提交状态不为等待中,就不用重复执行了
  51. if (!questionSubmit.getStatus().equals(QuestionSubmitStatusEnum.WAITING.getValue())) {
  52. throw new BusinessException(ResultCode.OPERATION_ERROR, "题目正在判题中");
  53. }
  54. System.out.println("2结束");
  55. // 3)更改判题(题目提交)的状态为 “判题中”,防止重复执行
  56. QuestionSubmit questionSubmitUpdate = new QuestionSubmit();
  57. questionSubmitUpdate.setId(questionSubmitId);
  58. questionSubmitUpdate.setStatus(QuestionSubmitStatusEnum.RUNNING.getValue());
  59. boolean update = questionSubmitService.updateById(questionSubmitUpdate);
  60. if (!update) {
  61. throw new BusinessException(ResultCode.SYSTEM_ERROR, "题目状态更新错误");
  62. }
  63. System.out.println("准备开始判题");
  64. // 4)调用沙箱,获取到执行结果
  65. CodeSandbox codeSandbox = CodeSandboxFactory.newInstance(type);
  66. System.out.println(codeSandbox);
  67. codeSandbox = new CodeSandboxProxy(codeSandbox);
  68. String language = questionSubmit.getLanguage();
  69. String code = questionSubmit.getCode();
  70. // 获取输入用例
  71. String judgeCaseStr = question.getJudgeCase();
  72. List<JudgeCase> judgeCaseList = JSONUtil.toList(judgeCaseStr, JudgeCase.class);
  73. List<String> inputList = judgeCaseList.stream().map(JudgeCase::getInput).collect(Collectors.toList());
  74. ExecuteCodeRequest executeCodeRequest = ExecuteCodeRequest.builder()
  75. .code(code)
  76. .language(language)
  77. .inputList(inputList)
  78. .build();
  79. ExecuteCodeResponse executeCodeResponse = codeSandbox.executeCode(executeCodeRequest);
  80. List<String> outputList = executeCodeResponse.getOutputList();
  81. // 5)根据沙箱的执行结果,设置题目的判题状态和信息
  82. JudgeContext judgeContext = new JudgeContext();
  83. judgeContext.setJudgeInfo(executeCodeResponse.getJudgeInfo());
  84. judgeContext.setInputList(inputList);
  85. judgeContext.setOutputList(outputList);
  86. judgeContext.setJudgeCaseList(judgeCaseList);
  87. judgeContext.setQuestion(question);
  88. judgeContext.setQuestionSubmit(questionSubmit);
  89. JudgeInfo judgeInfo = judgeManager.doJudge(judgeContext);
  90. // 6)修改数据库中的判题结果
  91. questionSubmitUpdate = new QuestionSubmit();
  92. questionSubmitUpdate.setId(questionSubmitId);
  93. questionSubmitUpdate.setStatus(QuestionSubmitStatusEnum.SUCCEED.getValue());
  94. questionSubmitUpdate.setJudgeInfo(JSONUtil.toJsonStr(judgeInfo));
  95. update = questionSubmitService.updateById(questionSubmitUpdate);
  96. if (!update) {
  97. throw new BusinessException(ResultCode.SYSTEM_ERROR, "题目状态更新错误");
  98. }
  99. QuestionSubmit questionSubmitResult = questionSubmitService.getById(questionId);
  100. return questionSubmitResult;
  101. }
  102. }