Procházet zdrojové kódy

优化 开始考试,交卷 相关的检查。

tom před 2 měsíci
rodič
revize
88882dcaa3

+ 11 - 0
ruoyi-sim/src/main/java/com/ruoyi/sim/controller/HardwareCommDebugController.java

@@ -134,4 +134,15 @@ public class HardwareCommDebugController extends BaseController {
         // todo:
         return commBuildService.buildSendMsgAR(simNum, orn, cmd, cmdId, data);
     }
+
+    /**
+     * todo:
+     *
+     * @return
+     */
+    @GetMapping(value = "/debugResetAnything/")
+    @ApiOperation("debug重置所有")
+    public AjaxResult debugResetAnything() {
+        return commSendService.debugResetAnything();
+    }
 }

+ 7 - 0
ruoyi-sim/src/main/java/com/ruoyi/sim/controller/RealExamCollectionController.java

@@ -124,4 +124,11 @@ public class RealExamCollectionController extends BaseController {
         l.info("[教师][正式使用]关闭训练集合;examCollectionId = {}", examCollectionId);
         return service.close(examCollectionId, RealExamCollection.Type.EXERCISE);
     }
+
+    @PutMapping(value = "/teacher/all/close")
+    @ApiOperation("[教师][正式使用]关闭考试+训练+练习")
+    public AjaxResult closeAll() {
+        l.info("[教师][正式使用]关闭考试+训练+练习");
+        return service.closeAll();
+    }
 }

+ 1 - 1
ruoyi-sim/src/main/java/com/ruoyi/sim/domain/SimMsg.java

@@ -253,7 +253,7 @@ public class SimMsg extends BaseEntity {
         Integer DEFAULT_VALUE = 0;
         Integer SUCCESS = 200;
         Integer SOCKET_CONNECT_EXCEPTION = 501;
-        Integer SOCKET_READ_TIMEOUT_EXCEPTION = 502;
+        Integer READ_TIMEOUT_EXCEPTION = 502;
         Integer RECEIVE_CHECK_FAIL = 520;
     }
 

+ 1 - 1
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommCheckService.java

