JudgeServiceImpl.java 11 KB

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