package com.zy.ai.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.zy.ai.domain.autotune.AutoTuneFlowTopologyItem; import com.zy.ai.domain.autotune.AutoTuneStationRuntimeItem; import com.zy.ai.service.FlowTopologySnapshotService; import com.zy.asrs.entity.StationFlowCapacity; import com.zy.asrs.service.StationFlowCapacityService; import com.zy.common.utils.NavigateUtils; import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @Service("flowTopologySnapshotService") public class FlowTopologySnapshotServiceImpl implements FlowTopologySnapshotService { @Autowired private StationFlowCapacityService stationFlowCapacityService; @Autowired private NavigateUtils navigateUtils; @Override public List buildSnapshot(List stationRuntimeSnapshot) { List capacities = loadCapacityList(); Map> adjacencyMap = loadSortedAdjacencyMap(); List itemList = new ArrayList<>(); for (StationFlowCapacity capacity : capacities) { if (capacity == null || capacity.getStationId() == null) { continue; } itemList.add(buildTopologyItem(capacity, adjacencyMap, stationRuntimeSnapshot)); } return itemList; } public AutoTuneFlowTopologyItem buildTopologyItem(StationFlowCapacity capacity, Map> adjacencyMap, List stationRuntimeSnapshot) { Integer targetStationId = capacity.getStationId(); Integer bufferCapacity = defaultInt(capacity.getBufferCapacity()); List adjacentStationIds = sortedList(adjacencyMap == null ? null : adjacencyMap.get(targetStationId)); List flowStationIds = buildFlowStationIds(targetStationId, adjacentStationIds); List flowRuntimeItems = filterRuntimeByStationIds(stationRuntimeSnapshot, flowStationIds); RuntimeCount runtimeCount = calculateRuntimeCount(flowRuntimeItems); AutoTuneFlowTopologyItem item = new AutoTuneFlowTopologyItem(); item.setTargetStationId(targetStationId); item.setDirection(capacity.getDirectionCode()); // 当前只有后端无向站点图可用,保守地把排序相邻站同时作为上下游候选。 item.setUpstreamStationIds(adjacentStationIds); item.setDownstreamStationIds(adjacentStationIds); item.setFlowStationIds(flowStationIds); item.setBufferCapacity(bufferCapacity); item.setOccupiedCount(runtimeCount.getOccupiedCount()); item.setFreeCount(Math.max(0, bufferCapacity - runtimeCount.getOccupiedCount())); item.setNonAutoingCount(runtimeCount.getNonAutoingCount()); item.setLoadingCount(runtimeCount.getLoadingCount()); item.setTaskHoldingCount(runtimeCount.getTaskHoldingCount()); return item; } public RuntimeCount calculateRuntimeCount(List runtimeItems) { RuntimeCount count = new RuntimeCount(); if (runtimeItems == null || runtimeItems.isEmpty()) { return count; } for (AutoTuneStationRuntimeItem runtimeItem : runtimeItems) { if (runtimeItem == null) { continue; } boolean autoing = Objects.equals(runtimeItem.getAutoing(), 1); boolean loading = Objects.equals(runtimeItem.getLoading(), 1); boolean taskHolding = runtimeItem.getTaskNo() != null && runtimeItem.getTaskNo() > 0; if (!autoing) { count.nonAutoingCount++; } if (loading) { count.loadingCount++; } if (taskHolding) { count.taskHoldingCount++; } if (loading || taskHolding) { count.occupiedCount++; } } return count; } public StationFlowCapacity findCapacity(List capacities, Integer stationId, String directionCode) { if (capacities == null || stationId == null || directionCode == null) { return null; } for (StationFlowCapacity capacity : capacities) { if (capacity == null) { continue; } if (Objects.equals(capacity.getStationId(), stationId) && directionCode.equals(capacity.getDirectionCode())) { return capacity; } } return null; } private List loadCapacityList() { if (stationFlowCapacityService == null) { return Collections.emptyList(); } QueryWrapper wrapper = new QueryWrapper<>(); wrapper.orderByAsc("station_id", "direction_code"); List capacityList = stationFlowCapacityService.list(wrapper); return capacityList == null ? Collections.emptyList() : capacityList; } private Map> loadSortedAdjacencyMap() { if (navigateUtils == null) { return Collections.emptyMap(); } Map> graph = navigateUtils.loadUndirectedStationGraphSnapshot(); if (graph == null || graph.isEmpty()) { return Collections.emptyMap(); } return graph.entrySet().stream() .filter(entry -> entry.getKey() != null) .collect(Collectors.toMap( Map.Entry::getKey, entry -> sortedList(entry.getValue()) )); } private List buildFlowStationIds(Integer targetStationId, List adjacentStationIds) { LinkedHashSet stationIds = new LinkedHashSet<>(); if (targetStationId != null) { stationIds.add(targetStationId); } stationIds.addAll(sortedList(adjacentStationIds)); return new ArrayList<>(stationIds); } private List filterRuntimeByStationIds(List runtimeItems, List stationIds) { if (runtimeItems == null || runtimeItems.isEmpty() || stationIds == null || stationIds.isEmpty()) { return Collections.emptyList(); } Set stationIdSet = new LinkedHashSet<>(stationIds); return runtimeItems.stream() .filter(item -> item != null && stationIdSet.contains(item.getStationId())) .collect(Collectors.toList()); } private static List sortedList(Iterable values) { if (values == null) { return new ArrayList<>(); } List result = new ArrayList<>(); for (Integer value : values) { if (value != null) { result.add(value); } } result.sort(Comparator.naturalOrder()); return result; } private int defaultInt(Integer value) { return value == null ? 0 : value; } @Data public static class RuntimeCount { private int occupiedCount; private int nonAutoingCount; private int loadingCount; private int taskHoldingCount; } }