From 3f7bea2d7e66c853118c6f7da7122ac890e44550 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期六, 21 三月 2026 20:25:18 +0800
Subject: [PATCH] #

---
 src/main/java/com/zy/core/thread/impl/ZyStationV5Thread.java |  103 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 98 insertions(+), 5 deletions(-)

diff --git a/src/main/java/com/zy/core/thread/impl/ZyStationV5Thread.java b/src/main/java/com/zy/core/thread/impl/ZyStationV5Thread.java
index e4572e1..d6403f8 100644
--- a/src/main/java/com/zy/core/thread/impl/ZyStationV5Thread.java
+++ b/src/main/java/com/zy/core/thread/impl/ZyStationV5Thread.java
@@ -50,6 +50,7 @@
 public class ZyStationV5Thread implements Runnable, com.zy.core.thread.StationThread {
 
     private static final int RUN_BLOCK_REROUTE_STATE_EXPIRE_SECONDS = 60 * 60 * 24;
+    private static final int SHORT_PATH_REPEAT_AVOID_THRESHOLD = 3;
 
     private List<StationProtocol> statusList = new ArrayList<>();
     private DeviceConfig deviceConfig;
@@ -437,22 +438,101 @@
         }
 
         Set<String> issuedRouteSignatureSet = rerouteState.getIssuedRouteSignatureSet();
