| 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.framework.common.Cools; | 
| import com.zy.acs.framework.exception.CoolException; | 
| import com.zy.acs.common.constant.RedisConstant; | 
| import com.zy.acs.common.utils.RedisSupport; | 
| import com.zy.acs.manager.core.service.astart.domain.DynamicNode; | 
| import com.zy.acs.manager.manager.entity.Code; | 
| import com.zy.acs.manager.manager.service.CodeService; | 
| import com.zy.acs.manager.manager.service.RouteService; | 
| import lombok.extern.slf4j.Slf4j; | 
|   | 
| import java.util.ArrayList; | 
| import java.util.List; | 
| import java.util.Optional; | 
|   | 
| /** | 
|  * 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; | 
|   | 
|     public static final Boolean CACHE_CODE_MATRIX = Boolean.FALSE; | 
|   | 
|     private String[][] codeMatrix; | 
|   | 
|     public static final Boolean CACHE_MAP_MATRIX = Boolean.FALSE; | 
|   | 
|     private int[][] mapMatrix; | 
|   | 
|     public static final Boolean CACHE_TURN_MATRIX = Boolean.FALSE; | 
|   | 
|     private int[][] turnMatrix; | 
|   | 
|     public static final Boolean CACHE_CDA_MATRIX = Boolean.FALSE; | 
|   | 
|     private String[][] cdaMatrix; | 
|   | 
|     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); | 
|         String[][] cdaMatrix; | 
|   | 
|         if (!CACHE_CDA_MATRIX) { | 
|             if (null == this.cdaMatrix) { | 
|                 cdaMatrix = this.initCdaMatrix(lev); | 
|                 setCdaMatrix(lev, cdaMatrix); | 
|             } else { | 
|                 cdaMatrix = this.cdaMatrix; | 
|             } | 
|         } else { | 
|             String cdaMatrixStr = redis.getValue(RedisConstant.AGV_MAP_ASTAR_CDA_FLAG, String.valueOf(lev)); | 
|             if (Cools.isEmpty(cdaMatrixStr)) { | 
|                 cdaMatrix = this.initCdaMatrix(lev); | 
|                 setCdaMatrix(lev, cdaMatrix); | 
|             } else { | 
|                 cdaMatrix = JSON.parseObject(cdaMatrixStr, String[][].class); | 
|             } | 
|         } | 
|         if (null == cdaMatrix) { | 
|             throw new CoolException("the floor " + lev + " cannot found cda matrix !!!"); | 
|         } | 
|         return cdaMatrix; | 
|     } | 
|   | 
|     public void setCdaMatrix(Integer lev, String[][] cdaMatrix) { | 
|         if (!CACHE_CDA_MATRIX) { | 
|             this.cdaMatrix = cdaMatrix; | 
|         } else { | 
|             redis.setValue(RedisConstant.AGV_MAP_ASTAR_CDA_FLAG, String.valueOf(lev), JSON.toJSONString(cdaMatrix)); | 
|         } | 
|     } | 
|   | 
|     public int[][] getTurnMatrix(Integer lev) { | 
|         lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV); | 
|         int[][] turnMatrix; | 
|         if (!CACHE_TURN_MATRIX) { | 
|             if (null == this.turnMatrix) { | 
|                 turnMatrix = this.initTurnMatrix(lev); | 
|                 setTurnMatrix(lev, turnMatrix); | 
|             } else { | 
|                 turnMatrix = this.turnMatrix; | 
|             } | 
|         } else { | 
|             String turnMatrixStr = redis.getValue(RedisConstant.AGV_MAP_ASTAR_TURN_FLAG, String.valueOf(lev)); | 
|             if (Cools.isEmpty(turnMatrixStr)) { | 
|                 turnMatrix = this.initTurnMatrix(lev); | 
|                 setTurnMatrix(lev, turnMatrix); | 
|             } else { | 
|                 turnMatrix = JSON.parseObject(turnMatrixStr, int[][].class); | 
|             } | 
|         } | 
|         if (null == turnMatrix) { | 
|             throw new CoolException("the floor " + lev + " cannot found turn matrix !!!"); | 
|         } | 
|         return turnMatrix; | 
|     } | 
|   | 
|     public void setTurnMatrix(Integer lev, int[][] turnMatrix) { | 
|         if (!CACHE_TURN_MATRIX) { | 
|             this.turnMatrix = turnMatrix; | 
|         } else { | 
|             redis.setValue(RedisConstant.AGV_MAP_ASTAR_TURN_FLAG, String.valueOf(lev), JSON.toJSONString(turnMatrix)); | 
|         } | 
|     } | 
|   | 
|     public int[][] getMapMatrix(Integer lev, List<String> lockNodes) { | 
|         lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV); | 
|         int[][] mapMatrix; | 
|         if (!CACHE_MAP_MATRIX) { | 
|             if (null == this.mapMatrix) { | 
|                 mapMatrix = this.initMapMatrix(lev); | 
|                 setMapMatrix(lev, mapMatrix); | 
|             } else { | 
|                 mapMatrix = this.mapMatrix; | 
|             } | 
|         } else { | 
|             String mapMatrixStr = redis.getValue(RedisConstant.AGV_MAP_ASTAR_FLAG, String.valueOf(lev)); | 
|             if (Cools.isEmpty(mapMatrixStr)) { | 
|                 mapMatrix = this.initMapMatrix(lev); | 
|                 setMapMatrix(lev, mapMatrix); | 
|             } else { | 
|                 mapMatrix = JSON.parseObject(mapMatrixStr, int[][].class); | 
|             } | 
|         } | 
|         if (null == mapMatrix) { | 
|             throw new CoolException("the floor " + lev + " cannot found map matrix !!!"); | 
|         } | 
|         if (!Cools.isEmpty(lockNodes)) { | 
|             mapMatrix = filterMapData(mapMatrix, lev, lockNodes); | 
|         } | 
|         return mapMatrix; | 
|     } | 
|   | 
|     public void setMapMatrix(Integer lev, int[][] mapMatrix) { | 
|         if (!CACHE_MAP_MATRIX) { | 
|             this.mapMatrix = mapMatrix; | 
|         } else { | 
|             redis.setValue(RedisConstant.AGV_MAP_ASTAR_FLAG, String.valueOf(lev), JSON.toJSONString(mapMatrix)); | 
|         } | 
|     } | 
|   | 
|     public String[][] getCodeMatrix(Integer lev) { | 
|         lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV); | 
|         String[][] codeMatrix; | 
|         if (!CACHE_CODE_MATRIX) { | 
|             if (null == this.codeMatrix) { | 
|                 codeMatrix = this.initCodeMatrix(lev); | 
|                 setCodeMatrix(lev, codeMatrix); | 
|             } else { | 
|                 codeMatrix = this.codeMatrix; | 
|             } | 
|         } else { | 
|             String codeMatrixStr = redis.getValue(RedisConstant.AGV_MAP_ASTAR_CODE_FLAG, String.valueOf(lev)); | 
|             if (Cools.isEmpty(codeMatrixStr)) { | 
|                 codeMatrix = this.initCodeMatrix(lev); | 
|                 setCodeMatrix(lev, codeMatrix); | 
|             } else { | 
|                 codeMatrix = JSON.parseObject(codeMatrixStr, String[][].class); | 
|             } | 
|         } | 
|         if (null == codeMatrix) { | 
|             throw new CoolException("the floor " + lev + " cannot found code matrix !!!"); | 
|         } | 
|         return codeMatrix; | 
|     } | 
|   | 
|     public void setCodeMatrix(Integer lev, String[][] codeMatrix) { | 
|         if (!CACHE_CODE_MATRIX) { | 
|             this.codeMatrix = codeMatrix; | 
|         } else { | 
|             redis.setValue(RedisConstant.AGV_MAP_ASTAR_CODE_FLAG, String.valueOf(lev), JSON.toJSONString(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) { | 
|         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) { | 
|         lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_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])) { | 
|                     cdaMatrix[i][j] = CdaNodeType.DISABLE.val; | 
|                 } else { | 
|                     Code currCode = codeService.selectByData(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) { | 
|         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.selectByData(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) { | 
|         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 synchronized String[][] initCodeMatrix(Integer lev) { | 
|         log.info("【ASTAR】正在计算矩阵数据......"); | 
|         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) | 
|         ); | 
| //        int xCount = codeService.selectDistinctCountFromX(); | 
| //        int yCount = codeService.selectDistinctCountFromY(); | 
| //        // [][] 第一个是排的数量 第二个是列的数量 | 
| //        String[][] codeMatrix = new String[yCount][xCount]; | 
|   | 
|         List<Double> xIdxList = new ArrayList<>(); | 
|         List<Double> yIdxList = new ArrayList<>(); | 
|         for (Code code : codeList) { | 
|             Double x = code.getX(); | 
|             Double y = code.getY(); | 
|             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()]; | 
|   | 
|         int idxX = -1; | 
|         int idxY = -1; | 
|         double lastX = -1; | 
|         double lastY = -1; | 
|         for (Code code : codeList) { | 
|             Double x = code.getX(); | 
|             Double y = code.getY(); | 
| //            if (y != lastY) { | 
| //                idxY ++; | 
| //                idxX = 0; | 
| //                lastY = y; | 
| //                lastX = x; | 
| //            } | 
| //            if (x != lastX) { | 
| //                idxX++; | 
| //                lastX = x; | 
| //            } | 
| //            codeMatrix[idxY][idxX] = code.getData(); | 
|   | 
|             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<String> queryCodeListFromDynamicNode(Integer lev, String nodeType) { | 
|         List<String> nodes = new ArrayList<>(); | 
|         if (Cools.isEmpty(nodeType)) { | 
|             return nodes; | 
|         } | 
|         lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV); | 
|         DynamicNode[][] dynamicMatrix = getDynamicMatrix(lev); | 
|         String[][] codeMatrix = this.getCodeMatrix(lev); | 
|         for (int i = 0; i < codeMatrix.length; i++) { | 
|             for (int j = 0; j < codeMatrix[i].length; j++) { | 
|                 if (nodeType.equals(dynamicMatrix[i][j].getVehicle())) { | 
|                     nodes.add(codeMatrix[i][j]); | 
|                 } | 
|             } | 
|         } | 
|         return nodes; | 
|     } | 
|   | 
|     public void modifyDynamicMatrix(Integer lev, List<String> codeList, String vehicle) { | 
|         this.modifyDynamicMatrix(lev, codeList, vehicle, false); | 
|     } | 
|   | 
|     public synchronized void modifyDynamicMatrix(Integer lev, List<String> codeList, String vehicle, boolean reset) { | 
|         lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV); | 
|         DynamicNode[][] dynamicMatrix = getDynamicMatrix(lev); | 
|   | 
|         if (!reset) { | 
|             if (Cools.isEmpty(codeList, vehicle)) { | 
|                 return; | 
|             } | 
|             int serial = 1; | 
|             for (String code : codeList) { | 
|                 int[] node = getCodeMatrixIdx(lev, code); | 
|                 dynamicMatrix[node[0]][node[1]] = new DynamicNode(vehicle, serial); | 
|                 serial++; | 
|             } | 
|         } else { | 
|             if (Cools.isEmpty(vehicle)) { | 
|                 return; | 
|             } | 
|             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<String> codeList) { | 
|         this.modifyDynamicMatrix(lev, codeList, 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(); | 
|         } | 
|     } | 
|   | 
| } |