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.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<int[]> whitePoints, List<int[]> 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<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"));
|
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(-1);
|
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(-1);
|
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;
|
}
|
|
BasMap basMap = JSON.parseObject(o.toString(), BasMap.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);
|
}
|
|
//获取严格模式参数
|
boolean mapStrict = true;//默认严格模式
|
Dict dict = dictService.getOne(new LambdaQueryWrapper<Dict>().eq(Dict::getFlag, "shuttleMapStrict"));
|
if (dict != null) {
|
mapStrict = Boolean.parseBoolean(dict.getValue());
|
}
|
|
if (mapStrict) {//严格模式下,载入库位状态
|
//过滤数据
|
//获取当前楼层库位数据
|
List<Loc> locs = locService.list(new LambdaQueryWrapper<Loc>()
|
.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<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.getLocSts$().equals("F")
|
|| loc.getLocSts$().equals("D")
|
|| loc.getLocSts$().equals("X")
|
) {
|
mapNode.setValue(-1);//禁用节点
|
}
|
} else if (mapType == NavigationMapType.NORMAL.id) {
|
//过滤库位状态X
|
if (loc.getLocSts$().equals("X")) {
|
mapNode.setValue(-1);//禁用节点
|
}
|
}
|
|
//更新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(66);//设置为车辆代码66
|
//更新list
|
list.set(y, mapNode);
|
lists.set(x, list);
|
}
|
}
|
|
return lists;
|
}
|
|
}
|