#
Junjie
1 天以前 c34f9c17fde14f78b3663803e9776d438e8481b9
src/main/java/com/zy/core/utils/StationOperateProcessUtils.java
@@ -27,6 +27,7 @@
import com.zy.core.model.Task;
import com.zy.core.model.command.StationCommand;
import com.zy.core.model.protocol.StationProtocol;
import com.zy.core.service.StationTaskLoopService;
import com.zy.core.thread.StationThread;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -67,6 +68,8 @@
    private StationPathPolicyService stationPathPolicyService;
    @Autowired
    private BasStationOptService basStationOptService;
    @Autowired
    private StationTaskLoopService stationTaskLoopService;
    //执行输送站点入库任务
    public synchronized void stationInExecute() {
@@ -586,6 +589,19 @@
        return countCurrentStationTask();
    }
    public synchronized int getCurrentOutboundTaskCountByTargetStation(Integer stationId) {
        if (stationId == null) {
            return 0;
        }
        return (int) wrkMastService.count(new QueryWrapper<WrkMast>()
                .eq("io_type", WrkIoType.OUT.id)
                .eq("sta_no", stationId)
                .in("wrk_sts",
                        WrkStsType.OUTBOUND_RUN.sts,
                        WrkStsType.OUTBOUND_RUN_COMPLETE.sts,
                        WrkStsType.STATION_RUN.sts));
    }
    // 检测出库排序
    public synchronized void checkStationOutOrder() {
        List<BasDevp> basDevps = basDevpService.list(new QueryWrapper<BasDevp>());
@@ -759,7 +775,7 @@
        if (!Objects.equals(dispatchStationId, wrkMast.getStaNo())
                && isCurrentOutOrderStation(currentStationId, outOrderStationIds)
                && isWatchingCircleArrival(wrkMast.getWrkNo(), currentStationId)) {
            return new OutOrderDispatchDecision(dispatchStationId, true);
            return new OutOrderDispatchDecision(dispatchStationId, true, null, false);
        }
        return new OutOrderDispatchDecision(dispatchStationId, false);
    }
