Bläddra i källkod

列车行驶计算

zhanghaijun 2 år sedan
förälder
incheckning
8eb3b90f13

+ 5 - 18
train-common/train-common-core/src/main/java/top/haijunit/common/utils/StreamUtils.java

@@ -2,6 +2,7 @@ package top.haijunit.common.utils;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.stream.StreamUtil;
 import cn.hutool.core.util.StrUtil;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
@@ -13,26 +14,12 @@ import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 /**
- * @Author develop
- * @Date 2022/7/23
- * @Description stream 流工具类
+ * @author develop
+ * @date 2022/7/23
+ * @description stream 流工具类
  */
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class StreamUtils {
-
-    /**
-     * 将collection过滤
-     *
-     * @param collection 需要转化的集合
-     * @param function   过滤方法
-     * @return 过滤后的list
-     */
-    public static <E> LinkedList<E> filterToLinkedList(Collection<E> collection, Predicate<E> function) {
-        if (CollUtil.isEmpty(collection)) {
-            return new LinkedList<>();
-        }
-        return collection.stream().filter(function).collect(Collectors.toCollection(LinkedList::new));
-    }
+public class StreamUtils extends StreamUtil {
 
     /**
      * 将collection过滤

+ 5 - 3
train-server/src/main/java/top/haijunit/train/service/SelectionService.java

@@ -7,6 +7,7 @@ import top.haijunit.train.domain.constant.DirectionEnum;
 import top.haijunit.train.domain.constant.RouteStatusEnum;
 import top.haijunit.train.domain.entity.RouteEntity;
 import top.haijunit.train.domain.entity.SelectionEntity;
+import top.haijunit.train.domain.entity.SignStopEntity;
 import top.haijunit.train.domain.repository.RouteRepository;
 import top.haijunit.train.domain.repository.SelectionRepository;
 import top.haijunit.train.domain.repository.SignStopRepository;
@@ -14,6 +15,7 @@ import top.haijunit.train.utils.NumberUtil;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -83,7 +85,7 @@ public class SelectionService {
         return list;
     }
 
-    // public BigDecimal getMaKilometer(List<Long> selectionIds) {
-    //
-    // }
+    public HashMap<Long, SignStopEntity> getStopSignalMap(LinkedList<Long> selectionAllList) {
+        return signStopRepository.findAllById(selectionAllList).stream().collect(HashMap::new, (map, entity) -> map.put(entity.getSelectionId(), entity), HashMap::putAll);
+    }
 }

+ 1 - 2
train-server/src/main/java/top/haijunit/train/simulation/domain/TrainItem.java

@@ -18,6 +18,7 @@ import java.time.LocalTime;
  * @description [一句话描述该类的功能]
  */
 @Getter
+@Setter
 public class TrainItem {
 
     // 列车Id
@@ -30,7 +31,6 @@ public class TrainItem {
     // 公里标
     private BigDecimal kilometer;
     // 运行方向
-    @Setter
     private DirectionEnum direction;
     // 当前区段Id
     private Long blockId;
@@ -43,7 +43,6 @@ public class TrainItem {
     // 运行速度
     private BigDecimal speed;
     // 运行加速度
-    @Setter
     private BigDecimal acceleration;
 
     public TrainItem(TrainEntity train, SelectionEntity selection) {

+ 72 - 21
train-server/src/main/java/top/haijunit/train/simulation/train/TrainComputerService.java

@@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import top.haijunit.train.domain.constant.TrainConstant;
 import top.haijunit.train.domain.entity.SelectionEntity;
+import top.haijunit.train.domain.entity.SignStopEntity;
 import top.haijunit.train.service.SelectionService;
 import top.haijunit.train.simulation.domain.RouteItem;
 import top.haijunit.train.simulation.domain.TrainItem;
@@ -12,8 +13,13 @@ import top.haijunit.train.utils.CalculatorUtil;
 import top.haijunit.train.utils.NumberUtil;
 
 import java.math.BigDecimal;
+import java.time.Duration;
 import java.time.LocalTime;
+import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.OptionalInt;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /**
  * @author zhanghaijun
@@ -28,32 +34,77 @@ public class TrainComputerService {
 
 
     public void run(TrainItem trainItem) {
+        TrainSimulationHolder.addTrainItem(this.runComputer(trainItem));
+    }
+
+    public TrainItem runComputer(TrainItem trainItem) {
+        // 进路数据
         LinkedList<RouteItem> routeList = TrainSimulationHolder.getRouteList(trainItem.getTrainId());
-        if (routeList == null || routeList.isEmpty()) {
+        // 区段数据
+        LinkedList<SelectionEntity> selectionAllList = routeList.stream().map(RouteItem::getSelectionList).flatMap(LinkedList::stream).collect(Collectors.toCollection(LinkedList::new));
+        // 停车标数据
+        HashMap<Long, SignStopEntity> stopSignalMap = selectionService.getStopSignalMap(selectionAllList.stream().map(SelectionEntity::getId).collect(Collectors.toCollection(LinkedList::new)));
+        // 当前的区段下标
+        OptionalInt optionIndex = IntStream.range(0, selectionAllList.size()).filter(i -> {
+            SelectionEntity entity = selectionAllList.get(i);
+            return NumberUtil.isContain(trainItem.getHeadKilometer(), entity.getStartKilometer(), entity.getEndKilometer());
+        }).findFirst();
+        if (optionIndex.isEmpty()) {
             log.error("列车没有进路,列车位置: {},列车速度: {},列车方向: {}", trainItem.getHeadKilometer(), trainItem.getSpeed(), trainItem.getDirection());
-            return;
+            return null;
         }
-        // 获取当前的世家
+        // 计算前的区段下标
+        int index = optionIndex.getAsInt();
+        // 计算后的区段下标
+        int currentIndex = -1;
+        // 获取当前的时间
         LocalTime now = LocalTime.now();
-        // 开始更新列车的数据:位置、速度、方向
         // 1、距离上一个周期 列车运行的距离
         BigDecimal decimal = trainItem.getDistance(now);
-
-        // 2、计算当前时间列车的应该的位置
-        BigDecimal kilometer = switch (trainItem.getDirection()) {
-            case UP -> trainItem.getKilometer().subtract(decimal).abs();
-            case DOWN -> trainItem.getKilometer().add(decimal).abs();
-        };
-        SelectionEntity selection = selectionService.getSelection(kilometer, trainItem.getDirection());
-        trainItem.setHeadKilometer(now, kilometer, selection);
-
-        // 更新列车运行状态
-        RouteItem lastRoute = routeList.getLast();
-        // MA TODO 停车标
-        BigDecimal distanceMa = switch (trainItem.getDirection()) {
-            case UP -> trainItem.getHeadKilometer().subtract(lastRoute.getHeadKilometer()).abs();
-            case DOWN -> trainItem.getHeadKilometer().subtract(lastRoute.getTailKilometer()).abs();
-        };
+        if (NumberUtil.isLessOrEqual(decimal, BigDecimal.ZERO) && Duration.between(trainItem.getUpdateTime(), now).getSeconds() < 3) {
+            // 停车状态 时间不足3S
+            return trainItem;
+        } else {
+            // 向前行驶计算
+            BigDecimal kilometer = trainItem.getHeadKilometer();
+            for (int i = index; i < selectionAllList.size(); i++) {
+                SelectionEntity entity = selectionAllList.get(i);
+                BigDecimal d = entity.getEndKilometer().subtract(kilometer);
+                if (NumberUtil.isGreaterOrEqual(d, decimal)) {
+                    currentIndex = i;
+                    break;
+                }
+                kilometer = entity.getEndKilometer();
+                decimal = decimal.subtract(d);
+            }
+            for (int i = index; i <= currentIndex; i++) {
+                SelectionEntity entity = selectionAllList.get(i);
+                if (stopSignalMap.containsKey(entity.getId())) {
+                    // 期间存在停车标 立即停车
+                    trainItem.setDirection(entity.getDirection());
+                    trainItem.setUpdateTime(now);
+                    trainItem.setSpeed(new BigDecimal("0.00"));
+                    trainItem.setAcceleration(new BigDecimal("0.00"));
+                    BigDecimal kilometerStop = entity.getStartKilometer().add(stopSignalMap.get(entity.getId()).getSelectionOff());
+                    trainItem.setKilometer(kilometerStop);
+                    return trainItem;
+                }
+            }
+            SelectionEntity currentSelection = selectionAllList.get(currentIndex);
+            trainItem.setHeadKilometer(now, currentSelection.getStartKilometer().add(decimal), currentSelection);
+        }
+        // 计算MA
+        BigDecimal distanceMa = new BigDecimal("0.00");
+        for (int i = currentIndex; i < selectionAllList.size(); i++) {
+            SelectionEntity entity = selectionAllList.get(i);
+            if (!stopSignalMap.containsKey(entity.getId())) {
+                distanceMa = distanceMa.add(entity.getSelectionLength());
+                continue;
+            }
+            SignStopEntity signStop = stopSignalMap.get(entity.getId());
+            distanceMa = distanceMa.add(signStop.getSelectionOff());
+            break;
+        }
         BigDecimal distance = CalculatorUtil.distance(trainItem.getSpeed(), TrainConstant.DECELERATION_LIMIT);
         // log.info("列车信息:列车:{},速度:{},加速度:{}, 滑行距离:{}", trainItem.getTrainId(), trainItem.getSpeed(), trainItem.getAcceleration(), distance);
         if (NumberUtil.isLessOrEqual(distanceMa, distance)) {
@@ -69,6 +120,6 @@ public class TrainComputerService {
             // 加速
             trainItem.setAcceleration(TrainConstant.ACCELERATION_LIMIT);
         }
-        TrainSimulationHolder.addTrainItem(trainItem);
+        return trainItem;
     }
 }

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

@@ -26,12 +26,7 @@ public class TrainSimulationHolder {
     private static final Map<Long, LinkedList<RouteItem>> TRAVEL_ROUTE_MAP = new ConcurrentHashMap<>();
 
     public static synchronized void addTrainItem(TrainItem trainItem) {
-        TRAVEL_TRAIN_MAP.remove(trainItem.getTrainId());
-        TRAVEL_TRAIN_MAP.put(trainItem.getTrainId(), trainItem);
-    }
-
-    public static TrainItem getTrainItem(Long trainId) {
-        return TRAVEL_TRAIN_MAP.getOrDefault(trainId, null);
+        TRAVEL_TRAIN_MAP.compute(trainItem.getTrainId(), (k, v) -> trainItem);
     }
 
     public static Collection<TrainItem> getTrainItem() {
@@ -39,8 +34,7 @@ public class TrainSimulationHolder {
     }
 
     public static synchronized void addRouteList(Long trainId, LinkedList<RouteItem> RouteItemList) {
-        TRAVEL_ROUTE_MAP.remove(trainId);
-        TRAVEL_ROUTE_MAP.put(trainId, RouteItemList);
+        TRAVEL_ROUTE_MAP.compute(trainId, (k, v) -> RouteItemList);
     }
 
     public static LinkedList<RouteItem> getRouteList(Long trainId) {

+ 8 - 1
train-server/src/main/java/top/haijunit/train/utils/CalculatorUtil.java

@@ -47,7 +47,14 @@ public class CalculatorUtil {
         // 将 Duration 转换为秒数
         BigDecimal seconds = BigDecimal.valueOf(time.getSeconds()).add(BigDecimal.valueOf(time.getNano(), 9));
         // 运行距离计算公式
-        BigDecimal distance = velocity.multiply(seconds).add(NumberUtil.div(acceleration.multiply(NumberUtil.pow(seconds, 2)), new BigDecimal("2")));
+        BigDecimal distance;
+        if (NumberUtil.isGreaterOrEqual(acceleration, BigDecimal.ZERO)) {
+            // 加速状态
+            distance = NumberUtil.div(NumberUtil.mul(acceleration, NumberUtil.pow(seconds, 2)), new BigDecimal(2));
+        } else {
+            // 减速状态
+            distance = NumberUtil.add(NumberUtil.mul(velocity, seconds), NumberUtil.div(NumberUtil.mul(acceleration, NumberUtil.pow(seconds, 2)), new BigDecimal(2)));
+        }
         return distance.max(BigDecimal.ZERO);
     }