| package com.zy.asrs.wcs.core.utils; | 
|   | 
| import com.alibaba.fastjson.JSON; | 
| import com.alibaba.fastjson.JSONArray; | 
| import com.alibaba.fastjson.JSONObject; | 
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
| import com.zy.asrs.framework.common.SpringUtils; | 
| import com.zy.asrs.wcs.core.domain.dto.BasMapDto; | 
| import com.zy.asrs.wcs.core.domain.dto.RedisMapDto; | 
| import com.zy.asrs.wcs.core.entity.Loc; | 
| import com.zy.asrs.wcs.core.model.MapNode; | 
| import com.zy.asrs.wcs.core.model.enums.MapNodeType; | 
| import com.zy.asrs.wcs.core.model.enums.NavigationMapType; | 
| import com.zy.asrs.wcs.core.service.LocService; | 
| import com.zy.asrs.wcs.rcs.constant.DeviceRedisConstant; | 
| import com.zy.asrs.wcs.system.entity.Dict; | 
| import com.zy.asrs.wcs.system.service.DictService; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| import org.springframework.stereotype.Component; | 
|   | 
| import java.io.*; | 
| import java.util.*; | 
|   | 
| /** | 
|  * A*算法地图获取类 | 
|  */ | 
| @Component | 
| public class NavigateMapData { | 
|   | 
|     @Autowired | 
|     private LocService locService; | 
|     @Autowired | 
|     private DictService dictService; | 
|     @Autowired | 
|     private NavigateMapData navigateMapData; | 
|   | 
|     private Integer lev;//地图楼层 | 
|   | 
|     public NavigateMapData() { | 
|         this.lev = 1; | 
|     } | 
|   | 
|     public NavigateMapData(Integer lev) { | 
|         this.lev = lev; | 
|     } | 
|   | 
|     public void setLev(Integer lev) { | 
|         this.lev = lev; | 
|     } | 
|   | 
|     public int[][] getData() { | 
|         return getDataFromRedis(NavigationMapType.NONE.id, null, null);//默认读取无过滤的全部地图数据 | 
|     } | 
|   | 
|     /** | 
|      * 尝试从redis获取数据 | 
|      */ | 
|     public int[][] getDataFromRedis(Integer mapType, List<int[]> whitePoints, List<int[]> shuttlePoints) { | 
|         String constantMap = DeviceRedisConstant.MAP; | 
|         if(mapType == NavigationMapType.NONE_LOCK.id){ | 
|             constantMap = DeviceRedisConstant.BASE_MAP; | 
|         } | 
|   | 
|         RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class); | 
|         Object o = redisUtil.get(constantMap + lev); | 
|         if (o == null) { | 
|             return null; | 
|         } | 
|   | 
|         BasMapDto basMap = JSON.parseObject(o.toString(), BasMapDto.class); | 
|         String mapData = basMap.getData(); | 
|         return this.getDataFormString(mapData, mapType, whitePoints, shuttlePoints); | 
|     } | 
|   | 
|     /** | 
|      * 从List数据中获取地图 | 
|      */ | 
|     public int[][] getDataFormString(String data, Integer mapType, List<int[]> whitePoints, List<int[]> shuttlePoints) { | 
|         ArrayList arrayList = JSON.parseObject(data, ArrayList.class); | 
|         List<List<MapNode>> lists = filterMap(mapType, arrayList, lev, whitePoints, shuttlePoints);//过滤地图数据 | 
|         int[][] map = new int[lists.size()][]; | 
|         int j = 0; | 
|         for (List<MapNode> list : lists) { | 
|             int[] tmp = new int[list.size()]; | 
|             int i = 0; | 
|             for (MapNode mapNode : list) { | 
|                 //将数据添加进二维数组 | 
|                 tmp[i++] = mapNode.getValue(); | 
|             } | 
|             //数据添加进一维数组 | 
|             map[j++] = tmp; | 
|         } | 
|   | 
|         return map; | 
|     } | 
|   | 
|     //获取JSON格式数据-原始地图 | 
|     public List<List<MapNode>> getJsonDataFromDict(Integer mapType, List<int[]> whitePoints, List<int[]> shuttlePoints) { | 
|         List<List<MapNode>> arrayList = getMapFromDict(lev); | 
|         return arrayList; | 
|     } | 
|   | 
|     //从数据字典中解析指定楼层地图数据 | 
|     public List<List<MapNode>> getMapFromDict(Integer currentLev) { | 
|         List<Dict> dicts = dictService.list(new LambdaQueryWrapper<Dict>() | 
|                 .like(Dict::getFlag, "map-" + currentLev) | 
|                 .eq(Dict::getStatus, 1)); | 
|   | 
|         TreeMap<Integer, ArrayList<ArrayList<MapNode>>> levData = new TreeMap<>(); | 
|         for (Dict dict : dicts) { | 
|             String[] split = dict.getFlag().split("-"); | 
|             int lev = Integer.parseInt(split[1]); | 
|   | 
|             TreeMap<Integer, List<JSONObject>> rows = new TreeMap<>(); | 
|             //排序Row | 
|             JSONArray value = JSON.parseArray(dict.getValue()); | 
|             for (Object o : value) { | 
|                 JSONObject item = JSON.parseObject(o.toString()); | 
|                 if (item.getString("type").equals("SHELF")) { | 
|                     JSONObject property = JSON.parseObject(item.getString("property")); | 
|                     Integer row1 = property.getInteger("row"); | 
|                     ArrayList<JSONObject> bays = new ArrayList<>(); | 
|                     if (rows.containsKey(row1)) { | 
|                         bays.addAll(rows.get(row1)); | 
|                     } | 
|                     bays.add(property); | 
|                     rows.put(row1, bays); | 
|                 } | 
|             } | 
|   | 
|             ArrayList<ArrayList<MapNode>> list = new ArrayList<>(); | 
|             //排序Bay | 
|             for (Map.Entry<Integer, List<JSONObject>> entry : rows.entrySet()) { | 
|                 ArrayList<MapNode> nodes = new ArrayList<>(); | 
|                 for (JSONObject object : entry.getValue()) { | 
|                     MapNode mapNode = new MapNode(); | 
|                     mapNode.setValue(object.getInteger("shelfType")); | 
|                     mapNode.setTop(object.getInteger("top")); | 
|                     mapNode.setBottom(object.getInteger("bottom")); | 
|                     mapNode.setLeft(object.getInteger("left")); | 
|                     mapNode.setRight(object.getInteger("right")); | 
|                     mapNode.setRow(object.getInteger("row")); | 
|                     mapNode.setBay(object.getInteger("bay")); | 
|                     mapNode.setNo(object.getString("row") + "-" + object.getString("bay")); | 
|                     mapNode.setXBase(object.getInteger("refx")); | 
|                     mapNode.setYBase(object.getInteger("refy")); | 
|   | 
|                     if(mapNode.getValue() == MapNodeType.CONVEYOR.id) { | 
|                         //输送线,判断小车是否可走 | 
|                         if (object.containsKey("conveyorHasGo")) { | 
|                             if(object.getBoolean("conveyorHasGo")) { | 
|                                 //小车可走 | 
|                                 mapNode.setValue(MapNodeType.CONVEYOR_CAR_GO.id); | 
|                             } | 
|                         } | 
|                     } | 
|   | 
|                     nodes.add(mapNode); | 
|                 } | 
|   | 
|                 Collections.sort(nodes, new Comparator<MapNode>() { | 
|                     @Override | 
|                     public int compare(MapNode o1, MapNode o2) { | 
|                         return Integer.compare(o1.getBay(), o2.getBay()); | 
|                     } | 
|                 }); | 
|   | 
|                 ArrayList<MapNode> sortNodes = new ArrayList<>(); | 
|                 int defaultBay = 1;//默认从1列开始 | 
|                 for (MapNode node : nodes) { | 
|                     if (node.getBay() == defaultBay) { | 
|                         defaultBay++; | 
|                         sortNodes.add(node); | 
|                         continue; | 
|                     } | 
|   | 
|                     //存在空缺节点,自动补足 | 
|                     for (int i = defaultBay; i < node.getBay(); i++) { | 
|                         MapNode mapNode = new MapNode(); | 
|                         mapNode.setValue(MapNodeType.DISABLE.id); | 
|                         mapNode.setTop(1000); | 
|                         mapNode.setBottom(1000); | 
|                         mapNode.setLeft(1000); | 
|                         mapNode.setRight(1000); | 
|                         mapNode.setRow(node.getRow()); | 
|                         mapNode.setBay(i); | 
|                         mapNode.setNo(node.getRow() + "-" + i); | 
|                         mapNode.setXBase(0); | 
|                         mapNode.setYBase(0); | 
|                         sortNodes.add(mapNode); | 
|                     } | 
|   | 
|                     defaultBay = node.getBay() + 1; | 
|                     sortNodes.add(node); | 
|                 } | 
|   | 
|                 list.add(sortNodes); | 
|             } | 
|   | 
|             levData.put(lev, list); | 
|         } | 
|   | 
|         for (Map.Entry<Integer, ArrayList<ArrayList<MapNode>>> entry : levData.entrySet()) { | 
|             ArrayList<ArrayList<MapNode>> lists = entry.getValue();//获取地图 | 
|   | 
|             MapNode mapNode = new MapNode(); | 
|             mapNode.setValue(MapNodeType.DISABLE.id); | 
|             mapNode.setTop(1000); | 
|             mapNode.setBottom(1000); | 
|             mapNode.setLeft(1000); | 
|             mapNode.setRight(1000); | 
|             mapNode.setRow(0); | 
|             mapNode.setBay(0); | 
|             mapNode.setNo("0-0"); | 
|             mapNode.setXBase(0); | 
|             mapNode.setYBase(0); | 
|   | 
|             //获取最长row | 
|             int row = 0; | 
|             //给每个row首尾增加-1节点 | 
|             for (ArrayList<MapNode> list : lists) { | 
|                 if (list.size() > row) { | 
|                     row = list.size(); | 
|                 } | 
|   | 
|                 list.add(0, mapNode.clone()); | 
|                 list.add(mapNode.clone()); | 
|             } | 
|   | 
|             ArrayList<MapNode> headNodes = new ArrayList<>(); | 
|             ArrayList<MapNode> footerNodes = new ArrayList<>(); | 
|             for (int i = 0; i < row+2; i++) { | 
|                 headNodes.add(mapNode.clone()); | 
|                 footerNodes.add(mapNode.clone()); | 
|             } | 
|   | 
|             lists.add(0, headNodes); | 
|             lists.add(footerNodes); | 
|   | 
|             Integer lev = entry.getKey(); | 
|             Date now = new Date(); | 
|             RedisMapDto map = new RedisMapDto(); | 
|             map.setData(JSON.toJSONString(lists)); | 
|             map.setCreateTime(now); | 
|             map.setUpdateTime(now); | 
|             map.setLev(lev); | 
|   | 
|             List<List<MapNode>> mapNodeList = new ArrayList<>(); | 
|             mapNodeList.addAll(lists); | 
|             return mapNodeList; | 
|         } | 
|   | 
|         return null; | 
|     } | 
|   | 
|     //获取JSON格式数据 | 
|     public List<List<MapNode>> getJsonData(Integer mapType, List<int[]> whitePoints, List<int[]> shuttlePoints) { | 
|         RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class); | 
|         Object o = redisUtil.get(DeviceRedisConstant.MAP + lev); | 
|         if (o == null) { | 
|             return null; | 
|         } | 
|   | 
|         BasMapDto basMap = JSON.parseObject(o.toString(), BasMapDto.class); | 
|         ArrayList arrayList = JSON.parseObject(basMap.getData(), ArrayList.class); | 
|         List<List<MapNode>> lists = filterMap(mapType, arrayList, lev, whitePoints, shuttlePoints);//过滤地图数据 | 
|         return lists; | 
|     } | 
|   | 
|     /** | 
|      * 过滤地图数据 | 
|      * mapType -1=>无过滤,1=》过滤库位状态DFX,2=》过滤库位状态X | 
|      * | 
|      * @param whitePoints 白名单节点,不需要被过滤 | 
|      * @param shuttlePoints 穿梭车节点,需要加载进地图 | 
|      */ | 
|     public List<List<MapNode>> filterMap(Integer mapType, List arrayList, Integer lev, List<int[]> whitePoints, List<int[]> shuttlePoints) { | 
|         List<List<MapNode>> lists = new ArrayList<>(); | 
|   | 
|         //重建数据格式 | 
|         for (int i = 0; i < arrayList.size(); i++) { | 
|             Object obj = arrayList.get(i); | 
|             List<MapNode> list = JSON.parseArray(obj.toString(), MapNode.class); | 
|             for (int j = 0; j < list.size(); j++) { | 
|                 MapNode mapNode = list.get(j); | 
|                 list.set(j, mapNode); | 
|             } | 
|             lists.add(list); | 
|         } | 
|   | 
|         //过滤数据 | 
|         //获取当前楼层库位数据 | 
|         List<Loc> locs = locService.list(new LambdaQueryWrapper<Loc>() | 
|                 .eq(Loc::getLev, lev) | 
|                 .eq(Loc::getStatus, 1) | 
|                 .orderByAsc(Loc::getRow, Loc::getBay)); | 
|         for (Loc loc : locs) { | 
|             Integer row = loc.getRow(); | 
|             Integer bay = loc.getBay(); | 
|   | 
|             boolean whiteFlag = false;//默认不存在白名单 | 
|             if (whitePoints != null) { | 
|                 for (int[] whitePoint : whitePoints) { | 
|                     if (whitePoint[0] == row && whitePoint[1] == bay) { | 
|                         //存在白名单 | 
|                         whiteFlag = true; | 
|                         break; | 
|                     } | 
|                 } | 
|             } | 
|             if (whiteFlag) { | 
|                 continue;//存在白名单,不执行下列过滤方案 | 
|             } | 
|   | 
|   | 
|             List<MapNode> list = lists.get(row); | 
|             MapNode mapNode = list.get(bay); | 
|   | 
|             if (mapType == NavigationMapType.NONE.id) { | 
|                 //不过滤任何数据 | 
|             } else if (mapType == NavigationMapType.DFX.id) { | 
|                 //车辆有货 | 
|                 //读取对应库位数据,将DFX库位状态的节点置为-1(障碍物) | 
|                 if (loc.getLocStsFlag().equals("F") | 
|                         || loc.getLocStsFlag().equals("D") | 
|                         || loc.getLocStsFlag().equals("X") | 
|                 ) { | 
|                     mapNode.setValue(MapNodeType.DISABLE.id);//禁用节点 | 
|                 } | 
|             } else if (mapType == NavigationMapType.NORMAL.id || mapType == NavigationMapType.NONE_LOCK.id) { | 
|                 //过滤库位状态X | 
|                 if (loc.getLocStsFlag().equals("X")) { | 
|                     mapNode.setValue(MapNodeType.DISABLE.id);//禁用节点 | 
|                 } | 
|             } | 
|   | 
|             //更新list | 
|             list.set(bay, mapNode); | 
|             lists.set(row, list); | 
|         } | 
|   | 
|         //加载车辆坐标到地图中 | 
|         if (shuttlePoints != null) { | 
|             for (int[] points : shuttlePoints) { | 
|                 int x = points[0]; | 
|                 int y = points[1]; | 
|                 List<MapNode> list = lists.get(x); | 
|                 MapNode mapNode = list.get(y); | 
|                 mapNode.setValue(MapNodeType.CAR.id);//设置为车辆代码66 | 
|                 //更新list | 
|                 list.set(y, mapNode); | 
|                 lists.set(x, list); | 
|             } | 
|         } | 
|   | 
|         return lists; | 
|     } | 
|   | 
| } |