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.common.wms.entity.BasMap; import com.zy.asrs.framework.common.SpringUtils; 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; 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 whitePoints, List shuttlePoints) { RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class); Object o = redisUtil.get(DeviceRedisConstant.MAP + lev); if (o == null) { return null; } BasMap basMap = JSON.parseObject(o.toString(), BasMap.class); return this.getDataFormString(basMap.getData(), mapType, whitePoints, shuttlePoints); } /** * 从List数据中获取地图 */ public int[][] getDataFormString(String data, Integer mapType, List whitePoints, List shuttlePoints) { ArrayList arrayList = JSON.parseObject(data, ArrayList.class); List> lists = filterMap(mapType, arrayList, lev, whitePoints, shuttlePoints);//过滤地图数据 int[][] map = new int[lists.size()][]; int j = 0; for (List 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> getJsonDataFromDict(Integer mapType, List whitePoints, List shuttlePoints) { List> arrayList = getMapFromDict(lev); return arrayList; } //从数据字典中解析指定楼层地图数据 public List> getMapFromDict(Integer currentLev) { List dicts = dictService.list(new LambdaQueryWrapper() .like(Dict::getFlag, "map-" + currentLev) .eq(Dict::getStatus, 1)); TreeMap>> levData = new TreeMap<>(); for (Dict dict : dicts) { String[] split = dict.getFlag().split("-"); int lev = Integer.parseInt(split[1]); TreeMap> 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 bays = new ArrayList<>(); if (rows.containsKey(row1)) { bays.addAll(rows.get(row1)); } bays.add(property); rows.put(row1, bays); } } ArrayList> list = new ArrayList<>(); //排序Bay for (Map.Entry> entry : rows.entrySet()) { ArrayList 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() { @Override public int compare(MapNode o1, MapNode o2) { return Integer.compare(o1.getBay(), o2.getBay()); } }); ArrayList 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>> entry : levData.entrySet()) { ArrayList> 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 list : lists) { if (list.size() > row) { row = list.size(); } list.add(0, mapNode.clone()); list.add(mapNode.clone()); } ArrayList headNodes = new ArrayList<>(); ArrayList 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> mapNodeList = new ArrayList<>(); mapNodeList.addAll(lists); return mapNodeList; } return null; } //获取JSON格式数据 public List> getJsonData(Integer mapType, List whitePoints, List shuttlePoints) { RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class); Object o = redisUtil.get(DeviceRedisConstant.MAP + lev); if (o == null) { return null; } BasMap basMap = JSON.parseObject(o.toString(), BasMap.class); ArrayList arrayList = JSON.parseObject(basMap.getData(), ArrayList.class); List> lists = filterMap(mapType, arrayList, lev, whitePoints, shuttlePoints);//过滤地图数据 return lists; } /** * 过滤地图数据 * mapType -1=>无过滤,1=》过滤库位状态DFX,2=》过滤库位状态X * * @param whitePoints 白名单节点,不需要被过滤 * @param shuttlePoints 穿梭车节点,需要加载进地图 */ public List> filterMap(Integer mapType, List arrayList, Integer lev, List whitePoints, List shuttlePoints) { List> lists = new ArrayList<>(); //重建数据格式 for (int i = 0; i < arrayList.size(); i++) { Object obj = arrayList.get(i); List 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); } //获取严格模式参数 boolean mapStrict = true;//默认严格模式 Dict dict = dictService.getOne(new LambdaQueryWrapper().eq(Dict::getFlag, "shuttleMapStrict")); if (dict != null) { mapStrict = Boolean.parseBoolean(dict.getValue()); } if (mapStrict) {//严格模式下,载入库位状态 //过滤数据 //获取当前楼层库位数据 List locs = locService.list(new LambdaQueryWrapper() .eq(Loc::getLev, lev) .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 list = lists.get(row); MapNode mapNode = list.get(bay); if (mapType == NavigationMapType.NONE.id) { //不过滤任何数据 } else if (mapType == NavigationMapType.DFX.id) { //车辆有货 //读取对应库位数据,将DFX库位状态的节点置为-1(障碍物) if (loc.getLocSts$().equals("F") || loc.getLocSts$().equals("D") || loc.getLocSts$().equals("X") ) { mapNode.setValue(MapNodeType.DISABLE.id);//禁用节点 } } else if (mapType == NavigationMapType.NORMAL.id) { //过滤库位状态X if (loc.getLocSts$().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 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; } }