ExamService.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. package com.ruoyi.web.service;
  2. import com.alibaba.fastjson2.JSONObject;
  3. import com.alibaba.fastjson2.util.DateUtils;
  4. import com.google.common.collect.Lists;
  5. import com.google.common.collect.Sets;
  6. import com.ruoyi.common.core.domain.entity.SysUser;
  7. import com.ruoyi.common.utils.SecurityUtils;
  8. import com.ruoyi.enums.ExamineeStatus;
  9. import com.ruoyi.enums.PaperStatus;
  10. import com.ruoyi.enums.PaperType;
  11. import com.ruoyi.ie.domain.AMarjorPlan;
  12. import com.ruoyi.ie.service.IAMarjorPlanService;
  13. import com.ruoyi.learn.domain.*;
  14. import com.ruoyi.learn.mapper.*;
  15. import com.ruoyi.learn.service.ILearnPaperService;
  16. import com.ruoyi.system.service.ISysUserService;
  17. import org.apache.commons.collections4.CollectionUtils;
  18. import org.apache.commons.lang3.StringUtils;
  19. import org.springframework.stereotype.Service;
  20. import org.springframework.transaction.annotation.Transactional;
  21. import javax.validation.ValidationException;
  22. import java.util.*;
  23. import java.util.stream.Collectors;
  24. /**
  25. * 考试服务
  26. */
  27. @Service
  28. public class ExamService {
  29. private final LearnAnswerMapper learnAnswerMapper;
  30. private final LearnExamineeMapper learnExamineeMapper;
  31. private final LearnStudentMapper learnStudentMapper;
  32. private Set<PaperType> paperTypeSet = Sets.newHashSet(PaperType.Real, PaperType.Custom, PaperType.Test);
  33. private final LearnPaperMapper paperMapper;
  34. private final LearnKnowledgeTreeMapper knowledgeTreeMapper;
  35. private final LearnExamineeMapper examineeMapper;
  36. private final ILearnPaperService learnPaperService;
  37. private final PaperService paperService;
  38. private final IAMarjorPlanService marjorPlanService;
  39. private final ISysUserService sysUserService;
  40. public ExamService(LearnPaperMapper paperMapper, LearnKnowledgeTreeMapper knowledgeTreeMapper, LearnExamineeMapper examineeMapper, ILearnPaperService learnPaperService, PaperService paperService, IAMarjorPlanService marjorPlanService, LearnAnswerMapper learnAnswerMapper, LearnExamineeMapper learnExamineeMapper, ISysUserService sysUserService, LearnStudentMapper learnStudentMapper) {
  41. this.paperMapper = paperMapper;
  42. this.knowledgeTreeMapper = knowledgeTreeMapper;
  43. this.examineeMapper = examineeMapper;
  44. this.learnPaperService = learnPaperService;
  45. this.paperService = paperService;
  46. this.marjorPlanService = marjorPlanService;
  47. this.learnAnswerMapper = learnAnswerMapper;
  48. this.learnExamineeMapper = learnExamineeMapper;
  49. this.sysUserService = sysUserService;
  50. this.learnStudentMapper = learnStudentMapper;
  51. }
  52. /**
  53. * 开卷 (卷, 实时组卷)
  54. * @return
  55. */
  56. @Transactional(rollbackFor = Exception.class)
  57. public AnswerSheet openExaminee(boolean directed, PaperType paperType, Long relatedId) {
  58. if(paperTypeSet.contains(paperType)) {
  59. return openExaminee(paperType, relatedId, SecurityUtils.getUserId());
  60. } else if(PaperType.Practice.equals(paperType)) {
  61. return openExaminee(relatedId, SecurityUtils.getUserId(), getDirectedKey(directed));
  62. } else if(PaperType.Simulated.equals(paperType)) {
  63. SysUser exist = sysUserService.selectUserById(SecurityUtils.getUserId());
  64. return openExaminee(relatedId, exist);
  65. }
  66. throw new RuntimeException("错误类型: " + paperType);
  67. }
  68. private String getDirectedKey(boolean directed) {
  69. if(!directed) {
  70. return "";
  71. }
  72. LearnStudent ls = learnStudentMapper.selectLearnStudentByStudentId(SecurityUtils.getUserId());
  73. return StringUtils.trimToEmpty(ls.getDirectKey());
  74. }
  75. public AnswerSheet loadExaminee(Long examineeId, Boolean examContinue) {
  76. LearnExaminee examinee = examineeMapper.selectLearnExamineeByExamineeId(examineeId);
  77. if(examContinue) {
  78. if(ExamineeStatus.Sign.getVal().equals(examinee.getState())) {
  79. LearnExaminee upExaminee = new LearnExaminee();
  80. upExaminee.setExamineeId(examineeId);
  81. upExaminee.setBeginTime(new Date());
  82. upExaminee.setState(ExamineeStatus.Exam.getVal());
  83. examineeMapper.updateLearnExaminee(upExaminee);
  84. } else if(!ExamineeStatus.Exam.getVal().equals(examinee.getState())) {
  85. throw new RuntimeException("已考完的卷不能继续做");
  86. }
  87. } else if(ExamineeStatus.Exam.getVal().equals(examinee.getState())) {
  88. throw new RuntimeException("考试中,不能提取答案");
  89. }
  90. LearnAnswer aCond = new LearnAnswer();
  91. aCond.setExamineeId(examineeId);
  92. Map<Long, LearnAnswer> answerMap = learnAnswerMapper.selectLearnAnswerList(aCond).stream().collect(Collectors.toMap(LearnAnswer::getQuestionId, t -> t));
  93. LearnPaper learnPaper = learnPaperService.selectLearnPaperById(examinee.getPaperId());
  94. List<PaperVO.QuestionAnswer> questionList = paperService.loadPaperQuestionAnswers(examinee.getPaperId(), answerMap, !examContinue);
  95. AnswerSheet answerSheet = buildAnswerSheet(learnPaper, examinee);
  96. answerSheet.setTotalCount(questionList.size());
  97. answerSheet.setWrongCount(examinee.getWrongCount());
  98. answerSheet.setQuestions(questionList);
  99. return answerSheet;
  100. }
  101. /**
  102. * 交卷
  103. * @param answerSheet
  104. */
  105. @Transactional(rollbackFor = Exception.class)
  106. public void commitAnswerSheet(AnswerSheet answerSheet) {
  107. LearnExaminee exitExaminee = learnExamineeMapper.selectLearnExamineeByExamineeId(answerSheet.getExamineeId());
  108. if(null == exitExaminee) {
  109. throw new RuntimeException("无此答卷" + answerSheet.getExamineeId());
  110. }
  111. LearnAnswer aCond = new LearnAnswer();
  112. aCond.setExamineeId(answerSheet.getExamineeId());
  113. Map<Long, LearnAnswer> answerMap = learnAnswerMapper.selectLearnAnswerList(aCond).stream().collect(Collectors.toMap(LearnAnswer::getQuestionId, t -> t));
  114. Map<Long, PaperVO.QuestionAnswer> questionMap = paperService.loadPaperQuestionAnswers(answerSheet.getPaperId(), answerMap, true).stream().collect(Collectors.toMap(PaperVO.QuestionAnswer::getId, t -> t));
  115. List<LearnAnswer> addList = Lists.newArrayList();
  116. List<LearnAnswer> updateList = Lists.newArrayList();
  117. Integer wrongCount = 0;
  118. for(PaperVO.QuestionAnswer question : answerSheet.getQuestions()) {
  119. if(CollectionUtils.isNotEmpty(question.getSubQuestions())) {
  120. for(PaperVO.QuestionAnswer sq : question.getSubQuestions()) {
  121. LearnAnswer answer = buildAnswer(answerSheet, questionMap, sq, addList, updateList);
  122. if(answerSheet.getIsDone() && !answer.getState().equals(1L)) {
  123. wrongCount++;
  124. }
  125. }
  126. } else {
  127. LearnAnswer answer = buildAnswer(answerSheet, questionMap, question, addList, updateList);
  128. if(answerSheet.getIsDone() && !answer.getState().equals(1L)) {
  129. wrongCount++;
  130. }
  131. }
  132. }
  133. if(addList.size() > 0) {
  134. addList.stream().forEach(t -> {
  135. learnAnswerMapper.insertLearnAnswer(t);
  136. });
  137. }
  138. if(updateList.size() > 0) {
  139. updateList.stream().forEach(t -> {
  140. learnAnswerMapper.updateLearnAnswer(t);
  141. });
  142. }
  143. LearnExaminee upExaminee = new LearnExaminee();
  144. upExaminee.setExamineeId(answerSheet.getExamineeId());
  145. upExaminee.setDuration(answerSheet.getDuration());
  146. if(answerSheet.getIsDone()) {
  147. upExaminee.setEndTime(new Date());
  148. upExaminee.setState(ExamineeStatus.Commit.getVal());
  149. upExaminee.setWrongCount(wrongCount);
  150. }
  151. learnExamineeMapper.updateLearnExaminee(upExaminee);
  152. if(answerSheet.getIsDone()) {
  153. // 关闭试卷
  154. LearnPaper up = new LearnPaper();
  155. up.setId(answerSheet.getPaperId());
  156. up.setStatus(PaperStatus.Valid.getVal());
  157. paperMapper.updateLearnPaper(up);
  158. }
  159. }
  160. private LearnAnswer buildAnswer(AnswerSheet answerSheet, Map<Long, PaperVO.QuestionAnswer> questionMap, PaperVO.QuestionAnswer question,
  161. List<LearnAnswer> addList, List<LearnAnswer> updateList) {
  162. LearnAnswer answer = new LearnAnswer();
  163. PaperVO.QuestionAnswer exist = questionMap.remove(question.getId());
  164. if(null == exist) {
  165. answer.setExamineeId(answerSheet.getExamineeId());
  166. answer.setStudentId(SecurityUtils.getUserId());
  167. answer.setQuestionId(question.getId());
  168. answer.setSeq(question.getSeq());
  169. answer.setKnowledgeId(answerSheet.getKnowledgeId());
  170. addList.add(answer);
  171. } else {
  172. answer.setAnswerId(exist.getAnswerId());
  173. updateList.add(answer);
  174. }
  175. answer.setAnswer(StringUtils.join(question.getAnswers(), ","));
  176. answer.setState(question.calcState(answerSheet.getIsDone()));
  177. return answer;
  178. }
  179. private AnswerSheet openExaminee(PaperType paperType, Long paperId, Long studentId) {
  180. LearnPaper paper = paperMapper.selectLearnPaperById(paperId);
  181. LearnExaminee learnExaminee = new LearnExaminee();
  182. learnExaminee.setStudentId(studentId);
  183. learnExaminee.setPaperId(paperId);
  184. learnExaminee.setPaperType(paperType.getVal());
  185. learnExaminee.setState(ExamineeStatus.Exam.getVal());
  186. List<LearnExaminee> examineeList = examineeMapper.selectLearnExamineeList(learnExaminee);
  187. if (CollectionUtils.isNotEmpty(examineeList)) {
  188. learnExaminee = examineeList.get(0);
  189. } else {
  190. learnExaminee.setState(ExamineeStatus.Exam.getVal());
  191. learnExaminee.setBeginTime(new Date());
  192. learnExaminee.setDuration(0L);
  193. examineeMapper.insertLearnExaminee(learnExaminee);
  194. }
  195. return buildAnswerSheet(paper, learnExaminee);
  196. }
  197. private AnswerSheet openExaminee(Long planId, SysUser sysUser) {
  198. AMarjorPlan plan = marjorPlanService.selectAMarjorPlanById(planId);
  199. if(null == plan) {
  200. throw new ValidationException("专业id无效");
  201. }
  202. LearnExaminee examinee = new LearnExaminee();
  203. examinee.setStudentId(SecurityUtils.getLoginUser().getUser().getUserId());
  204. examinee.setPaperType(PaperType.Simulated.getVal());
  205. List<LearnExaminee> examineeList = examineeMapper.selectLearnExamineeList(examinee);
  206. Set<Long> existPaperIdSet = Sets.newHashSet();
  207. for(LearnExaminee e : examineeList) {
  208. if((ExamineeStatus.Exam.getVal().equals(e.getState()) || ExamineeStatus.Sign.getVal().equals(e.getState())) && e.getPaperKey().equals(planId.toString())) {
  209. return buildAnswerSheet(learnPaperService.selectLearnPaperById(e.getPaperId()), e);
  210. }
  211. existPaperIdSet.add(e.getPaperId());
  212. }
  213. if(existPaperIdSet.size() >= sysUser.getEvalCount()) {
  214. throw new ValidationException("超过最大次数限制" + sysUser.getEvalCount() );
  215. }
  216. SysUser upUser = new SysUser();
  217. upUser.setUserId(sysUser.getUserId());
  218. upUser.setEvalCount(sysUser.getEvalCount() - 1);
  219. sysUserService.updateUserProfile(upUser);
  220. LearnPaper paper = getBestPaper(plan, existPaperIdSet);
  221. examinee.setPaperKey(paper.getId().toString());
  222. examinee.setState(ExamineeStatus.Sign.getVal());
  223. examinee.setDuration(0L);
  224. examineeMapper.insertLearnExaminee(examinee);
  225. return buildAnswerSheet(paper, examinee);
  226. }
  227. /**
  228. * 根据知识点生成一次性练习卷并开始做题
  229. * @return
  230. */
  231. private AnswerSheet openExaminee(Long knowledgeId, Long studentId, String directKey) {
  232. LearnKnowledgeTree knowledgeTree = knowledgeTreeMapper.selectLearnKnowledgeTreeById(knowledgeId);
  233. LearnPaper paper = new LearnPaper();
  234. paper.setPaperType(PaperType.Practice.name());
  235. paper.setRelateId(knowledgeId);
  236. paper.setYear(Calendar.getInstance().get(Calendar.YEAR));
  237. paper.setStatus(PaperStatus.TmpValid.getVal());
  238. paper.setDirectKey(studentId + "_" + StringUtils.trimToEmpty(directKey));
  239. List<LearnPaper> paperList = paperMapper.selectLearnPaperList(paper);
  240. if (CollectionUtils.isNotEmpty(paperList)) { // 有未做完的
  241. LearnPaper existPaper = paperList.get(0);
  242. LearnExaminee learnExaminee = new LearnExaminee();
  243. learnExaminee.setStudentId(studentId);
  244. learnExaminee.setPaperId(existPaper.getId());
  245. learnExaminee.setPaperType(PaperType.Practice.getVal());
  246. learnExaminee.setState(ExamineeStatus.Exam.getVal());
  247. List<LearnExaminee> examineeList = examineeMapper.selectLearnExamineeList(learnExaminee);
  248. if (CollectionUtils.isNotEmpty(examineeList)) {
  249. LearnExaminee examinee = examineeList.get(0);
  250. LearnAnswer aCond = new LearnAnswer();
  251. aCond.setExamineeId(examinee.getExamineeId());
  252. Map<Long, LearnAnswer> answerMap = learnAnswerMapper.selectLearnAnswerList(aCond).stream().collect(Collectors.toMap(LearnAnswer::getQuestionId, t -> t));
  253. List<PaperVO.QuestionAnswer> questionList = paperService.loadPaperQuestionAnswers(examinee.getPaperId(), answerMap, false);
  254. AnswerSheet answerSheet = buildAnswerSheet(existPaper, examinee);
  255. answerSheet.setQuestions(questionList);
  256. answerSheet.setKnowledgeId(existPaper.getRelateId());
  257. return answerSheet;
  258. }
  259. // 关闭试卷
  260. LearnPaper up = new LearnPaper();
  261. up.setId(learnExaminee.getPaperId());
  262. up.setStatus(PaperStatus.Valid.getVal());
  263. paperMapper.updateLearnPaper(up);
  264. }
  265. TestPaperVO.PaperDef paperDef = new TestPaperVO.PaperDef();
  266. paperDef.setTotal(15L);
  267. paperDef.setFillExclude(true);
  268. paperDef.setKnowIds(Lists.newArrayList(knowledgeId));
  269. List<TestPaperVO.TypeDef> typeDefList= Lists.newArrayList();
  270. typeDefList.add(new TestPaperVO.TypeDef("单选题", "单选题", 10, 1));
  271. typeDefList.add(new TestPaperVO.TypeDef("判断题", "判断题", 5, 2));
  272. paperDef.setTypes(typeDefList);
  273. List<LearnPaperQuestion> pqList = paperService.getQuestions(studentId, paperDef);
  274. paper.setPaperSource(0);
  275. paper.setSubjectId(knowledgeTree.getSubjectId());
  276. paper.setPaperName(studentId + "-" + knowledgeTree.getName() + "-" + DateUtils.format(new Date(), "yyyyMMddHHmmss"));
  277. paper.setRelateId(knowledgeId);
  278. paperService.savePaper(paper, pqList);
  279. LearnExaminee learnExaminee = new LearnExaminee();
  280. learnExaminee.setStudentId(studentId);
  281. learnExaminee.setPaperType(PaperType.Practice.getVal());
  282. learnExaminee.setPaperId(paper.getId());
  283. learnExaminee.setPaperKey(String.valueOf(knowledgeId));
  284. learnExaminee.setState(ExamineeStatus.Exam.getVal());
  285. learnExaminee.setBeginTime(new Date());
  286. learnExaminee.setDuration(0L);
  287. examineeMapper.insertLearnExaminee(learnExaminee);
  288. AnswerSheet answerSheet = buildAnswerSheet(paper, learnExaminee);
  289. answerSheet.setKnowledgeId(paper.getRelateId());
  290. return answerSheet;
  291. }
  292. private LearnPaper getBestPaper(AMarjorPlan plan, Set<Long> existPaperIdSet) {
  293. String groupName = StringUtils.trimToEmpty(plan.getMajorGroup());
  294. LearnPaper paperCond = new LearnPaper();
  295. paperCond.setPaperType(PaperType.Simulated.name());
  296. for(int i = 3; i>0; i--) {
  297. if(i == 3) {
  298. paperCond.setDirectKey(plan.getUniversityId() + "_" + groupName + "_" + plan.getMajorName());
  299. } else if(i == 2) {
  300. paperCond.setDirectKey(plan.getUniversityId() + "_" + groupName);
  301. } else if(StringUtils.isBlank(groupName)) {
  302. break;
  303. }
  304. List<LearnPaper> paperList = learnPaperService.selectLearnPaperList(paperCond);
  305. for(LearnPaper paper : paperList) {
  306. if(existPaperIdSet.add(paper.getId())) {
  307. return paper;
  308. }
  309. }
  310. }
  311. throw new ValidationException("未初始化院校定向模拟题库: " + plan.getId());
  312. }
  313. private AnswerSheet buildAnswerSheet(LearnPaper paper, LearnExaminee examinee) {
  314. AnswerSheet answerSheet = new AnswerSheet();
  315. answerSheet.setExamineeId(examinee.getExamineeId());
  316. answerSheet.setPaperId(examinee.getPaperId());
  317. answerSheet.setName(paper.getPaperName());
  318. answerSheet.setBeginTime(examinee.getBeginTime());
  319. if(StringUtils.isNotBlank(paper.getConditions())) {
  320. answerSheet.setConditions(JSONObject.parseObject(paper.getConditions(), AnswerSheet.PaperCond.class));
  321. }
  322. answerSheet.setScoringType("1");
  323. answerSheet.setMode(0L);
  324. answerSheet.setState(examinee.getState());
  325. answerSheet.setAllowAnswer(true);
  326. answerSheet.setAllowScore(false);
  327. return answerSheet;
  328. }
  329. }