From db031bf3b7ce28f8e2c912c1556a50c74b47143d Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期三, 31 十二月 2025 16:40:37 +0800
Subject: [PATCH] #

---
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java |   92 +++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 87 insertions(+), 5 deletions(-)

diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java
index ad7a709..bfbc67f 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java
@@ -276,6 +276,9 @@
                             int backpackLev = 0;
                             int backpack = agvService.getBackpack(agvId);
                             List<Integer> usedBackpacks = segmentService.selectUsedBackpacks(currSeg.getTravelId(), agvId);
+                            if (usedBackpacks.size() == backpackLev) {
+                                throw new CoolException("[Agv:" + agvNo + "] allocate inbound segment failed: no idle backpack to use");
+                            }
                             for (int lev = 1; lev <= backpack; lev++) {
                                 if (!usedBackpacks.contains(lev)) {
                                     backpackLev = lev;
@@ -313,29 +316,108 @@
                             // place segment
                             TaskTypeType taskType = Objects.requireNonNull(TaskTypeType.get(task.getTaskTypeEl()));
                             TaskPosDto.PosType posType;
-                            Long endCodeId;
+                            Code endCode;
                             switch (taskType) {
                                 case STA_TO_LOC:
                                     posType = TaskPosDto.PosType.DEST_LOC;
                                     Loc destLoc = locService.getById(task.getDestLoc());
-                                    endCodeId = destLoc.getCode();
+                                    endCode = codeService.getCacheById(destLoc.getCode());
                                     break;
                                 case STA_TO_STA:
                                     posType = TaskPosDto.PosType.DEST_STA;
                                     Sta destSta = staService.getById(task.getDestSta());
-                                    endCodeId = destSta.getCode();
+                                    endCode = codeService.getCacheById(destSta.getCode());
                                     break;
                                 default:
                                     throw new BusinessException("[Agv:" + agvNo + "] allocate inbound only supports STA_TO_LOC/STA_TO_STA");
                             }
 
+                            // calc placeSeg serial, through code position
+                            List<Segment> destSegList = segmentService.list(new LambdaQueryWrapper<Segment>()
+                                    .eq(Segment::getAgvId, agvId)
+                                    .eq(Segment::getTravelId, currSeg.getTravelId())
+                                    .ne(Segment::getState, SegmentStateType.FINISH.toString())
+                                    .in(Segment::getPosType,
+                                            TaskPosDto.PosType.DEST_LOC.toString(),
+                                            TaskPosDto.PosType.DEST_STA.toString())
+                                    .orderByAsc(Segment::getSerial)
+                            );
+
+                            // build destPosList and sort
+                            List<TaskPosDto> destPosList = new ArrayList<>();
+                            for (Segment destSeg : destSegList) {
+                                Code code = codeService.getCacheById(destSeg.getEndNode());
+                                if (code == null) continue;
+
+                                TaskPosDto dto = new TaskPosDto(destSeg.getTaskId(), new Double[]{code.getX(), code.getY()}, TaskPosDto.PosType.DEST_LOC);
+                                dto.setCodeId(code.getId());
+                                dto.setSegId(destSeg.getId());
+                                destPosList.add(dto);
+                            }
+                            TaskPosDto newDto = new TaskPosDto(task.getId(), new Double[]{endCode.getX(), endCode.getY()}, TaskPosDto.PosType.DEST_LOC);
+                            newDto.setCodeId(endCode.getId());
+                            destPosList.add(newDto);
+
+                            destPosList.sort((a, b) -> {
+                                int c1 = Double.compare(a.getXy()[0], b.getXy()[0]); // X
+                                if (c1 != 0) return c1;
+                                int c2 = Double.compare(a.getXy()[1], b.getXy()[1]); // Y
+                                if (c2 != 0) return c2;
+                                // 鍚屽潗鏍囨椂鐢� taskId 鎵撴暎锛堥伩鍏嶆帓搴忎笉绋冲畾锛�
+                                return Long.compare(a.getTaskId(), b.getTaskId());
+                            });
+
+                            // get placeSeg serial
+                            int placeSegSerial = 9999;
+                            // query placeSeg idx
+                            int idx = -1;
+                            for (int i = 0; i < destPosList.size(); i++) {
+                                if (Objects.equals(destPosList.get(i).getCodeId(), newDto.getCodeId())
+                                        && Objects.equals(destPosList.get(i).getTaskId(), newDto.getTaskId())) {
+                                    idx = i;
+                                    break;
+                                }
+                            }
+                            if (idx < 0) {
+                                throw new BusinessException("failed to locate new destination in sorted list");
+                            }
+
+                            // 鍚庣户鐐�
+                            TaskPosDto afterTaskPos = ((idx + 1) < destPosList.size()) ? destPosList.get(idx + 1) : null;
+                            if (null == afterTaskPos) {
+                                // loadSeg is the last one
+                                placeSegSerial = destSegList.get(destSegList.size() - 1).getSerial() + 1;
+                            } else {
+                                Segment afterSeg = destSegList.stream()
+                                        .filter(destSeg -> Objects.equals(destSeg.getId(), afterTaskPos.getSegId()))
+                                        .findFirst()
+                                        .orElse(null);
+                                if (null == afterSeg) {
+                                    placeSegSerial = destSegList.get(destSegList.size() - 1).getSerial() + 1;
+                                } else {
+                                    placeSegSerial = afterSeg.getSerial();
+                                }
+                            }
+//                            placeSegSerial = Math.max(placeSegSerial, currSeg.getSerial() + 1);
+
+                            // shift serial after
+                            segmentService.update(new LambdaUpdateWrapper<Segment>()
+                                    .eq(Segment::getAgvId, agvId)
+                                    .eq(Segment::getTravelId, currSeg.getTravelId())
+                                    .ge(Segment::getSerial, placeSegSerial)
+                                    .ne(Segment::getState, SegmentStateType.FINISH.toString())
+                                    .setSql("serial = serial + 1")
+                                    .set(Segment::getUpdateTime, now)
+                            );
+
+                            // save place segment
                             Segment placeSeg = new Segment();
                             placeSeg.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
                             placeSeg.setTravelId(currSeg.getTravelId());
                             placeSeg.setAgvId(agvId);
                             placeSeg.setTaskId(task.getId());
-                            placeSeg.setSerial();
-                            placeSeg.setEndNode(endCodeId);
+                            placeSeg.setSerial(placeSegSerial);
+                            placeSeg.setEndNode(endCode.getId());
                             placeSeg.setPosType(posType.toString());
                             placeSeg.setState(SegmentStateType.INIT.toString());
                             placeSeg.setBackpack(backpackLev);

--
Gitblit v1.9.1