JudgeServiceImpl.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. package com.nju.edu.eval.service.serviceImpl;
  2. import cn.seecoder.codejudge.client.JudgeDTO;
  3. import cn.seecoder.codejudge.client.JudgeResult;
  4. import cn.seecoder.codejudge.client.JudgeResultType;
  5. import cn.seecoder.judgement.dto.StudentAnswerDTO;
  6. import cn.seecoder.judgement.vo.JudgedAnswersVO;
  7. import com.nju.edu.eval.data.dao.ExamDao;
  8. import com.nju.edu.eval.data.dao.RecordDao;
  9. import com.nju.edu.eval.data.dao.ScoreDao;
  10. import com.nju.edu.eval.data.dao.UserDao;
  11. import com.nju.edu.eval.data.entity.Exam;
  12. import com.nju.edu.eval.data.entity.QuestionRecord;
  13. import com.nju.edu.eval.data.entity.Score;
  14. import com.nju.edu.eval.data.entity.User;
  15. import com.nju.edu.eval.exception.MyServiceException;
  16. import com.nju.edu.eval.exception.ThirdPartyServiceException;
  17. import com.nju.edu.eval.manager.JudgeManager;
  18. import com.nju.edu.eval.manager.QuestionManager;
  19. import com.nju.edu.eval.model.vo.judge.CodeJudgeVO;
  20. import com.nju.edu.eval.model.vo.judge.ObjectiveJudgeResOfExerciseVO;
  21. import com.nju.edu.eval.model.vo.judge.ObjectiveJudgeResVO;
  22. import com.nju.edu.eval.model.vo.judge.ObjectiveJudgeVO;
  23. import com.nju.edu.eval.model.vo.logdata.AnswerDTO;
  24. import com.nju.edu.eval.model.vo.logdata.ExamRecordLog;
  25. import com.nju.edu.eval.model.vo.question.CompleteQuestionVO;
  26. import com.nju.edu.eval.publicdatas.enums.CodeJudgeResultType;
  27. import com.nju.edu.eval.service.JudgeService;
  28. import com.nju.edu.eval.util.LogTracingUtil;
  29. import com.nju.edu.logTracking.enums.SeecSystem;
  30. import org.apache.logging.log4j.LogBuilder;
  31. import org.springframework.stereotype.Service;
  32. import java.util.*;
  33. import java.util.stream.Collectors;
  34. /**
  35. * @author mars
  36. */
  37. @Service
  38. public class JudgeServiceImpl implements JudgeService {
  39. private final JudgeManager judgeManager;
  40. private final QuestionManager questionManager;
  41. private final ScoreDao scoreDao;
  42. private final RecordDao recordDao;
  43. private final ExamDao examDao;
  44. private final UserDao userDao;
  45. public JudgeServiceImpl(JudgeManager judgeManager, QuestionManager questionManager, ScoreDao scoreDao, RecordDao recordDao, ExamDao examDao, UserDao userDao) {
  46. this.judgeManager = judgeManager;
  47. this.questionManager = questionManager;
  48. this.scoreDao = scoreDao;
  49. this.recordDao = recordDao;
  50. this.examDao = examDao;
  51. this.userDao = userDao;
  52. }
  53. @Override
  54. public ObjectiveJudgeResVO judgeObjectiveQuestionAnswers(Integer userId, Integer examId, ObjectiveJudgeVO objectiveJudgeVO) {
  55. try {
  56. // 提交给判题系统
  57. JudgedAnswersVO judgedAnswersVO = judgeManager.judgeObjectiveQuestionAnswers(userId, objectiveJudgeVO);
  58. User user = userDao.findById(userId).orElse(null);
  59. Exam exam = examDao.findById(examId).orElse(null);
  60. Score score = scoreDao.findByUserIdAndExamId(userId, examId);
  61. Date currentTime = new Date();
  62. if (score == null) {
  63. score = new Score(user, exam);
  64. }
  65. score.setSubmitTime(currentTime);
  66. scoreDao.save(score);
  67. List<QuestionRecord> records = score.getRecords();
  68. // 存储用以打日志的错题集
  69. List<AnswerDTO> err = new ArrayList<>();
  70. double curScore = 0.0;
  71. // 存储用户提交的记录
  72. for (Map.Entry<String, StudentAnswerDTO.AnswerRecordDTO> entry : objectiveJudgeVO.getRecords().entrySet()) {
  73. // 获得该题满分
  74. assert exam != null;
  75. String questionId = entry.getKey();
  76. double scoreOfQuestion = exam.getQuestionAndScore().get(questionId);
  77. // 看该题是否正确
  78. boolean isTrue = judgedAnswersVO.getAnswers().get(questionId).getCorrect();
  79. // 填入错题集
  80. if (!isTrue)
  81. err.add(new AnswerDTO(questionId, scoreOfQuestion));
  82. double actualScore = isTrue ? scoreOfQuestion : 0;
  83. curScore += actualScore;
  84. QuestionRecord questionRecord = new QuestionRecord(user, exam, entry.getKey(), score, (String) entry.getValue().getAnswer(), actualScore, currentTime);
  85. records.add(questionRecord);
  86. }
  87. double maxScore = Math.max(score.getScore() - score.getObjectiveScore() + curScore, score.getScore());
  88. score.setObjectiveScore(Math.max(curScore, score.getObjectiveScore()));
  89. score.setScore(maxScore);
  90. scoreDao.save(score);;
  91. // 提交记录日志
  92. LogTracingUtil.logRecord(new ExamRecordLog(examId, userId, currentTime, curScore, err));
  93. return new ObjectiveJudgeResVO(judgedAnswersVO.getSubmitAt(), judgedAnswersVO.getSubmitNumber());
  94. } catch (ThirdPartyServiceException exception) {
  95. throw new MyServiceException(exception.getCode(), exception.getMessage());
  96. }
  97. }
  98. @Override
  99. public JudgeResult judgeCodeQuestionAnswers(Integer userId, Integer examId, String questionId, CodeJudgeVO codeJudgeVO) {
  100. try {
  101. JudgeDTO judgeDTO = new JudgeDTO();
  102. judgeDTO.setCode(codeJudgeVO.getCode());
  103. judgeDTO.setLanguage(codeJudgeVO.getLanguage());
  104. CompleteQuestionVO question = questionManager.getQuestionById(questionId).get();
  105. judgeDTO.setMemoryLimit(question.getMemoryLimit());
  106. judgeDTO.setInputList(question.getInputOutputMapping().entrySet().stream().map(Map.Entry<String,String>::getKey).collect(Collectors.toList()));
  107. judgeDTO.setOutputList(question.getInputOutputMapping().entrySet().stream().map(Map.Entry<String,String>::getValue).collect(Collectors.toList()));
  108. JudgeResult judgeResult = judgeManager.judgeCodeQuestionAnswers(judgeDTO);
  109. CodeJudgeResultType message = CodeJudgeResultType.values()[JudgeResultType.ACCEPT.ordinal()];
  110. for (JudgeResult.Item item : judgeResult.getResultList()) {
  111. if (item.getResult() != JudgeResultType.ACCEPT) {
  112. message = CodeJudgeResultType.values()[item.getResult().ordinal()];
  113. break;
  114. }
  115. }
  116. User user = userDao.findById(userId).orElse(null);
  117. Exam exam = examDao.findById(examId).orElse(null);
  118. Score score = scoreDao.findByUserIdAndExamId(userId, examId);
  119. Date currentTime = new Date();
  120. if (score == null) {
  121. score = new Score(user, exam);
  122. }
  123. score.setSubmitTime(currentTime);
  124. scoreDao.save(score);
  125. List<QuestionRecord> records = score.getRecords();
  126. // 获得上一次用户提交的代码分数,如果没有,那就是0
  127. double preScore = 0.0;
  128. QuestionRecord previousRecord = recordDao.findFirstByUserIdAndExamIdAndQuestionIdOrderByActualScore(userId, examId, questionId);
  129. if (previousRecord != null) {
  130. preScore = previousRecord.getActualScore();
  131. }
  132. double curScore = 0.0;
  133. // 存储用户提交的记录
  134. // 获得该题满分
  135. double scoreOfQuestion = exam.getQuestionAndScore().get(questionId);
  136. // 遍历OJ结果,如果该测试用例AC则得分
  137. int accecptedNum = 0;
  138. for (JudgeResult.Item item: judgeResult.getResultList()) {
  139. if (item.getResult() == JudgeResultType.ACCEPT) {
  140. accecptedNum++;
  141. }
  142. }
  143. // 获得该题满分
  144. curScore = ((double) accecptedNum / judgeResult.getResultList().size()) * scoreOfQuestion;
  145. QuestionRecord questionRecord = new QuestionRecord(user, exam, questionId, score, judgeDTO.getCode(), curScore, currentTime);
  146. questionRecord.setMessage(message);
  147. records.add(questionRecord);
  148. // 更新成绩报告中的分数,通过减去该题最高得分来获得
  149. double maxScore = Math.max(score.getScore() - preScore + curScore, score.getScore());
  150. score.setScore(maxScore);
  151. scoreDao.save(score);
  152. // 提交记录日志
  153. List<AnswerDTO> err = new ArrayList<>();
  154. if (curScore != scoreOfQuestion)
  155. err.add(new AnswerDTO(questionId, scoreOfQuestion));
  156. LogTracingUtil.logRecord(new ExamRecordLog(examId, userId, currentTime, curScore, err));
  157. return judgeResult;
  158. } catch (ThirdPartyServiceException exception) {
  159. throw new MyServiceException(exception.getCode(), exception.getMessage());
  160. }
  161. }
  162. @Override
  163. public ObjectiveJudgeResOfExerciseVO judgeObjectiveQuestionAnswersOfExercise(Integer userId, ObjectiveJudgeVO objectiveJudgeVO) {
  164. try {
  165. // 提交给判题系统
  166. JudgedAnswersVO judgedAnswersVO = judgeManager.judgeObjectiveQuestionAnswers(userId, objectiveJudgeVO);
  167. Map<String, Boolean> result = new HashMap<>();
  168. User user = userDao.findById(userId).orElse(null);
  169. Date currentTime = new Date();
  170. double curScore = 0.0;
  171. // 存储用户提交的记录
  172. for (Map.Entry<String, StudentAnswerDTO.AnswerRecordDTO> entry : objectiveJudgeVO.getRecords().entrySet()) {
  173. // 获得该题满分
  174. String questionId = entry.getKey();
  175. // 看该题是否正确
  176. boolean isTrue = judgedAnswersVO.getAnswers().get(questionId).getCorrect();
  177. result.put(questionId, isTrue);
  178. }
  179. return new ObjectiveJudgeResOfExerciseVO(result);
  180. } catch (ThirdPartyServiceException exception) {
  181. throw new MyServiceException(exception.getCode(), exception.getMessage());
  182. }
  183. }
  184. @Override
  185. public JudgeResult judgeCodeQuestionAnswersOfExercise(Integer userId, String questionId, CodeJudgeVO codeJudgeVO) {
  186. try {
  187. JudgeDTO judgeDTO = new JudgeDTO();
  188. judgeDTO.setCode(codeJudgeVO.getCode());
  189. judgeDTO.setLanguage(codeJudgeVO.getLanguage());
  190. CompleteQuestionVO question = questionManager.getQuestionById(questionId).get();
  191. judgeDTO.setMemoryLimit(question.getMemoryLimit());
  192. judgeDTO.setInputList(question.getInputOutputMapping().entrySet().stream().map(Map.Entry<String,String>::getKey).collect(Collectors.toList()));
  193. judgeDTO.setOutputList(question.getInputOutputMapping().entrySet().stream().map(Map.Entry<String,String>::getValue).collect(Collectors.toList()));
  194. JudgeResult judgeResult = judgeManager.judgeCodeQuestionAnswers(judgeDTO);
  195. return judgeResult;
  196. } catch (ThirdPartyServiceException exception) {
  197. throw new MyServiceException(exception.getCode(), exception.getMessage());
  198. }
  199. }
  200. }