+        List<RerouteCandidateCommand> candidateCommandList = new ArrayList<>();
         for (List<NavigateNode> candidatePath : candidatePathList) {
             StationCommand rerouteCommand = buildMoveCommand(taskNo, stationId, targetStationId, palletSize, candidatePath);
             if (rerouteCommand == null || rerouteCommand.getNavigatePath() == null || rerouteCommand.getNavigatePath().isEmpty()) {
                 continue;
             }
             String routeSignature = buildPathSignature(rerouteCommand.getNavigatePath());
-            if (Cools.isEmpty(routeSignature) || issuedRouteSignatureSet.contains(routeSignature)) {
+            if (Cools.isEmpty(routeSignature)) {
+                continue;
+            }
+            RerouteCandidateCommand candidateCommand = new RerouteCandidateCommand();
+            candidateCommand.setCommand(rerouteCommand);
+            candidateCommand.setRouteSignature(routeSignature);
+            candidateCommand.setPathLength(rerouteCommand.getNavigatePath().size());
+            candidateCommand.setIssuedCount(rerouteState.getRouteIssueCountMap().getOrDefault(routeSignature, 0));
+            candidateCommandList.add(candidateCommand);
+        }
+        if (candidateCommandList.isEmpty()) {
+            return null;
+        }
+
+        List<RerouteCandidateCommand> orderedCandidateCommandList = reorderCandidateCommandsForLoopRelease(candidateCommandList);
+        for (RerouteCandidateCommand candidateCommand : orderedCandidateCommandList) {
+            if (candidateCommand == null || candidateCommand.getCommand() == null) {
+                continue;
+            }
+            if (issuedRouteSignatureSet.contains(candidateCommand.getRouteSignature())) {
                 continue;
             }
 
-            issuedRouteSignatureSet.add(routeSignature);
+            StationCommand rerouteCommand = candidateCommand.getCommand();
+            issuedRouteSignatureSet.add(candidateCommand.getRouteSignature());
             rerouteState.getIssuedRoutePathList().add(new ArrayList<>(rerouteCommand.getNavigatePath()));
             rerouteState.setLastSelectedRoute(new ArrayList<>(rerouteCommand.getNavigatePath()));
+            rerouteState.getRouteIssueCountMap().put(
+                    candidateCommand.getRouteSignature(),
+                    rerouteState.getRouteIssueCountMap().getOrDefault(candidateCommand.getRouteSignature(), 0) + 1
+            );
             return rerouteCommand;
         }
         return null;
+    }
+
+    private List<RerouteCandidateCommand> reorderCandidateCommandsForLoopRelease(List<RerouteCandidateCommand> candidateCommandList) {
+        if (candidateCommandList == null || candidateCommandList.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        int shortestPathLength = Integer.MAX_VALUE;
+        boolean shortestPathOverused = false;
+        boolean hasLongerCandidate = false;
+        for (RerouteCandidateCommand candidateCommand : candidateCommandList) {
+            if (candidateCommand == null || candidateCommand.getPathLength() == null || candidateCommand.getPathLength() <= 0) {
+                continue;
+            }
+            shortestPathLength = Math.min(shortestPathLength, candidateCommand.getPathLength());
+        }
+        if (shortestPathLength == Integer.MAX_VALUE) {
+            return candidateCommandList;
+        }
+
+        for (RerouteCandidateCommand candidateCommand : candidateCommandList) {
+            if (candidateCommand == null || candidateCommand.getPathLength() == null || candidateCommand.getPathLength() <= 0) {
+                continue;
+            }
+            if (candidateCommand.getPathLength() > shortestPathLength) {
+                hasLongerCandidate = true;
+            }
+            if (candidateCommand.getPathLength() == shortestPathLength
+                    && candidateCommand.getIssuedCount() != null
+                    && candidateCommand.getIssuedCount() >= SHORT_PATH_REPEAT_AVOID_THRESHOLD) {
+                shortestPathOverused = true;
+            }
+        }
+        if (!shortestPathOverused || !hasLongerCandidate) {
+            return candidateCommandList;
+        }
+
+        List<RerouteCandidateCommand> reorderedList = new ArrayList<>();
+        for (RerouteCandidateCommand candidateCommand : candidateCommandList) {
+            if (candidateCommand != null
+                    && candidateCommand.getPathLength() != null
+                    && candidateCommand.getPathLength() > shortestPathLength) {
+                reorderedList.add(candidateCommand);
+            }
+        }
+        for (RerouteCandidateCommand candidateCommand : candidateCommandList) {
+            if (candidateCommand == null || candidateCommand.getPathLength() == null) {
+                continue;
+            }
+            if (candidateCommand.getPathLength() <= shortestPathLength) {
+                reorderedList.add(candidateCommand);
+            }
+        }
+        return reorderedList;
     }
 
     private RunBlockRerouteState loadRunBlockRerouteState(Integer taskNo, Integer blockStationId) {
@@ -519,6 +599,7 @@
         private List<List<Integer>> issuedRoutePathList = new ArrayList<>();
         private List<Integer> lastSelectedRoute = new ArrayList<>();
         private Set<String> issuedRouteSignatureSet = new LinkedHashSet<>();
+        private Map<String, Integer> routeIssueCountMap = new HashMap<>();
 
         private RunBlockRerouteState normalize() {
             if (planCount == null || planCount < 0) {
@@ -533,13 +614,17 @@
             if (issuedRouteSignatureSet == null) {
                 issuedRouteSignatureSet = new LinkedHashSet<>();
             }
+            if (routeIssueCountMap == null) {
+                routeIssueCountMap = new HashMap<>();
+            }
             for (List<Integer> routePath : issuedRoutePathList) {
                 if (routePath == null || routePath.isEmpty()) {
                     continue;
                 }
-                StringBuilder builder = new StringBuilder(buildPathSignatureText(routePath));
-                if (builder.length() > 0) {
-                    issuedRouteSignatureSet.add(builder.toString());
+                String pathSignature = buildPathSignatureText(routePath);
+                if (!Cools.isEmpty(pathSignature)) {
+                    issuedRouteSignatureSet.add(pathSignature);
+                    routeIssueCountMap.putIfAbsent(pathSignature, 1);
                 }
             }
             return this;
@@ -568,4 +653,12 @@
             return builder.toString();
         }
     }
+
+    @Data
+    private static class RerouteCandidateCommand {
+        private StationCommand command;
+        private String routeSignature;
+        private Integer pathLength;
+        private Integer issuedCount;
+    }
 }

--
Gitblit v1.9.1