package com.example.onlinejudge.judge; import cn.hutool.json.JSONUtil; import com.example.onlinejudge.exception.BusinessException; import com.example.onlinejudge.judge.codesandbox.CodeSandbox; import com.example.onlinejudge.judge.codesandbox.CodeSandboxFactory; import com.example.onlinejudge.judge.codesandbox.CodeSandboxProxy; import com.example.onlinejudge.judge.codesandbox.model.ExecuteCodeRequest; import com.example.onlinejudge.judge.codesandbox.model.ExecuteCodeResponse; import com.example.onlinejudge.judge.codesandbox.model.JudgeInfo; import com.example.onlinejudge.judge.strategy.JudgeContext; import com.example.onlinejudge.model.dto.question.JudgeCase; import com.example.onlinejudge.model.entity.Question; import com.example.onlinejudge.model.entity.QuestionSubmit; import com.example.onlinejudge.common.result.ResultCode; import com.example.onlinejudge.model.enums.QuestionSubmitStatusEnum; import com.example.onlinejudge.service.QuestionService; import com.example.onlinejudge.service.QuestionSubmitService; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; import java.util.stream.Collectors; @Service public class JudgeServiceImpl implements JudgeService{ @Resource private QuestionService questionService; @Resource private QuestionSubmitService questionSubmitService; @Resource private JudgeManager judgeManager; @Value("${codesandbox.type:example}") private String type; @Override public QuestionSubmit doJudge(long questionSubmitId) { System.out.println("判题服务开始"); System.out.println("questionSubmitId: " + questionSubmitId); // 1)传入题目的提交 id,获取到对应的题目、提交信息(包含代码、编程语言等) QuestionSubmit questionSubmit = questionSubmitService.getById(questionSubmitId); if (questionSubmit == null) { System.out.println("提交信息不存在"); throw new BusinessException(ResultCode.NOT_FOUND_ERROR, "提交信息不存在"); } Long questionId = questionSubmit.getQuestionId(); Question question = questionService.getById(questionId); if (question == null) { System.out.println("题目不存在"); throw new BusinessException(ResultCode.NOT_FOUND_ERROR, "题目不存在"); } System.out.println("1结束"); // 2)如果题目提交状态不为等待中,就不用重复执行了 if (!questionSubmit.getStatus().equals(QuestionSubmitStatusEnum.WAITING.getValue())) { throw new BusinessException(ResultCode.OPERATION_ERROR, "题目正在判题中"); } System.out.println("2结束"); // 3)更改判题(题目提交)的状态为 “判题中”,防止重复执行 QuestionSubmit questionSubmitUpdate = new QuestionSubmit(); questionSubmitUpdate.setId(questionSubmitId); questionSubmitUpdate.setStatus(QuestionSubmitStatusEnum.RUNNING.getValue()); boolean update = questionSubmitService.updateById(questionSubmitUpdate); if (!update) { throw new BusinessException(ResultCode.SYSTEM_ERROR, "题目状态更新错误"); } System.out.println("准备开始判题"); // 4)调用沙箱,获取到执行结果 CodeSandbox codeSandbox = CodeSandboxFactory.newInstance(type); System.out.println(codeSandbox); codeSandbox = new CodeSandboxProxy(codeSandbox); String language = questionSubmit.getLanguage(); String code = questionSubmit.getCode(); // 获取输入用例 String judgeCaseStr = question.getJudgeCase(); List judgeCaseList = JSONUtil.toList(judgeCaseStr, JudgeCase.class); List inputList = judgeCaseList.stream().map(JudgeCase::getInput).collect(Collectors.toList()); ExecuteCodeRequest executeCodeRequest = ExecuteCodeRequest.builder() .code(code) .language(language) .inputList(inputList) .build(); ExecuteCodeResponse executeCodeResponse = codeSandbox.executeCode(executeCodeRequest); List outputList = executeCodeResponse.getOutputList(); // 5)根据沙箱的执行结果,设置题目的判题状态和信息 JudgeContext judgeContext = new JudgeContext(); judgeContext.setJudgeInfo(executeCodeResponse.getJudgeInfo()); judgeContext.setInputList(inputList); judgeContext.setOutputList(outputList); judgeContext.setJudgeCaseList(judgeCaseList); judgeContext.setQuestion(question); judgeContext.setQuestionSubmit(questionSubmit); JudgeInfo judgeInfo = judgeManager.doJudge(judgeContext); // 6)修改数据库中的判题结果 questionSubmitUpdate = new QuestionSubmit(); questionSubmitUpdate.setId(questionSubmitId); questionSubmitUpdate.setStatus(QuestionSubmitStatusEnum.SUCCEED.getValue()); questionSubmitUpdate.setJudgeInfo(JSONUtil.toJsonStr(judgeInfo)); update = questionSubmitService.updateById(questionSubmitUpdate); if (!update) { throw new BusinessException(ResultCode.SYSTEM_ERROR, "题目状态更新错误"); } QuestionSubmit questionSubmitResult = questionSubmitService.getById(questionId); return questionSubmitResult; } }