From 63b01db83d9aad8a15276b4236a9a22e4aeef065 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 05 五月 2026 12:30:59 +0800
Subject: [PATCH] # Agent数据分析V3.0.1.7

---
 src/test/java/com/zy/ai/service/impl/AutoTuneSnapshotServiceImplTest.java |  245 ++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 221 insertions(+), 24 deletions(-)

diff --git a/src/test/java/com/zy/ai/service/impl/AutoTuneSnapshotServiceImplTest.java b/src/test/java/com/zy/ai/service/impl/AutoTuneSnapshotServiceImplTest.java
index d1b62d8..46b35d1 100644
--- a/src/test/java/com/zy/ai/service/impl/AutoTuneSnapshotServiceImplTest.java
+++ b/src/test/java/com/zy/ai/service/impl/AutoTuneSnapshotServiceImplTest.java
@@ -1,12 +1,26 @@
 package com.zy.ai.service.impl;
 
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.zy.ai.domain.autotune.AutoTuneRoutePressureSnapshot;
+import com.zy.ai.domain.autotune.AutoTuneRuleSnapshotItem;
+import com.zy.ai.domain.autotune.AutoTuneSnapshot;
+import com.zy.ai.domain.autotune.AutoTuneStationRuntimeItem;
+import com.zy.ai.domain.autotune.AutoTuneTaskDetailItem;
+import com.zy.ai.domain.autotune.AutoTuneTaskSnapshot;
+import com.zy.ai.service.FlowTopologySnapshotService;
+import com.zy.ai.service.RoutePressureSnapshotService;
+import com.zy.asrs.entity.BasDevp;
 import com.zy.asrs.entity.BasStation;
-import com.zy.asrs.entity.StationFlowCapacity;
 import com.zy.asrs.entity.WrkMast;
+import com.zy.asrs.service.BasDevpService;
 import com.zy.asrs.service.BasStationService;
-import com.zy.asrs.service.StationFlowCapacityService;
 import com.zy.asrs.service.WrkMastService;
+import com.zy.core.enums.WrkIoType;
+import com.zy.core.enums.WrkStsType;
+import com.zy.core.model.StationObjModel;
+import com.zy.core.model.protocol.StationProtocol;
+import com.zy.system.service.ConfigService;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
@@ -14,10 +28,12 @@
 
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
@@ -31,7 +47,11 @@
 
     @BeforeEach
     void setUp() {
+        ConfigService configService = mock(ConfigService.class);
         service = new AutoTuneSnapshotServiceImpl();
+        ReflectionTestUtils.setField(service, "configService", configService);
+        ReflectionTestUtils.setField(service, "autoTuneControlModeService",
+                new AutoTuneControlModeServiceImpl(configService));
     }
 
     @Test
@@ -47,6 +67,46 @@
         assertEquals(0, result.get("102"));
         assertEquals(-1, result.get("103"));
         assertEquals(5, result.get("104"));
+    }
+
+    @Test
+    void buildStationOutBufferCapacityMapPreservesConfiguredCapacity() {
+        Map<String, Integer> result = service.buildStationOutBufferCapacityMap(Arrays.asList(
+                station(101, 1, null),
+                station(102, 1, 0),
+                station(103, 1, 3)
+        ));
+
+        assertNull(result.get("101"));
+        assertEquals(0, result.get("102"));
+        assertEquals(3, result.get("103"));
+    }
+
+    @Test
+    void buildRuleSnapshotExposesStepRangeCooldownAndRiskNote() {
+        List<AutoTuneRuleSnapshotItem> result = service.buildRuleSnapshot();
+
+        AutoTuneRuleSnapshotItem stationOutTaskRule = findRule(result, "station", "outTaskLimit");
+        assertEquals(0, stationOutTaskRule.getMinValue());
+        assertNull(stationOutTaskRule.getMaxValue());
+        assertEquals(3, stationOutTaskRule.getMaxStep());
+        assertEquals(10, stationOutTaskRule.getCooldownMinutes());
+        assertEquals(Boolean.FALSE, stationOutTaskRule.getDynamicMaxValue());
+        assertNull(stationOutTaskRule.getDynamicMaxSource());
+        assertEquals("鍗曟璋冩暣骞呭害涓嶈兘瓒呰繃 maxStep锛沷utBufferCapacity 浠h〃鍑哄簱绔欑紦瀛樹綅缃暟閲忥紝瓒呰繃璇ュ閲忓彲鑳戒娇浠诲姟鍑虹幇鍦ㄤ富骞查亾锛屼粎浣滀负椋庨櫓鍙傝�冿紝涓嶆槸鍚堟硶鎬т笂闄愩��",
+                stationOutTaskRule.getNote());
+
+        AutoTuneRuleSnapshotItem crnMaxOutRule = findRule(result, "crn", "maxOutTask");
+        assertEquals(3, crnMaxOutRule.getMaxStep());
+        assertNull(crnMaxOutRule.getDynamicMaxSource());
+        assertEquals("鍗曟璋冩暣骞呭害涓嶈兘瓒呰繃 maxStep銆�", crnMaxOutRule.getNote());
+
+        AutoTuneRuleSnapshotItem crnMaxInRule = findRule(result, "crn", "maxInTask");
+        assertEquals(3, crnMaxInRule.getMaxStep());
+
+        assertRuleMaxStep(result, "sys_config", "crnOutBatchRunningLimit", 3);
+        assertRuleMaxStep(result, "dual_crn", "maxOutTask", 3);
+        assertRuleMaxStep(result, "dual_crn", "maxInTask", 3);
     }
 
     @Test
