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<AutoTuneFlowTopologyItem> buildSnapshot(List<AutoTuneStationRuntimeItem> stationRuntimeSnapshot) {
|
List<BasStation> outStations = loadOutStationList();
|
Map<Integer, List<Integer>> adjacencyMap = loadSortedAdjacencyMap();
|
List<AutoTuneFlowTopologyItem> 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<Integer, List<Integer>> adjacencyMap,
|
List<AutoTuneStationRuntimeItem> stationRuntimeSnapshot) {
|
Integer targetStationId = station.getStationId();
|
Integer bufferCapacity = station.getOutBufferCapacity();
|
List<Integer> adjacentStationIds = sortedList(adjacencyMap == null ? null : adjacencyMap.get(targetStationId));
|
List<Integer> flowStationIds = buildFlowStationIds(targetStationId, adjacentStationIds);
|
List<AutoTuneStationRuntimeItem> 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<AutoTuneStationRuntimeItem> 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<BasStation> loadOutStationList() {
|
if (basDevpService == null || basStationService == null) {
|
return Collections.emptyList();
|
}
|
Set<Integer> stationIds = loadOutStationIds();
|
if (stationIds.isEmpty()) {
|
return Collections.emptyList();
|
}
|
QueryWrapper<BasStation> wrapper = new QueryWrapper<>();
|
wrapper.in("station_id", stationIds);
|
wrapper.orderByAsc("station_id");
|
List<BasStation> stationList = basStationService.list(wrapper);
|
return stationList == null ? Collections.emptyList() : stationList;
|
}
|
|
private Set<Integer> loadOutStationIds() {
|
LinkedHashSet<Integer> stationIds = new LinkedHashSet<>();
|
if (basDevpService == null) {
|
return stationIds;
|
}
|
QueryWrapper<BasDevp> wrapper = new QueryWrapper<>();
|
wrapper.eq("status", 1);
|
wrapper.orderByAsc("devp_no");
|
List<BasDevp> basDevpList = basDevpService.list(wrapper);
|
for (BasDevp basDevp : safeList(basDevpList)) {
|
List<StationObjModel> 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<Integer, List<Integer>> loadSortedAdjacencyMap() {
|
if (navigateUtils == null) {
|
return Collections.emptyMap();
|
}
|
Map<Integer, Set<Integer>> 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<Integer> buildFlowStationIds(Integer targetStationId,
|
List<Integer> adjacentStationIds) {
|
LinkedHashSet<Integer> stationIds = new LinkedHashSet<>();
|
if (targetStationId != null) {
|
stationIds.add(targetStationId);
|
}
|
stationIds.addAll(sortedList(adjacentStationIds));
|
return new ArrayList<>(stationIds);
|
}
|
|
private List<AutoTuneStationRuntimeItem> filterRuntimeByStationIds(List<AutoTuneStationRuntimeItem> runtimeItems,
|
List<Integer> stationIds) {
|
if (runtimeItems == null || runtimeItems.isEmpty() || stationIds == null || stationIds.isEmpty()) {
|
return Collections.emptyList();
|
}
|
Set<Integer> stationIdSet = new LinkedHashSet<>(stationIds);
|
return runtimeItems.stream()
|
.filter(item -> item != null && stationIdSet.contains(item.getStationId()))
|
.collect(Collectors.toList());
|
}
|
|
private static List<Integer> sortedList(Iterable<Integer> values) {
|
if (values == null) {
|
return new ArrayList<>();
|
}
|
List<Integer> 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 <T> List<T> safeList(List<T> value) {
|
return value == null ? Collections.emptyList() : value;
|
}
|
|
@Data
|
public static class RuntimeCount {
|
private int occupiedCount;
|
private int nonAutoingCount;
|
private int loadingCount;
|
private int taskHoldingCount;
|
}
|
}
|