@@ -154,7 +154,7 @@ public class CommCheckService {
             return AjaxResult.success(msg);
         } else if (Objects.equals(result, SimMsg.Result.RECEIVE_CHECK_FAIL)) {
             return AjaxResult.error("失败,报文回复异常。");
-        } else if (Objects.equals(result, SimMsg.Result.SOCKET_READ_TIMEOUT_EXCEPTION)) {
+        } else if (Objects.equals(result, SimMsg.Result.READ_TIMEOUT_EXCEPTION)) {
             // 更新SimId
             seatService.updateSimIdBySeatNum(seat.getSeatNum(), Sim.ID_0);
             String msgTemp = "座号[{0}]-没有连接任何接模拟器,检查线缆连接和线缆开关";

+ 2 - 2
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommParseUtils.java

@@ -14,14 +14,14 @@ public class CommParseUtils {
      */
     public static String subContentData(SimMsg sm) {
         if (StringUtils.isBlank(sm.getReceiveMsg())) {
-            throw new IllegalArgumentException("sm isBlank");
+            throw new IllegalArgumentException("模拟器回复为空!");
         }
         return StringUtils.substring(sm.getReceiveMsg(), 10, 18);
     }
 
     public static String subSimNum(SimMsg sm) {
         if (StringUtils.isBlank(sm.getReceiveMsg())) {
-            throw new IllegalArgumentException("sm isBlank");
+            throw new IllegalArgumentException("模拟器回复为空!");
         }
         return StringUtils.substring(sm.getReceiveMsg(), 2, 4);
     }

+ 34 - 1
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommSendService.java

@@ -867,7 +867,7 @@ public class CommSendService {
             // SocketTimeoutException
             l.error("SocketTimeoutException");
             e.printStackTrace();
-            sm.setResult(SimMsg.Result.SOCKET_READ_TIMEOUT_EXCEPTION);
+            sm.setResult(SimMsg.Result.READ_TIMEOUT_EXCEPTION);
             if (sim != null) {
                 l.info("fail sim.getSimId() = {}", sim.getSimId());
             }
@@ -981,4 +981,37 @@ public class CommSendService {
             throw new IllegalArgumentException("error gggSimBySeatId");
         }
     }
+
+    /**
+     * todo:
+     *
+     * @return
+     */
+    public AjaxResult debugResetAnything() {
+        // Step:关闭所有Socket连接
+
+        // Step:ping路由器,返回在线情况。
+
+        // Step:ping教员端主机,返回在线情况。
+
+        // Step:ping所有学员端主机,返回在线情况列表。
+
+        // Step:ping所有RS485,返回在线情况列表。
+
+        // Step:建立所有模拟器Socket,返回情况列表。
+
+        // Step:有Socket的前提下,尝试查询所有模拟器连接情况,得到连接的模拟器 型号、序列号信息
+
+        // Step:所有连接的模拟器,清除每一个模拟器的各个故障
+
+        // Step:所有连接的模拟器,读取每一个模拟器的各个故障,是否处于考试准备ok状态
+
+        // 删除debug表中所有数据。
+        try {
+            Thread.sleep(5000L);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+        return AjaxResult.success("全部重置成功。todo:123456");
+    }
 }

+ 10 - 25
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/RealExamCollectionService.java

@@ -319,7 +319,7 @@ public class RealExamCollectionService extends Ele6RYBaseService {
         switch (examCollectionType) {
             case RealExamCollection.Type.EXERCISE: {
                 if (existOpenedByType(RealExamCollection.Type.EXAM)) {
-                    return AjaxResult.error("存在已经打开的考试,请关闭后再操作!");
+                    return AjaxResult.error("存在已经打开的考试,<br/>请关闭后再操作!");
                 }
                 closeAllExcludeIdByType(RealExamCollection.Type.EXERCISE, rec.getExamCollectionId());
                 closeAllByType(RealExamCollection.Type.SELF_EXERCISE);
@@ -327,10 +327,10 @@ public class RealExamCollectionService extends Ele6RYBaseService {
             }
             case RealExamCollection.Type.SELF_EXERCISE: {
                 if (existOpenedByType(RealExamCollection.Type.EXAM)) {
-                    return AjaxResult.error("存在已经打开的考试,请关闭后再操作!");
+                    return AjaxResult.error("存在已经打开的考试,<br/>请关闭后再操作!");
                 }
                 if (existOpenedByType(RealExamCollection.Type.EXERCISE)) {
-                    return AjaxResult.error("存在已经打开的训练,请关闭后再操作!");
+                    return AjaxResult.error("存在已经打开的训练,<br/>请关闭后再操作!");
                 }
                 // 练习可以同时打开多个。
                 break;
@@ -400,6 +400,13 @@ public class RealExamCollectionService extends Ele6RYBaseService {
         return AjaxResult.success("关闭成功!");
     }
 
+    public AjaxResult close() {
+        closeAllByType(RealExamCollection.Type.EXERCISE);
+        closeAllByType(RealExamCollection.Type.SELF_EXERCISE);
+        closeAllByType(RealExamCollection.Type.EXAM);
+        return AjaxResult.success("所有的考试、训练、练习都关闭成功!");
+    }
+
     public List<RealExamCollection> listAllByType(String examCollectionType) {
         RealExamCollection q = new RealExamCollection();
         q.setExamCollectionType(examCollectionType);
@@ -490,26 +497,4 @@ public class RealExamCollectionService extends Ele6RYBaseService {
         }
         return list.get(0);
     }
-
-
-    public AjaxResult resetAllSuperMan() {
-        // Step:关闭所有Socket连接
-
-        // Step:ping路由器,返回在线情况。
-
-        // Step:ping教员端主机,返回在线情况。
-
-        // Step:ping所有学员端主机,返回在线情况列表。
-
-        // Step:ping所有RS485,返回在线情况列表。
-
-        // Step:建立所有模拟器Socket,返回情况列表。
-
-        // Step:有Socket的前提下,尝试查询所有模拟器连接情况,得到连接的模拟器 型号、序列号信息
-
-        // Step:所有连接的模拟器,清除每一个模拟器的各个故障
-
-        // Step:所有连接的模拟器,读取每一个模拟器的各个故障,是否处于考试准备ok状态
-        return null;
-    }
 }

+ 57 - 6
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/RealExamService.java

@@ -3,6 +3,7 @@ package com.ruoyi.sim.service.impl;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.Spliterator;
 
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.utils.DateUtils;
@@ -318,7 +319,24 @@ public class RealExamService {
             }
         }
         RealExam re = selectRealExamByExamId(examId);
+        // check:考试状态
+        if (StringUtils.equals(re.getExamStatus(), RealExam.State.SUBMITTED) ||
+                StringUtils.equals(re.getExamStatus(), RealExam.State.CALCULATING_SCORE) ||
+                StringUtils.equals(re.getExamStatus(), RealExam.State.GOT_REPORT)) {
+            return AjaxResult.error("已经交卷,禁止重复开始考试!");
+        }
         RealExamCollection rec = realExamCollectionService.selectRealExamCollectionByExamCollectionId(re.getExamCollectionId());
+        // Check:考试集合数据有效性。
+        if (rec == null) {
+            return AjaxResult.error("考试集合数据异常!");
+        }
+        if (!StringUtils.equals(rec.getExamCollectionState(), RealExamCollection.State.OPENED)) {
+            return AjaxResult.error("教师端对应考试/训练尚未打开!<br/>请向教员说明情况。");
+        }
+        // Check:检查参数examCollectionType有效性
+        if (!StringUtils.equals(examCollectionType, rec.getExamCollectionType())) {
+            return AjaxResult.error("考试集合类型不对应!");
+        }
         // Check:检查参数studentBindIp有效性
         if (StringUtils.isBlank(studentBindIp)) {
             return AjaxResult.error("IP地址无效");
@@ -327,10 +345,6 @@ public class RealExamService {
         if (seat == null) {
             return AjaxResult.error("没有IP对应座次数据!");
         }
-        // Check:检查参数examCollectionType有效性
-        if (!StringUtils.equals(examCollectionType, rec.getExamCollectionType())) {
-            return AjaxResult.error("考试集合类型不对应!");
-        }
         // Check:ping通 路由器。
         {
             AjaxResult ar = commCheckService.checkRouterState(simConfig.getRouterIp());
@@ -373,12 +387,20 @@ public class RealExamService {
                 return ar;
             }
         }
+        // Step:正式开始考试。锁定 座次 和 模拟器。
         // Step:重新查询。已经确定simId和simState了。
         {
             // 修改exam表对应examId的一条数据,填充并锁定seat_id和sim_id值。
             // 设置上seatId和simId
             re = selectRealExamByExamId(examId);
             seat = seatService.uniqueByBindIp(studentBindIp);
+            if (seat.getCurrentSimId() == 0L) {
+                return AjaxResult.success("参数错误,座次上CurrentSimId = 0");
+            }
+            if (seat.getSeatId() == 0L) {
+                return AjaxResult.success("参数错误,座次上getSeatId = 0");
+            }
+            l.debug("seat = {}", seat);
             re.setSeatId(seat.getSeatId());
             re.setSimId(seat.getCurrentSimId());
             updateRealExam(re);
@@ -407,7 +429,6 @@ public class RealExamService {
                 return ar;
             }
         }
-        // Step:正式开始考试。
         // Step:清除对应一台模拟器 所有 真实的 故障部位故障。
         {
             commSendService.clearOneSimAllFaultByExam(re);
@@ -475,6 +496,8 @@ public class RealExamService {
         return AjaxResult.success(vo);
     }
 
+    public static final Long DURATION_10_MIN = 1000L * 60 * 10;
+
     /**
      * [学生]交卷考试
      *
@@ -491,10 +514,38 @@ public class RealExamService {
             }
         }
         RealExam re = selectRealExamByExamId(examId);
+        if (re == null ||
+                re.getExamId() == 0L ||
+                re.getSimId() == null ||
+                re.getSimId() == 0L ||
+                re.getExamCollectionId() == null ||
+                re.getExamCollectionId() == 0L) {
+            l.debug("RealExam = {}", re);
+            return AjaxResult.error("交卷数据错误!");
+        }
+        if (re.getStartTime() == null) {
+            return AjaxResult.error("考试开始时间异常!");
+        }
+        // check:考试状态
+        if (StringUtils.equals(re.getExamStatus(), RealExam.State.SUBMITTED)) {
+            return AjaxResult.error("已经交卷,禁止重复交卷,<br/>请刷新自动结束考试!");
+        }
         RealExamCollection rec = realExamCollectionService.selectRealExamCollectionByExamCollectionId(re.getExamCollectionId());
+        // 允许考试时长,毫秒
+        Long millisecondsAllowed = rec.getLimitDuration() * 60 * 1000 + DURATION_10_MIN;
+        // Check:已经超时的交卷。
+        if (DateUtils.getNowDate().getTime() > re.getStartTime().getTime() + millisecondsAllowed) {
+            // 修改考试状态
+            re.setExamStatus(RealExam.State.SUBMITTED);
+            // 修改真实考试结束时间。
+            re.setEndTime(DateUtils.getNowDate());
+            updateRealExam(re);
+            return AjaxResult.success("考试时间已经超时,自动结束考试!");
+        }
+
         // Check:检查参数studentBindIp有效性
         if (StringUtils.isBlank(studentBindIp)) {
-            return AjaxResult.error("IP地址无效");
+            return AjaxResult.error("IP地址无效");
         }
         // 现在交卷的座次
         Seat seatNow = seatService.uniqueByBindIp(studentBindIp);