|
|
@@ -0,0 +1,601 @@
|
|
|
+package com.zd.laboratory.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.date.StopWatch;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.zd.algorithm.api.speaker.entity.ParamVo;
|
|
|
+import com.zd.algorithm.api.speaker.entity.PlayVo;
|
|
|
+import com.zd.algorithm.api.speaker.feign.RemoteSpeakService;
|
|
|
+import com.zd.common.core.utils.*;
|
|
|
+import com.zd.laboratory.config.TimeWaitConfigUtils;
|
|
|
+import com.zd.laboratory.domain.LabAudioSynthesis;
|
|
|
+import com.zd.laboratory.domain.LabBuildFloorLayout;
|
|
|
+import com.zd.laboratory.domain.LabExitLineVertex;
|
|
|
+import com.zd.laboratory.domain.LabExitPointRelay;
|
|
|
+import com.zd.laboratory.domain.vo.*;
|
|
|
+import com.zd.laboratory.mapper.*;
|
|
|
+import com.zd.laboratory.service.ILabBuildFloorLayoutService;
|
|
|
+import com.zd.laboratory.service.ILabExitLineVertexService;
|
|
|
+import com.zd.laboratory.socket.command.Symbol;
|
|
|
+import com.zd.laboratory.socket.service.SocketService;
|
|
|
+import com.zd.model.domain.R;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.CompletableFuture;
|
|
|
+import java.util.concurrent.ExecutionException;
|
|
|
+import java.util.concurrent.atomic.LongAdder;
|
|
|
+import java.util.function.Consumer;
|
|
|
+import java.util.function.Function;
|
|
|
+import java.util.function.Predicate;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 逃生线路顶点Service业务层处理
|
|
|
+ *
|
|
|
+ * @author zd
|
|
|
+ * @date 2022-11-3
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class LabExitLineVertexServiceImpl implements ILabExitLineVertexService {
|
|
|
+ private final static Logger logger = LoggerFactory.getLogger(LabExitLineVertexServiceImpl.class);
|
|
|
+
|
|
|
+ private int V; // 顶点的个数
|
|
|
+ private static int M = 65535;// 设置一个最大值
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private LabExitLineVertexMapper labExitLineVertexMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private LabExitPointRelayMapper labExitPointRelayMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private SocketService socketService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private LabAudioSynthesisMapper labAudioSynthesisMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RemoteSpeakService remoteSpeakService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TimeWaitConfigUtils timeWaitConfigUtils;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private LabBuildFloorLayoutMapper labBuildFloorLayoutMapper;
|
|
|
+
|
|
|
+
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(LabExitLineVertexServiceImpl.class);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询逃生线路主
|
|
|
+ *
|
|
|
+ * @param id 逃生线路主主键
|
|
|
+ * @return 逃生线路主
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public LabExitLineVertex selectLabExitLineVertexById(Long id) {
|
|
|
+ LabExitLineVertex labExitLineVO = labExitLineVertexMapper.selectLabExitLineVertexById(id);
|
|
|
+ return labExitLineVO;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询逃生线路主列表
|
|
|
+ *
|
|
|
+ * @param labExitLineVertex 逃生线路主
|
|
|
+ * @return 逃生线路主
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List <LabExitLineVertex> selectLabExitLineVertexList(LabExitLineVertex labExitLineVertex) {
|
|
|
+ List <LabExitLineVertex> labExitLineVOList = labExitLineVertexMapper.selectLabExitLineVertexList(labExitLineVertex);
|
|
|
+
|
|
|
+ return labExitLineVOList;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询逃生线路主
|
|
|
+ *
|
|
|
+ * @param labExitLineVertex 逃生线路主主键
|
|
|
+ * @return 逃生线路主
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public int getCalculationLine(LabExitLineVertex labExitLineVertex) {
|
|
|
+// List<LabExitLineVertex> labExitLineVOList = labExitLineVertexMapper.selectLabExitLineVertexList(labExitLineVertex);
|
|
|
+// if(labExitLineVOList.size()>0){
|
|
|
+// String relationData = labExitLineVOList.get(0).getRelationalData();
|
|
|
+// List <LabExitLineJoinPointVO> relationalData = JSONArray.parseArray(relationData, LabExitLineJoinPointVO.class);
|
|
|
+// V=relationalData.size();
|
|
|
+// ArrayList <Integer[][]> list=flody(relationalData);
|
|
|
+// display_path(list,relationalData);
|
|
|
+// }
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询逃生线路主
|
|
|
+ *
|
|
|
+ * @param labExitLineEvacuationVo 逃生线路Vo
|
|
|
+ * @return 逃生线路主
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Map <String, Object> executeEvacuation(LabExitLineEvacuationVo labExitLineEvacuationVo) {
|
|
|
+ LabExitLineVertex labExitLineVertex = new LabExitLineVertex();
|
|
|
+ labExitLineVertex.setBuildId(labExitLineEvacuationVo.getBuildId());
|
|
|
+ labExitLineVertex.setFloorId(labExitLineEvacuationVo.getFloorId());
|
|
|
+ List <LabExitLineVertex> labExitLineVOList = labExitLineVertexMapper.selectLabExitLineVertexList(labExitLineVertex);
|
|
|
+ if (labExitLineVOList.size() > 0) {
|
|
|
+ String relationData = labExitLineVOList.get(0).getRelationalData();
|
|
|
+ List <LabExitLineJoinPointVO> newRelationalData = JSONArray.parseArray(relationData, LabExitLineJoinPointVO.class);
|
|
|
+ //调用坏点计算
|
|
|
+ badPoints(newRelationalData, labExitLineEvacuationVo);
|
|
|
+ //设置顶点数
|
|
|
+ V = newRelationalData.size();
|
|
|
+ //floyd计算顶点到各个点的线路
|
|
|
+ ArrayList <Integer[][]> list = flody(newRelationalData);
|
|
|
+ //这里需要在通过floyd计算一次原始数据,作为发生预案的楼层,只有一个疏散口,那么所有的实验室,都向这个疏散口撤离。
|
|
|
+ List <LabExitLineJoinPointVO> oldRelationalData = JSONArray.parseArray(relationData, LabExitLineJoinPointVO.class);
|
|
|
+ ArrayList <Integer[][]> oldList = flody(oldRelationalData);
|
|
|
+ //计算楼层各个实验室的逃生线路
|
|
|
+ Map <String, Object> joinPointVOS = displayPath(list, newRelationalData, labExitLineEvacuationVo, oldList, oldRelationalData);
|
|
|
+ return joinPointVOS;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //todo 计算坏点(目前只有发生预案的实验室需要标记为坏点),需要把非坏点关联坏点点位全部改成无限大
|
|
|
+ public void badPoints(List <LabExitLineJoinPointVO> newRelationalData, LabExitLineEvacuationVo labExitLineEvacuationVo) {
|
|
|
+ Optional.ofNullable(newRelationalData).orElseGet(Collections::emptyList)
|
|
|
+ .parallelStream()
|
|
|
+ .filter(a -> !a.getPointName().equals(labExitLineEvacuationVo.getStartPointName()))
|
|
|
+ .forEach(a -> Optional.ofNullable(a.getPointVOList()).orElseGet(Collections::emptyList)
|
|
|
+ .stream()
|
|
|
+ .filter(b -> b.getPointName().equals(labExitLineEvacuationVo.getStartPointName()))
|
|
|
+ .forEach(b -> b.setPointDistance(M))
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ //todo 计算完成的路线,灯的数据
|
|
|
+ public Map <String, Object> displayPath(ArrayList <Integer[][]> list, List <LabExitLineJoinPointVO> linePointVOList, LabExitLineEvacuationVo labExitLineEvacuationVo, ArrayList <Integer[][]> oldList, List <LabExitLineJoinPointVO> oldRelationalData) {
|
|
|
+
|
|
|
+ logger.info("当前线程:{}", Thread.currentThread().getName());
|
|
|
+
|
|
|
+ StopWatch sw = new StopWatch("queryLinePoint_TIME");
|
|
|
+ sw.start("调用异步任务");
|
|
|
+ //2.异步线程结果
|
|
|
+ List <CompletableFuture <Map <String, Object>>> completableFutures = new ArrayList <>();
|
|
|
+
|
|
|
+ Integer[][] path = list.get(0);
|
|
|
+ Integer[] chain = new Integer[V];
|
|
|
+ logger.info("orign->dist" + " dist " + " path");
|
|
|
+ for (int i = 0; i < V; i++) {
|
|
|
+ for (int j = 0; j < V; j++) {
|
|
|
+ if (i != j) {//只是避免了vi->vi的输出
|
|
|
+ if (linePointVOList.get(i).getPointAttribute() == 4 && linePointVOList.get(i).getPointVOList().get(j).getPointAttribute() == 1) {
|
|
|
+ CompletableFuture <Map <String, Object>> setCompletableFuture = optimalRoute(linePointVOList, path, chain, i, j, oldList, oldRelationalData);
|
|
|
+ completableFutures.add(setCompletableFuture);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sw.stop();
|
|
|
+ CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[completableFutures.size()])).join();
|
|
|
+ logger.info("子线程全部完成");
|
|
|
+
|
|
|
+ return filterLinePoint(completableFutures, labExitLineEvacuationVo.getStartPointName(), labExitLineEvacuationVo);
|
|
|
+ }
|
|
|
+
|
|
|
+ //todo 预案触发实验室的主线路到逃生点全部返回,其他实验室赛选过滤最优线路,如果和主线路有重叠或者逆向,需要移除重叠以后的数据点。
|
|
|
+ public Map <String, Object> filterLinePoint(List <CompletableFuture <Map <String, Object>>> completableFutures, final String startPointName, LabExitLineEvacuationVo labExitLineEvacuationVo) {
|
|
|
+ //todo 断言名字是否相同
|
|
|
+ Predicate <String> checkPointName = x -> x.equals(startPointName);
|
|
|
+ List <List <LabExitLineJoinPointVO>> startPointList = new ArrayList <>();
|
|
|
+ Map <String, Integer> sortKeyMap = new LinkedHashMap <>();
|
|
|
+ Map <String, List <LabExitLineJoinPointVO>> otherPointMap = new LinkedHashMap <>();
|
|
|
+ Optional.ofNullable(completableFutures).orElseGet(Collections::emptyList)
|
|
|
+ .stream()
|
|
|
+ .forEach(a -> {
|
|
|
+ try {
|
|
|
+ String pointName = (String) a.get().get("pointName");
|
|
|
+ if (checkPointName.test(pointName)) {
|
|
|
+ startPointList.add((List <LabExitLineJoinPointVO>) a.get().get("joinPointVOS"));
|
|
|
+ } else {
|
|
|
+ LabExitLineJoinPointVO pointDistanceVo = (LabExitLineJoinPointVO) a.get().get("pointDistanceVo");
|
|
|
+ if (sortKeyMap.get(pointName) == null || sortKeyMap.get(pointName) > pointDistanceVo.getPointDistance()) {
|
|
|
+ sortKeyMap.put(pointName, pointDistanceVo.getPointDistance());
|
|
|
+ otherPointMap.put(pointName, (List <LabExitLineJoinPointVO>) a.get().get("joinPointVOS"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } catch (ExecutionException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ //todo 将过滤好的otherPointMap转换成list
|
|
|
+ Function <Map <String, List <LabExitLineJoinPointVO>>, List <List <LabExitLineJoinPointVO>>> otherPointList =
|
|
|
+ a -> a.entrySet().stream().map(Map.Entry::getValue).collect(Collectors.toList());
|
|
|
+
|
|
|
+ Map <String, Object> allPointMap = new LinkedHashMap <>();
|
|
|
+ joinLine(allPointMap, startPointList, labExitLineEvacuationVo).accept(otherPointList.apply(otherPointMap));
|
|
|
+ //todo 开启逃生灯绑定继电器的数据
|
|
|
+ openLightJoinRelay((Set <LabExitLineJoinPointVO>) allPointMap.get("lightPointSet"),labExitLineEvacuationVo);
|
|
|
+ return allPointMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 开启逃生灯关联的继电器
|
|
|
+ *
|
|
|
+ * @param oldLightPointSet 疏散线路的所有需要开启的灯
|
|
|
+ */
|
|
|
+ public void openLightJoinRelay(Set <LabExitLineJoinPointVO> oldLightPointSet,LabExitLineEvacuationVo labExitLineEvacuationVo){
|
|
|
+ //这里重新构建一个set,过滤主线路里面的一些重复数据
|
|
|
+ Set<LabExitLineJoinPointVO> lightPointList = Optional.ofNullable(oldLightPointSet).orElseGet(Collections::emptySet)
|
|
|
+ .stream().collect(Collectors.toSet());
|
|
|
+
|
|
|
+ LabExitPointRelay labExitPointRelay = new LabExitPointRelay();
|
|
|
+ labExitPointRelay.setBuildId(labExitLineEvacuationVo.getBuildId());
|
|
|
+ labExitPointRelay.setFloorId(labExitLineEvacuationVo.getFloorId());
|
|
|
+ List <LabExitPointRelay> labExitPointRelays = labExitPointRelayMapper.selectLabExitPointRelayList(labExitPointRelay);
|
|
|
+ //todo 这里需要两层for循环,比对点名称一样的,开启继电器开关
|
|
|
+ Consumer<LabExitPointRelay> consumer = a->Optional.ofNullable(lightPointList).orElseGet(Collections::emptySet)
|
|
|
+ .stream()
|
|
|
+ .filter(b->b.getPointName().equals(a.getPointName()))
|
|
|
+ .forEach(b->{
|
|
|
+ //这里打卡继电器的开关
|
|
|
+ socketService.sendCommand(Symbol.order.control, a.getRelayCode(), Symbol.command.open, a.getRelayBit());
|
|
|
+ try {
|
|
|
+ Thread.sleep(timeWaitConfigUtils.getWaitTime());
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ Optional.ofNullable(labExitPointRelays).orElseGet(Collections::emptyList)
|
|
|
+ .stream()
|
|
|
+ .forEach(a->consumer.accept(a));
|
|
|
+ //todo 调用楼层的喇叭
|
|
|
+ openHorn(labExitLineEvacuationVo);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 开启喇叭播放音乐
|
|
|
+ *
|
|
|
+ * @param labExitLineEvacuationVo 楼栋和楼层的基础数据
|
|
|
+ */
|
|
|
+ public void openHorn(LabExitLineEvacuationVo labExitLineEvacuationVo){
|
|
|
+ try{
|
|
|
+ //这里查询预案下的合成音乐
|
|
|
+ LabAudioSynthesis labAudioSynthesis = new LabAudioSynthesis();
|
|
|
+ labAudioSynthesis.setSceneType(2);
|
|
|
+ List<LabAudioSynthesis> audioSyntheses = labAudioSynthesisMapper.selectLabAudioSynthesisList(labAudioSynthesis);
|
|
|
+ if(audioSyntheses.size()>0){
|
|
|
+ //预案调用喇叭
|
|
|
+ R deviceList = remoteSpeakService.getDeviceList(1,10,labExitLineEvacuationVo.getFloorId());
|
|
|
+ if(deviceList.getCode()==200){
|
|
|
+ List<Map<String,Object>> mapList = (List <Map <String, Object>>) deviceList.getData();
|
|
|
+ for(Map<String,Object> map:mapList){
|
|
|
+ log.info("喇叭日志============================="+map);
|
|
|
+ if(StringUtils.isNotNull(map.get("deviceSn")) && StringUtils.isNotNull(map.get("port"))){
|
|
|
+ List<PlayVo> playVoList = new ArrayList<>();
|
|
|
+ PlayVo playVo = new PlayVo();
|
|
|
+ playVo.setSn(map.get("deviceSn")+"");
|
|
|
+ playVo.setDeviceIp(map.get("deviceIp")+"");
|
|
|
+ playVo.setPort(Integer.parseInt(map.get("port")+""));
|
|
|
+ ParamVo paramVo=new ParamVo();
|
|
|
+ paramVo.setVol(Integer.parseInt(map.get("deviceVol").toString()));
|
|
|
+ playVo.setParams(paramVo);
|
|
|
+ playVoList.add(playVo);
|
|
|
+ remoteSpeakService.textParseUrlAppIps(audioSyntheses.get(0).getNewMusicUrl(),playVoList);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ log.error("开启喇叭失败!!!!!:"+e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关联过滤线路
|
|
|
+ *
|
|
|
+ * @param allPointMap 所有线路map
|
|
|
+ * @param startPointList 预案发生的点关联的所有线路
|
|
|
+ * @return 逃生线路主
|
|
|
+ */
|
|
|
+ public Consumer <List <List <LabExitLineJoinPointVO>>> joinLine(Map <String, Object> allPointMap, List <List <LabExitLineJoinPointVO>> startPointList, LabExitLineEvacuationVo labExitLineEvacuationVo) {
|
|
|
+ Set <LabExitLineJoinPointVO> linePointSet = new LinkedHashSet <>();
|
|
|
+ Set <LabExitLineJoinPointVO> lightPointSet = new LinkedHashSet <>();
|
|
|
+ List <List <LabExitLineJoinPointVO>> groupPointList = new ArrayList <>();
|
|
|
+
|
|
|
+ //todo 添加一个过滤只有灯点的消费者
|
|
|
+ Consumer <List <LabExitLineJoinPointVO>> lightPoint = a -> Optional.ofNullable(a).orElseGet(Collections::emptyList)
|
|
|
+ .stream()
|
|
|
+ .filter(b -> b.getPointAttribute() == 2).forEach(b -> lightPointSet.add(b));
|
|
|
+ //todo 预案点保存线路和灯
|
|
|
+ Consumer <List <List <LabExitLineJoinPointVO>>> consumer1 = a -> Optional.ofNullable(a)
|
|
|
+ .orElseGet(Collections::emptyList)
|
|
|
+ .stream()
|
|
|
+ .forEach(b -> {
|
|
|
+ linePointSet.addAll(b);
|
|
|
+ //属性是2,说明只返回灯点
|
|
|
+ lightPoint.accept(b);
|
|
|
+ //todo 在添加一个完成线路点的集合
|
|
|
+ suppleBuildAndFloor(b.stream().collect(Collectors.toSet()), labExitLineEvacuationVo);
|
|
|
+ groupPointList.add(b);
|
|
|
+ });
|
|
|
+ consumer1.accept(startPointList);
|
|
|
+
|
|
|
+ //todo 加一个子线路的消费者,如果子线路和主线路重合,需要给删除的delAdder添加1,否则0
|
|
|
+ LongAdder delAdder = new LongAdder();
|
|
|
+ Consumer <LabExitLineJoinPointVO> checkSonPoint = x -> startPointList.stream().forEach(b -> {
|
|
|
+ Optional.ofNullable(b).orElseGet(Collections::emptyList)
|
|
|
+ .stream()
|
|
|
+ .forEach(d -> {
|
|
|
+ boolean bb = d.getPointName().equals(x.getPointName());
|
|
|
+ if (bb && delAdder.intValue() == 0) {
|
|
|
+ delAdder.increment();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ //todo 其他点保存线路和灯
|
|
|
+ Consumer <List <List <LabExitLineJoinPointVO>>> consumer2 = a -> Optional.ofNullable(a)
|
|
|
+ .orElseGet(Collections::emptyList)
|
|
|
+ .stream()
|
|
|
+ .forEach(b -> {
|
|
|
+ //todo 这里判断是否一直删除,boolean不能传入,暂时用这个校验
|
|
|
+ delAdder.reset();
|
|
|
+ Optional.ofNullable(b).orElseGet(Collections::emptyList)
|
|
|
+ .stream()
|
|
|
+ .forEach(t -> {
|
|
|
+ checkSonPoint.accept(t);
|
|
|
+ if (delAdder.intValue() == 0) {
|
|
|
+ linePointSet.add(t);
|
|
|
+ //属性是2,说明只返回灯点
|
|
|
+ if (t.getPointAttribute() == 2) {
|
|
|
+ lightPointSet.add(t);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ //todo 在添加一个完成线路点的集合
|
|
|
+ suppleBuildAndFloor(b.stream().collect(Collectors.toSet()), labExitLineEvacuationVo);
|
|
|
+ groupPointList.add(b);
|
|
|
+ });
|
|
|
+
|
|
|
+ allPointMap.put("groupPointList", groupPointList);
|
|
|
+ //补全线路下的所有灯的部门id和楼层id
|
|
|
+ suppleBuildAndFloor(linePointSet, labExitLineEvacuationVo);
|
|
|
+ //补全灯点的部门id和楼层id
|
|
|
+ suppleBuildAndFloor(lightPointSet, labExitLineEvacuationVo);
|
|
|
+ allPointMap.put("linePointSet", linePointSet);
|
|
|
+ allPointMap.put("lightPointSet", lightPointSet);
|
|
|
+
|
|
|
+ return consumer2;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //补全部门id和楼层id
|
|
|
+ public void suppleBuildAndFloor(Set <LabExitLineJoinPointVO> lineSet, LabExitLineEvacuationVo labExitLineEvacuationVo) {
|
|
|
+ lineSet.forEach(a -> {
|
|
|
+ a.setBuildId(labExitLineEvacuationVo.getBuildId());
|
|
|
+ a.setFloorId(labExitLineEvacuationVo.getFloorId());
|
|
|
+ a.setPointVOList(null);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //todo 针对实验室计算出当前实验室的各种线路,过滤到最优线路
|
|
|
+ public CompletableFuture <Map <String, Object>> optimalRoute(List <LabExitLineJoinPointVO> linePointVOList, Integer[][] path, Integer[] chain, int i, int j, ArrayList <Integer[][]> oldList, List <LabExitLineJoinPointVO> oldRelationalData) {
|
|
|
+ //输出源到目的地
|
|
|
+ logger.info("\n " + (linePointVOList.get(i).getPointName()) + "->" + (linePointVOList.get(i).getPointVOList().get(j).getPointName()) + " ");
|
|
|
+ //保存两个点之间的途径点。
|
|
|
+ List <LabExitLineJoinPointVO> joinPointVOS = new ArrayList <>();
|
|
|
+ //todo 这里用map保存三个结果,一个是计算好的线路,一个是顶点名称,一个是计算的顶点到最优线路距离.
|
|
|
+ Map <String, Object> joinPointMap = new HashMap <>();
|
|
|
+ //输出最短路径的长度
|
|
|
+ if (linePointVOList.get(i).getPointVOList().get(j).getPointDistance() == M) {
|
|
|
+ logger.info(" NA ");
|
|
|
+ //todo 这里原来是NA,也就是说没有匹配到线路,如果线路出现坏点,并且没有其他备用线路,那么就选择坏点线路
|
|
|
+ int countPoint = 0;
|
|
|
+ for (int x = 0; x < V; x++) {
|
|
|
+ for (int y = 0; y < V; y++) {
|
|
|
+ if (x != y) {//只是避免了vi->vi的输出
|
|
|
+ if (oldRelationalData.get(x).getPointAttribute() == 4 && oldRelationalData.get(x).getPointVOList().get(y).getPointAttribute() == 1) {
|
|
|
+ if (linePointVOList.get(i).getPointName().equals(oldRelationalData.get(x).getPointVOList().get(y).getPointName())) {
|
|
|
+ countPoint++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // todo 这里需要在做一次线路计算,出现NA有可能是实验室发生预案后,其他实验室路径这个实验室已经被标记坏点,但是其他实验室有没有备用线路选择,所以只能继续往危险的实验室路径撤离。
|
|
|
+ if (countPoint < 1) {
|
|
|
+ getHistoryLinePoint(oldRelationalData, oldList.get(0), chain, i, j, joinPointVOS);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ getHistoryLinePoint(linePointVOList, path, chain, i, j, joinPointVOS);
|
|
|
+ }
|
|
|
+
|
|
|
+ joinPointMap.put("joinPointVOS", joinPointVOS);
|
|
|
+ joinPointMap.put("pointName", linePointVOList.get(i).getPointName());
|
|
|
+ joinPointMap.put("pointDistanceVo", linePointVOList.get(i).getPointVOList().get(j));
|
|
|
+
|
|
|
+ return CompletableFuture.completedFuture(joinPointMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取历史途径的线路点
|
|
|
+ public void getHistoryLinePoint(List <LabExitLineJoinPointVO> linePointVOList, Integer[][] path, Integer[] chain, int i, int j, List <LabExitLineJoinPointVO> joinPointVOS) {
|
|
|
+ logger.info(linePointVOList.get(i).getPointVOList().get(j).getPointDistance() + " ");
|
|
|
+ int count = 0;
|
|
|
+ int k = j;
|
|
|
+ do {
|
|
|
+ k = chain[count++] = path[i][k];
|
|
|
+ } while (i != k);
|
|
|
+ chain = reverse(chain, count);
|
|
|
+ //输出路径
|
|
|
+ joinPointVOS.add(linePointVOList.get(chain[0]));
|
|
|
+ logger.info(linePointVOList.get(chain[0]).getPointName() + "##" + linePointVOList.get(chain[0]).getPointAttribute());
|
|
|
+
|
|
|
+ for (k = 1; k < count; k++) {
|
|
|
+ joinPointVOS.add(linePointVOList.get(chain[k]));
|
|
|
+ logger.info("->" + (linePointVOList.get(chain[k]).getPointName()) + "##" + linePointVOList.get(chain[k]).getPointAttribute());
|
|
|
+
|
|
|
+ }
|
|
|
+ joinPointVOS.add(linePointVOList.get(j));
|
|
|
+ logger.info("->" + linePointVOList.get(j).getPointName() + "##" + linePointVOList.get(j).getPointAttribute());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 新增逃生线路主
|
|
|
+ *
|
|
|
+ * @param lineVertexVo 逃生线路主
|
|
|
+ * @return 结果
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public int insertLabExitLineVertex(LabExitLineVertexVo lineVertexVo) {
|
|
|
+ LabExitLineVertex labExitLineVertex = new LabExitLineVertex();
|
|
|
+ labExitLineVertex.setBuildId(lineVertexVo.getBuildId());
|
|
|
+ labExitLineVertex.setFloorId(lineVertexVo.getFloorId());
|
|
|
+ labExitLineVertex.setRelationalData(JSONArray.toJSONString(lineVertexVo.getRelationalData()));
|
|
|
+ labExitLineVertex.setLayoutData(lineVertexVo.getLayoutData());
|
|
|
+ labExitLineVertex.setImgUrl(lineVertexVo.getImgUrl());
|
|
|
+ labExitLineVertex.setCanvasWidth(lineVertexVo.getCanvasWidth());
|
|
|
+ labExitLineVertex.setCanvasHeight(lineVertexVo.getCanvasHeight());
|
|
|
+ labExitLineVertexMapper.deleteLabExitLineVertexByFloorId(labExitLineVertex);
|
|
|
+ //设置其他公共字段
|
|
|
+ SaveUtil.setCommonAttr(labExitLineVertex);
|
|
|
+ labExitLineVertexMapper.insertLabExitLineVertex(labExitLineVertex);
|
|
|
+
|
|
|
+ //todo 循环插入点和实验室id关系布局数据
|
|
|
+ Consumer<List<LabBuildFloorLayout>> consumer = a -> Optional.ofNullable(a)
|
|
|
+ .orElseGet(Collections::emptyList)
|
|
|
+ .stream()
|
|
|
+ .forEach(b->{
|
|
|
+ //补全楼栋楼层id
|
|
|
+ b.setBuildId(lineVertexVo.getBuildId());
|
|
|
+ b.setFloorId(lineVertexVo.getFloorId());
|
|
|
+ //设置其他公共字段
|
|
|
+ SaveUtil.setCommonAttr(b);
|
|
|
+ labBuildFloorLayoutMapper.insertLabBuildFloorLayout(b);
|
|
|
+ });
|
|
|
+ //todo 删除布局图点和实验室id关系数据
|
|
|
+ LabBuildFloorLayout labBuildFloorLayout = new LabBuildFloorLayout();
|
|
|
+ labBuildFloorLayout.setBuildId(lineVertexVo.getBuildId());
|
|
|
+ labBuildFloorLayout.setFloorId(lineVertexVo.getFloorId());
|
|
|
+ labBuildFloorLayoutMapper.deleteLabBuildFloorLayout(labBuildFloorLayout);
|
|
|
+ //todo 消费者调用函数
|
|
|
+ consumer.accept(lineVertexVo.getBuildFloorLayouts());
|
|
|
+
|
|
|
+
|
|
|
+ //todo 删除点和继电器绑定关系
|
|
|
+ LabExitPointRelay exitPointRelay = new LabExitPointRelay();
|
|
|
+ exitPointRelay.setBuildId(lineVertexVo.getBuildId());
|
|
|
+ exitPointRelay.setFloorId(lineVertexVo.getFloorId());
|
|
|
+ labExitPointRelayMapper.deleteLabExitPointRelay(exitPointRelay);
|
|
|
+ //todo 点和继电器绑定关系
|
|
|
+ Optional.ofNullable(lineVertexVo.getExitPointRelayList())
|
|
|
+ .orElseGet(Collections::emptyList)
|
|
|
+ .stream()
|
|
|
+ .forEach(a->{
|
|
|
+ //补全楼栋楼层id
|
|
|
+ a.setBuildId(lineVertexVo.getBuildId());
|
|
|
+ a.setFloorId(lineVertexVo.getFloorId());
|
|
|
+ //设置其他公共字段
|
|
|
+ SaveUtil.setCommonAttr(a);
|
|
|
+ labExitPointRelayMapper.insertLabExitPointRelay(a);
|
|
|
+ });
|
|
|
+// Consumer<List<LabExitJoinSubpoint>> consumer = a -> Optional.ofNullable(a)
|
|
|
+// .orElseGet(Collections::emptyList)
|
|
|
+// .stream()
|
|
|
+// .forEach(b->{
|
|
|
+// //补全楼栋楼层id
|
|
|
+// b.setBuildId(lineVertexVo.getBuildId());
|
|
|
+// b.setFloorId(lineVertexVo.getFloorId());
|
|
|
+// //设置其他公共字段
|
|
|
+// SaveUtil.setCommonAttr(b);
|
|
|
+// labExitJoinSubpointMapper.insertLabExitJoinSubpoint(b);
|
|
|
+// });
|
|
|
+// //todo 删除楼层的点和实验室id关系数据
|
|
|
+// LabExitJoinSubpoint labExitJoinSubpoint = new LabExitJoinSubpoint();
|
|
|
+// labExitJoinSubpoint.setBuildId(lineVertexVo.getBuildId());
|
|
|
+// labExitJoinSubpoint.setFloorId(lineVertexVo.getFloorId());
|
|
|
+// labExitJoinSubpointMapper.deleteLabExitJoinSubpointByFloorId(labExitJoinSubpoint);
|
|
|
+// //todo 消费者调用函数
|
|
|
+// consumer.accept(lineVertexVo.getJoinSubpointList());
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 修改逃生线路主
|
|
|
+ *
|
|
|
+ * @param labExitLineVertex 逃生线路主
|
|
|
+ * @return 结果
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public int updateLabExitLineVertex(LabExitLineVertex labExitLineVertex) {
|
|
|
+ labExitLineVertex.setUpdateTime(DateUtils.getNowDate());
|
|
|
+ labExitLineVertex.setUpdateBy(SecurityUtils.getUsername());
|
|
|
+ return labExitLineVertexMapper.updateLabExitLineVertex(labExitLineVertex);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量删除逃生线路主
|
|
|
+ *
|
|
|
+ * @param ids 需要删除的逃生线路主主键
|
|
|
+ * @return 结果
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public int deleteLabExitLineVertexByIds(Long[] ids) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public ArrayList <Integer[][]> flody(List <LabExitLineJoinPointVO> dist) {
|
|
|
+ Integer[][] path = new Integer[V][V];//存储的是从i->j经过的最后一个节点
|
|
|
+ for (int i = 0; i < V; i++) {
|
|
|
+ for (int j = 0; j < V; j++) {
|
|
|
+ path[i][j] = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (int k = 0; k < V; k++) {
|
|
|
+ for (int i = 0; i < V; i++) {
|
|
|
+ for (int j = 0; j < V; j++) {
|
|
|
+ if (dist.get(i).getPointVOList().get(j).getPointDistance() > MAXSUM(dist.get(i).getPointVOList().get(k).getPointDistance(), dist.get(k).getPointVOList().get(j).getPointDistance())) {
|
|
|
+ path[i][j] = path[k][j];//存储的是从i->j经过的最后一个节点
|
|
|
+ dist.get(i).getPointVOList().get(j).setPointDistance(MAXSUM(dist.get(i).getPointVOList().get(k).getPointDistance(), dist.get(k).getPointVOList().get(j).getPointDistance()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ArrayList <Integer[][]> list = new ArrayList <Integer[][]>();
|
|
|
+ list.add(path);
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public static Integer[] reverse(Integer[] chain, int count) {
|
|
|
+ int temp;
|
|
|
+ for (int i = 0, j = count - 1; i < j; i++, j--) {
|
|
|
+ temp = chain[i];
|
|
|
+ chain[i] = chain[j];
|
|
|
+ chain[j] = temp;
|
|
|
+ }
|
|
|
+ return chain;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static int MAXSUM(int a, int b) {
|
|
|
+ return (a != M && b != M) ? (a + b) : M;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|