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.BasDevp; import com.zy.asrs.entity.BasStation; import com.zy.asrs.service.BasDevpService; import com.zy.asrs.service.BasStationService; import com.zy.common.utils.NavigateUtils; import com.zy.core.model.StationObjModel; 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 { private static final String DIRECTION_OUT = "OUT"; @Autowired private BasDevpService basDevpService; @Autowired private BasStationService basStationService; @Autowired private NavigateUtils navigateUtils; @Override public List buildSnapshot(List stationRuntimeSnapshot) { List outStations = loadOutStationList(); Map> adjacencyMap = loadSortedAdjacencyMap(); List itemList = new ArrayList<>(); for (BasStation station : outStations) { if (station == null || station.getStationId() == null) { continue; } itemList.add(buildTopologyItem(station, adjacencyMap, stationRuntimeSnapshot)); } return itemList; } public AutoTuneFlowTopologyItem buildTopologyItem(BasStation station, Map> adjacencyMap, List stationRuntimeSnapshot) { Integer targetStationId = station.getStationId(); Integer bufferCapacity = station.getOutBufferCapacity(); 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(DIRECTION_OUT); item.setAdjacentStationIds(adjacentStationIds); // 当前只存在无向站点邻接图,不能把邻接事实冒充为上下游方向事实。 item.setUpstreamStationIds(Collections.emptyList()); item.setDownstreamStationIds(Collections.emptyList()); item.setFlowStationIds(flowStationIds); item.setBufferCapacity(bufferCapacity); item.setOccupiedCount(runtimeCount.getOccupiedCount()); item.setFreeCount(resolveFreeCount(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; } private List loadOutStationList() { if (basDevpService == null || basStationService == null) { return Collections.emptyList(); } Set stationIds = loadOutStationIds(); if (stationIds.isEmpty()) { return Collections.emptyList(); } QueryWrapper wrapper = new QueryWrapper<>(); wrapper.in("station_id", stationIds); wrapper.orderByAsc("station_id"); List stationList = basStationService.list(wrapper); return stationList == null ? Collections.emptyList() : stationList; } private Set loadOutStationIds() { LinkedHashSet stationIds = new LinkedHashSet<>(); if (basDevpService == null) { return stationIds; } QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("status", 1); wrapper.orderByAsc("devp_no"); List basDevpList = basDevpService.list(wrapper); for (BasDevp basDevp : safeList(basDevpList)) { List outStationList = safeList(basDevp == null ? null : basDevp.getOutStationList$()); for (StationObjModel stationObjModel : outStationList) { if (stationObjModel != null && stationObjModel.getStationId() != null) { stationIds.add(stationObjModel.getStationId()); } } } return stationIds; } 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 Integer resolveFreeCount(Integer bufferCapacity, int occupiedCount) { if (bufferCapacity == null) { return null; } return Math.max(0, Math.max(0, bufferCapacity) - occupiedCount); } private List safeList(List value) { return value == null ? Collections.emptyList() : value; } @Data public static class RuntimeCount { private int occupiedCount; private int nonAutoingCount; private int loadingCount; private int taskHoldingCount; } }