package top.haijunit.train.service; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import top.haijunit.common.utils.StreamUtils; import top.haijunit.train.domain.constant.CacheNames; import top.haijunit.train.domain.constant.DirectionEnum; import top.haijunit.train.domain.constant.SectionStatusEnum; 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; import top.haijunit.train.simulation.domain.SectionItem; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * @author zhanghaijun * @date 2023/12/9 11:14 * @description 进路区段计算 */ @Slf4j @Service @RequiredArgsConstructor public class SectionService { private final RouteRepository routeRepository; private final SelectionRepository selectionRepository; private final SignStopRepository signStopRepository; /** * 获取所有停车标信息 * @return 停车标集合 */ @Cacheable(cacheNames = CacheNames.SECTION, key = "'StopSignalMap'") public HashMap getStopSignalMap() { List list = signStopRepository.findAll(); return list.stream().collect(HashMap::new, (map, entity) -> map.put(entity.getSelectionId(), entity), HashMap::putAll); } @Cacheable(cacheNames = CacheNames.SECTION, key = "'id-'+#id") public SectionItem getSectionItem(String id) { return StreamUtils.filter(getAllSection(), item -> { return item.getId().equals(id); }).stream().findFirst().orElseThrow(() -> new IllegalArgumentException(String.format("不存在该区段,uid: %s", id))); } @Cacheable(cacheNames = CacheNames.SECTION, key = "'sectionId-'+#sectionId+'-direction-'+#direction.name()") public SectionItem getSectionItem(Long sectionId, DirectionEnum direction) { List filter = StreamUtils.filter(getAllSection(), item -> item.getSectionId().equals(sectionId)); if (filter.size() == 1) { return filter.get(0); } return StreamUtils.filter(getAllSection(), item -> { return item.getSectionId().equals(sectionId) && item.getDirection().equals(direction); }).stream().findFirst().orElseThrow(() -> new IllegalArgumentException(String.format("不存在该区段,sectionId: %s", sectionId))); } @Cacheable(cacheNames = CacheNames.SECTION, key = "'routeId-'+#routeId") public List getSectionAll(Long routeId) { return StreamUtils.filter(getAllSection(), item -> item.getRouteId().equals(routeId)); } @Cacheable(cacheNames = CacheNames.SECTION, key = "'routeIds-' + T(java.util.Objects).hash(#routeIds)") public List getSectionAll(Collection routeIds) { if (CollUtil.isEmpty(routeIds)) { return new ArrayList<>(); } List allSection = getAllSection(); Long firstRouteId = CollUtil.getFirst(allSection).getRouteId(); Long lastRouteId = CollUtil.getLast(allSection).getRouteId(); if (CollUtil.containsAll(routeIds, CollUtil.newArrayList(firstRouteId, lastRouteId))) { // 保证首尾相连的顺序 ArrayList result = new ArrayList<>(); result.addAll(StreamUtils.filter(allSection, item -> item.getRouteId().equals(lastRouteId))); result.addAll(StreamUtils.filter(allSection, item -> item.getRouteId().equals(firstRouteId))); return result; } return StreamUtils.filter(getAllSection(), item -> CollUtil.contains(routeIds, item.getRouteId())); } @Cacheable(cacheNames = CacheNames.SECTION + "-RouteNextId", key = "'sectionId-'+#sectionId+'-direction-'+#direction.name()") public Long getRouteNextId(Long sectionId, DirectionEnum direction) { SectionItem sectionItem = this.getSectionItem(sectionId, direction); RouteEntity route = routeRepository.findById(sectionItem.getRouteId()).orElseThrow(() -> new IllegalArgumentException(String.format("未找到进路数据,routeId: %s", sectionItem.getRouteId()))); RouteEntity entity = routeRepository.findById(route.getNextId()).orElseThrow(() -> new IllegalArgumentException(String.format("未找到进路数据, routeId: %s", route.getNextId()))); if (null == entity) { throw new IllegalArgumentException(String.format("没有找到下一个进路,区段Id:%s", sectionId)); } return entity.getId(); } /** * 获取所有进路的区段 * * @return 全部进路的区段 */ @Cacheable(cacheNames = CacheNames.SECTION, key = "'section_all'") public List getAllSection() { List sectionList = new ArrayList<>(); List routeList = routeRepository.findAll(); Map selectionMap = selectionRepository.findAll().stream().collect(Collectors.toMap(SelectionEntity::getId, Function.identity(), (v1, v2) -> v1)); for (RouteEntity route : routeList) { ArrayList selectionIds = route.getSelectionList(); for (int i = 0; i < selectionIds.size(); i++) { Long sectionId = selectionIds.get(i); SelectionEntity selection = selectionMap.get(sectionId); if (null == selection) { throw new IllegalArgumentException(String.format("未找到区段数据,区段Id: %s", sectionId)); } // 区段数据 SectionItem sectionItem = new SectionItem(); sectionItem.setSectionId(selection.getId()); sectionItem.setSectionName(selection.getName()); sectionItem.setSectionLength(selection.getSelectionLength()); sectionItem.setStartKilometer(selection.getStartKilometer()); sectionItem.setSwitch(selection.isSwitch()); sectionItem.setTurnBack(selection.getZfState()); sectionItem.setStationId(selection.getStationId()); // 进路数据 sectionItem.setId(getSectionUId(route.getId(), selection.getId())); sectionItem.setRouteId(route.getId()); sectionItem.setRouteName(route.getName()); sectionItem.setDirection(route.getDirection()); sectionItem.setSectionStatus(SectionStatusEnum.IDLE); // 区段连接数据 if (i == 0) { // 进路的第一个区段 sectionItem.setPreId(this.getRouteSectionLast(route.getId())); sectionItem.setNextId(getSectionUId(route.getId(), selectionIds.get(i + 1))); } else if (i + 1 >= selectionIds.size()) { // 进路的最后一个区段 sectionItem.setPreId(getSectionUId(route.getId(), selectionIds.get(i - 1))); sectionItem.setNextId(this.getRouteSectionFirst(route.getNextId())); } else { sectionItem.setPreId(getSectionUId(route.getId(), selectionIds.get(i - 1))); sectionItem.setNextId(getSectionUId(route.getId(), selectionIds.get(i + 1))); } sectionList.add(sectionItem); } } return sectionList; } private String getRouteSectionFirst(Long routeId) { RouteEntity route = routeRepository.findById(routeId).orElseThrow(() -> new IllegalArgumentException(String.format("未找到进路数据,进路Id: %s", routeId))); return getSectionUId(routeId, CollUtil.getFirst(route.getSelectionList())); } private String getRouteSectionLast(Long routeNextId) { RouteEntity entity = routeRepository.findByNextId(routeNextId); RouteEntity route = Optional.of(entity).orElseThrow(() -> new IllegalArgumentException(String.format("未找到进路数据,进路Id: %s", routeNextId))); return getSectionUId(route.getId(), CollUtil.getLast(route.getSelectionList())); } /** * 进路区段的唯一标识 用于查询唯一的下一个、下一个 * @param routeI 所在的进路Id * @param selectionId 区段Id * @return 进路区段Id */ private String getSectionUId(long routeI, long selectionId) { return StrUtil.join("-", routeI, selectionId); } }