| package com.zy.acs.manager.core.service; | 
|   | 
| import com.zy.acs.framework.common.Cools; | 
| import com.zy.acs.common.utils.RedisSupport; | 
| import com.zy.acs.manager.common.domain.MockAgvDto; | 
| import com.zy.acs.manager.common.domain.MockDto; | 
| import com.zy.acs.manager.common.domain.MockStepDto; | 
| import com.zy.acs.manager.common.domain.MockVo; | 
| import com.zy.acs.manager.common.exception.BusinessException; | 
| import com.zy.acs.manager.core.domain.AgvMockDto; | 
| import com.zy.acs.manager.core.domain.TaskPosDto; | 
| import com.zy.acs.manager.core.service.astart.AStarNavigateService; | 
| import com.zy.acs.manager.core.service.astart.MapDataDispatcher; | 
| import com.zy.acs.manager.manager.entity.Agv; | 
| import com.zy.acs.manager.manager.entity.AgvDetail; | 
| import com.zy.acs.manager.manager.entity.Code; | 
| import com.zy.acs.manager.manager.entity.CodeGap; | 
| import com.zy.acs.manager.manager.service.AgvDetailService; | 
| import com.zy.acs.manager.manager.service.AgvService; | 
| import com.zy.acs.manager.manager.service.CodeGapService; | 
| import com.zy.acs.manager.manager.service.CodeService; | 
| import com.zy.acs.manager.system.service.ConfigService; | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| import org.springframework.stereotype.Service; | 
| import org.springframework.transaction.annotation.Transactional; | 
|   | 
| import java.util.*; | 
|   | 
| /** | 
|  * Created by vincent on 2023/7/29 | 
|  */ | 
| @Slf4j | 
| @Service | 
| public class MockService { | 
|   | 
|     private final RedisSupport redis = RedisSupport.defaultRedisSupport; | 
|   | 
|     @Autowired | 
|     private MapService mapService; | 
|     @Autowired | 
|     private AgvService agvService; | 
|     @Autowired | 
|     private AgvDetailService agvDetailService; | 
|     @Autowired | 
|     private CodeService codeService; | 
|     @Autowired | 
|     private CodeGapService codeGapService; | 
|     @Autowired | 
|     private MapDataDispatcher mapDataDispatcher; | 
|     @Autowired | 
|     private AStarNavigateService aStarNavigateService; | 
|     @Autowired | 
|     private ConfigService configService; | 
|   | 
|     public void astarMock() { | 
|         Code startCode = codeService.selectByData("00000028"); | 
|         Code endCode = codeService.selectByData("00000057"); | 
|   | 
|         List<String> strings = mapService.checkoutPath("1", startCode, endCode, false); | 
|   | 
|         List<String> pathList = mapService.validFeasibility(startCode, endCode); | 
|   | 
|         System.out.println("end"); | 
|     } | 
|   | 
|     @Transactional | 
|     public List<MockVo> submit(List<MockAgvDto> agvList, List<MockDto> taskList) { | 
|         final String sameGroupXy = configService.getVal("sameGroupXy", String.class); | 
|         List<MockVo> result = new ArrayList<>(); | 
|   | 
|         if (Cools.isEmpty(taskList)) { | 
|             throw new BusinessException("请添加 MOCK 任务"); | 
|         } | 
|         taskList.sort((o1, o2) -> o2.getPriority() - o1.getPriority()); | 
|   | 
|         // 以 agv 分组 | 
|         List<AgvMockDto> taskDtos = new ArrayList<>(); | 
|         for (MockDto task : taskList) { | 
|             AgvMockDto taskDto = new AgvMockDto(task.getAgv(), task); | 
|             if (AgvMockDto.has(taskDtos, taskDto)) { | 
|                 AgvMockDto dto = AgvMockDto.find(taskDtos, taskDto); | 
|                 assert dto != null; | 
|                 dto.getTaskList().add(task); | 
|             } else { | 
|                 taskDtos.add(taskDto); | 
|             } | 
|         } | 
|   | 
|         // 重组当前 agv 的所有任务 | 
|         for (AgvMockDto taskDto : taskDtos) { | 
|   | 
|             /** | 
|              * key:y 坐标 + 任务类别(货架取货、站点取货、货架放货、站点放货) | 
|              * val:任务id + 任务坐标 + 条码 + 任务类别 | 
|              */ | 
|             Map<String, List<TaskPosDto>> groups = new HashMap<>(); | 
|   | 
|             for (MockDto mockDto : taskDto.getTaskList()) { | 
|                 Code startCode = codeService.selectByData(mockDto.getStart()); | 
|                 Code endCode = codeService.selectByData(mockDto.getEnd()); | 
|   | 
|                 TaskPosDto.packagePosGroup(groups, null, startCode, TaskPosDto.PosType.ORI_LOC, sameGroupXy); | 
|                 TaskPosDto.packagePosGroup(groups, null, endCode, TaskPosDto.PosType.DEST_LOC, sameGroupXy); | 
|             } | 
|   | 
|             // 二维数组 ( 每组的 y坐标 和 任务类别 一致) | 
|             ArrayList<List<TaskPosDto>> list = new ArrayList<>(groups.values()); | 
|             // 二位数组 子数组 已经能确定 y坐标为一致。所有 get(0).xy[1] 为排序(就是一排一排任务进行排序),对 一排排任务以 y坐标 就行降序排序 | 
|             list.sort((o1, o2) -> { | 
|                 double o1CompVal = (o1.get(0).getFirstWeight(sameGroupXy) * 100) + o1.get(0).getPosType().compOffset; | 
|                 double o2CompVal = (o2.get(0).getFirstWeight(sameGroupXy) * 100) + o2.get(0).getPosType().compOffset; | 
|                 return (int) (o1CompVal - o2CompVal); | 
|             }); | 
|   | 
|             // 对一排任务进行 x坐标 顺序排序,防止来回走行 | 
|             for (List<TaskPosDto> taskPosDtoList : list) { | 
|                 taskPosDtoList.sort((o1, o2) -> (int) (o1.getSecondWeight(sameGroupXy) * 100 - o2.getSecondWeight(sameGroupXy) * 100)); | 
|             } | 
|   | 
|             // 上一次的 code, 第一次为 agv 当前code | 
|             String lastCodeData = this.getPosCode(agvList, taskDto.getAgvId()); | 
|             if (Cools.isEmpty(lastCodeData)) { | 
|                 throw new BusinessException(taskDto.getAgvId() + "号 agv 不在条码定位上!"); | 
|             } | 
|             Code lastCode = codeService.selectByData(lastCodeData); | 
|   | 
|             // 走行路径集合 | 
|             List<MockStepDto> stepList = new ArrayList<>(); | 
|             stepList.add(new MockStepDto(lastCodeData, Boolean.FALSE)); | 
|   | 
|             for (List<TaskPosDto> taskPosDtoList : list) { | 
|   | 
|                 for (TaskPosDto dto : taskPosDtoList) { | 
|   | 
|                     // 目标 code | 
|                     Code code = codeService.getById(dto.getCodeId()); | 
|   | 
|                     if (!lastCode.getData().equals(code.getData())) { | 
|   | 
|                         // 计算路径节点 | 
|                         List<String> pathList = mapService.checkoutPath(taskDto.getAgvId(), lastCode, code, true); | 
|                         mapDataDispatcher.clearDynamicMatrixByCodeList(null, pathList); | 
| //                        List<String> pathList = mapService.validFeasibility(lastCode, code); | 
|   | 
|                         if (Cools.isEmpty(pathList)) { | 
|                             throw new BusinessException(lastCode.getData() + " 至 " + code.getData() + "没有路径!"); | 
|                         } | 
|   | 
|                         // 第一个节点为本身, 所以从 下标1 开始 | 
|                         for (int i = 1; i < pathList.size(); i++) { | 
|   | 
|                             String next = pathList.get(i); | 
|                             Code nextCode = codeService.selectByData(next); | 
|   | 
|                             boolean pause = nextCode.getId().equals(dto.getCodeId()); | 
|                             String action = ""; | 
|                             if (pause) { | 
|                                 switch (dto.getPosType()){ | 
|                                     case ORI_LOC: | 
|                                     case ORI_STA: | 
|                                         action = "PICK"; | 
|                                         break; | 
|                                     case DEST_LOC: | 
|                                     case DEST_STA: | 
|                                         action = "DROP"; | 
|                                         break; | 
|                                     default: | 
|                                         break; | 
|                                 } | 
|                             } | 
|   | 
|                             stepList.add(new MockStepDto(nextCode.getData(), pause, action)); | 
|   | 
|                             lastCode = nextCode; | 
|                         } | 
|   | 
|                     } | 
|                 } | 
|             } | 
|   | 
|             result.add(new MockVo(taskDto.getAgvId(), stepList)); | 
|         } | 
|   | 
|         plusData(result); | 
|   | 
|   | 
|   | 
|         for (MockVo mockVo : result) { | 
| //            redis.setObject("PATH", mockVo.getAgv(), mockVo.getStepList().stream().map(MockStepDto::getCode).collect(Collectors.toList())); | 
|         } | 
|   | 
|         return result; | 
|     } | 
|   | 
|   | 
|     private String getPosCode(List<MockAgvDto> agvList, String agv) { | 
|         for (MockAgvDto agvDto : agvList) { | 
|             if (agv.equals(agvDto.getAgv())) { | 
|                 return agvDto.getPos(); | 
|             } | 
|         } | 
|         return null; | 
|     } | 
|   | 
|     private void plusData(List<MockVo> result) { | 
|         for (MockVo mockVo : result) { | 
|             int size = mockVo.getStepList().size(); | 
|             int time = size * 500; | 
|   | 
|             Code lastCode = null; | 
|             double totalDistance = 0; | 
|             for (MockStepDto stepDto : mockVo.getStepList()) { | 
|                 Code code = codeService.selectByData(stepDto.getCode()); | 
|   | 
|                 if (null != lastCode) { | 
|                     CodeGap gap = codeGapService.findByCodeOfBoth(code.getId(), lastCode.getId()); | 
|                     if (null != gap) { | 
|                         totalDistance += gap.getDistance(); | 
|                         stepDto.setDistance(gap.getDistance()); | 
|                     } | 
|                 } | 
|   | 
|                 lastCode = code; | 
|             } | 
|   | 
|             for (MockStepDto stepDto : mockVo.getStepList()) { | 
|                 if (null != stepDto.getDistance()) { | 
|                     double rate = stepDto.getDistance() / totalDistance; | 
|                     stepDto.setTime((int)(rate * time)); | 
|                 } | 
|             } | 
|   | 
|   | 
|         } | 
|   | 
|   | 
|     } | 
|   | 
|   | 
|   | 
|     public List<MockVo> imitate() { | 
|         Agv agv = agvService.selectByUuid("1"); | 
|         AgvDetail agvDetail = agvDetailService.selectByAgvId(agv.getId()); | 
|         MockAgvDto mockAgvDto = new MockAgvDto(); | 
|         mockAgvDto.setAgv(agv.getUuid()); | 
|         mockAgvDto.setPos(codeService.getById(agvDetail.getCode()).getData()); | 
|         List<MockAgvDto> mockAgvDtos = new ArrayList<>(); | 
|         mockAgvDtos.add(mockAgvDto); | 
|   | 
|         List<MockDto> taskList = new ArrayList<>(); | 
|         List<Code> codeList = codeService.list(); | 
|         Random random = new Random(); | 
|         List<Integer> exitCodes = new ArrayList<>(); | 
|         for (int i = 0; i < agv.getStage(); i++) { | 
|             MockDto mockDto = new MockDto(); | 
|             mockDto.setAgv(agv.getUuid()); | 
|   | 
|             int startIdx; | 
|             do { | 
|                 startIdx = random.nextInt(codeList.size()); | 
|             } while (exitCodes.contains(startIdx)); | 
|             exitCodes.add(startIdx); | 
|             Code startCode = codeList.get(startIdx); | 
|   | 
|             int endIdx; | 
|             do { | 
|                 endIdx = random.nextInt(codeList.size()); | 
|             } while (exitCodes.contains(endIdx)); | 
|             exitCodes.add(endIdx); | 
|             Code endCode = codeList.get(endIdx); | 
|   | 
|             mockDto.setStart(startCode.getData()); | 
|             mockDto.setEnd(endCode.getData()); | 
|             taskList.add(mockDto); | 
|         } | 
|         return this.submit(mockAgvDtos, taskList); | 
|     } | 
|   | 
|   | 
| } |