@@ -66,29 +126,97 @@
     }
 
     @Test
-    void loadStationOutTaskLimitsOnlyQueriesConfiguredOutDirectionStations() {
+    void buildTaskSnapshotExposesStationLimitBlockedTasksAndOutboundOrder() {
+        WrkMastService wrkMastService = mock(WrkMastService.class);
+        when(wrkMastService.list(any(Wrapper.class))).thenReturn(Arrays.asList(
+                outboundTask(190264, WrkStsType.STATION_RUN.sts, 101, 1,
+                        "MANUAL_OUT_20260427181201", 9, ""),
+                outboundTask(190263, WrkStsType.NEW_OUTBOUND.sts, 101, 1,
+                        "MANUAL_OUT_20260427181201", 8,
+                        "鐩爣鍑哄簱绔�:101 宸茶揪鍑哄簱浠诲姟涓婇檺锛屽綋鍓�=1锛屼笂闄�=1")
+        ));
+        ReflectionTestUtils.setField(service, "wrkMastService", wrkMastService);
+
+        AutoTuneTaskSnapshot snapshot = ReflectionTestUtils.invokeMethod(service, "buildTaskSnapshot");
+
+        assertEquals(2, snapshot.getActiveTaskCount());
+        assertEquals(1, snapshot.getByStatus().get("101"));
+        assertEquals(1, snapshot.getByStatus().get("104"));
+
+        List<AutoTuneTaskDetailItem> blockedTasks = snapshot.getStationLimitBlockedTasks();
+        assertEquals(1, blockedTasks.size());
+        assertEquals(190263, blockedTasks.get(0).getWrkNo());
+        assertEquals("鐢熸垚鍑哄簱浠诲姟", blockedTasks.get(0).getWrkStsDesc());
+        assertTrue(blockedTasks.get(0).getSystemMsg().contains("鍑哄簱浠诲姟涓婇檺"));
+
+        List<AutoTuneTaskDetailItem> outboundSamples = snapshot.getOutboundTaskSamples();
+        assertEquals(2, outboundSamples.size());
+        assertEquals(190263, outboundSamples.get(0).getWrkNo());
+        assertEquals(8, outboundSamples.get(0).getBatchSeq());
+        assertEquals(190264, outboundSamples.get(1).getWrkNo());
+        assertEquals(9, outboundSamples.get(1).getBatchSeq());
+    }
+
+    @Test
+    void buildSnapshotIncludesRoutePressureSnapshot() {
+        WrkMastService wrkMastService = mock(WrkMastService.class);
+        FlowTopologySnapshotService flowTopologySnapshotService = mock(FlowTopologySnapshotService.class);
+        RoutePressureSnapshotService routePressureSnapshotService = mock(RoutePressureSnapshotService.class);
+        AutoTuneRoutePressureSnapshot routePressureSnapshot = new AutoTuneRoutePressureSnapshot();
+        List<WrkMast> activeTasks = Collections.singletonList(
+                outboundTask(190263, WrkStsType.NEW_OUTBOUND.sts, 101, 1,
+                        "BATCH", 8, "鐩爣鍑哄簱绔�:101 宸茶揪鍑哄簱浠诲姟涓婇檺锛屽綋鍓�=1锛屼笂闄�=1")
+        );
+        when(wrkMastService.list(any(Wrapper.class))).thenReturn(activeTasks);
+        when(flowTopologySnapshotService.buildSnapshot(any())).thenReturn(Collections.emptyList());
+        when(routePressureSnapshotService.buildSnapshot(any(), any(), any())).thenReturn(routePressureSnapshot);
+        ReflectionTestUtils.setField(service, "wrkMastService", wrkMastService);
+        ReflectionTestUtils.setField(service, "flowTopologySnapshotService", flowTopologySnapshotService);
+        ReflectionTestUtils.setField(service, "routePressureSnapshotService", routePressureSnapshotService);
+
+        AutoTuneSnapshot snapshot = service.buildSnapshot();
+
+        assertSame(routePressureSnapshot, snapshot.getRoutePressureSnapshot());
+        assertEquals(1, snapshot.getTaskSnapshot().getActiveTaskCount());
+
+        ArgumentCaptor<List<WrkMast>> activeTasksCaptor = ArgumentCaptor.forClass(List.class);
+        ArgumentCaptor<AutoTuneTaskSnapshot> taskSnapshotCaptor = ArgumentCaptor.forClass(AutoTuneTaskSnapshot.class);
+        ArgumentCaptor<List<AutoTuneStationRuntimeItem>> stationRuntimeCaptor = ArgumentCaptor.forClass(List.class);
+        verify(routePressureSnapshotService).buildSnapshot(
+                activeTasksCaptor.capture(),
+                taskSnapshotCaptor.capture(),
+                stationRuntimeCaptor.capture()
+        );
+        assertSame(activeTasks, activeTasksCaptor.getValue());
+        assertSame(snapshot.getTaskSnapshot(), taskSnapshotCaptor.getValue());
+        assertSame(snapshot.getStationRuntimeSnapshot(), stationRuntimeCaptor.getValue());
+        verify(wrkMastService).list(any(Wrapper.class));
+    }
+
+    @Test
+    void loadOutStationListOnlyQueriesBasDevpOutStations() {
         BasStationService basStationService = mock(BasStationService.class);
-        StationFlowCapacityService stationFlowCapacityService = mock(StationFlowCapacityService.class);
+        BasDevpService basDevpService = mock(BasDevpService.class);
         ReflectionTestUtils.setField(service, "basStationService", basStationService);
-        ReflectionTestUtils.setField(service, "stationFlowCapacityService", stationFlowCapacityService);
-        when(stationFlowCapacityService.list(any(Wrapper.class))).thenReturn(Arrays.asList(
-                capacity(101, "OUT"),
-                capacity(102, "OUT")
+        ReflectionTestUtils.setField(service, "basDevpService", basDevpService);
+        when(basDevpService.list(any(Wrapper.class))).thenReturn(Arrays.asList(
+                basDevp(1, 101, 102),
+                basDevp(2, 102)
         ));
         when(basStationService.list(any(Wrapper.class))).thenReturn(Arrays.asList(
                 station(101, 2),
                 station(102, 3)
         ));
 
-        Map<String, Integer> result = ReflectionTestUtils.invokeMethod(service, "loadStationOutTaskLimits");
+        java.util.List<BasStation> result = ReflectionTestUtils.invokeMethod(service, "loadOutStationList");
 
         assertEquals(2, result.size());
-        assertEquals(2, result.get("101"));
-        assertEquals(3, result.get("102"));
+        assertEquals(101, result.get(0).getStationId());
+        assertEquals(102, result.get(1).getStationId());
 
-        ArgumentCaptor<Wrapper<StationFlowCapacity>> capacityWrapperCaptor = ArgumentCaptor.forClass(Wrapper.class);
-        verify(stationFlowCapacityService).list(capacityWrapperCaptor.capture());
-        assertTrue(capacityWrapperCaptor.getValue().getSqlSegment().contains("direction_code ="));
+        ArgumentCaptor<Wrapper<BasDevp>> basDevpWrapperCaptor = ArgumentCaptor.forClass(Wrapper.class);
+        verify(basDevpService).list(basDevpWrapperCaptor.capture());
+        assertTrue(basDevpWrapperCaptor.getValue().getSqlSegment().contains("status ="));
 
         ArgumentCaptor<Wrapper<BasStation>> stationWrapperCaptor = ArgumentCaptor.forClass(Wrapper.class);
         verify(basStationService).list(stationWrapperCaptor.capture());
@@ -96,30 +224,99 @@
     }
 
     @Test
-    void loadStationOutTaskLimitsDoesNotQueryStationsWhenNoOutCapacityExists() {
+    void loadOutStationListDoesNotQueryStationsWhenBasDevpOutStationsAreEmpty() {
         BasStationService basStationService = mock(BasStationService.class);
-        StationFlowCapacityService stationFlowCapacityService = mock(StationFlowCapacityService.class);
+        BasDevpService basDevpService = mock(BasDevpService.class);
         ReflectionTestUtils.setField(service, "basStationService", basStationService);
-        ReflectionTestUtils.setField(service, "stationFlowCapacityService", stationFlowCapacityService);
-        when(stationFlowCapacityService.list(any(Wrapper.class))).thenReturn(Collections.emptyList());
+        ReflectionTestUtils.setField(service, "basDevpService", basDevpService);
+        when(basDevpService.list(any(Wrapper.class))).thenReturn(Collections.singletonList(basDevp(1)));
 
-        Map<String, Integer> result = ReflectionTestUtils.invokeMethod(service, "loadStationOutTaskLimits");
+        java.util.List<BasStation> result = ReflectionTestUtils.invokeMethod(service, "loadOutStationList");
 
         assertTrue(result.isEmpty());
         verify(basStationService, never()).list(any(Wrapper.class));
     }
 
+    @Test
+    void toRuntimeItemExposesRunBlockForRoutePressure() {
+        StationProtocol protocol = new StationProtocol();
+        protocol.setStationId(101);
+        protocol.setAutoing(true);
+        protocol.setLoading(false);
+        protocol.setTaskNo(0);
+        protocol.setRunBlock(true);
+
+        AutoTuneStationRuntimeItem item = ReflectionTestUtils.invokeMethod(service, "toRuntimeItem", protocol);
+
+        assertEquals(1, item.getRunBlock());
+    }
+
     private BasStation station(Integer stationId, Integer outTaskLimit) {
+        return station(stationId, outTaskLimit, null);
+    }
+
+    private BasStation station(Integer stationId, Integer outTaskLimit, Integer outBufferCapacity) {
         BasStation station = new BasStation();
         station.setStationId(stationId);
         station.setOutTaskLimit(outTaskLimit);
+        station.setOutBufferCapacity(outBufferCapacity);
         return station;
     }
 
-    private StationFlowCapacity capacity(Integer stationId, String directionCode) {
-        StationFlowCapacity capacity = new StationFlowCapacity();
-        capacity.setStationId(stationId);
-        capacity.setDirectionCode(directionCode);
-        return capacity;
+    private WrkMast outboundTask(Integer wrkNo,
+                                 long wrkSts,
+                                 Integer stationNo,
+                                 Integer crnNo,
+                                 String batch,
+                                 Integer batchSeq,
+                                 String systemMsg) {
+        WrkMast wrkMast = new WrkMast();
+        wrkMast.setWrkNo(wrkNo);
+        wrkMast.setWrkSts(wrkSts);
+        wrkMast.setIoType(WrkIoType.OUT.id);
+        wrkMast.setStaNo(stationNo);
+        wrkMast.setCrnNo(crnNo);
+        wrkMast.setBatch(batch);
+        wrkMast.setBatchSeq(batchSeq);
+        wrkMast.setSystemMsg(systemMsg);
+        return wrkMast;
+    }
+
+    private BasDevp basDevp(Integer devpNo, Integer... stationIds) {
+        BasDevp basDevp = new BasDevp();
+        basDevp.setDevpNo(devpNo);
+        basDevp.setStatus(1);
+        if (stationIds == null || stationIds.length == 0) {
+            return basDevp;
+        }
+        basDevp.setOutStationList(JSON.toJSONString(Arrays.stream(stationIds)
+                .map(this::stationObjModel)
+                .toList()));
+        return basDevp;
+    }
+
+    private StationObjModel stationObjModel(Integer stationId) {
+        StationObjModel stationObjModel = new StationObjModel();
+        stationObjModel.setStationId(stationId);
+        return stationObjModel;
+    }
+
+    private AutoTuneRuleSnapshotItem findRule(List<AutoTuneRuleSnapshotItem> rules,
+                                              String targetType,
+                                              String targetKey) {
+        for (AutoTuneRuleSnapshotItem rule : rules) {
+            if (targetType.equals(rule.getTargetType()) && targetKey.equals(rule.getTargetKey())) {
+                return rule;
+            }
+        }
+        throw new AssertionError("rule not found: " + targetType + "/" + targetKey);
+    }
+
+    private void assertRuleMaxStep(List<AutoTuneRuleSnapshotItem> rules,
+                                   String targetType,
+                                   String targetKey,
+                                   int expectedMaxStep) {
+        AutoTuneRuleSnapshotItem rule = findRule(rules, targetType, targetKey);
+        assertEquals(expectedMaxStep, rule.getMaxStep());
     }
 }

--
Gitblit v1.9.1