|  |  | 
 |  |  |  | 
 |  |  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
 |  |  | import com.zy.acs.common.utils.GsonUtils; | 
 |  |  | import com.zy.acs.common.utils.RedisSupport; | 
 |  |  | 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.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; | 
 |  |  | 
 |  |  | @Slf4j | 
 |  |  | @Component | 
 |  |  | public class TrafficService { | 
 |  |  |  | 
 |  |  |     public static final Integer MIN_SLICE_PATH_LENGTH = 3; | 
 |  |  |  | 
 |  |  |     public static final Integer MAX_JAM_TIMEOUT = 5 * 1000; | 
 |  |  |  | 
 |  |  |     private final RedisSupport redis = RedisSupport.defaultRedisSupport; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private AgvService agvService; | 
 |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private SnowflakeIdWorker snowflakeIdWorker; | 
 |  |  |     @Autowired | 
 |  |  |     private ActionService actionService; | 
 |  |  |     private AgvModelService agvModelService; | 
 |  |  |     @Autowired | 
 |  |  |     private RetreatNavigateService retreatNavigateService; | 
 |  |  |     @Autowired | 
 |  |  |     private TaskService taskService; | 
 |  |  |     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; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             // 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()); | 
 |  |  | 
 |  |  |             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,there hadn't any idle funSta,TaskTypeType:{}", 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; | 
 |  |  |             } | 
 |  |  | 
 |  |  |             // execute ----------------------------------------------- | 
 |  |  |             //        ArrayList<List<TaskPosDto>> list = JSON.parseObject(travel.getTaskContent(), new TypeReference<ArrayList<List<TaskPosDto>>>() {}); | 
 |  |  |  | 
 |  |  |             // get path list | 
 |  |  |             avoidWaveCalculator.calcWaveScope();    // * sync wave scope | 
 |  |  |             // * sync wave scope | 
 |  |  |             if (!avoidWaveCalculator.calcWaveScope()) { | 
 |  |  |                 log.error("failed to calculate avoid wave matrix ..."); | 
 |  |  |                 return; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             // checkout path | 
 |  |  |             Code startCode = codeService.getById(agvDetail.getRecentCode()); | 
 |  |  |             Code endCode = codeService.getById(endNode); | 
 |  |  |             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; | 
 |  |  |             } | 
 |  |  | 
 |  |  |             String lastCodeData = pathList.get(pathList.size() - 1); | 
 |  |  |             if (!endCode.getData().equals(lastCodeData)) { | 
 |  |  |                 // slice | 
 |  |  |                 Code lastCode = codeService.selectByData(lastCodeData); | 
 |  |  |                 Code lastCode = codeService.getCacheByData(lastCodeData); | 
 |  |  |  | 
 |  |  | //                if (pathList.size() <= MIN_SLICE_PATH_LENGTH) { | 
 |  |  | //                    return; | 
 |  |  | 
 |  |  |             } 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; | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |  | 
 |  |  |                 } | 
 |  |  | //                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); | 
 |  |  |             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); | 
 |  |  | 
 |  |  |         String agvNo = agv.getUuid(); | 
 |  |  |         Date now = new Date(); | 
 |  |  |         Jam jam = jamService.getJam(agv.getId(), startCode.getId(), segment.getId()); | 
 |  |  |         // judge avoid of jam | 
 |  |  |         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); | 
 |  |  |  | 
 |  |  | 
 |  |  |             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, unlockPathList, agvNo, pathList);    // jamAgvNo may was wave | 
 |  |  |             List<BlockVehicleDto> blockVehicleList = this.slicePathAndReturnBlockVehicleList(lev, draftPath, agvNo, pathList);    // jamAgvNo may was wave | 
 |  |  |  | 
 |  |  |             if (!Cools.isEmpty(pathList)) { | 
 |  |  |  | 
 |  |  | 
 |  |  |                     assert !Cools.isEmpty(blockVehicleList); | 
 |  |  |  | 
 |  |  |                     boolean hasUnavoidableBlocks = blockVehicleList.stream().anyMatch(blockVehicleDto -> !blockVehicleDto.isAvoidable()); | 
 |  |  |                     if (hasUnavoidableBlocks && pathList.size() <= MIN_SLICE_PATH_LENGTH) { | 
 |  |  |                     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(); | 
 |  |  |                     } | 
 |  |  | 
 |  |  |                     Integer maxJamTimeoutFactor = null; | 
 |  |  |  | 
 |  |  |                     // persist jam data | 
 |  |  |                     ArrayList<String> jamPath = new ArrayList<>(unlockPathList); | 
 |  |  |                     jam = this.createOrUpdateJam(agv, startCode, segment, jam, jamPath); | 
 |  |  |                     jam = this.createOrUpdateJam(agv, startCode, segment, jam, draftPath); | 
 |  |  |  | 
 |  |  |                     // ? has unAvoidable block vehicles | 
 |  |  |                     if (blockVehicleList.stream().anyMatch(blockVehicleDto -> !blockVehicleDto.isAvoidable())) { | 
 |  |  | 
 |  |  |                         if (!Cools.isEmpty(jam.getAvoAgv()) | 
 |  |  |                                 && BlockVehicleDto.customContain(blockVehicleList, agvService.getById(jam.getAvoAgv()).getUuid())) { | 
 |  |  |  | 
 |  |  |                             maxJamTimeoutFactor = 10; | 
 |  |  |                             maxJamTimeoutFactor = 4; | 
 |  |  |  | 
 |  |  |                         } else { | 
 |  |  |  | 
 |  |  |                             // select optimal block vehicle | 
 |  |  | //                            String blockAgvNo = blockVehicleList.stream() | 
 |  |  | //                                    .filter(BlockVehicleDto::isAvoidable) | 
 |  |  | //                                    .map(BlockVehicleDto::getVehicle) | 
 |  |  | //                                    .findFirst().orElse(null); | 
 |  |  |                             String blockAgvNo = this.checkoutBestSolutionOfBlocks(blockVehicleList); | 
 |  |  |                             String blockAgvNo = this.checkoutBestSolutionOfBlocks(blockVehicleList, segment); | 
 |  |  |                             if (Cools.isEmpty(blockAgvNo)) { | 
 |  |  |  | 
 |  |  |                             // block vehicle info | 
 |  |  |                             Agv blockAgv = agvService.selectByUuid(blockAgvNo); | 
 |  |  |                             String blockAgvCode = codeService.getById(agvDetailService.selectByAgvId(blockAgv.getId()).getRecentCode()).getData(); | 
 |  |  |                                 maxJamTimeoutFactor = 2; | 
 |  |  |  | 
 |  |  |                             do { | 
 |  |  |                             } else { | 
 |  |  |  | 
 |  |  |                                 // 阻塞车辆正在原地作业,等待 ===>> 超过等待时间,绕路 | 
 |  |  |                                 List<Segment> runningSegList = segmentService.getByAgvAndState(blockAgv.getId(), SegmentStateType.RUNNING.toString()); | 
 |  |  |                                 if (!Cools.isEmpty(runningSegList)) { | 
 |  |  |                                     maxJamTimeoutFactor = 1; | 
 |  |  |                                     break; | 
 |  |  |                                 // 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); | 
 |  |  |                                 } | 
 |  |  |  | 
 |  |  |                                 // 判断下个任务是否为原地任务,如果是则等待 ===>> 超过等待时间,绕路;如果不是,让阻塞车辆避让 | 
 |  |  |                                 List<Segment> waitingSegList = segmentService.getJustWaitingSeg(blockAgv.getId()); | 
 |  |  |                                 if (null != waitingSegList | 
 |  |  |                                         && waitingSegList.stream().anyMatch( | 
 |  |  |                                                 waitingSeg -> waitingSeg.getEndNode().equals(codeService.selectByData(blockAgvCode).getId()) | 
 |  |  |                                 )) { | 
 |  |  |                                     maxJamTimeoutFactor = 1; | 
 |  |  |                                     break; | 
 |  |  |                                 } | 
 |  |  |                                 do { | 
 |  |  |  | 
 |  |  |                                 // notify block vehicle to avoid | 
 |  |  |                                 if (this.notifyVehicleAvoid(blockAgvNo, blockAgvCode, jamPath, agvNo, jam)) { | 
 |  |  |                                     if (jam.getCycleAvo() == 1) { | 
 |  |  |                                         jam.setCycleCode(endCode.getId()); | 
 |  |  |                                     // 阻塞车辆正在原地作业,等待 ===>> 超过等待时间,绕路 | 
 |  |  |                                     List<Segment> runningSegList = segmentService.getByAgvAndState(blockAgvId, SegmentStateType.RUNNING.toString()); | 
 |  |  |                                     if (!Cools.isEmpty(runningSegList)) { | 
 |  |  |                                         maxJamTimeoutFactor = 1; | 
 |  |  |                                         break; | 
 |  |  |                                     } | 
 |  |  |                                     jam.setAvoAgv(blockAgv.getId()); | 
 |  |  |                                     jam.setNotifyTime(new Date()); | 
 |  |  |                                     if (!jamService.updateById(jam)) { | 
 |  |  |                                         throw new CoolException(jam.getUuid() + "-jam failed to update!!!"); | 
 |  |  |  | 
 |  |  |                                     // 判断下个任务是否为原地任务,如果是则等待 ===>> 超过等待时间,绕路;如果不是,让阻塞车辆避让 | 
 |  |  |                                     List<Segment> waitingSegList = segmentService.getJustWaitingSeg(blockAgvId); | 
 |  |  |                                     if (null != waitingSegList | 
 |  |  |                                             && waitingSegList.stream().anyMatch( | 
 |  |  |                                             waitingSeg -> waitingSeg.getEndNode().equals(codeService.getCacheByData(blockAgvCode).getId()) | 
 |  |  |                                     )) { | 
 |  |  |                                         maxJamTimeoutFactor = 1; | 
 |  |  |                                         break; | 
 |  |  |                                     } | 
 |  |  |                                 } else { | 
 |  |  |  | 
 |  |  |                                     maxJamTimeoutFactor = 1; | 
 |  |  |                                 } | 
 |  |  |                                     // 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 { | 
 |  |  |  | 
 |  |  |                             } while (false); | 
 |  |  |                                         maxJamTimeoutFactor = 1; | 
 |  |  |                                     } | 
 |  |  |  | 
 |  |  |                                 } while (false); | 
 |  |  |                             } | 
 |  |  |  | 
 |  |  |                         } | 
 |  |  |  | 
 |  |  |                     } | 
 |  |  |  | 
 |  |  |                     // handle jam timeout | 
 |  |  |                     if (null != maxJamTimeoutFactor) { | 
 |  |  |                         if (System.currentTimeMillis() - jam.getStartTime().getTime() > MAX_JAM_TIMEOUT * maxJamTimeoutFactor) { | 
 |  |  |                         if (System.currentTimeMillis() - jam.getStartTime().getTime() > (long) MapDataConstant.MAX_JAM_TIMEOUT * maxJamTimeoutFactor) { | 
 |  |  |  | 
 |  |  |                             if (!Cools.isEmpty(lockPathList)) { | 
 |  |  |  | 
 |  |  | 
 |  |  |         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(JamStateType.FINISH.toString()); | 
 |  |  |                 if (!jamService.updateById(jam)) { | 
 |  |  |                 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()); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  | 
 |  |  |                     .eq(Jam::getState, JamStateType.RUNNING.toString()))) { | 
 |  |  |                 expiredJam.setEndTime(now); | 
 |  |  |                 expiredJam.setUpdateTime(now); | 
 |  |  |                 expiredJam.setState(JamStateType.FINISH.toString()); | 
 |  |  |                 expiredJam.setState(JamStateType.DEPRECATED.toString()); | 
 |  |  |                 if (!jamService.updateById(expiredJam)) { | 
 |  |  |                     log.error("Jam[{}] failed to update!!!", expiredJam.getUuid()); | 
 |  |  |                 } | 
 |  |  | 
 |  |  |     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); | 
 |  |  |         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[node[0]][node[1]]; | 
 |  |  |             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 (1 < mapDataDispatcher.queryCodeListFromDynamicNode(lev, otherWave).size()) { | 
 |  |  |                         if (mapService.isWalkingByVehicle(lev, otherWave)) { | 
 |  |  |                             blockVehicleList.add(new BlockVehicleDto(otherWave, false)); | 
 |  |  |                         } else { | 
 |  |  |                             blockVehicleList.add(new BlockVehicleDto(otherWave, true)); | 
 |  |  | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |  | 
 |  |  | //            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; | 
 |  |  | //            } | 
 |  |  |  | 
 |  |  |             pathList.add(code); | 
 |  |  |             pathList.add(codeData); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         if (pathList.size() <= 1) { | 
 |  |  | 
 |  |  |      * 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()))) { | 
 |  |  |         Long agvId = agvService.getAgvId(agvNo); | 
 |  |  |         if (!Cools.isEmpty(segmentService.getByAgvAndState(agvId, SegmentStateType.RUNNING.toString()))) { | 
 |  |  |             log.warn("{}号车辆避让失败,存在进行中任务!!!", agvNo); | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         String endCodeData = finalNode.getCodeData(); | 
 |  |  |         Code endCode = codeService.selectByData(endCodeData); | 
 |  |  |         jam.setAvoCode(endCode.getId()); | 
 |  |  |         Code endCode = codeService.getCacheByData(endCodeData); | 
 |  |  |  | 
 |  |  |         List<Segment> waitingSegList = segmentService.getByAgvAndState(agv.getId(), SegmentStateType.WAITING.toString()); | 
 |  |  |         List<Segment> waitingSegList = segmentService.getByAgvAndState(agvId, SegmentStateType.WAITING.toString()); | 
 |  |  |         if (!Cools.isEmpty(waitingSegList)) { | 
 |  |  |  | 
 |  |  |             if (waitingSegList.size() > 1) { | 
 |  |  | 
 |  |  |             Segment insertSeg = new Segment(); | 
 |  |  |             insertSeg.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3)); | 
 |  |  |             insertSeg.setTravelId(segment.getTravelId()); | 
 |  |  |             insertSeg.setAgvId(agv.getId()); | 
 |  |  |             insertSeg.setAgvId(agvId); | 
 |  |  |             insertSeg.setTaskId(segment.getTaskId()); | 
 |  |  |             insertSeg.setSerial(segment.getSerial() - 1); | 
 |  |  |             insertSeg.setEndNode(endCode.getId()); | 
 |  |  | 
 |  |  |                 return false; | 
 |  |  |             } else { | 
 |  |  |                 jam.setAvoSeg(insertSeg.getId()); | 
 |  |  |                 jam.setAvoCode(endCode.getId()); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |         } else { | 
 |  |  |  | 
 |  |  |             return mainLockWrapService.buildMinorTask(agv, TaskTypeType.MOVE, endCodeData, jam); | 
 |  |  |             return mainLockWrapService.buildMinorTask(agvId, TaskTypeType.MOVE, endCodeData, jam); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         return true; | 
 |  |  | 
 |  |  |         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) { | 
 |  |  |     private String checkoutBestSolutionOfBlocks(List<BlockVehicleDto> blockVehicleList, Segment segment) { | 
 |  |  |         assert !Cools.isEmpty(blockVehicleList); | 
 |  |  |         for (BlockVehicleDto blockVehicleDto : blockVehicleList) { | 
 |  |  |             if (!blockVehicleDto.isAvoidable()) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |             // 没有避让中的任务 | 
 |  |  |             if (Cools.isEmpty(jamService.getUnfinishedAvoSegByAvo(blockVehicleDto.getVehicle(), null))) { | 
 |  |  |                 return blockVehicleDto.getVehicle(); | 
 |  |  |             // 当前vehicle正在进行避让作业 | 
 |  |  |             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; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | } |