Junjie
14 小时以前 41aeff86351d1dd94fe2408175f96475f227c1b9
src/main/java/com/zy/core/utils/station/StationOutboundDecisionSupport.java
@@ -116,6 +116,7 @@
        if (wrkMast == null || wrkMast.getStaNo() == null) {
            return null;
        }
        DecisionPathCache decisionPathCache = new DecisionPathCache();
        if (!shouldApplyOutOrder(wrkMast, outOrderStationIds)) {
            return OutOrderDispatchDecision.direct(wrkMast.getStaNo());
        }
@@ -124,13 +125,14 @@
                wrkMast.getSourceStaNo(),
                wrkMast.getStaNo(),
                outOrderStationIds,
                pathLenFactor
                pathLenFactor,
                decisionPathCache
        );
        if (dispatchStationId == null) {
            return null;
        }
        if (isCurrentOutOrderDispatchStation(currentStationId, wrkMast, outOrderStationIds, pathLenFactor)) {
            return resolveCurrentOutOrderDispatchDecision(currentStationId, wrkMast, outOrderStationIds, pathLenFactor);
        if (isCurrentOutOrderDispatchStation(currentStationId, wrkMast, outOrderStationIds, pathLenFactor, decisionPathCache)) {
            return resolveCurrentOutOrderDispatchDecision(currentStationId, wrkMast, outOrderStationIds, pathLenFactor, decisionPathCache);
        }
        if (!Objects.equals(dispatchStationId, wrkMast.getStaNo())
                && isCurrentOutOrderStation(currentStationId, outOrderStationIds)
@@ -197,12 +199,35 @@
                                                        Integer sourceStationId,
                                                        Integer targetStationId,
                                                        Double pathLenFactor) {
        return calcOutboundNavigatePath(wrkMast, sourceStationId, targetStationId, pathLenFactor, null);
    }
    private List<NavigateNode> calcOutboundNavigatePath(WrkMast wrkMast,
                                                        Integer sourceStationId,
                                                        Integer targetStationId,
                                                        Double pathLenFactor,
                                                        DecisionPathCache decisionPathCache) {
        Double normalizedFactor = normalizePathLenFactor(pathLenFactor);
        Integer currentTaskNo = wrkMast == null ? null : wrkMast.getWrkNo();
        if (currentTaskNo == null) {
            return navigateUtils.calcByStationId(sourceStationId, targetStationId, normalizedFactor);
        if (decisionPathCache == null) {
            if (currentTaskNo == null) {
                return navigateUtils.calcOptimalPathByStationId(sourceStationId, targetStationId, null, normalizedFactor);
            }
            return navigateUtils.calcOptimalPathByStationId(sourceStationId, targetStationId, currentTaskNo, normalizedFactor);
        }
        return navigateUtils.calcByStationId(sourceStationId, targetStationId, currentTaskNo, normalizedFactor);
        String cacheKey = buildPathCacheKey(currentTaskNo, sourceStationId, targetStationId, normalizedFactor);
        List<NavigateNode> cachedPath = decisionPathCache.pathMap.get(cacheKey);
        if (cachedPath != null) {
            return cachedPath;
        }
        List<NavigateNode> path = currentTaskNo == null
                ? navigateUtils.calcOptimalPathByStationId(sourceStationId, targetStationId, null, normalizedFactor)
                : navigateUtils.calcOptimalPathByStationId(sourceStationId, targetStationId, currentTaskNo, normalizedFactor);
        if (path == null) {
            path = Collections.emptyList();
        }
        decisionPathCache.pathMap.put(cacheKey, path);
        return path;
    }
    private boolean isBatchOutboundTaskWithSeq(WrkMast wrkMast) {
@@ -246,7 +271,8 @@
    private boolean isCurrentOutOrderDispatchStation(Integer currentStationId,
                                                     WrkMast wrkMast,
                                                     List<Integer> outOrderStationIds,
                                                     Double pathLenFactor) {
                                                     Double pathLenFactor,
                                                     DecisionPathCache decisionPathCache) {
        if (!shouldApplyOutOrder(wrkMast, outOrderStationIds) || currentStationId == null) {
            return false;
        }
@@ -255,7 +281,8 @@
                wrkMast.getSourceStaNo(),
                wrkMast.getStaNo(),
                outOrderStationIds,
                pathLenFactor
                pathLenFactor,
                decisionPathCache
        );
        return dispatchStationId != null
                && !Objects.equals(dispatchStationId, wrkMast.getStaNo())
@@ -272,8 +299,9 @@
    private OutOrderDispatchDecision resolveCurrentOutOrderDispatchDecision(Integer currentStationId,
                                                                           WrkMast wrkMast,
                                                                           List<Integer> outOrderStationIds,
                                                                           Double pathLenFactor) {
        if (!isCurrentOutOrderDispatchStation(currentStationId, wrkMast, outOrderStationIds, pathLenFactor)) {
                                                                           Double pathLenFactor,
                                                                           DecisionPathCache decisionPathCache) {
        if (!isCurrentOutOrderDispatchStation(currentStationId, wrkMast, outOrderStationIds, pathLenFactor, decisionPathCache)) {
            return null;
        }
@@ -299,7 +327,7 @@
        List<NavigateNode> initPath;
        try {
            initPath = calcOutboundNavigatePath(wrkMast, wrkMast.getSourceStaNo(), wrkMast.getStaNo(), pathLenFactor);
            initPath = calcOutboundNavigatePath(wrkMast, wrkMast.getSourceStaNo(), wrkMast.getStaNo(), pathLenFactor, decisionPathCache);
        } catch (Exception e) {
            News.taskInfo(wrkMast.getWrkNo(), "批次:{} 计算排序路径失败,当前站点={}", wrkMast.getBatch(), currentStationId);
            return null;
@@ -310,7 +338,7 @@
                ? currentBatchSeq.equals(wrkMast.getBatchSeq())
                : Integer.valueOf(seq + 1).equals(wrkMast.getBatchSeq());
        if (toTarget) {
            if (hasReachableOutReleaseSlot(wrkMast, currentStationId, wrkMast.getStaNo(), pathLenFactor)) {
            if (hasReachableOutReleaseSlot(wrkMast, currentStationId, wrkMast.getStaNo(), pathLenFactor, decisionPathCache)) {
                return OutOrderDispatchDecision.direct(wrkMast.getStaNo());
            }
            StationTaskLoopService.LoopEvaluation loopEvaluation = evaluateOutOrderLoop(
@@ -323,7 +351,8 @@
                    currentStationId,
                    outOrderStationIds,
                    loopEvaluation.getExpectedLoopIssueCount(),
                    pathLenFactor
                    pathLenFactor,
                    decisionPathCache
            );
            if (circleTarget == null) {
                News.taskInfo(wrkMast.getWrkNo(), "目标站当前不可进,且未找到可执行的下一排序检测点,当前站点={}", currentStationId);
@@ -342,7 +371,8 @@
                currentStationId,
                outOrderStationIds,
                loopEvaluation.getExpectedLoopIssueCount(),
                pathLenFactor
                pathLenFactor,
                decisionPathCache
        );
        if (circleTarget == null) {
            News.taskInfo(wrkMast.getWrkNo(), "未找到可执行的下一排序检测点,当前站点={}", currentStationId);
@@ -377,7 +407,8 @@
                                                  Integer sourceStationId,
                                                  Integer finalTargetStationId,
                                                  List<Integer> outOrderList,
                                                  Double pathLenFactor) {
                                                  Double pathLenFactor,
                                                  DecisionPathCache decisionPathCache) {
        if (finalTargetStationId == null) {
            return null;
        }
@@ -386,7 +417,7 @@
        }
        try {
            List<NavigateNode> nodes = calcOutboundNavigatePath(wrkMast, sourceStationId, finalTargetStationId, pathLenFactor);
            List<NavigateNode> nodes = calcOutboundNavigatePath(wrkMast, sourceStationId, finalTargetStationId, pathLenFactor, decisionPathCache);
            for (int i = nodes.size() - 1; i >= 0; i--) {
                Integer stationId = getStationIdFromNode(nodes.get(i));
                if (stationId == null) {
@@ -407,13 +438,14 @@
    private boolean hasReachableOutReleaseSlot(WrkMast wrkMast,
                                               Integer currentStationId,
                                               Integer finalTargetStationId,
                                               Double pathLenFactor) {
                                               Double pathLenFactor,
                                               DecisionPathCache decisionPathCache) {
        if (currentStationId == null || finalTargetStationId == null) {
            return true;
        }
        try {
            List<NavigateNode> nodes = calcOutboundNavigatePath(wrkMast, currentStationId, finalTargetStationId, pathLenFactor);
            List<NavigateNode> nodes = calcOutboundNavigatePath(wrkMast, currentStationId, finalTargetStationId, pathLenFactor, decisionPathCache);
            if (nodes == null || nodes.isEmpty()) {
                return true;
            }
@@ -462,7 +494,8 @@
                                                 Integer currentStationId,
                                                 List<Integer> orderedOutStationList,
                                                 Integer expectedLoopIssueCount,
                                                 Double pathLenFactor) {
                                                 Double pathLenFactor,
                                                 DecisionPathCache decisionPathCache) {
        if (currentStationId == null || orderedOutStationList == null || orderedOutStationList.size() <= 1) {
            return null;
        }
@@ -477,7 +510,7 @@
                continue;
            }
            try {
                List<NavigateNode> path = calcOutboundNavigatePath(wrkMast, currentStationId, candidateStationId, pathLenFactor);
                List<NavigateNode> path = calcOutboundNavigatePath(wrkMast, currentStationId, candidateStationId, pathLenFactor, decisionPathCache);
                if (path != null && !path.isEmpty()) {
                    candidateList.add(new CircleTargetCandidate(candidateStationId, path.size(), offset));
                }
@@ -609,7 +642,21 @@
        return pathLenFactor;
    }
    private String buildPathCacheKey(Integer currentTaskNo,
                                     Integer sourceStationId,
                                     Integer targetStationId,
                                     Double normalizedFactor) {
        return String.valueOf(currentTaskNo) + "->"
                + String.valueOf(sourceStationId) + "->"
                + String.valueOf(targetStationId) + "@"
                + String.format(java.util.Locale.ROOT, "%.4f", normalizedFactor == null ? 0.0d : normalizedFactor);
    }
    private boolean isBlank(String value) {
        return value == null || value.trim().isEmpty();
    }
    private static class DecisionPathCache {
        private final Map<String, List<NavigateNode>> pathMap = new HashMap<>();
    }
}