| package com.zy.acs.manager.core.service.floyd; | 
|   | 
| import com.alibaba.fastjson.JSON; | 
| import com.alibaba.fastjson.TypeReference; | 
| 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.manager.common.exception.BusinessException; | 
| import com.zy.acs.manager.core.service.astart.MapDataDispatcher; | 
| import com.zy.acs.manager.manager.entity.Code; | 
| import com.zy.acs.manager.manager.entity.CodeGap; | 
| import com.zy.acs.manager.manager.entity.Route; | 
| import com.zy.acs.manager.manager.service.CodeGapService; | 
| import com.zy.acs.manager.manager.service.CodeService; | 
| import com.zy.acs.manager.manager.service.RouteService; | 
| import com.zy.acs.manager.system.service.ConfigService; | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| import org.springframework.stereotype.Component; | 
|   | 
| import javax.annotation.PostConstruct; | 
| import java.util.ArrayList; | 
| import java.util.Collections; | 
| import java.util.List; | 
|   | 
| /** | 
|  * Created by vincent on 2023/6/15 | 
|  */ | 
| @Slf4j | 
| @Component | 
| public class FloydNavigateService { | 
|   | 
|     public static final double INF = 999999.0; | 
|   | 
|     private final RedisSupport redis = RedisSupport.defaultRedisSupport; | 
|   | 
|     @Autowired | 
|     private CodeService codeService; | 
|     @Autowired | 
|     private CodeGapService codeGapService; | 
|     @Autowired | 
|     private RouteService routeService; | 
|     @Autowired | 
|     private ConfigService configService; | 
|   | 
|     private List<Long> matrixHeader; | 
|     private Double[][] adjacencyMatrix; | 
|     private int[][] pathMatrix; | 
|     private Double[][] floydMatrix; | 
|   | 
|     public List<Integer> calculatePath(Integer origin, Integer destination) { | 
|         List<Integer> path = new ArrayList<>(); | 
|   | 
|         path.add(destination); | 
|   | 
|         Integer current = destination; | 
|         while (!current.equals(origin)) { | 
|             current = this.pathMatrix[origin][current]; | 
|             path.add(current); | 
|         } | 
|   | 
|         Collections.reverse(path); | 
|         return path; | 
|     } | 
|   | 
|     public int codeIdx(Long codeId) { | 
|         return this.matrixHeader.indexOf(codeId); | 
|     } | 
|   | 
|     public Long getCodeId(int idx) { | 
|         return this.matrixHeader.get(idx); | 
|     } | 
|   | 
|     @SuppressWarnings("all") | 
|     @PostConstruct | 
|     public void generateMatrix() { | 
|         Integer lev = MapDataDispatcher.MAP_DEFAULT_LEV; | 
|   | 
|         String floydHeaderMatrixStr = redis.getValue(RedisConstant.MAP_FLOYD_MATRIX_HEADER_FLAG, String.valueOf(lev)); | 
|         String floydPathMatrixStr = redis.getValue(RedisConstant.MAP_FLOYD_MATRIX_PATH_FLAG, String.valueOf(lev)); | 
|         String floydMatrixStr = redis.getValue(RedisConstant.MAP_FLOYD_MATRIX_FLAG, String.valueOf(lev)); | 
|   | 
|         if (!Cools.isEmpty(floydMatrixStr) && !Cools.isEmpty(floydPathMatrixStr) && !Cools.isEmpty(floydHeaderMatrixStr)) { | 
|             this.matrixHeader = JSON.parseObject(floydHeaderMatrixStr, new TypeReference<ArrayList<Long>>() {}); | 
|             this.pathMatrix = JSON.parseObject(floydPathMatrixStr, int[][].class); | 
|             this.floydMatrix = JSON.parseObject(floydMatrixStr, Double[][].class); | 
|         } else { | 
|   | 
|             log.info("【FLOYD】正在计算矩阵数据......"); | 
|             List<Code> codeList = codeService.list(new LambdaQueryWrapper<Code>().eq(Code::getStatus, 1).eq(Code::getDeleted, false)); | 
|   | 
|             int size = codeList.size(); | 
|   | 
|             matrixHeader = new ArrayList<>(size); | 
|             adjacencyMatrix = new Double[size][size]; | 
|             pathMatrix = new int[size][size]; | 
|   | 
|             for (int i = 0; i < size; i++) { | 
|                 Code startCode = codeList.get(i); | 
|                 matrixHeader.add(startCode.getId()); | 
|                 for (int j = 0; j < size; j++) { | 
|                     Code endCode = codeList.get(j); | 
|                     Route route = routeService.findByCodeOfBoth(startCode.getId(), endCode.getId()); | 
|                     CodeGap codeGap = codeGapService.findByCodeOfBoth(startCode.getId(), endCode.getId()); | 
|   | 
|                     double distance = INF; | 
|                     int path = -1; | 
|   | 
|                     if (null != route && null != codeGap && codeGap.getDistance() > 0) { | 
|                         if (i != j) { | 
|                             distance = codeGap.getDistance(); | 
|                         } | 
|                         path = i; | 
|                     } | 
|   | 
|   | 
|                     adjacencyMatrix[i][j] = distance; | 
|   | 
|                     pathMatrix[i][j] = path; | 
|                 } | 
|             } | 
|   | 
|             floydMatrix = this.floydAlgorithm(adjacencyMatrix); | 
|   | 
|             redis.setValue(RedisConstant.MAP_FLOYD_MATRIX_HEADER_FLAG, String.valueOf(lev), JSON.toJSONString(matrixHeader)); | 
|             redis.setValue(RedisConstant.MAP_FLOYD_MATRIX_PATH_FLAG, String.valueOf(lev), JSON.toJSONString(pathMatrix)); | 
|             redis.setValue(RedisConstant.MAP_FLOYD_MATRIX_FLAG, String.valueOf(lev), JSON.toJSONString(floydMatrix)); | 
|         } | 
|   | 
|     } | 
|   | 
|     /** | 
|      * Floyd | 
|      */ | 
|     @SuppressWarnings("all") | 
|     private Double[][] floydAlgorithm(Double[][] graph) { | 
|         int n = graph.length; | 
|         Double[][] shortestPaths = new Double[n][n]; | 
|   | 
|         for (int i = 0; i < n; i++) { | 
|             for (int j = 0; j < n; j++) { | 
|                 shortestPaths[i][j] = graph[i][j]; | 
|             } | 
|         } | 
|   | 
|         for (int k = 0; k < n; k++) { | 
|             for (int i = 0; i < n; i++) { | 
|                 for (int j = 0; j < n; j++) { | 
|                     if (shortestPaths[i][k] + shortestPaths[k][j] < shortestPaths[i][j]) { | 
|                         shortestPaths[i][j] = shortestPaths[i][k] + shortestPaths[k][j]; | 
|                         pathMatrix[i][j] = pathMatrix[k][j]; | 
|                     } | 
|                 } | 
|             } | 
|         } | 
|   | 
|         return shortestPaths; | 
|     } | 
|   | 
|     public Double[][] getAdjacencyMatrix() { | 
|         if (null == adjacencyMatrix) { | 
|             throw new BusinessException("核心算法还在进行中"); | 
|         } | 
|         return adjacencyMatrix; | 
|     } | 
|   | 
|     public int[][] getPathMatrix() { | 
|         if (null == pathMatrix) { | 
|             throw new BusinessException("核心算法还在进行中"); | 
|         } | 
|         return pathMatrix; | 
|     } | 
|   | 
|     public List<Long> getMatrixHeader() { | 
|         if (null == matrixHeader) { | 
|             throw new BusinessException("核心算法还在进行中"); | 
|         } | 
|         return matrixHeader; | 
|     } | 
|   | 
|     public Double[][] getFloydMatrix() { | 
|         if (null == floydMatrix) { | 
|             throw new BusinessException("核心算法还在进行中"); | 
|         } | 
|         return floydMatrix; | 
|     } | 
| } |