From 13ea8b334572c2423abb8d156fd8428f8d074172 Mon Sep 17 00:00:00 2001
From: zhang <zc857179121@qq.com>
Date: 星期四, 03 七月 2025 08:24:58 +0800
Subject: [PATCH] 1

---
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/TrafficService.java | 1398 ++++++++++++++++++++++++++++++---------------------------
 1 files changed, 741 insertions(+), 657 deletions(-)

diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/TrafficService.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/TrafficService.java
index db6cd89..2b4dc48 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/TrafficService.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/TrafficService.java
@@ -1,658 +1,742 @@
-package com.zy.acs.manager.core.service;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.zy.acs.common.utils.GsonUtils;
-import com.zy.acs.common.utils.Utils;
-import com.zy.acs.framework.common.Cools;
-import com.zy.acs.framework.common.SnowflakeIdWorker;
-import com.zy.acs.framework.exception.CoolException;
-import com.zy.acs.manager.common.utils.MapDataUtils;
-import com.zy.acs.manager.core.constant.MapDataConstant;
-import com.zy.acs.manager.core.domain.BlockVehicleDto;
-import com.zy.acs.manager.core.domain.TaskPosDto;
-import com.zy.acs.manager.core.domain.type.BlockSeverityType;
-import com.zy.acs.manager.core.service.astart.MapDataDispatcher;
-import com.zy.acs.manager.core.service.astart.NavigateNode;
-import com.zy.acs.manager.core.service.astart.RetreatNavigateNode;
-import com.zy.acs.manager.core.service.astart.WaveNodeType;
-import com.zy.acs.manager.manager.entity.*;
-import com.zy.acs.manager.manager.enums.JamStateType;
-import com.zy.acs.manager.manager.enums.SegmentStateType;
-import com.zy.acs.manager.manager.enums.TaskTypeType;
-import com.zy.acs.manager.manager.service.*;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.transaction.interceptor.TransactionAspectSupport;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * Wavefront
- * Created by vincent on 6/25/2024
- */
-@Slf4j
-@Component
-public class TrafficService {
-
-    @Autowired
-    private AgvService agvService;
-    @Autowired
-    private AgvDetailService agvDetailService;
-    @Autowired
-    private CodeService codeService;
-    @Autowired
-    private TravelService travelService;
-    @Autowired
-    private SegmentService segmentService;
-    @Autowired
-    private MainService mainService;
-    @Autowired
-    private MainLockWrapService mainLockWrapService;
-    @Autowired
-    private MapService mapService;
-    @Autowired
-    private MapDataDispatcher mapDataDispatcher;
-    @Autowired
-    private SnowflakeIdWorker snowflakeIdWorker;
-    @Autowired
-    private AgvModelService agvModelService;
-    @Autowired
-    private RetreatNavigateService retreatNavigateService;
-    @Autowired
-    private TaskService taskService;
-    @Autowired
-    private JamService jamService;
-    @Autowired
-    private AvoidWaveCalculator avoidWaveCalculator;
-
-    @Transactional
-    public synchronized void trigger(Segment segment) {
-        try {
-            Date now = new Date();
-            Travel travel = travelService.getById(segment.getTravelId());
-            Agv agv = agvService.getById(travel.getAgvId());
-            AgvDetail agvDetail = agvDetailService.selectByAgvId(travel.getAgvId());
-            long endNode = segment.getEndNode();
-
-            // valid ----------------------------------------------------
-            if (!agvService.judgeEnable(agv.getId())) {
-                return;
-            }
-            if (!Cools.isEmpty(segmentService.getByAgvAndState(agv.getId(), SegmentStateType.RUNNING.toString()))) {
-                return;
-            }
-            List<Segment> waitingSegList = segmentService.getByAgvAndState(agv.getId(), SegmentStateType.WAITING.toString());
-            if (!Cools.isEmpty(waitingSegList)) {
-                for (Segment waitingSeg : waitingSegList) {
-                    if (!waitingSeg.getId().equals(segment.getId())) {
-//                        log.error("AGV[{}] 浠诲姟寮傚父锛屾湇鍔″櫒閿欒锛侊紒锛�", agv.getUuid());
-                        return;
-                    }
-                }
-            }
-
-            // dead lane
-            if (jamService.count(new LambdaQueryWrapper<Jam>()
-                    .eq(Jam::getJamAgv, agv.getId())
-                    .eq(Jam::getJamSeg, segment.getId())
-                    .eq(Jam::getCycleAvo, 1)
-                    .eq(Jam::getCycleCode, endNode)
-                    .eq(Jam::getState, JamStateType.RUNNING.toString())
-            ) > 0) {
-                return;
-            }
-
-            // deprecate jam
-            if (this.isExpiredJamByAvo(segment.getId())) {
-                mainService.settleSegmentList(Utils.singletonList(segment), null);
-                return;
-            }
-
-            // execute -----------------------------------------------
-            //        ArrayList<List<TaskPosDto>> list = JSON.parseObject(travel.getTaskContent(), new TypeReference<ArrayList<List<TaskPosDto>>>() {});
-
-            // get path list
-            avoidWaveCalculator.calcWaveScope();    // * sync wave scope
-
-            // checkout path
-            Code startCode = codeService.getById(agvDetail.getRecentCode());
-            Code endCode = codeService.getById(endNode);
-            List<String> pathList = this.checkoutPath(agv, startCode, endCode, segment);
-            if (Cools.isEmpty(pathList)) {
-                return;
-            }
-
-            List<Segment> segmentList = new ArrayList<>();
-            segmentList.add(segment);
-
-            String lastCodeData = pathList.get(pathList.size() - 1);
-            if (!endCode.getData().equals(lastCodeData)) {
-                // slice
-                Code lastCode = codeService.selectByData(lastCodeData);
-
-//                if (pathList.size() <= MIN_SLICE_PATH_LENGTH) {
-//                    return;
-//                }
-
-                // revert
-                segment.setState(SegmentStateType.INIT.toString());
-                segment.setUpdateTime(now);
-                if (!segmentService.updateById(segment)) {
-                    log.error("Segment [{}] failed to update 锛侊紒锛�", segment.getGroupId() + " - " + segment.getSerial());
-                }
-                segmentList.clear();
-
-                // new move seg
-                Segment insertSeg = new Segment();
-                insertSeg.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
-                insertSeg.setTravelId(travel.getId());
-                insertSeg.setAgvId(agv.getId());
-                insertSeg.setTaskId(segment.getTaskId());
-                insertSeg.setSerial(segment.getSerial() - 1);
-                insertSeg.setEndNode(lastCode.getId());
-                insertSeg.setPosType(TaskPosDto.PosType.MOVE.toString());
-                insertSeg.setState(SegmentStateType.WAITING.toString());
-                if (!segmentService.save(insertSeg)) {
-                    log.error("Segment [{}] failed to save 锛侊紒锛�", segment.getTravelId() + " - " + segment.getSerial());
-                }
-                segmentList.add(insertSeg);
-
-            } else {
-
-                // complete first segment then merge behind segment
-                int serial = segment.getSerial();
-                boolean interrupt = false;
-                while (!interrupt) {
-
-                    Segment nextStep = segmentService.getNextStepOfInit(travel.getId(), serial);
-                    serial ++;
-                    if (null == nextStep) {
-                        interrupt = true;
-                    } else {
-                        if (nextStep.getEndNode() == endNode) {
-
-                            segmentList.add(nextStep);
-                        } else {
-                            interrupt = true;
-                        }
-                    }
-
-                }
-            }
-
-            mapService.lockPath(null, pathList, agv.getUuid());
-
-            mainService.generateAction(segment.getAgvId(), segmentList, pathList);
-
-        } catch (Exception e) {
-            log.error("TrafficService.trigger", e);
-            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
-
-        }
-    }
-
-    private List<String> checkoutPath(Agv agv, Code startCode, Code endCode, Segment segment) {
-        Integer lev = null;
-        String agvNo = agv.getUuid();
-        Date now = new Date();
-        Jam jam = jamService.getJam(agv.getId(), startCode.getId(), segment.getId());
-        BlockSeverityType blockSeverity = BlockSeverityType.query(null == jam ? null : jam.getDuration());
-        // judge avoid of jam 濡傛灉宸茬粡鍦ㄩ伩璁╃偣锛堝洜涓哄綋鍓嶈溅鎵ц浜嗛伩璁╀换鍔★級锛岄偅涔堝垯涓嶈兘鍐嶅幓妫�绱箣鍓嶇殑闃诲璺緞
-        List<Jam> unfinishedOriginJamByCurrAgv = jamService.getUnfinishedOriginJamByAvo(agv.getId(), startCode.getId(), segment.getId());
-        List<String> blackPath = this.getBlackPathList(unfinishedOriginJamByCurrAgv);
-
-        // 缁撴灉闆�
-        List<String> pathList = new ArrayList<>();
-
-        // 鏃犻殰纰嶈В
-        List<String> unlockPathList = mapService.checkoutPath(agvNo, startCode, endCode, false, blackPath, segment);
-        // 閬胯瑙�
-        List<String> lockPathList = mapService.checkoutPath(agvNo, startCode, endCode, true, blackPath, segment);
-
-        if (!Cools.isEmpty(lockPathList) && // 瀛樺湪閬胯瑙�
-            Math.abs(lockPathList.size() - unlockPathList.size()) <= Arrays.stream(mapDataDispatcher.getCodeMatrix(lev)).mapToInt(row -> row.length).sum() / 10
-        ) {
-
-            pathList = lockPathList;
-        } else {
-
-            // preview path
-            List<String> draftPath = new ArrayList<>(unlockPathList);
-            if (blockSeverity.equals(BlockSeverityType.SEVERE)) {
-                unlockPathList.remove(endCode.getData());
-                blackPath.addAll(unlockPathList);
-                List<String> newUnlockPathList = mapService.checkoutPath(agvNo, startCode, endCode, false, blackPath, segment);
-                if (!Cools.isEmpty(newUnlockPathList)) {
-                    draftPath = newUnlockPathList;
-                }
-            }
-            // 鍙蛋琛岃矾寰勯泦鍚堣绠�
-            List<BlockVehicleDto> blockVehicleList = this.slicePathAndReturnBlockVehicleList(lev, draftPath, agvNo, pathList);    // jamAgvNo may was wave
-
-            if (!Cools.isEmpty(pathList)) {
-
-                if (!pathList.get(pathList.size() - 1).equals(endCode.getData())) {
-                    assert !Cools.isEmpty(blockVehicleList);
-
-                    boolean hasUnavoidableBlocks = blockVehicleList.stream().anyMatch(blockVehicleDto -> !blockVehicleDto.isAvoidable());
-                    if (hasUnavoidableBlocks && pathList.size() <= MapDataConstant.MIN_SLICE_PATH_LENGTH) {
-                        log.info("AGV[{}] waiting in place, because the path list is too short...", agvNo);
-                        pathList.clear();
-                    }
-
-                    boolean hasCycleJam = blockVehicleList.stream().anyMatch(
-                            blockVehicleDto -> null != jamService.getCycleJam(agv.getId(), segment.getId(), blockVehicleDto.getVehicle())
-                    );
-                    if (hasCycleJam) {
-                        log.info("AGV[{}] waiting in place, because has cycle jam...", agvNo);
-                        pathList.clear();
-                    }
-                }
-
-            // 鏃犲彲璧拌璺緞
-            } else {
-
-                if (Cools.isEmpty(blockVehicleList)) {
-                    log.warn("AGV[{}] can't reach to code: {}, because there is too many vehicle in the lane...", agvNo, endCode.getData());
-                } else {
-
-                    assert !Cools.isEmpty(blockVehicleList);
-                    Integer maxJamTimeoutFactor = null;
-
-                    // persist jam data
-                    jam = this.createOrUpdateJam(agv, startCode, segment, jam, draftPath);
-
-                    // ? has unAvoidable block vehicles
-                    if (blockVehicleList.stream().anyMatch(blockVehicleDto -> !blockVehicleDto.isAvoidable())) {
-
-                        // set factor of jam timeout
-                        maxJamTimeoutFactor = 1;
-                    } else {
-
-                        // ? already do notify to avoid
-                        if (!Cools.isEmpty(jam.getAvoAgv())
-                                && BlockVehicleDto.customContain(blockVehicleList, agvService.getById(jam.getAvoAgv()).getUuid())) {
-
-                            maxJamTimeoutFactor = 4;
-
-                        } else {
-
-                            // select optimal block vehicle
-                            String blockAgvNo = this.checkoutBestSolutionOfBlocks(blockVehicleList, segment);
-                            if (Cools.isEmpty(blockAgvNo)) {
-
-                                maxJamTimeoutFactor = 2;
-
-                            } else {
-
-                                // block vehicle info
-                                Agv blockAgv = agvService.selectByUuid(blockAgvNo);
-                                String blockAgvCode = codeService.getById(agvDetailService.selectByAgvId(blockAgv.getId()).getRecentCode()).getData();
-
-                                // create new jam if already notify the avoid vehicle
-                                if (!Cools.isEmpty(jam.getAvoAgv(), jam.getAvoSeg()) && !blockAgv.getId().equals(jam.getAvoAgv())) {
-                                    jam = this.setupNewJam(jam, agv, startCode, segment, draftPath);
-                                }
-
-                                do {
-
-                                    // 闃诲杞﹁締姝e湪鍘熷湴浣滀笟锛岀瓑寰� ===>> 瓒呰繃绛夊緟鏃堕棿锛岀粫璺�
-                                    List<Segment> runningSegList = segmentService.getByAgvAndState(blockAgv.getId(), SegmentStateType.RUNNING.toString());
-                                    if (!Cools.isEmpty(runningSegList)) {
-                                        maxJamTimeoutFactor = 1;
-                                        break;
-                                    }
-
-                                    // 鍒ゆ柇涓嬩釜浠诲姟鏄惁涓哄師鍦颁换鍔★紝濡傛灉鏄垯绛夊緟 ===>> 瓒呰繃绛夊緟鏃堕棿锛岀粫璺紱濡傛灉涓嶆槸锛岃闃诲杞﹁締閬胯
-                                    List<Segment> waitingSegList = segmentService.getJustWaitingSeg(blockAgv.getId());
-                                    if (null != waitingSegList
-                                            && waitingSegList.stream().anyMatch(
-                                            waitingSeg -> waitingSeg.getEndNode().equals(codeService.selectByData(blockAgvCode).getId())
-                                    )) {
-                                        maxJamTimeoutFactor = 1;
-                                        break;
-                                    }
-
-                                    // notify block vehicle to avoid
-                                    if (this.notifyVehicleAvoid(blockAgvNo, blockAgvCode, draftPath, agvNo, jam)) {
-                                        if (jam.getCycleAvo() == 1) {
-                                            jam.setCycleCode(endCode.getId());
-                                        }
-                                        jam.setAvoAgv(blockAgv.getId());
-                                        jam.setNotifyTime(new Date());
-                                        if (!jamService.updateById(jam)) {
-                                            throw new CoolException(jam.getUuid() + "-jam failed to update锛侊紒锛�");
-                                        }
-                                    } else {
-
-                                        maxJamTimeoutFactor = 1;
-                                    }
-
-                                } while (false);
-                            }
-
-                        }
-
-                    }
-
-                    // handle jam timeout
-                    if (null != maxJamTimeoutFactor) {
-                        if (System.currentTimeMillis() - jam.getStartTime().getTime() > MapDataConstant.MAX_JAM_TIMEOUT * maxJamTimeoutFactor) {
-
-                            if (!Cools.isEmpty(lockPathList)) {
-
-                                pathList = lockPathList;
-                            } else {
-                                log.error("{}鍙疯溅杈嗘绱{}] ===>> [{}]璺緞澶辫触锛屽師鍥狅細{}"
-                                        , agvNo, startCode.getData(), endCode.getData(), "璺緞闃诲瓒呮椂");
-                            }
-                        } else {
-                            log.warn("{}鍙疯溅杈嗘鍦ㄧ瓑寰呬氦閫氬牭濉烇紝闃诲杞﹁締锛氥�恵}銆�"
-                                    , agvNo
-                                    , blockVehicleList.stream().map(BlockVehicleDto::getVehicle).collect(Collectors.toList()).toString()
-                            );
-                        }
-                    }
-
-                }
-
-            }
-        }
-
-        if (!Cools.isEmpty(pathList)) {
-
-            if (null != jam) {
-                boolean beDeprecate = false;
-                if (blockSeverity.equals(BlockSeverityType.SEVERE) && !Cools.isEmpty(jam.getJamPath())) {
-                    List<String> jamPath = GsonUtils.fromJsonToList(jam.getJamPath(), String.class);
-                    if (!this.comparePathLists(jamPath, pathList)) {    // jamPath >= pathList
-                        beDeprecate = true;
-                    }
-                }
-                jam.setEndTime(now);
-                jam.setUpdateTime(now);
-                jam.setState(beDeprecate ? JamStateType.DEPRECATED.toString() : JamStateType.FINISH.toString());
-                if (jamService.updateById(jam)) {
-                    if (beDeprecate) {
-                        // search previous jam that jamSeg from this segment
-                        List<Jam> previousJams = jamService.list(new LambdaQueryWrapper<Jam>()
-                                .eq(Jam::getJamSeg, segment.getId())
-                                .eq(Jam::getState, JamStateType.FINISH.toString())
-                        );
-                        for (Jam previousJam : previousJams) {
-                            previousJam.setState(JamStateType.DEPRECATED.toString());
-                            previousJam.setUpdateTime(now);
-                            if (!jamService.updateById(previousJam)) {
-                                log.error("Jam[{}] failed to update锛侊紒锛�", previousJam.getUuid());
-                            }
-                        }
-                    }
-                } else {
-                    log.error("Jam[{}] failed to update锛侊紒锛�", jam.getUuid());
-                }
-            }
-            // deal expired jam
-            for (Jam expiredJam : jamService.list(new LambdaQueryWrapper<Jam>()
-                    .eq(Jam::getJamAgv, agv.getId())
-                    .eq(Jam::getState, JamStateType.RUNNING.toString()))) {
-                expiredJam.setEndTime(now);
-                expiredJam.setUpdateTime(now);
-                expiredJam.setState(JamStateType.DEPRECATED.toString());
-                if (!jamService.updateById(expiredJam)) {
-                    log.error("Jam[{}] failed to update锛侊紒锛�", expiredJam.getUuid());
-                }
-            }
-
-        }
-
-        return pathList;
-    }
-
-    private List<BlockVehicleDto> slicePathAndReturnBlockVehicleList(Integer lev, List<String> fullPathList, String agvNo, List<String> pathList) {
-        List<BlockVehicleDto> blockVehicleList = new ArrayList<>();
-
-//        DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(lev);
-        String[][] waveMatrix = mapDataDispatcher.getWaveMatrix(lev);
-        for (String code : fullPathList) {
-            int[] node = mapDataDispatcher.getCodeMatrixIdx(lev, code);
-
-            String waveNode = waveMatrix[node[0]][node[1]];
-            assert !waveNode.equals(WaveNodeType.DISABLE.val);
-            if (!waveNode.equals(WaveNodeType.ENABLE.val)) {
-                List<String> waveNodeList = MapDataUtils.parseWaveNode(waveNode);
-                List<String> otherWaveList = MapDataUtils.hasOtherWave(waveNodeList, agvNo);
-                if (!Cools.isEmpty(otherWaveList)) {
-                    for (String otherWave : otherWaveList) {
-                        if (1 < mapDataDispatcher.queryCodeListFromDynamicNode(lev, otherWave).size()) {
-                            blockVehicleList.add(new BlockVehicleDto(otherWave, false));
-                        } else {
-                            blockVehicleList.add(new BlockVehicleDto(otherWave, true));
-                        }
-                    }
-                    break;
-                }
-            }
-
-//            DynamicNode dynamicNode = dynamicMatrix[node[0]][node[1]];
-//            String vehicle = dynamicNode.getVehicle();
-//            assert !vehicle.equals(DynamicNodeType.BLOCK.val);
-//            if (!vehicle.equals(DynamicNodeType.ACCESS.val) && !vehicle.equals(agvNo)) {
-//                blockVehicleList.add(vehicle);
-//                break;
+//package com.zy.acs.manager.core.service;
+//
+//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+//import com.zy.acs.common.utils.GsonUtils;
+//import com.zy.acs.common.utils.Utils;
+//import com.zy.acs.framework.common.Cools;
+//import com.zy.acs.framework.common.SnowflakeIdWorker;
+//import com.zy.acs.framework.exception.CoolException;
+//import com.zy.acs.manager.common.utils.MapDataUtils;
+//import com.zy.acs.manager.core.constant.MapDataConstant;
+//import com.zy.acs.manager.core.domain.BlockVehicleDto;
+//import com.zy.acs.manager.core.domain.TaskPosDto;
+//import com.zy.acs.manager.core.domain.type.BlockSeverityType;
+//import com.zy.acs.manager.core.service.astart.MapDataDispatcher;
+//import com.zy.acs.manager.core.service.astart.NavigateNode;
+//import com.zy.acs.manager.core.service.astart.RetreatNavigateNode;
+//import com.zy.acs.manager.core.service.astart.WaveNodeType;
+//import com.zy.acs.manager.manager.entity.*;
+//import com.zy.acs.manager.manager.enums.JamStateType;
+//import com.zy.acs.manager.manager.enums.SegmentStateType;
+//import com.zy.acs.manager.manager.enums.TaskTypeType;
+//import com.zy.acs.manager.manager.service.*;
+//import com.zy.acs.manager.system.service.ConfigService;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.stereotype.Component;
+//import org.springframework.transaction.annotation.Transactional;
+//import org.springframework.transaction.interceptor.TransactionAspectSupport;
+//
+//import java.util.ArrayList;
+//import java.util.Arrays;
+//import java.util.Date;
+//import java.util.List;
+//import java.util.stream.Collectors;
+//
+///**
+// * Wavefront
+// * Created by vincent on 6/25/2024
+// */
+//@Slf4j
+//@Component
+//public class TrafficService {
+//
+//    @Autowired
+//    private AgvService agvService;
+//    @Autowired
+//    private AgvDetailService agvDetailService;
+//    @Autowired
+//    private CodeService codeService;
+//    @Autowired
+//    private TravelService travelService;
+//    @Autowired
+//    private SegmentService segmentService;
+//    @Autowired
+//    private MainLxtService mainService;
+//    @Autowired
+//    private MainLockWrapService mainLockWrapService;
+//    @Autowired
+//    private MapService mapService;
+//    @Autowired
+//    private MapDataDispatcher mapDataDispatcher;
+//    @Autowired
+//    private SnowflakeIdWorker snowflakeIdWorker;
+//    @Autowired
+//    private AgvModelService agvModelService;
+//    @Autowired
+//    private RetreatNavigateService retreatNavigateService;
+//    @Autowired
+//    private ConfigService configService;
+//    @Autowired
+//    private JamService jamService;
+//    @Autowired
+//    private AvoidWaveCalculator avoidWaveCalculator;
+//    @Autowired
+//    private TaskService taskService;
+//    @Autowired
+//    private FuncStaService funcStaService;
+//
+//    @Transactional
+//    public synchronized void trigger(Segment segment) {
+//        try {
+//            Date now = new Date();
+//
+//            // deprecate jam
+//            if (this.isExpiredJamByAvo(segment.getId())) {
+//                mainService.settleSegmentList(Utils.singletonList(segment), null);
+//                return;
 //            }
-
-            pathList.add(code);
-        }
-
-        if (pathList.size() <= 1) {
-            pathList.clear();
-        }
-
-        return blockVehicleList.stream().distinct().collect(Collectors.toList());
-    }
-
-    /**
-     * avoidPathList include wave node and dynamic node
-     */
-    private boolean notifyVehicleAvoid(String agvNo, String agvPosCode, List<String> avoidPathList, String sponsor, Jam jam) {
-        Agv agv = agvService.selectByUuid(agvNo);
-        if (!Cools.isEmpty(segmentService.getByAgvAndState(agv.getId(), SegmentStateType.RUNNING.toString()))) {
-            log.warn("{}鍙疯溅杈嗛伩璁╁け璐ワ紝瀛樺湪杩涜涓换鍔★紒锛侊紒", agvNo);
-            return false;
-        }
-
-        int[] startMapIdx = mapDataDispatcher.getCodeMatrixIdx(null, agvPosCode);
-        RetreatNavigateNode startNode = new RetreatNavigateNode(startMapIdx[0], startMapIdx[1], agvPosCode);
-
-        assert avoidPathList.size() >= 2;
-        RetreatNavigateNode finalNode = retreatNavigateService.execute(agvNo, startNode, avoidPathList, sponsor, jam);
-        if (null == finalNode) {
-            log.warn("{}鍙疯溅杈嗛伩璁╁け璐ワ紝妫�绱㈤伩璁╃偣澶辫触锛侊紒锛�", agvNo);
-            return false;
-        }
-
-        String endCodeData = finalNode.getCodeData();
-        Code endCode = codeService.selectByData(endCodeData);
-
-        List<Segment> waitingSegList = segmentService.getByAgvAndState(agv.getId(), SegmentStateType.WAITING.toString());
-        if (!Cools.isEmpty(waitingSegList)) {
-
-            if (waitingSegList.size() > 1) {
-                log.error("閬胯閫氱煡澶辫触锛寋}鍙疯溅杈嗗瓨鍦ㄥ涓瓑寰呬腑鐨凷egment锛侊紒锛�", agvNo);
-                return false;
-            }
-            // revert
-            Date now = new Date();
-            for (Segment seg : waitingSegList) {
-                seg.setState(SegmentStateType.INIT.toString());
-                seg.setUpdateTime(now);
-                if (!segmentService.updateById(seg)) {
-                    log.error("Segment [{}] 鏇存柊澶辫触 锛侊紒锛�", seg.getTravelId() + " - " + seg.getSerial());
-                }
-            }
-            Segment segment = waitingSegList.get(0);
-
-            Segment insertSeg = new Segment();
-            insertSeg.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
-            insertSeg.setTravelId(segment.getTravelId());
-            insertSeg.setAgvId(agv.getId());
-            insertSeg.setTaskId(segment.getTaskId());
-            insertSeg.setSerial(segment.getSerial() - 1);
-            insertSeg.setEndNode(endCode.getId());
-            insertSeg.setPosType(TaskPosDto.PosType.MOVE.toString());
-            insertSeg.setState(SegmentStateType.WAITING.toString());
-            if (!segmentService.save(insertSeg)) {
-                log.error("Segment [{}] 淇濆瓨澶辫触 锛侊紒锛�", segment.getTravelId() + " - " + segment.getSerial());
-                return false;
-            } else {
-                jam.setAvoSeg(insertSeg.getId());
-                jam.setAvoCode(endCode.getId());
-            }
-
-        } else {
-
-            return mainLockWrapService.buildMinorTask(agv, TaskTypeType.MOVE, endCodeData, jam);
-        }
-
-        return true;
-    }
-
-    private Jam createOrUpdateJam(Agv agv, Code startCode, Segment segment, Jam jam, List<String> jamPath) {
-        if (jam == null) {
-            jam = new Jam();
-            jam.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
-            jam.setJamAgv(agv.getId());
-            jam.setJamCode(startCode.getId());
-            jam.setJamSeg(segment.getId());
-            jam.setJamPath(GsonUtils.toJson(jamPath));
-            jam.setStartTime(new Date());
-            jam.setState(JamStateType.RUNNING.toString());
-            if (!jamService.save(jam)) {
-                log.error("AGV[{}] failed to save jam", agv.getUuid());
-                throw new CoolException("failed to save jam");
-            }
-        } else {
-            jam.setDuration(System.currentTimeMillis() - jam.getStartTime().getTime());
-            if (!jamService.updateById(jam)) {
-                log.error("AGV[{}] failed to update jam", agv.getUuid());
-            }
-        }
-        return jam;
-    }
-
-    private Jam setupNewJam(Jam originJam, Agv agv, Code startCode, Segment segment, List<String> draftPath) {
-        originJam.setUpdateTime(new Date());
-        originJam.setState(JamStateType.FINISH.toString());
-        if (!jamService.updateById(originJam)) {
-            log.error("Jam[{}] failed to update", originJam.getUuid());
-            return originJam;
-        } else {
-            return this.createOrUpdateJam(
-                    agv
-                    , startCode
-                    , segment
-                    , null
-                    , draftPath
-            );
-        }
-    }
-
-    private List<String> getBlackPathList(List<Jam> unfinishedOriginJamByCurrAgv) {
-        List<String> blackPathList = new ArrayList<>();
-        Integer lev = MapDataDispatcher.MAP_DEFAULT_LEV;
-        if (!Cools.isEmpty(unfinishedOriginJamByCurrAgv)) {
-            for (Jam jam : unfinishedOriginJamByCurrAgv) {
-                if (!Cools.isEmpty(jam.getJamPath())) {
-
-                    List<String> list = GsonUtils.fromJsonToList(jam.getJamPath(), String.class);
-
-                    Agv jamAgv = agvService.getById(jam.getJamAgv());
-                    List<String> jamDynamicNodes = mapDataDispatcher.queryCodeListFromDynamicNode(lev, jamAgv.getUuid());
-                    // jamDynamicNodes has sorted
-                    String firstCodeNode = jamDynamicNodes.stream().findFirst().orElse(null);
-
-                    if (!Cools.isEmpty(firstCodeNode)) {
-                        int idx = list.indexOf(firstCodeNode);
-                        if (idx != -1) {
-                            list = new ArrayList<>(list.subList(idx, list.size()));
-
-                            // the wave of first node
-                            Double avoidDistance = MapDataUtils.getVehicleWaveSafeDistance(
-                                    agvModelService.getById(jamAgv.getAgvModel()).getDiameter(),
-                                    MapDataConstant.MAX_DISTANCE_BETWEEN_ADJACENT_AGV_FACTOR
-                            );
-                            List<String> waveCodeList = mapService.getWaveScopeByCode(lev, firstCodeNode, avoidDistance)
-                                    .stream().map(NavigateNode::getCodeData).distinct().collect(Collectors.toList());
-                            list.addAll(waveCodeList);
-                        } else {
-                            // 濡傛灉琚樆濉炶溅杈嗗凡缁忎笉鍦ㄥ師鏉ョ殑闃诲璺緞涓紝鑰冭檻閬胯杞﹁蛋琛屾椂涓嶉渶瑕佹妸涔嬪墠鐨勯樆濉炶矾寰勫姞鍏ラ粦鍚嶅崟
-                            list = new ArrayList<>();
-                        }
-                    }
-
-                    blackPathList.addAll(list);
-                }
-            }
-        }
-        return blackPathList.stream().distinct().collect(Collectors.toList());
-    }
-
-    private String checkoutBestSolutionOfBlocks(List<BlockVehicleDto> blockVehicleList, Segment segment) {
-        assert !Cools.isEmpty(blockVehicleList);
-        for (BlockVehicleDto blockVehicleDto : blockVehicleList) {
-            if (!blockVehicleDto.isAvoidable()) {
-                continue;
-            }
-            // 褰撳墠vehicle姝e湪杩涜閬胯浣滀笟
-            if (!Cools.isEmpty(jamService.getUnfinishedAvoSegByAvo(blockVehicleDto.getVehicle(), null))) {
-                continue;
-            }
-            return blockVehicleDto.getVehicle();
-        }
-        return null;
-    }
-
-    public boolean comparePathLists(List<String> list1, List<String> list2) {
-        if (list1.equals(list2)) {
-            return true;
-        }
-        if (list1.containsAll(list2)) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * 1. the jam was deprecated
-     * 2. the jam segment is finished
-     *
-     * all these by avoid segment
-     */
-    private boolean isExpiredJamByAvo(Long avoSeg) {
-        List<Jam> jamList = jamService.list(new LambdaQueryWrapper<Jam>()
-//                .eq(Jam::getAvoAgv, avoAgv)
-                .eq(Jam::getAvoSeg, avoSeg));
-        if (Cools.isEmpty(jamList)) {
-            return false;
-        }
-        if (jamList.size() > 1) {
-            log.error("AvoSeg[id = {}] seg data has exception, result in two jams", avoSeg);
-        }
-        Jam jam = jamList.get(0);
-        if (jam.getState().equals(JamStateType.DEPRECATED.toString())) {
-            return true;
-        }
-        Segment jamSegment = segmentService.getById(jam.getJamSeg());
-        if (jamSegment.getState().equals(SegmentStateType.FINISH.toString())) {
-            return true;
-        }
-        return false;
-    }
-
-}
+//
+//            // temporary -----------------
+//            Integer algoExtensionTime = configService.getVal("algoExtensionTime", Integer.class);
+//            if (null != algoExtensionTime && algoExtensionTime > 0) {
+//                Thread.sleep(algoExtensionTime);
+//            }
+//            // ---------------------------
+//
+//            Travel travel = travelService.getById(segment.getTravelId());
+//            Agv agv = agvService.getById(travel.getAgvId());
+//            AgvDetail agvDetail = agvDetailService.selectByAgvId(travel.getAgvId());
+//            long endNode = segment.getEndNode();
+//
+//            // valid ----------------------------------------------------
+//            if (!agvService.judgeEnable(agv.getId())) {
+//                return;
+//            }
+//
+//            // resolve deadlock
+////            if (configService.getVal("unlockSwitch", Boolean.class)) {
+////
+////                boolean preSegIsStandbyDeadLock = false;
+////                Segment previousSeg = segmentService.getPreviousStepOfFinish(segment.getTravelId(), segment.getSerial(), MapDataConstant.RESOLVE_DEADLOCK);
+////                preSegIsStandbyDeadLock = previousSeg != null;
+////                if (preSegIsStandbyDeadLock && !jamService.isAvoidSeg(segment.getId())) {
+////                    if (0 < segmentService.count(new LambdaQueryWrapper<Segment>()
+////                            .in(Segment::getState, SegmentStateType.WAITING.toString(), SegmentStateType.RUNNING.toString())
+////                            .eq(Segment::getMemo, MapDataConstant.RESOLVE_DEADLOCK))) {
+////                        return;
+////                    }
+////                }
+////
+////                Jam jam = jamService.getJam(agv.getId(), agvDetail.getRecentCode(), segment.getId());
+////                if (!preSegIsStandbyDeadLock && (null != jam && null != jam.getDuration() && jam.getDuration() > (BlockSeverityType.SEVERE.duration - MapDataConstant.MAX_JAM_TIMEOUT)
+////                        || DateUtils.diffToMilliseconds(segment.getUpdateTime(), now)  > (BlockSeverityType.SEVERE.duration - MapDataConstant.MAX_JAM_TIMEOUT))
+////                        && (Cools.isEmpty(segment.getMemo()) || !segment.getMemo().equals(MapDataConstant.RESOLVE_DEADLOCK))) {
+////
+////                    Task task = taskService.getById(segment.getTaskId());
+////                    if (task.getTaskSts().equals(TaskStsType.PROGRESS.val())
+////                            && DateUtils.diffToMilliseconds(task.getUpdateTime(), now) > MapDataConstant.DEADLOCK_TASK_TIMEOUT) {
+////
+////                        Code endCode = null;
+////                        List<FuncSta> idleFunStaList = funcStaService.findInIdleStatus(FuncStaType.STANDBY, segment.getAgvId());
+////                        if (!Cools.isEmpty(idleFunStaList)) {
+////                            idleFunStaList = idleFunStaList.stream().filter(funcSta -> {
+////                                return 0 == segmentService.count(new LambdaQueryWrapper<Segment>()
+////                                                .eq(Segment::getEndNode, funcSta.getCode())
+////                                                .in(Segment::getState, SegmentStateType.WAITING.toString(), SegmentStateType.RUNNING.toString())
+////                                                .eq(Segment::getMemo, MapDataConstant.RESOLVE_DEADLOCK)
+////                                );
+////                            }).collect(Collectors.toList());
+////                            FuncSta funcSta = funcStaService.checkoutFurthestFunSta(agvDetailService.getCurrentCode(segment.getAgvId()).getId(), idleFunStaList);
+////                            if (null != funcSta) {
+////                                endCode = codeService.getCacheById(funcSta.getCode());
+////                            }
+////                        }
+////                        if (null == endCode) {
+////                            log.warn("AGV[{}] failed to search destination锛宼here hadn't any idle funSta锛孴askTypeType锛歿}", segment.getAgvId(), FuncStaType.STANDBY);
+////                            return;
+////                        }
+////
+////                        segment.setState(SegmentStateType.INIT.toString());
+////                        segment.setUpdateTime(now);
+////                        if (!segmentService.updateById(segment)) {
+////                            log.error("Segment [{}] failed to update 锛侊紒锛�", segment.getGroupId() + " - " + segment.getSerial());
+////                            return;
+////                        }
+////
+////                        // new move seg
+////                        Segment insertSeg = new Segment();
+////                        insertSeg.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
+////                        insertSeg.setTravelId(segment.getTravelId());
+////                        insertSeg.setAgvId(segment.getAgvId());
+////                        insertSeg.setTaskId(segment.getTaskId());
+////                        insertSeg.setSerial(segment.getSerial() - 1);
+////                        insertSeg.setEndNode(endCode.getId());
+////                        insertSeg.setPosType(TaskPosDto.PosType.MOVE.toString());
+////                        insertSeg.setState(SegmentStateType.WAITING.toString());
+////                        insertSeg.setMemo(MapDataConstant.RESOLVE_DEADLOCK);
+////                        if (!segmentService.save(insertSeg)) {
+////                            log.error("Segment [{}] failed to save 锛侊紒锛�", segment.getTravelId() + " - " + segment.getSerial());
+////                            return;
+////                        }
+////                        return;
+////                    }
+////                }
+////            }
+//
+//            if (!Cools.isEmpty(segmentService.getByAgvAndState(agv.getId(), SegmentStateType.RUNNING.toString()))) {
+//                return;
+//            }
+//            List<Segment> waitingSegList = segmentService.getByAgvAndState(agv.getId(), SegmentStateType.WAITING.toString());
+//            if (!Cools.isEmpty(waitingSegList)) {
+//                for (Segment waitingSeg : waitingSegList) {
+//                    if (!waitingSeg.getId().equals(segment.getId())) {
+////                        log.error("AGV[{}] 浠诲姟寮傚父锛屾湇鍔″櫒閿欒锛侊紒锛�", agv.getUuid());
+//                        return;
+//                    }
+//                }
+//            }
+//
+//            // dead lane
+//            if (jamService.count(new LambdaQueryWrapper<Jam>()
+//                    .eq(Jam::getJamAgv, agv.getId())
+//                    .eq(Jam::getJamSeg, segment.getId())
+//                    .eq(Jam::getCycleAvo, 1)
+//                    .eq(Jam::getCycleCode, endNode)
+//                    .eq(Jam::getState, JamStateType.RUNNING.toString())
+//            ) > 0) {
+//                return;
+//            }
+//
+//            // execute -----------------------------------------------
+//            //        ArrayList<List<TaskPosDto>> list = JSON.parseObject(travel.getTaskContent(), new TypeReference<ArrayList<List<TaskPosDto>>>() {});
+//
+//            // * sync wave scope
+//            if (!avoidWaveCalculator.calcWaveScope()) {
+//                log.error("failed to calculate avoid wave matrix ...");
+//                return;
+//            }
+//
+//            // checkout path
+//            Code startCode = codeService.getCacheById(agvDetail.getRecentCode());
+//            Code endCode = codeService.getCacheById(endNode);
+//            long startTime = System.currentTimeMillis();
+//            List<String> pathList = this.checkoutPath(agv, startCode, endCode, segment);
+////            System.out.println("checkoutPath: " + (System.currentTimeMillis() - startTime));
+//            if (Cools.isEmpty(pathList)) {
+//                return;
+//            }
+//
+//            List<Segment> segmentList = new ArrayList<>();
+//            segmentList.add(segment);
+//
+//            String lastCodeData = pathList.get(pathList.size() - 1);
+//            if (!endCode.getData().equals(lastCodeData)) {
+//                // slice
+//                Code lastCode = codeService.getCacheByData(lastCodeData);
+//
+////                if (pathList.size() <= MIN_SLICE_PATH_LENGTH) {
+////                    return;
+////                }
+//
+//                // revert
+//                segment.setState(SegmentStateType.INIT.toString());
+//                segment.setUpdateTime(now);
+//                if (!segmentService.updateById(segment)) {
+//                    log.error("Segment [{}] failed to update 锛侊紒锛�", segment.getGroupId() + " - " + segment.getSerial());
+//                }
+//                segmentList.clear();
+//
+//                // new move seg
+//                Segment insertSeg = new Segment();
+//                insertSeg.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
+//                insertSeg.setTravelId(travel.getId());
+//                insertSeg.setAgvId(agv.getId());
+//                insertSeg.setTaskId(segment.getTaskId());
+//                insertSeg.setSerial(segment.getSerial() - 1);
+//                insertSeg.setEndNode(lastCode.getId());
+//                insertSeg.setPosType(TaskPosDto.PosType.MOVE.toString());
+//                insertSeg.setState(SegmentStateType.WAITING.toString());
+//                if (!segmentService.save(insertSeg)) {
+//                    log.error("Segment [{}] failed to save 锛侊紒锛�", segment.getTravelId() + " - " + segment.getSerial());
+//                }
+//                segmentList.add(insertSeg);
+//
+//            } else {
+//
+//                // complete first segment then merge behind segment
+//                int serial = segment.getSerial();
+//                boolean interrupt = false;
+//                while (!interrupt) {
+//
+//                    Segment nextStep = segmentService.getNextStepOfInit(travel.getId(), serial);
+//                    serial ++;
+//                    if (null == nextStep) {
+//                        interrupt = true;
+//                    } else {
+//                        if (nextStep.getEndNode() == endNode) {
+//
+//                            segmentList.add(nextStep);
+//                        } else {
+//                            interrupt = true;
+//                        }
+//                    }
+//
+//                }
+//            }
+//
+//            mapService.lockPath(null, pathList, agv.getUuid());
+//
+//            startTime = System.currentTimeMillis();
+//            mainService.generateAction(segment.getAgvId(), segmentList, pathList, now);
+////            System.out.println("generateAction: " + (System.currentTimeMillis() - startTime));
+//
+//        } catch (Exception e) {
+//            log.error("TrafficService.trigger", e);
+//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+//
+//        }
+//    }
+//
+//    private List<String> checkoutPath(Agv agv, Code startCode, Code endCode, Segment segment) {
+//        Integer lev = null;
+//        String agvNo = agv.getUuid();
+//        Date now = new Date();
+//        Jam jam = jamService.getJam(agv.getId(), startCode.getId(), segment.getId());
+//        BlockSeverityType blockSeverity = BlockSeverityType.query(null == jam ? null : jam.getDuration());
+//        // judge avoid of jam 濡傛灉宸茬粡鍦ㄩ伩璁╃偣锛堝洜涓哄綋鍓嶈溅鎵ц浜嗛伩璁╀换鍔★級锛岄偅涔堝垯涓嶈兘鍐嶅幓妫�绱箣鍓嶇殑闃诲璺緞
+//        List<Jam> unfinishedOriginJamByCurrAgv = jamService.getUnfinishedOriginJamByAvo(agv.getId(), startCode.getId(), segment.getId());
+//        List<String> blackPath = this.getBlackPathList(unfinishedOriginJamByCurrAgv);
+//
+//        // 缁撴灉闆�
+//        List<String> pathList = new ArrayList<>();
+//
+//        // 鏃犻殰纰嶈В
+//        List<String> unlockPathList = mapService.checkoutPath(agvNo, startCode, endCode, false, blackPath, segment);
+//        // 閬胯瑙�
+//        List<String> lockPathList = mapService.checkoutPath(agvNo, startCode, endCode, true, blackPath, segment);
+//
+//        if (!Cools.isEmpty(lockPathList) && // 瀛樺湪閬胯瑙�
+//            Math.abs(lockPathList.size() - unlockPathList.size()) <= Arrays.stream(mapDataDispatcher.getCodeMatrix(lev)).mapToInt(row -> row.length).sum() / 10
+//        ) {
+//
+//            pathList = lockPathList;
+//        } else {
+//
+//            // preview path
+//            List<String> draftPath = new ArrayList<>(unlockPathList);
+//            if (blockSeverity.equals(BlockSeverityType.SEVERE)) {
+//                unlockPathList.remove(endCode.getData());
+//                blackPath.addAll(unlockPathList);
+//                List<String> newUnlockPathList = mapService.checkoutPath(agvNo, startCode, endCode, false, blackPath, segment);
+//                if (!Cools.isEmpty(newUnlockPathList)) {
+//                    draftPath = newUnlockPathList;
+//                }
+//            }
+//            // 鍙蛋琛岃矾寰勯泦鍚堣绠�
+//            List<BlockVehicleDto> blockVehicleList = this.slicePathAndReturnBlockVehicleList(lev, draftPath, agvNo, pathList);    // jamAgvNo may was wave
+//
+//            if (!Cools.isEmpty(pathList)) {
+//
+//                if (!pathList.get(pathList.size() - 1).equals(endCode.getData())) {
+//                    assert !Cools.isEmpty(blockVehicleList);
+//
+//                    boolean hasUnavoidableBlocks = blockVehicleList.stream().anyMatch(blockVehicleDto -> !blockVehicleDto.isAvoidable());
+//                    if (hasUnavoidableBlocks && pathList.size() <= MapDataConstant.MIN_SLICE_PATH_LENGTH) {
+//                        log.info("AGV[{}] waiting in place, because the path list is too short...", agvNo);
+//                        pathList.clear();
+//                    }
+//
+//                    boolean hasCycleJam = blockVehicleList.stream().anyMatch(
+//                            blockVehicleDto -> null != jamService.getCycleJam(agv.getId(), segment.getId(), blockVehicleDto.getVehicle())
+//                    );
+//                    if (hasCycleJam) {
+//                        log.info("AGV[{}] waiting in place, because has cycle jam...", agvNo);
+//                        pathList.clear();
+//                    }
+//                }
+//
+//            // 鏃犲彲璧拌璺緞
+//            } else {
+//
+//                if (Cools.isEmpty(blockVehicleList)) {
+//                    log.warn("AGV[{}] can't reach to code: {}, because there is too many vehicle in the lane...", agvNo, endCode.getData());
+//                } else {
+//
+//                    assert !Cools.isEmpty(blockVehicleList);
+//                    Integer maxJamTimeoutFactor = null;
+//
+//                    // persist jam data
+//                    jam = this.createOrUpdateJam(agv, startCode, segment, jam, draftPath);
+//
+//                    // ? has unAvoidable block vehicles
+//                    if (blockVehicleList.stream().anyMatch(blockVehicleDto -> !blockVehicleDto.isAvoidable())) {
+//
+//                        // set factor of jam timeout
+//                        maxJamTimeoutFactor = 1;
+//                    } else {
+//
+//                        // ? already do notify to avoid
+//                        if (!Cools.isEmpty(jam.getAvoAgv())
+//                                && BlockVehicleDto.customContain(blockVehicleList, agvService.getById(jam.getAvoAgv()).getUuid())) {
+//
+//                            maxJamTimeoutFactor = 4;
+//
+//                        } else {
+//
+//                            // select optimal block vehicle
+//                            String blockAgvNo = this.checkoutBestSolutionOfBlocks(blockVehicleList, segment);
+//                            if (Cools.isEmpty(blockAgvNo)) {
+//
+//                                maxJamTimeoutFactor = 2;
+//
+//                            } else {
+//
+//                                // block vehicle info
+//                                Long blockAgvId = agvService.getAgvId(blockAgvNo);
+//                                String blockAgvCode = codeService.getCacheById(agvDetailService.selectMajorByAgvId(blockAgvId).getRecentCode()).getData();
+//
+//                                // create new jam if already notify the avoid vehicle
+//                                if (!Cools.isEmpty(jam.getAvoAgv(), jam.getAvoSeg()) && !blockAgvId.equals(jam.getAvoAgv())) {
+//                                    jam = this.setupNewJam(jam, agv, startCode, segment, draftPath);
+//                                }
+//
+//                                do {
+//
+//                                    // 闃诲杞﹁締姝e湪鍘熷湴浣滀笟锛岀瓑寰� ===>> 瓒呰繃绛夊緟鏃堕棿锛岀粫璺�
+//                                    List<Segment> runningSegList = segmentService.getByAgvAndState(blockAgvId, SegmentStateType.RUNNING.toString());
+//                                    if (!Cools.isEmpty(runningSegList)) {
+//                                        maxJamTimeoutFactor = 1;
+//                                        break;
+//                                    }
+//
+//                                    // 鍒ゆ柇涓嬩釜浠诲姟鏄惁涓哄師鍦颁换鍔★紝濡傛灉鏄垯绛夊緟 ===>> 瓒呰繃绛夊緟鏃堕棿锛岀粫璺紱濡傛灉涓嶆槸锛岃闃诲杞﹁締閬胯
+//                                    List<Segment> waitingSegList = segmentService.getJustWaitingSeg(blockAgvId);
+//                                    if (null != waitingSegList
+//                                            && waitingSegList.stream().anyMatch(
+//                                            waitingSeg -> waitingSeg.getEndNode().equals(codeService.getCacheByData(blockAgvCode).getId())
+//                                    )) {
+//                                        maxJamTimeoutFactor = 1;
+//                                        break;
+//                                    }
+//
+//                                    // notify block vehicle to avoid
+//                                    if (this.notifyVehicleAvoid(blockAgvNo, blockAgvCode, draftPath, agvNo, jam)) {
+//                                        if (jam.getCycleAvo() == 1) {
+//                                            jam.setCycleCode(endCode.getId());
+//                                        }
+//                                        jam.setAvoAgv(blockAgvId);
+//                                        jam.setNotifyTime(new Date());
+//                                        if (!jamService.updateById(jam)) {
+//                                            throw new CoolException(jam.getUuid() + "-jam failed to update锛侊紒锛�");
+//                                        }
+//                                    } else {
+//
+//                                        maxJamTimeoutFactor = 1;
+//                                    }
+//
+//                                } while (false);
+//                            }
+//
+//                        }
+//
+//                    }
+//
+//                    // handle jam timeout
+//                    if (null != maxJamTimeoutFactor) {
+//                        if (System.currentTimeMillis() - jam.getStartTime().getTime() > (long) MapDataConstant.MAX_JAM_TIMEOUT * maxJamTimeoutFactor) {
+//
+//                            if (!Cools.isEmpty(lockPathList)) {
+//
+//                                pathList = lockPathList;
+//                            } else {
+//                                log.error("{}鍙疯溅杈嗘绱{}] ===>> [{}]璺緞澶辫触锛屽師鍥狅細{}"
+//                                        , agvNo, startCode.getData(), endCode.getData(), "璺緞闃诲瓒呮椂");
+//                            }
+//                        } else {
+//                            log.warn("{}鍙疯溅杈嗘鍦ㄧ瓑寰呬氦閫氬牭濉烇紝闃诲杞﹁締锛氥�恵}銆�"
+//                                    , agvNo
+//                                    , blockVehicleList.stream().map(BlockVehicleDto::getVehicle).collect(Collectors.toList()).toString()
+//                            );
+//                        }
+//                    }
+//
+//                }
+//
+//            }
+//        }
+//
+//        if (!Cools.isEmpty(pathList)) {
+//
+//            if (null != jam) {
+//                boolean beDeprecate = false;
+//                if (blockSeverity.equals(BlockSeverityType.SEVERE) && !Cools.isEmpty(jam.getJamPath())) {
+//                    List<String> jamPath = GsonUtils.fromJsonToList(jam.getJamPath(), String.class);
+//                    if (!this.comparePathLists(jamPath, pathList)) {    // jamPath >= pathList
+//                        beDeprecate = true;
+//                    }
+//                }
+//                jam.setEndTime(now);
+//                jam.setUpdateTime(now);
+//                jam.setState(beDeprecate ? JamStateType.DEPRECATED.toString() : JamStateType.FINISH.toString());
+//                if (jamService.updateById(jam)) {
+//                    if (beDeprecate) {
+//                        // search previous jam that jamSeg from this segment
+//                        List<Jam> previousJams = jamService.list(new LambdaQueryWrapper<Jam>()
+//                                .eq(Jam::getJamSeg, segment.getId())
+//                                .eq(Jam::getState, JamStateType.FINISH.toString())
+//                        );
+//                        for (Jam previousJam : previousJams) {
+//                            previousJam.setState(JamStateType.DEPRECATED.toString());
+//                            previousJam.setUpdateTime(now);
+//                            if (!jamService.updateById(previousJam)) {
+//                                log.error("Jam[{}] failed to update锛侊紒锛�", previousJam.getUuid());
+//                            }
+//                        }
+//                    }
+//                } else {
+//                    log.error("Jam[{}] failed to update锛侊紒锛�", jam.getUuid());
+//                }
+//            }
+//            // deal expired jam
+//            for (Jam expiredJam : jamService.list(new LambdaQueryWrapper<Jam>()
+//                    .eq(Jam::getJamAgv, agv.getId())
+//                    .eq(Jam::getState, JamStateType.RUNNING.toString()))) {
+//                expiredJam.setEndTime(now);
+//                expiredJam.setUpdateTime(now);
+//                expiredJam.setState(JamStateType.DEPRECATED.toString());
+//                if (!jamService.updateById(expiredJam)) {
+//                    log.error("Jam[{}] failed to update锛侊紒锛�", expiredJam.getUuid());
+//                }
+//            }
+//
+//        }
+//
+//        return pathList;
+//    }
+//
+//    private List<BlockVehicleDto> slicePathAndReturnBlockVehicleList(Integer lev, List<String> fullPathList, String agvNo, List<String> pathList) {
+//        List<BlockVehicleDto> blockVehicleList = new ArrayList<>();
+//
+//        String[][] waveMatrix = mapDataDispatcher.getWaveMatrix(lev);
+//        List<int[]> codeMatrixIdxList = mapDataDispatcher.getCodeMatrixIdxList(lev, fullPathList);
+//        for (int i = 0; i < fullPathList.size(); i++) {
+//            String codeData = fullPathList.get(i);
+//            int[] codeMatrixIdx = codeMatrixIdxList.get(i);
+//
+//            String waveNode = waveMatrix[codeMatrixIdx[0]][codeMatrixIdx[1]];
+//            assert !waveNode.equals(WaveNodeType.DISABLE.val);
+//            if (!waveNode.equals(WaveNodeType.ENABLE.val)) {
+//                List<String> waveNodeList = MapDataUtils.parseWaveNode(waveNode);
+//                List<String> otherWaveList = MapDataUtils.hasOtherWave(waveNodeList, agvNo);
+//                if (!Cools.isEmpty(otherWaveList)) {
+//                    for (String otherWave : otherWaveList) {
+//                        if (mapService.isWalkingByVehicle(lev, otherWave)) {
+//                            blockVehicleList.add(new BlockVehicleDto(otherWave, false));
+//                        } else {
+//                            blockVehicleList.add(new BlockVehicleDto(otherWave, true));
+//                        }
+//                    }
+//                    break;
+//                }
+//            }
+//
+//            pathList.add(codeData);
+//        }
+//
+//        if (pathList.size() <= 1) {
+//            pathList.clear();
+//        }
+//
+//        return blockVehicleList.stream().distinct().collect(Collectors.toList());
+//    }
+//
+//    /**
+//     * avoidPathList include wave node and dynamic node
+//     */
+//    private boolean notifyVehicleAvoid(String agvNo, String agvPosCode, List<String> avoidPathList, String sponsor, Jam jam) {
+//        Long agvId = agvService.getAgvId(agvNo);
+//        if (!Cools.isEmpty(segmentService.getByAgvAndState(agvId, SegmentStateType.RUNNING.toString()))) {
+//            log.warn("{}鍙疯溅杈嗛伩璁╁け璐ワ紝瀛樺湪杩涜涓换鍔★紒锛侊紒", agvNo);
+//            return false;
+//        }
+//
+//        int[] startMapIdx = mapDataDispatcher.getCodeMatrixIdx(null, agvPosCode);
+//        RetreatNavigateNode startNode = new RetreatNavigateNode(startMapIdx[0], startMapIdx[1], agvPosCode);
+//
+//        assert avoidPathList.size() >= 2;
+//        RetreatNavigateNode finalNode = retreatNavigateService.execute(agvNo, startNode, avoidPathList, sponsor, jam);
+//        if (null == finalNode) {
+//            log.warn("{}鍙疯溅杈嗛伩璁╁け璐ワ紝妫�绱㈤伩璁╃偣澶辫触锛侊紒锛�", agvNo);
+//            return false;
+//        }
+//
+//        String endCodeData = finalNode.getCodeData();
+//        Code endCode = codeService.getCacheByData(endCodeData);
+//
+//        List<Segment> waitingSegList = segmentService.getByAgvAndState(agvId, SegmentStateType.WAITING.toString());
+//        if (!Cools.isEmpty(waitingSegList)) {
+//
+//            if (waitingSegList.size() > 1) {
+//                log.error("閬胯閫氱煡澶辫触锛寋}鍙疯溅杈嗗瓨鍦ㄥ涓瓑寰呬腑鐨凷egment锛侊紒锛�", agvNo);
+//                return false;
+//            }
+//            // revert
+//            Date now = new Date();
+//            for (Segment seg : waitingSegList) {
+//                seg.setState(SegmentStateType.INIT.toString());
+//                seg.setUpdateTime(now);
+//                if (!segmentService.updateById(seg)) {
+//                    log.error("Segment [{}] 鏇存柊澶辫触 锛侊紒锛�", seg.getTravelId() + " - " + seg.getSerial());
+//                }
+//            }
+//            Segment segment = waitingSegList.get(0);
+//
+//            Segment insertSeg = new Segment();
+//            insertSeg.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
+//            insertSeg.setTravelId(segment.getTravelId());
+//            insertSeg.setAgvId(agvId);
+//            insertSeg.setTaskId(segment.getTaskId());
+//            insertSeg.setSerial(segment.getSerial() - 1);
+//            insertSeg.setEndNode(endCode.getId());
+//            insertSeg.setPosType(TaskPosDto.PosType.MOVE.toString());
+//            insertSeg.setState(SegmentStateType.WAITING.toString());
+//            if (!segmentService.save(insertSeg)) {
+//                log.error("Segment [{}] 淇濆瓨澶辫触 锛侊紒锛�", segment.getTravelId() + " - " + segment.getSerial());
+//                return false;
+//            } else {
+//                jam.setAvoSeg(insertSeg.getId());
+//                jam.setAvoCode(endCode.getId());
+//            }
+//
+//        } else {
+//
+//            return mainLockWrapService.buildMinorTask(agvId, TaskTypeType.MOVE, endCodeData, jam);
+//        }
+//
+//        return true;
+//    }
+//
+//    private Jam createOrUpdateJam(Agv agv, Code startCode, Segment segment, Jam jam, List<String> jamPath) {
+//        if (jam == null) {
+//            jam = new Jam();
+//            jam.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
+//            jam.setJamAgv(agv.getId());
+//            jam.setJamCode(startCode.getId());
+//            jam.setJamSeg(segment.getId());
+//            jam.setJamPath(GsonUtils.toJson(jamPath));
+//            jam.setStartTime(new Date());
+//            jam.setState(JamStateType.RUNNING.toString());
+//            if (!jamService.save(jam)) {
+//                log.error("AGV[{}] failed to save jam", agv.getUuid());
+//                throw new CoolException("failed to save jam");
+//            }
+//        } else {
+//            jam.setDuration(System.currentTimeMillis() - jam.getStartTime().getTime());
+//            if (!jamService.updateById(jam)) {
+//                log.error("AGV[{}] failed to update jam", agv.getUuid());
+//            }
+//        }
+//        return jam;
+//    }
+//
+//    private Jam setupNewJam(Jam originJam, Agv agv, Code startCode, Segment segment, List<String> draftPath) {
+//        originJam.setUpdateTime(new Date());
+//        originJam.setState(JamStateType.FINISH.toString());
+//        if (!jamService.updateById(originJam)) {
+//            log.error("Jam[{}] failed to update", originJam.getUuid());
+//            return originJam;
+//        } else {
+//            return this.createOrUpdateJam(
+//                    agv
+//                    , startCode
+//                    , segment
+//                    , null
+//                    , draftPath
+//            );
+//        }
+//    }
+//
+//    private List<String> getBlackPathList(List<Jam> unfinishedOriginJamByCurrAgv) {
+//        List<String> blackPathList = new ArrayList<>();
+//        Integer lev = MapDataDispatcher.MAP_DEFAULT_LEV;
+//        if (!Cools.isEmpty(unfinishedOriginJamByCurrAgv)) {
+//            for (Jam jam : unfinishedOriginJamByCurrAgv) {
+//                if (!Cools.isEmpty(jam.getJamPath())) {
+//
+//                    List<String> list = GsonUtils.fromJsonToList(jam.getJamPath(), String.class);
+//
+//                    Agv jamAgv = agvService.getById(jam.getJamAgv());
+//                    List<String> jamDynamicNodes = mapService.queryCodeListFromDynamicNode(lev, jamAgv.getUuid());
+//                    // jamDynamicNodes has sorted
+//                    String firstCodeNode = jamDynamicNodes.stream().findFirst().orElse(null);
+//
+//                    if (!Cools.isEmpty(firstCodeNode)) {
+//                        int idx = list.indexOf(firstCodeNode);
+//                        if (idx != -1) {
+//                            list = new ArrayList<>(list.subList(idx, list.size()));
+//
+//                            // the wave of first node
+//                            Double avoidDistance = MapDataUtils.getVehicleWaveSafeDistance(
+//                                    agvModelService.getById(jamAgv.getAgvModel()).getDiameter(),
+//                                    MapDataConstant.MAX_DISTANCE_BETWEEN_ADJACENT_AGV_FACTOR
+//                            );
+//                            List<String> waveCodeList = mapService.getWaveScopeByCode(lev, firstCodeNode, avoidDistance)
+//                                    .stream().map(NavigateNode::getCodeData).distinct().collect(Collectors.toList());
+//                            list.addAll(waveCodeList);
+//                        } else {
+//                            // 濡傛灉琚樆濉炶溅杈嗗凡缁忎笉鍦ㄥ師鏉ョ殑闃诲璺緞涓紝鑰冭檻閬胯杞﹁蛋琛屾椂涓嶉渶瑕佹妸涔嬪墠鐨勯樆濉炶矾寰勫姞鍏ラ粦鍚嶅崟
+//                            list = new ArrayList<>();
+//                        }
+//                    }
+//
+//                    blackPathList.addAll(list);
+//                }
+//            }
+//        }
+//        return blackPathList.stream().distinct().collect(Collectors.toList());
+//    }
+//
+//    private String checkoutBestSolutionOfBlocks(List<BlockVehicleDto> blockVehicleList, Segment segment) {
+//        assert !Cools.isEmpty(blockVehicleList);
+//        for (BlockVehicleDto blockVehicleDto : blockVehicleList) {
+//            if (!blockVehicleDto.isAvoidable()) {
+//                continue;
+//            }
+//            // 褰撳墠vehicle姝e湪杩涜閬胯浣滀笟
+//            if (!Cools.isEmpty(jamService.getUnfinishedAvoSegByAvo(blockVehicleDto.getVehicle(), null))) {
+//                continue;
+//            }
+//            return blockVehicleDto.getVehicle();
+//        }
+//        return null;
+//    }
+//
+//    public boolean comparePathLists(List<String> list1, List<String> list2) {
+//        if (list1.equals(list2)) {
+//            return true;
+//        }
+//        if (list1.containsAll(list2)) {
+//            return true;
+//        }
+//        return false;
+//    }
+//
+//    /**
+//     * 1. the jam was deprecated
+//     * 2. the jam segment is finished
+//     *
+//     * all these by avoid segment
+//     */
+//    private boolean isExpiredJamByAvo(Long avoSeg) {
+//        List<Jam> jamList = jamService.list(new LambdaQueryWrapper<Jam>()
+////                .eq(Jam::getAvoAgv, avoAgv)
+//                .eq(Jam::getAvoSeg, avoSeg));
+//        if (Cools.isEmpty(jamList)) {
+//            return false;
+//        }
+//        if (jamList.size() > 1) {
+//            log.error("AvoSeg[id = {}] seg data has exception, result in two jams", avoSeg);
+//        }
+//        Jam jam = jamList.get(0);
+//        if (jam.getState().equals(JamStateType.DEPRECATED.toString())) {
+//            return true;
+//        }
+//        Segment jamSegment = segmentService.getById(jam.getJamSeg());
+//        if (jamSegment.getState().equals(SegmentStateType.FINISH.toString())) {
+//            return true;
+//        }
+//        return false;
+//    }
+//
+//}

--
Gitblit v1.9.1