TrainTravel.java 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package top.haijunit.train.simulation.domain;
  2. import cn.hutool.core.util.StrUtil;
  3. import liquibase.util.StringUtil;
  4. import lombok.AllArgsConstructor;
  5. import lombok.Data;
  6. import lombok.RequiredArgsConstructor;
  7. import top.haijunit.train.domain.constant.DirectionEnum;
  8. import top.haijunit.train.domain.entity.SignStopEntity;
  9. import top.haijunit.train.utils.NumberUtil;
  10. import java.math.BigDecimal;
  11. import java.util.HashMap;
  12. import java.util.List;
  13. import java.util.Optional;
  14. /**
  15. * @author zhanghaijun
  16. * @date 2023/12/17 21:30
  17. * @description [一句话描述该类的功能]
  18. * @version 1.0
  19. */
  20. @Data
  21. public class TrainTravel {
  22. // 可行驶的区段集合
  23. private final List<SectionItem> sectionList;
  24. // 停车标的位置
  25. private final HashMap<Long, SignStopEntity> signStopMap;
  26. public TrainTravel(List<SectionItem> sectionList, List<SignStopEntity> signStopEntityList) {
  27. this.sectionList = sectionList;
  28. this.signStopMap = signStopEntityList.stream().collect(HashMap::new, (map, entity) -> map.put(entity.getSelectionId(), entity), HashMap::putAll);
  29. }
  30. public TrainTravel(List<SectionItem> sectionList, HashMap<Long, SignStopEntity> signStopMap) {
  31. this.sectionList = sectionList;
  32. this.signStopMap = signStopMap;
  33. }
  34. public TravelItem travel(TrainItem train, BigDecimal distance) {
  35. Optional<SectionItem> sectionOptional = sectionList.stream().filter(item -> {
  36. return item.getSectionId().equals(train.getBlockId()) && item.getDirection().equals(train.getDirection());
  37. }).findFirst();
  38. return sectionOptional.map(sectionItem -> travel(sectionItem.getId(), train.getOffset(), distance)).orElse(null);
  39. }
  40. /**
  41. * 列车行驶
  42. * @param section 当前区段
  43. * @param offset 偏移量
  44. * @param distance 行驶距离
  45. * @return 行驶后的位置
  46. */
  47. public TravelItem travel(String id, BigDecimal offset, BigDecimal distance) {
  48. Optional<SectionItem> sectionOptional = sectionList.stream().filter(item -> StrUtil.equals(item.getId(), id)).findFirst();
  49. if (sectionOptional.isEmpty()) {
  50. return null;
  51. }
  52. SectionItem sectionItem = sectionOptional.get();
  53. if (null == offset) {
  54. // 偏移量为当前区段长度 上行的开始位置是区段的末端
  55. offset = sectionItem.getSectionLength();
  56. }
  57. BigDecimal travelDistance = NumberUtil.mul(sectionItem.getDirection().getFactor(), distance.abs());
  58. BigDecimal travelOffset = NumberUtil.add(offset, travelDistance);
  59. // 计算停车标
  60. SignStopEntity stopEntity = signStopMap.get(sectionItem.getSectionId());
  61. if (null != stopEntity) {
  62. BigDecimal minInclude = NumberUtil.min(offset.abs(), travelOffset);
  63. BigDecimal maxInclude = NumberUtil.max(offset.abs(), travelOffset);
  64. Boolean isStop = switch (sectionItem.getDirection()) {
  65. case UP -> NumberUtil.isGreaterOrEqual(stopEntity.getSelectionOff().abs(), minInclude) && NumberUtil.isLess(stopEntity.getSelectionOff().abs(), maxInclude);
  66. case DOWN -> NumberUtil.isGreater(stopEntity.getSelectionOff().abs(), minInclude) && NumberUtil.isLessOrEqual(stopEntity.getSelectionOff().abs(), maxInclude);
  67. };
  68. if (isStop) {
  69. return new TravelItem(sectionItem, stopEntity.getSelectionOff().abs(), true);
  70. }
  71. }
  72. if (NumberUtil.isLess(travelOffset, BigDecimal.ZERO)) {
  73. // <0 上行 行驶到下一个区段
  74. return travel(sectionItem.getNextId(), null, travelOffset.abs());
  75. } else if (NumberUtil.isGreaterOrEqual(travelOffset, sectionItem.getSectionLength())) {
  76. // >= 区段的长度 下行 实行到下一个区段
  77. return travel(sectionItem.getNextId(), BigDecimal.ZERO, travelOffset.subtract(sectionItem.getSectionLength()));
  78. } else {
  79. // 行驶后的位置在当前区段
  80. return new TravelItem(sectionItem, travelOffset, false);
  81. }
  82. }
  83. @Data
  84. @AllArgsConstructor
  85. public static class TravelItem {
  86. // 区段
  87. private SectionItem section;
  88. // 偏移量
  89. private BigDecimal offset;
  90. // 是否停车
  91. private boolean isStop;
  92. }
  93. }