Browse Source

列车行驶区段计算优化

zhanghaijun 2 years ago
parent
commit
91e24b1b25

+ 1 - 0
train-server/src/main/java/top/haijunit/train/service/SectionService.java

@@ -40,6 +40,7 @@ public class SectionService {
      * 获取所有停车标信息
      * @return 停车标集合
      */
+    @Cacheable(cacheNames = CacheNames.SECTION, key = "'StopSignalMap'")
     public HashMap<Long, SignStopEntity> getStopSignalMap() {
         List<SignStopEntity> list = signStopRepository.findAll();
         return list.stream().collect(HashMap::new, (map, entity) -> map.put(entity.getSelectionId(), entity), HashMap::putAll);

+ 11 - 3
train-server/src/main/java/top/haijunit/train/simulation/domain/TrainTravel.java

@@ -5,6 +5,7 @@ import liquibase.util.StringUtil;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import top.haijunit.train.domain.constant.DirectionEnum;
 import top.haijunit.train.domain.entity.SignStopEntity;
 import top.haijunit.train.utils.NumberUtil;
@@ -17,9 +18,9 @@ import java.util.Optional;
 /**
  * @author zhanghaijun
  * @date 2023/12/17 21:30
- * @description [一句话描述该类的功能]
- * @version 1.0
+ * @description 列车行驶计算
  */
+@Slf4j
 @Data
 public class TrainTravel {
 
@@ -55,7 +56,13 @@ public class TrainTravel {
     public TravelItem travel(String id, BigDecimal offset, BigDecimal distance) {
         Optional<SectionItem> sectionOptional = sectionList.stream().filter(item -> StrUtil.equals(item.getId(), id)).findFirst();
         if (sectionOptional.isEmpty()) {
-            return null;
+            // 未找到区段
+            SectionItem sectionLast = this.sectionList.stream().filter(item -> item.getNextId().equals(id)).findFirst().orElseThrow(() -> new IllegalArgumentException(String.format("找不到进路区段, sectionUid: %s", id)));
+            return new TravelItem(sectionLast, switch (sectionLast.getDirection()) {
+                case UP -> BigDecimal.ZERO;
+                // 区段是含头不含尾,所以要保证列车在当前区段-2
+                case DOWN -> NumberUtil.sub(sectionLast.getSectionLength(), 2);
+            }, true);
         }
         SectionItem sectionItem = sectionOptional.get();
         if (null == offset) {
@@ -77,6 +84,7 @@ public class TrainTravel {
                 return new TravelItem(sectionItem, stopEntity.getSelectionOff().abs(), true);
             }
         }
+        // TODO 计算MA 区段折返标志
         if (NumberUtil.isLess(travelOffset, BigDecimal.ZERO)) {
             // <0 上行 行驶到下一个区段
             return travel(sectionItem.getNextId(), null, travelOffset.abs());

+ 12 - 13
train-server/src/main/java/top/haijunit/train/simulation/train/TrainComputerService.java

@@ -66,18 +66,16 @@ public class TrainComputerService {
             HashMap<Long, SignStopEntity> stopSignalMap = sectionService.getStopSignalMap();
             TrainTravel trainTravel = new TrainTravel(sectionList, stopSignalMap);
             TrainTravel.TravelItem travel = trainTravel.travel(train, distance);
-            if (null != travel) {
-                train.setSpeed(CalculatorUtil.velocity(train.getSpeed(), train.getAcceleration(), train.getUpdateTimeMillis(), nowMillis).abs());
-                train.setOffset(travel.getOffset());
-                train.setBlockId(travel.getSection().getSectionId());
-                train.setBlockNo(travel.getSection().getSectionName());
-                train.setDirection(travel.getSection().getDirection());
-                train.setUpdateTimeMillis(nowMillis);
-                if (travel.isStop()) {
-                    train.setSpeed(BigDecimal.ZERO);
-                    train.setAcceleration(BigDecimal.ZERO);
-                    return train;
-                }
+            train.setSpeed(CalculatorUtil.velocity(train.getSpeed(), train.getAcceleration(), train.getUpdateTimeMillis(), nowMillis).abs());
+            train.setOffset(travel.getOffset());
+            train.setBlockId(travel.getSection().getSectionId());
+            train.setBlockNo(travel.getSection().getSectionName());
+            train.setDirection(travel.getSection().getDirection());
+            train.setUpdateTimeMillis(nowMillis);
+            if (travel.isStop()) {
+                train.setSpeed(BigDecimal.ZERO);
+                train.setAcceleration(BigDecimal.ZERO);
+                return train;
             }
         } else {
             // 停车后更新时间
@@ -114,7 +112,8 @@ public class TrainComputerService {
         return getDistanceMa(list, sectionOptional.get(), train.getOffset(), BigDecimal.ZERO);
     }
 
-    private BigDecimal getDistanceMa(LinkedList<SectionItem> list, SectionItem sectionItem, BigDecimal offset, BigDecimal distance) {
+    public BigDecimal getDistanceMa(Collection<SectionItem> list, SectionItem sectionItem, BigDecimal offset, BigDecimal distance) {
+        // TODO 计算MA 区段的停车标、折返标志
         BigDecimal sectionDistance = null == offset ? sectionItem.getSectionLength() : switch (sectionItem.getDirection()) {
             case UP -> offset.abs();
             case DOWN -> NumberUtil.sub(sectionItem.getSectionLength().abs(), offset.abs());

+ 33 - 7
train-server/src/test/java/top/haijunit/train/test/ComputerRouteTest.java

@@ -1,25 +1,31 @@
 package top.haijunit.train.test;
 
+import cn.hutool.core.collection.CollUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.aspectj.lang.annotation.Before;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.*;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.CsvSource;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
+import top.haijunit.common.utils.StreamUtils;
 import top.haijunit.train.TrainServerMain;
+import top.haijunit.train.domain.constant.DirectionEnum;
 import top.haijunit.train.domain.entity.SignStopEntity;
+import top.haijunit.train.domain.entity.TrainEntity;
 import top.haijunit.train.service.SectionService;
 import top.haijunit.train.simulation.domain.SectionItem;
+import top.haijunit.train.simulation.domain.TrainItem;
 import top.haijunit.train.simulation.domain.TrainTravel;
+import top.haijunit.train.simulation.train.TrainComputerService;
+import top.haijunit.train.utils.NumberUtil;
 
 import java.math.BigDecimal;
 import java.util.HashMap;
 import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /**
  * @author zhanghaijun
@@ -33,6 +39,8 @@ public class ComputerRouteTest {
 
     @Autowired
     private SectionService sectionService;
+    @Autowired
+    private TrainComputerService trainComputerService;
     // 进路区段集合
     private List<SectionItem> sectionItems;
 
@@ -40,8 +48,8 @@ public class ComputerRouteTest {
     @BeforeEach
     void localAllRoute() {
         this.sectionItems = sectionService.getAllSection();
-        this.sectionItems.forEach(item -> log.info("id:{}, 进路:{}, 区段名称:{}, 区段Id:{}, 上一个:{}, 下一个:{}, 道岔:{}, 折返:{}", item.getId(), item.getRouteName(), item.getSectionName(), item.getSectionId(), item.getPreId(), item.getNextId(), item.isSwitch(), item.isTurnBack()));
-        log.info("------ 进路区段集合 ------");
+        // this.sectionItems.forEach(item -> log.info("id:{}, 进路:{}, 区段名称:{}, 区段Id:{}, 上一个:{}, 下一个:{}, 道岔:{}, 折返:{}", item.getId(), item.getRouteName(), item.getSectionName(), item.getSectionId(), item.getPreId(), item.getNextId(), item.isSwitch(), item.isTurnBack()));
+        // log.info("------ 进路区段集合 ------");
     }
 
     @DisplayName("列车行驶-上行")
@@ -69,6 +77,24 @@ public class ComputerRouteTest {
         HashMap<Long, SignStopEntity> stopSignalMap = sectionService.getStopSignalMap();
         TrainTravel trainTravel = new TrainTravel(this.sectionItems, stopSignalMap);
         TrainTravel.TravelItem travel = trainTravel.travel(id, new BigDecimal(offset), new BigDecimal(distance));
-        log.info("当前的位置, 方向:{}, 是否停车:{}, 区段:{}, 偏移量:{}", travel.getSection().getDirection().getDescribe(), travel.isStop(), travel.getSection().getSectionName(), travel.getOffset());
+        SectionItem section = travel.getSection();
+        log.info("当前的位置, 方向:{}, 是否停车:{}, 区段:{}, 偏移量:{}", section.getDirection().getDescribe(), travel.isStop(), section.getSectionName(), travel.getOffset());
+        Assertions.assertTrue(NumberUtil.isLess(travel.getOffset(), section.getSectionLength()));
+    }
+
+    @DisplayName("计算MA")
+    @ParameterizedTest
+    @CsvSource({"108001-103009,50,3", "108001-103009,40,3", "108005-103018,50,3", "108005-103018,40,3"})
+    void computeMa(String id, Integer offset, Integer count) {
+        this.trainDistanceMaTest(id, offset, count);
+    }
+
+    private void trainDistanceMaTest(String id, Integer offset, Integer count) {
+        int index = IntStream.range(0, this.sectionItems.size()).filter(i -> this.sectionItems.get(i).getId().equals(id)).findFirst().orElse(-1);
+        List<SectionItem> list = CollUtil.sub(this.sectionItems, index, index + count);
+        SectionItem sectionItem = this.sectionItems.stream().filter(item -> item.getId().equals(id)).findFirst().orElseThrow();
+        Assertions.assertTrue(NumberUtil.isLess(new BigDecimal(offset), sectionItem.getSectionLength()));
+        BigDecimal distanceMa = trainComputerService.getDistanceMa(list, sectionItem, new BigDecimal(offset), BigDecimal.ZERO);
+        log.error("MA计算, 当前区段: {}, 方向: {}, 偏移量: {}, 进路: {}, MA: {}", sectionItem.getSectionName(), sectionItem.getDirection().getDescribe(), offset, list.stream().map(item -> item.getSectionName() + "|" + item.getSectionLength()).collect(Collectors.joining(",")), distanceMa);
     }
 }

+ 20 - 0
train-server/src/test/java/top/haijunit/train/test/ComputerTrainTest.java

@@ -0,0 +1,20 @@
+package top.haijunit.train.test;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.DisplayName;
+import org.springframework.boot.test.context.SpringBootTest;
+import top.haijunit.train.TrainServerMain;
+
+/**
+ * @author zhanghaijun
+ * @date 2023/12/18 14:22
+ * @description 列车行驶 单元测试
+ */
+@Slf4j
+@DisplayName("进路测试")
+@SpringBootTest(classes = TrainServerMain.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
+public class ComputerTrainTest {
+
+
+
+}

+ 0 - 32
train-server/src/test/java/top/haijunit/train/test/DemoTest.java

@@ -1,32 +0,0 @@
-package top.haijunit.train.test;
-
-import lombok.extern.slf4j.Slf4j;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.ValueSource;
-import org.springframework.boot.test.context.SpringBootTest;
-
-/**
- * @author zhanghaijun
- * @description [一句话描述该类的功能]
- * @version 1.0
- */
-@Slf4j
-@SpringBootTest
-public class DemoTest {
-
-    @Test
-    public void test() {
-        log.info("test");
-        Assertions.assertEquals("666", new String("666"));
-    }
-
-    @DisplayName("测试 @ValueSource 注解")
-    @ParameterizedTest
-    @ValueSource(strings = {"t1", "t2", "t3"})
-    public void testValueSource(String str) {
-        System.out.println(str);
-    }
-}