@@ -810,20 +826,38 @@
            if (hasReachableOutReleaseSlot(currentStationId, wrkMast.getStaNo())) {
                return new OutOrderDispatchDecision(wrkMast.getStaNo(), false);
            }
            Integer circleTarget = resolveNextCircleOrderTarget(currentStationId, outOrderStationIds);
            StationTaskLoopService.LoopEvaluation loopEvaluation = evaluateOutOrderLoop(
                    wrkMast.getWrkNo(),
                    currentStationId,
                    outOrderStationIds
            );
            Integer circleTarget = resolveNextCircleOrderTarget(
                    currentStationId,
                    outOrderStationIds,
                    loopEvaluation.getExpectedLoopIssueCount()
            );
            if (circleTarget == null) {
                News.taskInfo(wrkMast.getWrkNo(), "目标站当前不可进,且未找到可执行的下一排序检测点,当前站点={}", currentStationId);
                return null;
            }
            return new OutOrderDispatchDecision(circleTarget, true);
            return new OutOrderDispatchDecision(circleTarget, true, loopEvaluation, true);
        }
        Integer circleTarget = resolveNextCircleOrderTarget(currentStationId, outOrderStationIds);
        StationTaskLoopService.LoopEvaluation loopEvaluation = evaluateOutOrderLoop(
                wrkMast.getWrkNo(),
                currentStationId,
                outOrderStationIds
        );
        Integer circleTarget = resolveNextCircleOrderTarget(
                currentStationId,
                outOrderStationIds,
                loopEvaluation.getExpectedLoopIssueCount()
        );
        if (circleTarget == null) {
            News.taskInfo(wrkMast.getWrkNo(), "未找到可执行的下一排序检测点,当前站点={}", currentStationId);
            return null;
        }
        return new OutOrderDispatchDecision(circleTarget, true);
        return new OutOrderDispatchDecision(circleTarget, true, loopEvaluation, true);
    }
    private boolean shouldApplyOutOrder(WrkMast wrkMast, List<Integer> outOrderStationIds) {
@@ -869,9 +903,36 @@
        }
        if (dispatchDecision.isCircle()) {
            saveWatchCircleCommand(wrkMast.getWrkNo(), command);
            if (dispatchDecision.shouldCountLoopIssue()
                    && stationTaskLoopService != null
                    && dispatchDecision.getLoopEvaluation() != null) {
                stationTaskLoopService.recordLoopIssue(dispatchDecision.getLoopEvaluation(), "OUT_ORDER_CIRCLE");
            }
        } else {
            clearWatchCircleCommand(wrkMast.getWrkNo());
        }
    }
    private StationTaskLoopService.LoopEvaluation evaluateOutOrderLoop(Integer taskNo,
                                                                       Integer currentStationId,
                                                                       List<Integer> outOrderStationIds) {
        if (stationTaskLoopService == null) {
            return new StationTaskLoopService.LoopEvaluation(
                    taskNo,
                    currentStationId,
                    StationTaskLoopService.LoopIdentitySnapshot.empty(),
                    0,
                    0,
                    false
            );
        }
        return stationTaskLoopService.evaluateLoop(
                taskNo,
                currentStationId,
                true,
                outOrderStationIds,
                "outOrderCircle"
        );
    }
    private Integer resolveDispatchOutOrderTarget(Integer sourceStationId,
@@ -955,13 +1016,16 @@
                || (stationProtocol.getTaskNo() != null && stationProtocol.getTaskNo() > 0);
    }
    private Integer resolveNextCircleOrderTarget(Integer currentStationId, List<Integer> orderedOutStationList) {
    private Integer resolveNextCircleOrderTarget(Integer currentStationId,
                                                 List<Integer> orderedOutStationList,
                                                 Integer expectedLoopIssueCount) {
        if (currentStationId == null || orderedOutStationList == null || orderedOutStationList.size() <= 1) {
            return null;
        }
        int startIndex = orderedOutStationList.indexOf(currentStationId);
        int total = orderedOutStationList.size();
        List<Integer> reachableStationIdList = new ArrayList<>();
        for (int offset = 1; offset < total; offset++) {
            int candidateIndex = (startIndex + offset + total) % total;
            Integer candidateStationId = orderedOutStationList.get(candidateIndex);
@@ -971,11 +1035,29 @@
            try {
                List<NavigateNode> path = navigateUtils.calcByStationId(currentStationId, candidateStationId);
                if (path != null && !path.isEmpty()) {
                    return candidateStationId;
                    reachableStationIdList.add(candidateStationId);
                }
            } catch (Exception ignore) {}
        }
        return null;
        if (reachableStationIdList.isEmpty()) {
            return null;
        }
        int gradualIndex = resolveGradualCircleTargetIndex(expectedLoopIssueCount, reachableStationIdList.size());
        return reachableStationIdList.get(gradualIndex);
    }
    private int resolveGradualCircleTargetIndex(Integer expectedLoopIssueCount, int candidateCount) {
        if (candidateCount <= 1) {
            return 0;
        }
        if (expectedLoopIssueCount == null || expectedLoopIssueCount <= 2) {
            return 0;
        }
        int gradualIndex = expectedLoopIssueCount - 2;
        if (gradualIndex < 1) {
            gradualIndex = 1;
        }
        return Math.min(gradualIndex, candidateCount - 1);
    }
    private boolean tryAcquireOutOrderDispatchLock(Integer wrkNo, Integer stationId) {
@@ -1410,10 +1492,21 @@
    private static class OutOrderDispatchDecision {
        private final Integer targetStationId;
        private final boolean circle;
        private final StationTaskLoopService.LoopEvaluation loopEvaluation;
        private final boolean countLoopIssue;
        private OutOrderDispatchDecision(Integer targetStationId, boolean circle) {
            this(targetStationId, circle, null, false);
        }
        private OutOrderDispatchDecision(Integer targetStationId,
                                         boolean circle,
                                         StationTaskLoopService.LoopEvaluation loopEvaluation,
                                         boolean countLoopIssue) {
            this.targetStationId = targetStationId;
            this.circle = circle;
            this.loopEvaluation = loopEvaluation;
            this.countLoopIssue = countLoopIssue;
        }
        private Integer getTargetStationId() {
@@ -1423,6 +1516,14 @@
        private boolean isCircle() {
            return circle;
        }
        private StationTaskLoopService.LoopEvaluation getLoopEvaluation() {
            return loopEvaluation;
        }
        private boolean shouldCountLoopIssue() {
            return countLoopIssue;
        }
    }
    private void saveLoopLoadReserve(Integer wrkNo, LoopHitResult loopHitResult) {