RealExamService.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. package com.ruoyi.sim.service.impl;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.Objects;
  5. import com.ruoyi.common.core.domain.AjaxResult;
  6. import com.ruoyi.common.utils.DateUtils;
  7. import com.ruoyi.sim.config.SimConfig;
  8. import com.ruoyi.sim.domain.*;
  9. import com.ruoyi.sim.domain.vo.RealExamVo;
  10. import com.ruoyi.sim.domain.vo.StudentRealExamIngVo;
  11. import com.ruoyi.sim.domain.vo.StudentRealExamPostVo;
  12. import com.ruoyi.sim.domain.vo.StudentRealExamPreVo;
  13. import org.slf4j.Logger;
  14. import org.slf4j.LoggerFactory;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.stereotype.Service;
  17. import com.ruoyi.sim.mapper.RealExamMapper;
  18. import org.springframework.transaction.annotation.Transactional;
  19. /**
  20. * 考试Service业务层处理
  21. *
  22. * @author tom
  23. * @date 2024-12-15
  24. */
  25. @Service
  26. public class RealExamService {
  27. @Autowired
  28. private RealExamMapper realExamMapper;
  29. /**
  30. * 查询考试
  31. *
  32. * @param examId 考试主键
  33. * @return 考试
  34. */
  35. public RealExam selectRealExamByExamId(Long examId) {
  36. return realExamMapper.selectRealExamByExamId(examId);
  37. }
  38. /**
  39. * 查询考试列表
  40. *
  41. * @param realExam 考试
  42. * @return 考试
  43. */
  44. public List<RealExam> selectRealExamList(RealExam realExam) {
  45. return realExamMapper.selectRealExamList(realExam);
  46. }
  47. /**
  48. * 新增考试
  49. *
  50. * @param realExam 考试
  51. * @return 结果
  52. */
  53. public int insertRealExam(RealExam realExam) {
  54. realExam.setCreateTime(DateUtils.getNowDate());
  55. return realExamMapper.insertRealExam(realExam);
  56. }
  57. /**
  58. * 修改考试
  59. *
  60. * @param realExam 考试
  61. * @return 结果
  62. */
  63. public int updateRealExam(RealExam realExam) {
  64. realExam.setUpdateTime(DateUtils.getNowDate());
  65. return realExamMapper.updateRealExam(realExam);
  66. }
  67. /**
  68. * 批量删除考试
  69. *
  70. * @param examIds 需要删除的考试主键
  71. * @return 结果
  72. */
  73. public int deleteRealExamByExamIds(Long[] examIds) {
  74. return realExamMapper.deleteRealExamByExamIds(examIds);
  75. }
  76. /**
  77. * 删除考试信息
  78. *
  79. * @param examId 考试主键
  80. * @return 结果
  81. */
  82. public int deleteRealExamByExamId(Long examId) {
  83. return realExamMapper.deleteRealExamByExamId(examId);
  84. }
  85. // -------------------------------- tom add --------------------------------
  86. private static final Logger l = LoggerFactory.getLogger(CommSendService.class);
  87. @Autowired
  88. private CommReceiveService commReceiveService;
  89. @Autowired
  90. private StudentService studentService;
  91. @Autowired
  92. private SimService simService;
  93. @Autowired
  94. private SeatService seatService;
  95. @Autowired
  96. private RealExamCollectionService realExamCollectionService;
  97. @Autowired
  98. private RealExamFaultService realExamFaultService;
  99. @Autowired
  100. private CommSendService commSendService;
  101. @Autowired
  102. private SimConfig simConfig;
  103. public List<RealExamVo> list(RealExam q) {
  104. List<RealExamVo> list = new ArrayList<>();
  105. realExamMapper.selectRealExamList(q).forEach(re -> {
  106. RealExamVo v = new RealExamVo();
  107. RealExamCollection rec = realExamCollectionService.selectRealExamCollectionByExamCollectionId(re.getExamCollectionId());
  108. v.setRealExam(re);
  109. v.setRealExamCollection(rec);
  110. list.add(v);
  111. });
  112. return list;
  113. }
  114. public List<RealExam> listAllByStatus(String state) {
  115. RealExam q = new RealExam();
  116. q.setExamStatus(state);
  117. return selectRealExamList(q);
  118. }
  119. /**
  120. * 交卷自动修改关联状态
  121. *
  122. * @param examId
  123. * @param state
  124. * @return
  125. */
  126. @Transactional
  127. public int updateOneState(long examId, final String state) {
  128. RealExam q = selectRealExamByExamId(examId);
  129. // todo:屏蔽
  130. if (false && RealExam.State.SUBMITTED.equals(state)) {
  131. // 关联故障list同步锁死。
  132. realExamFaultService.listAllType2LoopReadStateByExamId(q.getExamId())
  133. .forEach(ref -> {
  134. ref.setRefState(RealExamFault.State.FINISH);
  135. realExamFaultService.updateRealExamFault(ref);
  136. });
  137. }
  138. q.setExamStatus(state);
  139. return updateRealExam(q);
  140. }
  141. /**
  142. * [学生]进入考试。
  143. *
  144. * @return RealExam
  145. */
  146. public AjaxResult studentEnterRealExam(Long examId) {
  147. RealExam re = selectRealExamByExamId(examId);
  148. if (re == null) {
  149. AjaxResult.error("realExamId error!");
  150. }
  151. // todo:应该在登录位置实现
  152. // todo: temp
  153. updateOneState(examId, RealExam.State.LOGGED_IN);
  154. // todo: temp
  155. realExamFaultService.resetAllType2(examId);
  156. return AjaxResult.success(re);
  157. }
  158. /**
  159. * [轮询][学生]准备考试界面。
  160. *
  161. * @param realExamId
  162. * @return StudentRealExamPreVo
  163. */
  164. public AjaxResult studentLoopPrepareRealExam(Long realExamId) {
  165. l.info("studentLoopPrepareRealExam");
  166. // check
  167. if (realExamId == null || realExamId == 0) {
  168. // todo:
  169. }
  170. //
  171. RealExam re = selectRealExamByExamId(realExamId);
  172. if (re == null) {
  173. // todo:
  174. }
  175. // todo: 日期,不可进入考试。
  176. //
  177. // todo: 验证学生登录身份
  178. Objects.requireNonNull(re);
  179. RealExamCollection collection =
  180. realExamCollectionService.selectRealExamCollectionByExamCollectionId(re.getExamCollectionId());
  181. // check collection
  182. Sim sim = simService.selectSimBySimId(re.getSimId());
  183. // check sim
  184. Student student = studentService.selectStudentByUserId(re.getUserId());
  185. // check student
  186. Seat seat = seatService.selectSeatBySeatId(re.getSeatId());
  187. // check seat
  188. StudentRealExamPreVo vo = new StudentRealExamPreVo();
  189. vo.setRealExam(re);
  190. vo.setRealExamCollection(collection);
  191. vo.setSim(sim);
  192. vo.setStudent(student);
  193. vo.setSeat(seat);
  194. // todo:多人请求同时进入的问题
  195. boolean next = studentPrepareRealExamCheck(vo);
  196. vo.setNext(next);
  197. if (!next) {
  198. // 执行模拟器通信,让模拟器准备好。
  199. // 异步执行
  200. commSendService.clearListFaultByRealExamAsync(re);
  201. }
  202. l.info("vo = {}", vo);
  203. return AjaxResult.success(vo);
  204. }
  205. public boolean studentPrepareRealExamCheck(StudentRealExamPreVo v) {
  206. if (v == null ||
  207. v.getRealExam() == null ||
  208. v.getRealExamCollection() == null ||
  209. v.getSim() == null ||
  210. v.getStudent() == null ||
  211. v.getSeat() == null) {
  212. return false;
  213. }
  214. // todo:在考试日期内。
  215. // check 一个模拟器的所有选中故障点位都下发成功,准备是否可以
  216. //
  217. // todo:??
  218. // 学生答题中可以再次进入。
  219. String examStatus = v.getRealExam().getExamStatus();
  220. String simStatus = v.getSim().getSimState();
  221. // 兜底
  222. {
  223. if (realExamFaultService.isAllType2StateXiaFa(v.getRealExam().getExamId())) {
  224. updateOneState(v.getRealExam().getExamId(), RealExam.State.SIM_PREPARE_OK);
  225. }
  226. }
  227. // 模拟器不通信。
  228. if (!simConfig.isCommGlobal()) {
  229. return true;
  230. }
  231. if ((RealExam.State.SIM_PREPARE_OK.equals(examStatus) ||
  232. RealExam.State.ANSWERING.equals(examStatus)) &&
  233. Sim.State.ONLINE.equals(simStatus)
  234. ) {
  235. return true;
  236. }
  237. return false;
  238. }
  239. /**
  240. * [学生]开始考试
  241. *
  242. * @param examId
  243. * @return RealExam
  244. */
  245. @Transactional
  246. public AjaxResult studentStartRealExam(Long examId) {
  247. l.info("studentStartRealExam");
  248. RealExam re = selectRealExamByExamId(examId);
  249. l.info("re = {}", re);
  250. re.setExamStatus(RealExam.State.ANSWERING);
  251. re.setStartTime(DateUtils.getNowDate());
  252. updateRealExam(re);
  253. return AjaxResult.success(re);
  254. }
  255. /**
  256. * [轮询][学生]正在考试界面。
  257. *
  258. * @param realExamId
  259. * @return StudentRealExamIngVo
  260. */
  261. public AjaxResult studentLoopAnsweringRealExam(Long realExamId) {
  262. RealExam re = selectRealExamByExamId(realExamId);
  263. RealExamCollection rec = realExamCollectionService.selectRealExamCollectionByExamCollectionId(re.getExamCollectionId());
  264. StudentRealExamIngVo vo = new StudentRealExamIngVo();
  265. vo.setRealExam(re);
  266. long remaining = (re.getStartTime().getTime() + rec.getLimitDuration() * 60 * 1000) - DateUtils.getNowDate().getTime();
  267. vo.setRemainingMilliseconds(remaining);
  268. vo.setCompulsiveSubmit(remaining >= RealExam.EXAM_TIMEOUT_LIMIT);
  269. l.info("studentLoopAnsweringRealExam vo = {}", vo);
  270. return AjaxResult.success(vo);
  271. }
  272. /**
  273. * [学生]交卷
  274. *
  275. * @param examId
  276. * @return RealExam
  277. */
  278. public AjaxResult studentSubmitRealExam(Long examId) {
  279. // 最后检查一下模拟器状态。
  280. // 最后读取一下模拟器电阻值。
  281. // todo:
  282. RealExam re1 = selectRealExamByExamId(examId);
  283. commSendService.readOneExamAtLastAsync(re1);
  284. submit(examId);
  285. return AjaxResult.success(re1);
  286. }
  287. /**
  288. * @param examId
  289. */
  290. @Transactional
  291. public void submit(long examId) {
  292. l.info("submit");
  293. RealExam re2 = selectRealExamByExamId(examId);
  294. re2.setExamStatus(RealExam.State.SUBMITTED);
  295. re2.setEndTime(DateUtils.getNowDate());
  296. updateRealExam(re2);
  297. }
  298. /**
  299. * [轮询][学生]结束考试界面。
  300. *
  301. * @param examId
  302. * @return StudentRealExamPostVo
  303. */
  304. public AjaxResult studentLoopPostRealExam(Long examId) {
  305. RealExam re = selectRealExamByExamId(examId);
  306. StudentRealExamPostVo vo = new StudentRealExamPostVo();
  307. {
  308. }
  309. vo.setRealExam(re);
  310. vo.setListPart1(realExamFaultService.getReportListPart1(examId));
  311. vo.setListPart2(realExamFaultService.getReportListPart2(examId));
  312. vo.setPart3(realExamFaultService.getReportPart3(examId));
  313. return AjaxResult.success(vo);
  314. }
  315. }