package top.haijunit.train.simulation.domain; import cn.hutool.core.util.StrUtil; import liquibase.util.StringUtil; import lombok.AllArgsConstructor; import lombok.Data; import lombok.RequiredArgsConstructor; import top.haijunit.train.domain.constant.DirectionEnum; import top.haijunit.train.domain.entity.SignStopEntity; import top.haijunit.train.utils.NumberUtil; import java.math.BigDecimal; import java.util.HashMap; import java.util.List; import java.util.Optional; /** * @author zhanghaijun * @date 2023/12/17 21:30 * @description [一句话描述该类的功能] * @version 1.0 */ @Data public class TrainTravel { // 可行驶的区段集合 private final List sectionList; // 停车标的位置 private final HashMap signStopMap; public TrainTravel(List sectionList, List signStopEntityList) { this.sectionList = sectionList; this.signStopMap = signStopEntityList.stream().collect(HashMap::new, (map, entity) -> map.put(entity.getSelectionId(), entity), HashMap::putAll); } public TrainTravel(List sectionList, HashMap signStopMap) { this.sectionList = sectionList; this.signStopMap = signStopMap; } public TravelItem travel(TrainItem train, BigDecimal distance) { Optional sectionOptional = sectionList.stream().filter(item -> { return item.getSectionId().equals(train.getBlockId()) && item.getDirection().equals(train.getDirection()); }).findFirst(); return sectionOptional.map(sectionItem -> travel(sectionItem.getId(), train.getOffset(), distance)).orElse(null); } /** * 列车行驶 * @param section 当前区段 * @param offset 偏移量 * @param distance 行驶距离 * @return 行驶后的位置 */ public TravelItem travel(String id, BigDecimal offset, BigDecimal distance) { Optional sectionOptional = sectionList.stream().filter(item -> StrUtil.equals(item.getId(), id)).findFirst(); if (sectionOptional.isEmpty()) { return null; } SectionItem sectionItem = sectionOptional.get(); if (null == offset) { // 偏移量为当前区段长度 上行的开始位置是区段的末端 offset = sectionItem.getSectionLength(); } BigDecimal travelDistance = NumberUtil.mul(sectionItem.getDirection().getFactor(), distance.abs()); BigDecimal travelOffset = NumberUtil.add(offset, travelDistance); // 计算停车标 SignStopEntity stopEntity = signStopMap.get(sectionItem.getSectionId()); if (null != stopEntity) { BigDecimal minInclude = NumberUtil.min(offset.abs(), travelOffset); BigDecimal maxInclude = NumberUtil.max(offset.abs(), travelOffset); Boolean isStop = switch (sectionItem.getDirection()) { case UP -> NumberUtil.isGreaterOrEqual(stopEntity.getSelectionOff().abs(), minInclude) && NumberUtil.isLess(stopEntity.getSelectionOff().abs(), maxInclude); case DOWN -> NumberUtil.isGreater(stopEntity.getSelectionOff().abs(), minInclude) && NumberUtil.isLessOrEqual(stopEntity.getSelectionOff().abs(), maxInclude); }; if (isStop) { return new TravelItem(sectionItem, stopEntity.getSelectionOff().abs(), true); } } if (NumberUtil.isLess(travelOffset, BigDecimal.ZERO)) { // <0 上行 行驶到下一个区段 return travel(sectionItem.getNextId(), null, travelOffset.abs()); } else if (NumberUtil.isGreaterOrEqual(travelOffset, sectionItem.getSectionLength())) { // >= 区段的长度 下行 实行到下一个区段 return travel(sectionItem.getNextId(), BigDecimal.ZERO, travelOffset.subtract(sectionItem.getSectionLength())); } else { // 行驶后的位置在当前区段 return new TravelItem(sectionItem, travelOffset, false); } } @Data @AllArgsConstructor public static class TravelItem { // 区段 private SectionItem section; // 偏移量 private BigDecimal offset; // 是否停车 private boolean isStop; } }