zhanghaijun лет назад: 2
Родитель
Сommit
a967bf9b89

+ 3 - 6
train-server/src/main/java/top/haijunit/train/domain/entity/SwitchEntity.java

@@ -7,7 +7,6 @@ import top.haijunit.train.domain.constant.SwitchStateEnum;
 import java.io.Serializable;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.time.LocalTime;
 import java.time.LocalTime;
-import java.time.temporal.ChronoUnit;
 
 
 /**
 /**
  * @author zhang
  * @author zhang
@@ -39,10 +38,8 @@ public class SwitchEntity implements Serializable {
     // 所属车站编号
     // 所属车站编号
     private Long stationId;
     private Long stationId;
 
 
-    // 道岔状态的更新时间,默认为一小时前
-    @Transient
-    private LocalTime updateStateTime = LocalTime.now().minusHours(1);
+    // 道岔状态的更新时间
+    private LocalTime updateStateTime;
     // 道岔的状态
     // 道岔的状态
-    @Transient
-    private SwitchStateEnum state = SwitchStateEnum.REVERSE;
+    private SwitchStateEnum switchState;
 }
 }

+ 41 - 0
train-server/src/main/java/top/haijunit/train/service/RouteService.java

@@ -0,0 +1,41 @@
+package top.haijunit.train.service;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import top.haijunit.train.domain.entity.RouteEntity;
+import top.haijunit.train.domain.repository.RouteRepository;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @author zhanghaijun
+ * @date 2023/11/29 06:54
+ * @description [一句话描述该类的功能]
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class RouteService {
+
+    private final RouteRepository routeRepository;
+
+    public RouteEntity isTrigger(BigDecimal kilometer, BigDecimal nextPrePosition) {
+        return routeRepository.findAll().stream().filter(item -> item.isTrigger(kilometer, nextPrePosition)).findFirst().orElse(null);
+    }
+
+    public RouteEntity getNextRoute(Long id) {
+        List<RouteEntity> routeList = routeRepository.findAll();
+        for (int i = 0; i < routeList.size(); i++) {
+            if (routeList.get(i).getId().equals(id)) {
+                if (i == routeList.size() - 1) {
+                    return routeList.get(0);
+                } else {
+                    return routeList.get(i + 1);
+                }
+            }
+        }
+        return null;
+    }
+}

+ 53 - 0
train-server/src/main/java/top/haijunit/train/service/SwitchService.java

@@ -0,0 +1,53 @@
+package top.haijunit.train.service;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.MapUtils;
+import org.springframework.stereotype.Service;
+import top.haijunit.train.domain.constant.SwitchStateEnum;
+import top.haijunit.train.domain.entity.SwitchEntity;
+import top.haijunit.train.domain.repository.SwitchRepository;
+
+import java.time.LocalTime;
+import java.util.Map;
+
+/**
+ * @author zhanghaijun
+ * @date 2023/11/29 06:23
+ * @description 道岔处理
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class SwitchService {
+
+    private final SwitchRepository switchRepository;
+
+    /**
+     * 改变道岔的状态
+     *
+     * @param switchStateMap 改变后的的道岔状态
+     * @return 是否发生了变化,变化后需要等待时间
+     */
+    public boolean changeSwitchState(Map<Long, SwitchStateEnum> switchStateMap) {
+        boolean isChanged = false;
+        if (MapUtils.isEmpty(switchStateMap)) {
+            return isChanged;
+        }
+        for (Map.Entry<Long, SwitchStateEnum> entry : switchStateMap.entrySet()) {
+            SwitchEntity switchEntity = switchRepository.findById(entry.getKey()).orElse(null);
+            if (switchEntity == null) {
+                log.error("-----道岔不存在, id: {}", entry.getKey());
+                continue;
+            }
+            if (switchEntity.getSwitchState() != entry.getValue()) {
+                switchEntity.setSwitchState(entry.getValue());
+                switchEntity.setUpdateStateTime(LocalTime.now());
+                switchRepository.save(switchEntity);
+                isChanged = true;
+            }
+        }
+        return isChanged;
+    }
+
+}

+ 43 - 51
train-server/src/main/java/top/haijunit/train/simulation/TrainComputerService.java

@@ -5,13 +5,12 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import top.haijunit.train.domain.constant.RouteStatusEnum;
 import top.haijunit.train.domain.constant.RouteStatusEnum;
 import top.haijunit.train.domain.constant.SignalStateEnum;
 import top.haijunit.train.domain.constant.SignalStateEnum;
-import top.haijunit.train.domain.constant.SwitchStateEnum;
 import top.haijunit.train.domain.entity.RouteEntity;
 import top.haijunit.train.domain.entity.RouteEntity;
