package com.zy.acs.manager.core.service.astart;
|
|
import com.alibaba.fastjson.JSON;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.zy.acs.common.constant.RedisConstant;
|
import com.zy.acs.common.utils.RedisSupport;
|
import com.zy.acs.framework.common.Cools;
|
import com.zy.acs.framework.exception.CoolException;
|
import com.zy.acs.manager.core.service.astart.domain.DynamicNode;
|
import com.zy.acs.manager.core.utils.RouteGenerator;
|
import com.zy.acs.manager.manager.entity.Code;
|
import com.zy.acs.manager.manager.entity.Route;
|
import com.zy.acs.manager.manager.enums.StatusType;
|
import com.zy.acs.manager.manager.service.CodeService;
|
import com.zy.acs.manager.manager.service.RouteService;
|
import lombok.extern.slf4j.Slf4j;
|
|
import java.util.*;
|
|
/**
|
* Created by vincent on 6/6/2024
|
*/
|
@Slf4j
|
public class MapDataDispatcher {
|
|
public static final Integer MAP_DEFAULT_LEV = 1;
|
|
private final RedisSupport redis = RedisSupport.defaultRedisSupport;
|
|
List<Double> xIdxList;
|
List<Double> yIdxList;
|
|
private String[][] codeMatrix;
|
|
private int[][] mapMatrix;
|
|
private int[][] turnMatrix;
|
|
private String[][] cdaMatrix;
|
|
public Map<String, Boolean> routeCdaMap = new HashMap<>();
|
|
private final CodeService codeService;
|
|
private final RouteService routeService;
|
|
public MapDataDispatcher(CodeService codeService, RouteService routeService) {
|
this.codeService = codeService;
|
this.routeService = routeService;
|
}
|
|
public String[][] getWaveMatrix(Integer lev) {
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
String[][] waveMatrix;
|
String waveMatrixStr = redis.getValue(RedisConstant.AGV_MAP_ASTAR_WAVE_FLAG, String.valueOf(lev));
|
if (Cools.isEmpty(waveMatrixStr)) {
|
waveMatrix = this.initWaveMatrix(lev);
|
setWaveMatrix(lev, waveMatrix);
|
} else {
|
waveMatrix = JSON.parseObject(waveMatrixStr, String[][].class);
|
}
|
if (null == waveMatrix) {
|
throw new CoolException("the floor " + lev + " cannot found wave matrix !!!");
|
}
|
return waveMatrix;
|
}
|
|
public void setWaveMatrix(Integer lev, String[][] waveMatrix) {
|
redis.setValue(RedisConstant.AGV_MAP_ASTAR_WAVE_FLAG, String.valueOf(lev), JSON.toJSONString(waveMatrix));
|
}
|
|
public DynamicNode[][] getDynamicMatrix(Integer lev) {
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
DynamicNode[][] dynamicMatrix;
|
String dynamicMatrixStr = redis.getValue(RedisConstant.AGV_MAP_ASTAR_DYNAMIC_FLAG, String.valueOf(lev));
|
if (Cools.isEmpty(dynamicMatrixStr)) {
|
dynamicMatrix = this.initDynamicMatrix(lev);
|
setDynamicMatrix(lev, dynamicMatrix);
|
} else {
|
dynamicMatrix = JSON.parseObject(dynamicMatrixStr, DynamicNode[][].class);
|
}
|
if (null == dynamicMatrix) {
|
throw new CoolException("the floor " + lev + " cannot found dynamic matrix !!!");
|
}
|
return dynamicMatrix;
|
}
|
|
public void setDynamicMatrix(Integer lev, DynamicNode[][] dynamicMatrix) {
|
redis.setValue(RedisConstant.AGV_MAP_ASTAR_DYNAMIC_FLAG, String.valueOf(lev), JSON.toJSONString(dynamicMatrix));
|
}
|
|
public String[][] getCdaMatrix(Integer lev) {
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
// redis
|
if (null == this.cdaMatrix) {
|
String cdaMatrixStr = redis.getValue(RedisConstant.AGV_MAP_ASTAR_CDA_FLAG, String.valueOf(lev));
|
if (!Cools.isEmpty(cdaMatrixStr)) {
|
this.cdaMatrix = JSON.parseObject(cdaMatrixStr, String[][].class);
|
}
|
}
|
// init
|
if (null == this.cdaMatrix) {
|
String[][] initCdaMatrix = this.initCdaMatrix(lev);
|
setCdaMatrix(lev, initCdaMatrix);
|
}
|
// valid
|
if (null == this.cdaMatrix) {
|
throw new CoolException("the floor " + lev + " cannot found cda matrix !!!");
|
}
|
return this.cdaMatrix;
|
}
|
|
public void setCdaMatrix(Integer lev, String[][] cdaMatrix) {
|
redis.setValue(RedisConstant.AGV_MAP_ASTAR_CDA_FLAG, String.valueOf(lev), JSON.toJSONString(cdaMatrix));
|
this.cdaMatrix = cdaMatrix;
|
}
|
|
public int[][] getTurnMatrix(Integer lev) {
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
// redis
|
if (null == this.turnMatrix) {
|
String turnMatrixStr = redis.getValue(RedisConstant.AGV_MAP_ASTAR_TURN_FLAG, String.valueOf(lev));
|
if (!Cools.isEmpty(turnMatrixStr)) {
|
this.turnMatrix = JSON.parseObject(turnMatrixStr, int[][].class);
|
}
|
}
|
// init
|
if (null == this.turnMatrix) {
|
int[][] initTurnMatrix = this.initTurnMatrix(lev);
|
setTurnMatrix(lev, initTurnMatrix);
|
}
|
// valid
|
if (null == this.turnMatrix) {
|
throw new CoolException("the floor " + lev + " cannot found turn matrix !!!");
|
}
|
return this.turnMatrix;
|
}
|
|
public void setTurnMatrix(Integer lev, int[][] turnMatrix) {
|
redis.setValue(RedisConstant.AGV_MAP_ASTAR_TURN_FLAG, String.valueOf(lev), JSON.toJSONString(turnMatrix));
|
this.turnMatrix = turnMatrix;
|
}
|
|
public int[][] getMapMatrix(Integer lev, List<String> lockNodes) {
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
// redis
|
if (null == this.mapMatrix) {
|
String mapMatrixStr = redis.getValue(RedisConstant.AGV_MAP_ASTAR_FLAG, String.valueOf(lev));
|
if (!Cools.isEmpty(mapMatrixStr)) {
|
this.mapMatrix = JSON.parseObject(mapMatrixStr, int[][].class);
|
}
|
}
|
// init
|
if (null == this.mapMatrix) {
|
int[][] initMapMatrix = this.initMapMatrix(lev);
|
setMapMatrix(lev, initMapMatrix);
|
}
|
// valid
|
if (null == this.mapMatrix) {
|
throw new CoolException("the floor " + lev + " cannot found map matrix !!!");
|
}
|
return this.mapMatrix;
|
}
|
|
public void setMapMatrix(Integer lev, int[][] mapMatrix) {
|
redis.setValue(RedisConstant.AGV_MAP_ASTAR_FLAG, String.valueOf(lev), JSON.toJSONString(mapMatrix));
|
this.mapMatrix = mapMatrix;
|
}
|
|
public String[][] getCodeMatrix(Integer lev) {
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
// redis
|
if (null == this.codeMatrix) {
|
String codeMatrixStr = redis.getValue(RedisConstant.AGV_MAP_ASTAR_CODE_FLAG, String.valueOf(lev));
|
if (!Cools.isEmpty(codeMatrixStr)) {
|
this.codeMatrix = JSON.parseObject(codeMatrixStr, String[][].class);
|
}
|
}
|
// init
|
if (null == this.codeMatrix) {
|
String[][] initCodeMatrix = this.initCodeMatrix(lev);
|
setCodeMatrix(lev, initCodeMatrix);
|
}
|
// valid
|
if (null == this.codeMatrix) {
|
throw new CoolException("the floor " + lev + " cannot found code matrix !!!");
|
}
|
return this.codeMatrix;
|
}
|
|
public void setCodeMatrix(Integer lev, String[][] codeMatrix) {
|
redis.setValue(RedisConstant.AGV_MAP_ASTAR_CODE_FLAG, String.valueOf(lev), JSON.toJSONString(codeMatrix));
|
this.codeMatrix = codeMatrix;
|
}
|
|
public String[][] initWaveMatrix(Integer lev) {
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
|
String[][] codeMatrix = getCodeMatrix(lev);
|
String[][] waveMatrix = new String[codeMatrix.length][codeMatrix[0].length];
|
|
for (int i = 0; i < codeMatrix.length; i++) {
|
for (int j = 0; j < codeMatrix[i].length; j++) {
|
if (CodeNodeType.NONE.val.equals(codeMatrix[i][j])) {
|
waveMatrix[i][j] = WaveNodeType.DISABLE.val;
|
} else {
|
waveMatrix[i][j] = WaveNodeType.ENABLE.val;
|
}
|
}
|
}
|
|
return waveMatrix;
|
}
|
|
public synchronized DynamicNode[][] initDynamicMatrix(Integer lev) {
|
log.info("There is initializing Dynamic Matrix......");
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
|
String[][] codeMatrix = getCodeMatrix(lev);
|
DynamicNode[][] dynamicMatrix = new DynamicNode[codeMatrix.length][codeMatrix[0].length];
|
|
for (int i = 0; i < codeMatrix.length; i++) {
|
for (int j = 0; j < codeMatrix[i].length; j++) {
|
if (CodeNodeType.NONE.val.equals(codeMatrix[i][j])) {
|
dynamicMatrix[i][j] = new DynamicNode(DynamicNodeType.BLOCK.val);
|
} else {
|
dynamicMatrix[i][j] = new DynamicNode(DynamicNodeType.ACCESS.val);
|
}
|
}
|
}
|
|
return dynamicMatrix;
|
}
|
|
public synchronized String[][] initCdaMatrix(Integer lev) {
|
log.info("There is initializing Cda Matrix......");
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
|
if (Cools.isEmpty(xIdxList, yIdxList)) {
|
this.initCodeMatrix(lev);
|
}
|
|
String[][] codeMatrix = getCodeMatrix(lev);
|
String[][] cdaMatrix = new String[codeMatrix.length][codeMatrix[0].length];
|
|
for (int i = 0; i < codeMatrix.length; i++) {
|
for (int j = 0; j < codeMatrix[i].length; j++) {
|
if (CodeNodeType.NONE.val.equals(codeMatrix[i][j])) {
|
List<Double> cdaArr = new ArrayList<>();
|
cdaArr.add(xIdxList.get(j));
|
cdaArr.add(yIdxList.get(i));
|
cdaMatrix[i][j] = JSON.toJSONString(cdaArr);
|
} else {
|
Code currCode = codeService.getCacheByData(codeMatrix[i][j]);
|
if (null != currCode) {
|
List<Double> cdaArr = new ArrayList<>();
|
cdaArr.add(currCode.getX());
|
cdaArr.add(currCode.getY());
|
cdaMatrix[i][j] = JSON.toJSONString(cdaArr);
|
} else {
|
cdaMatrix[i][j] = CdaNodeType.EMPTY.val;
|
}
|
}
|
|
}
|
}
|
|
return cdaMatrix;
|
}
|
|
public synchronized int[][] initTurnMatrix(Integer lev) {
|
log.info("There is initializing Turn Matrix......");
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
|
String[][] codeMatrix = getCodeMatrix(lev);
|
int[][] turnMatrix = new int[codeMatrix.length][codeMatrix[0].length];
|
|
for (int i = 0; i < codeMatrix.length; i++) {
|
for (int j = 0; j < codeMatrix[i].length; j++) {
|
if (CodeNodeType.NONE.val.equals(codeMatrix[i][j])) {
|
turnMatrix[i][j] = TurnNodeType.NONE.val;
|
} else {
|
Code currCode = codeService.getCacheByData(codeMatrix[i][j]);
|
List<String> neighborCodeList = routeService.findCodeDataOfSingle(currCode.getId());
|
|
switch (neighborCodeList.size()) {
|
case 0:
|
case 1:
|
turnMatrix[i][j] = TurnNodeType.STRAIGHT.val;
|
break;
|
case 2:
|
String firstCode = neighborCodeList.get(0); assert !Cools.isEmpty(firstCode);
|
String secondCode = neighborCodeList.get(1); assert !Cools.isEmpty(secondCode);
|
|
int[] firstIdx = this.getCodeMatrixIdx(lev, firstCode);
|
int[] secondIdx = this.getCodeMatrixIdx(lev, secondCode);
|
|
if (firstIdx[0] != secondIdx[0] && firstIdx[1] != secondIdx[1]) {
|
turnMatrix[i][j] = TurnNodeType.TURN.val;
|
} else {
|
turnMatrix[i][j] = TurnNodeType.STRAIGHT.val;
|
}
|
|
break;
|
default:
|
turnMatrix[i][j] = TurnNodeType.TURN.val;
|
break;
|
}
|
}
|
}
|
}
|
|
// System.out.println("====================================================");
|
// printMatrix(turnMatrix);
|
|
return turnMatrix;
|
}
|
|
|
public synchronized int[][] initMapMatrix(Integer lev) {
|
log.info("There is initializing Map Matrix......");
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
|
String[][] codeMatrix = getCodeMatrix(lev);
|
int[][] mapMatrix = new int[codeMatrix.length][codeMatrix[0].length];
|
|
for (int i = 0; i < codeMatrix.length; i++) {
|
for (int j = 0; j < codeMatrix[i].length; j++) {
|
if (CodeNodeType.NONE.val.equals(codeMatrix[i][j])) {
|
mapMatrix[i][j] = MapNodeType.DISABLE.val;
|
} else {
|
mapMatrix[i][j] = MapNodeType.ENABLE.val;
|
}
|
}
|
}
|
|
// printMatrix(mapMatrix);
|
|
return mapMatrix;
|
}
|
|
public boolean validRouteCdaKey(String routeCdaKey) {
|
if (Cools.isEmpty(routeCdaKey)) {
|
return false;
|
}
|
Boolean result = this.routeCdaMap.get(routeCdaKey);
|
if (null == result) {
|
return false;
|
}
|
return result;
|
}
|
|
public synchronized void initRouteMap(Integer lev) {
|
log.info("There is initializing Route Map......");
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
Set<String> routeKeys = redis.getMapKeys(RedisConstant.AGV_MAP_ROUTE_HASH_FLAG);
|
Set<String> routeCdaKeys = redis.getMapKeys(RedisConstant.AGV_MAP_ROUTE_CDA_HASH_FLAG);
|
|
List<Route> routeList = routeService.list(new LambdaQueryWrapper<Route>().eq(Route::getStatus, StatusType.ENABLE.val));
|
if (routeKeys.size() == routeList.size() && routeKeys.size() == routeCdaKeys.size()) {
|
for (String routeCdaKey : routeCdaKeys) {
|
this.routeCdaMap.put(routeCdaKey, Boolean.TRUE);
|
}
|
return;
|
}
|
for (Route route : routeList) {
|
Code startCode = codeService.getById(route.getStartCode());
|
int[] startCodeIdx = getCodeMatrixIdx(lev, startCode.getData());
|
Code endCode = codeService.getById(route.getEndCode());
|
int[] codeMatrixIdx = getCodeMatrixIdx(lev, endCode.getData());
|
|
String routeKey = RouteGenerator.generateRouteKey(startCode.getData(), endCode.getData());
|
if (Cools.isEmpty(routeKey)) {
|
continue;
|
}
|
redis.setMap(RedisConstant.AGV_MAP_ROUTE_HASH_FLAG, routeKey, Boolean.TRUE);
|
|
String routeCdaKey = RouteGenerator.generateRouteCdaKey(startCodeIdx, codeMatrixIdx);
|
if (Cools.isEmpty(routeCdaKey)) {
|
continue;
|
}
|
redis.setMap(RedisConstant.AGV_MAP_ROUTE_CDA_HASH_FLAG, routeCdaKey, Boolean.TRUE);
|
this.routeCdaMap.put(routeCdaKey, Boolean.TRUE);
|
}
|
}
|
|
public synchronized String[][] initCodeMatrix(Integer lev) {
|
log.info("There is initializing Code Matrix......");
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
List<Code> codeList = codeService.list(new LambdaQueryWrapper<Code>()
|
.eq(Code::getStatus, 1)
|
.orderByAsc(Code::getY)
|
.orderByAsc(Code::getX)
|
);
|
|
xIdxList = new ArrayList<>();
|
yIdxList = new ArrayList<>();
|
for (Code code : codeList) {
|
Double x = code.getX();
|
Double y = code.getY();
|
if (null == x || null == y) { continue; }
|
if (!xIdxList.contains(x)) {
|
xIdxList.add(x);
|
}
|
if (!yIdxList.contains(y)) {
|
yIdxList.add(y);
|
}
|
}
|
xIdxList.sort((o1, o2) -> (int) ((o1 * 100) - (o2 * 100)));
|
yIdxList.sort((o1, o2) -> (int) ((o1 * 100) - (o2 * 100)));
|
|
// [][] 第一个是排的数量 第二个是列的数量
|
String[][] codeMatrix = new String[yIdxList.size()][xIdxList.size()];
|
|
for (Code code : codeList) {
|
Double x = code.getX();
|
Double y = code.getY();
|
|
codeMatrix[yIdxList.indexOf(y)][xIdxList.indexOf(x)] = code.getData();
|
}
|
|
for (int i = 0; i < codeMatrix.length; i++) {
|
for (int j = 0; j < codeMatrix[i].length; j++) {
|
if (codeMatrix[i][j] == null) {
|
codeMatrix[i][j] = CodeNodeType.NONE.val;
|
}
|
}
|
}
|
|
printMatrix(codeMatrix);
|
|
return codeMatrix;
|
}
|
|
public int[] getCodeMatrixIdx(Integer lev, String codeData) {
|
if (Cools.isEmpty(codeData)) {
|
return null;
|
}
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
String[][] codeMatrix = this.getCodeMatrix(lev);
|
|
for (int i = 0; i < codeMatrix.length; i++) {
|
for (int j = 0; j < codeMatrix[i].length; j++) {
|
if (codeMatrix[i][j].equals(codeData)) {
|
return new int[]{i, j};
|
}
|
}
|
}
|
return null;
|
}
|
|
public List<int[]> getCodeMatrixIdxList(Integer lev, List<String> codeDataList) {
|
if (Cools.isEmpty(codeDataList)) {
|
return new ArrayList<>();
|
}
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
String[][] codeMatrix = this.getCodeMatrix(lev);
|
|
List<int[]> codeMatrixIdxList = new ArrayList<>();
|
|
Map<String, int[]> map = new HashMap<>();
|
Set<String> codeDataSet = new HashSet<>(codeDataList);
|
|
for (int i = 0; i < codeMatrix.length; i++) {
|
for (int j = 0; j < codeMatrix[i].length; j++) {
|
String codeData = codeMatrix[i][j];
|
if (codeDataSet.contains(codeData)) {
|
map.put(codeData, new int[]{i, j});
|
}
|
}
|
}
|
|
for (String codeData : codeDataList) {
|
int[] codeMatrixIdx = map.get(codeData);
|
if (codeMatrixIdx != null) {
|
codeMatrixIdxList.add(codeMatrixIdx);
|
}
|
}
|
return codeMatrixIdxList;
|
}
|
|
public void modifyDynamicMatrix(Integer lev, List<int[]> codeIdxList, String vehicle) {
|
this.modifyDynamicMatrix(lev, codeIdxList, vehicle, false);
|
}
|
|
public synchronized void modifyDynamicMatrix(Integer lev, List<int[]> codeIdxList, String vehicle, boolean reset) {
|
if (Cools.isEmpty(vehicle)) {
|
return;
|
}
|
lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV);
|
DynamicNode[][] dynamicMatrix = getDynamicMatrix(lev);
|
|
if (!reset) {
|
// long time = System.currentTimeMillis() / 1000;
|
int serial = 1;
|
for (int[] codeMatrixIdx : codeIdxList) {
|
dynamicMatrix[codeMatrixIdx[0]][codeMatrixIdx[1]] = new DynamicNode(vehicle, serial);
|
serial++;
|
}
|
} else {
|
for (int i = 0; i < dynamicMatrix.length; i++) {
|
for (int j = 0; j < dynamicMatrix[i].length; j++) {
|
DynamicNode dynamicNode = dynamicMatrix[i][j];
|
if (vehicle.equals(dynamicNode.getVehicle())) {
|
dynamicMatrix[i][j] = new DynamicNode(DynamicNodeType.ACCESS.val);
|
}
|
}
|
}
|
}
|
|
setDynamicMatrix(lev, dynamicMatrix);
|
}
|
|
public void clearDynamicMatrixByCodeList(Integer lev, List<int[]> codeIdxList) {
|
this.modifyDynamicMatrix(lev, codeIdxList, DynamicNodeType.ACCESS.val);
|
}
|
|
public int[][] filterMapData(int[][] mapMatrix, Integer lev, List<String> lockNodes) {
|
String[][] codeMatrix = getCodeMatrix(lev);
|
for (int i = 0; i < codeMatrix.length; i++) {
|
for (int j = 0; j < codeMatrix[i].length; j++) {
|
String code = codeMatrix[i][j];
|
if (lockNodes.contains(code)) {
|
mapMatrix[i][j] = MapNodeType.LOCKED.val;
|
}
|
}
|
}
|
return mapMatrix;
|
}
|
|
public <T> void printMatrix(T[][] matrix) {
|
for (T[] list : matrix) {
|
for (T t : list) {
|
System.out.format("%10s", t);
|
}
|
System.out.println();
|
}
|
}
|
|
public void printMatrix(int[][] matrix) {
|
for (int[] list : matrix) {
|
for (int t : list) {
|
System.out.format("%10s", t);
|
}
|
System.out.println();
|
}
|
}
|
|
}
|