-import top.haijunit.train.domain.repository.RouteRepository;
+import top.haijunit.train.service.RouteService;
+import top.haijunit.train.service.SwitchService;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
-import java.util.Collection;
-import java.util.List;
+import java.util.LinkedList;
 
 
 /**
 /**
  * @author zhanghaijun
  * @author zhanghaijun
@@ -23,56 +22,49 @@ import java.util.List;
 @RequiredArgsConstructor
 @RequiredArgsConstructor
 public class TrainComputerService {
 public class TrainComputerService {
 
 
-    private final RouteRepository routeRepository;
+    private final SwitchService switchService;
+    private final RouteService routeService;
 
 
-    public void routeCompute() {
-        Collection<TrainItem> trainItems = TrainSimulationHolder.getTrainItem();
-        List<RouteEntity> routeList = routeRepository.findAll();
-        // 1、数据库初始化,所以进路状态都是空闲状态
-        // 2、遍历所有车辆,车辆是否占用此进路,占用则改变状态为占用
-        // 3、遍历所有车辆,判断是否在MA范围内,标识状态为锁定
-        // 4、遍历所有车辆,判断是否需要触发进路,触发则改变状态为锁定
-        for (RouteEntity route : routeList) {
-            for (TrainItem train : trainItems) {
-                // TODO 假设向前走100米
-                BigDecimal nextPrePosition = train.getKilometer().add(new BigDecimal(100));
-                if (!route.isTrigger(train.getKilometer(), nextPrePosition)) {
-                    continue;
-                }
-                // a)检查进路当前是否为出清/空闲状态,否则返回触发失败;
-                if (!route.getRouteStatus().equals(RouteStatusEnum.IDLE)) {
-                    continue;
-                }
-                if (!route.getSwitchList().isEmpty()) {
-                    // b)检查进路中道岔状态是否与进路要求的状态一致
-                    if (!route.getSwitchStateList().stream().allMatch(switchState -> switchState.equals(SwitchStateEnum.REVERSE))) {
-                        // 切换道岔状态
-                        continue;
-                    }
-                }
-                // c)出清(如果包括道岔,道岔已就位),将进路至于锁闭状态
-                RouteEntity nextRoute = nextRoute(route.getId());
-                if (null == nextRoute) {
-                    continue;
-                }
-                nextRoute.setRouteStatus(RouteStatusEnum.LOCK);
-                // d)将进路的信号状态置为红色
-                nextRoute.setSignalState(String.valueOf(SignalStateEnum.RED_YELLOW.getCode()));
-            }
+    public void routeCompute(TrainItem train) {
+        LinkedList<RouteEntity> routeList = TrainSimulationHolder.getRouteList(train.getId());
+        // 1、是否触发进路计算
+        // 2、寻找下一跳进路
+        // 3、下一条进路是否为空闲
+        // 4、下一条进路是否包括道岔,道岔状态是否正确
+        // 5、将下一条进路状态置为锁定状态
+        // 6、释放车尾已过的进路
+        // TODO 假设向前走100米
+        BigDecimal nextPrePosition = train.getKilometer().add(new BigDecimal(100));
+        RouteEntity routeTrigger = routeService.isTrigger(train.getKilometer(), nextPrePosition);
+        if (null == routeTrigger) {
+            // 没有触发进路
+            return;
         }
         }
-    }
-
-    private RouteEntity nextRoute(Long id) {
-        List<RouteEntity> routeList = routeRepository.findAll();
-        for (int i = 0; i < routeList.size(); i++) {
-            if (routeList.get(i).getId().equals(id)) {
-                if (i == routeList.size() - 1) {
-                    return routeList.get(0);
-                } else {
-                    return routeList.get(i + 1);
-                }
+        // 找到下一个进路
+        RouteEntity nextRoute = routeService.getNextRoute(routeTrigger.getId());
+        if (null == nextRoute) {
+            // 没有找到下一个进路
+            return;
+        }
+        // a)检查进路当前是否为出清/空闲状态,否则返回触发失败;
+        if (!TrainSimulationHolder.isRouteIdle(nextRoute.getId())) {
+            // 下一跳进路为非出清状态
+            return;
+        }
+        if (!routeTrigger.getSwitchList().isEmpty()) {
+            // b)检查进路中道岔状态是否与进路要求的状态一致
+            boolean changed = switchService.changeSwitchState(routeTrigger.getSwitchMap());
+            if (changed) {
+                // TODo 切换道岔需要时间
+                return;
             }
             }
         }
         }
-        return null;
+        // c)出清(如果包括道岔,道岔已就位),将进路至于锁闭状态
+        nextRoute.setRouteStatus(RouteStatusEnum.LOCK);
+        // d)将进路的信号状态置为红色
+        nextRoute.setSignalState(String.valueOf(SignalStateEnum.RED_YELLOW.getCode()));
+        routeList.addLast(nextRoute);
+        // TODO 释放车尾已过的进路
+
     }
     }
 }
 }

+ 13 - 8
train-server/src/main/java/top/haijunit/train/simulation/TrainSimulationHolder.java

@@ -2,12 +2,10 @@ package top.haijunit.train.simulation;
 
 
 import lombok.AccessLevel;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import lombok.NoArgsConstructor;
+import top.haijunit.train.domain.constant.RouteStatusEnum;
 import top.haijunit.train.domain.entity.RouteEntity;
 import top.haijunit.train.domain.entity.RouteEntity;
 
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 
 
 /**
 /**
@@ -21,7 +19,7 @@ public class TrainSimulationHolder {
     // 列车数据共享
     // 列车数据共享
     private static final Map<Long, TrainItem> TRAVEL_TRAIN_MAP = new ConcurrentHashMap<>();
     private static final Map<Long, TrainItem> TRAVEL_TRAIN_MAP = new ConcurrentHashMap<>();
     // 进路数据共享
     // 进路数据共享
-    private static final Map<Long, List<RouteEntity>> TRAVEL_ROUTE_MAP = new ConcurrentHashMap<>();
+    private static final Map<Long, LinkedList<RouteEntity>> TRAVEL_ROUTE_MAP = new ConcurrentHashMap<>();
 
 
     public static void addTrainItem(TrainItem trainItem) {
     public static void addTrainItem(TrainItem trainItem) {
         TRAVEL_TRAIN_MAP.remove(trainItem.getId());
         TRAVEL_TRAIN_MAP.remove(trainItem.getId());
@@ -36,13 +34,20 @@ public class TrainSimulationHolder {
         return TRAVEL_TRAIN_MAP.values();
         return TRAVEL_TRAIN_MAP.values();
     }
     }
 
 
-    public static void addRouteList(Long trainId, List<RouteEntity> routeEntityList) {
+    public static void addRouteList(Long trainId, LinkedList<RouteEntity> routeEntityList) {
         TRAVEL_ROUTE_MAP.remove(trainId);
         TRAVEL_ROUTE_MAP.remove(trainId);
         TRAVEL_ROUTE_MAP.put(trainId, routeEntityList);
         TRAVEL_ROUTE_MAP.put(trainId, routeEntityList);
     }
     }
 
 
-    public static List<RouteEntity> getRouteList(Long trainId) {
-        return TRAVEL_ROUTE_MAP.getOrDefault(trainId, new ArrayList<>());
+    public static LinkedList<RouteEntity> getRouteList(Long trainId) {
+        return TRAVEL_ROUTE_MAP.getOrDefault(trainId, new LinkedList<>());
+    }
+
+    public static boolean isRouteIdle(Long routeId) {
+        for (Map.Entry<Long, LinkedList<RouteEntity>> entry : TRAVEL_ROUTE_MAP.entrySet()) {
+            return entry.getValue().stream().noneMatch(item -> item.getId().equals(routeId) && !item.getRouteStatus().equals(RouteStatusEnum.IDLE));
+        }
+        return true;
     }
     }
 
 
 }
 }

+ 2 - 0
train-server/src/main/resources/db/changelog/db-server-train.xml

@@ -196,6 +196,8 @@
             <column name="next_selection_id" type="${autoing.type}" defaultValueNumeric="0" remarks="岔后区段号"/>
             <column name="next_selection_id" type="${autoing.type}" defaultValueNumeric="0" remarks="岔后区段号"/>
             <column name="next_side_selection_id" type="${autoing.type}" defaultValueNumeric="0" remarks="岔后侧向区段号"/>
             <column name="next_side_selection_id" type="${autoing.type}" defaultValueNumeric="0" remarks="岔后侧向区段号"/>
             <column name="switch_tie" type="${autoing.type}" defaultValueNumeric="0" remarks="关联道岔"/>
             <column name="switch_tie" type="${autoing.type}" defaultValueNumeric="0" remarks="关联道岔"/>
+            <column name="update_state_time" type="datetime" defaultValue="${time.now}" remarks="状态更新时间"/>
+            <column name="switch_state" type="${number.type}" defaultValueNumeric="2" remarks="所属车站编号"/>
             <column name="station_id" type="${autoing.type}" defaultValueNumeric="0" remarks="所属车站编号"/>
             <column name="station_id" type="${autoing.type}" defaultValueNumeric="0" remarks="所属车站编号"/>
         </createTable>
         </createTable>
     </changeSet>
     </changeSet>

+ 3 - 3
train-server/src/main/resources/db/changelog/db-server.xml

@@ -19,9 +19,9 @@
     <property name="number.type" value="int" dbms="mysql,mariadb"/>
     <property name="number.type" value="int" dbms="mysql,mariadb"/>
     <property name="number.type" value="serial"/>
     <property name="number.type" value="serial"/>
 
 
-    <property name="now" value="now()" dbms="h2"/>
-    <property name="now" value="now()" dbms="mysql,mariadb"/>
-    <property name="now" value="sysdate"/>
+    <property name="time.now" value="now()" dbms="h2"/>
+    <property name="time.now" value="now()" dbms="mysql,mariadb"/>
+    <property name="time.now" value="sysdate"/>
 
 
     <changeSet author="zhanghaijun" id="mysql_charsets_change" runOnChange="true" runAlways="true" failOnError="false" dbms="mysql,mariadb">
     <changeSet author="zhanghaijun" id="mysql_charsets_change" runOnChange="true" runAlways="true" failOnError="false" dbms="mysql,mariadb">
         <validCheckSum>ANY</validCheckSum>
         <validCheckSum>ANY</validCheckSum>