/** * Calculates patrol's <b>Coordinates</b>.</br> * * @param guardians : a list of <b>Guardians</b> to share the patrol. * @return a list containing the <b>Coordinates</b> checkpoints of the patrol. (Debug) */ public ArrayList<Coordinate> calculCoordinatesPatrouille(ArrayList<Guardian> guardians) { // long debut = System.currentTimeMillis(); int dimension = grid.getDimension(); // ArrayList de coordonnees pour l'itineraire de patrouille ArrayList<Coordinate> validCoordinates = new ArrayList<Coordinate>(); // ArrayList de coordonnees pour l'itineraire de patrouille // HashMap de coordonnees, et de l'ArrayList contenant le champ de vision a partir de cette // coordoneee HashMap<Coordinate, ArrayList<Coordinate>> visible = new HashMap<Coordinate, ArrayList<Coordinate>>(); // init ArrayList, tableau et HashMap for (int i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) { Coordinate coordTemp = new Coordinate(i, j); // System.out.println(grid); if (grid.isValid(coordTemp) && grid.isDirectlyAccessible(coordTemp)) { validCoordinates.add(coordTemp); visible.put(coordTemp, visualFieldCalculation(coordTemp)); } } } // Remplissage d'une HashMap avec les gardians pour Cle, et une ArrayList de coordonnees // atteignables en Valeur HashMap<Guardian, ArrayList<Coordinate>> guardianToCoordinates = new HashMap<Guardian, ArrayList<Coordinate>>(); for (Guardian guard : guardians) { ArrayList<Coordinate> accessibleCoordinatesGuardian = new ArrayList<Coordinate>(); for (Coordinate coord : validCoordinates) { ArrayList<Coordinate> itineraireTemp = routeCalculation(guard.getPosition(), coord, false); if (itineraireTemp.size() > 2 || areAdjacent(guard.getPosition(), coord)) // Coord accessible accessibleCoordinatesGuardian.add(coord); } accessibleCoordinatesGuardian.add(guard.getPosition()); Collections.sort(accessibleCoordinatesGuardian, new Tri.SortByCoordinate()); guardianToCoordinates.put(guard, accessibleCoordinatesGuardian); } // System.out.println(guardianVersCoordinates); // System.out.println(); // System.out.println(); // Fusion en ArrayList si plusieurs gardiens ont les mêmes coordonnees atteignables HashMap<ArrayList<Coordinate>, ArrayList<Guardian>> coordinatesToGuardians = new HashMap<ArrayList<Coordinate>, ArrayList<Guardian>>(); for (Guardian guard : guardians) { ArrayList<Guardian> guardiansCoord = coordinatesToGuardians.get(guardianToCoordinates.get(guard)); if (guardiansCoord == null) { guardiansCoord = new ArrayList<Guardian>(); } if (!guardiansCoord.contains(guard)) guardiansCoord.add(guard); coordinatesToGuardians.put(guardianToCoordinates.get(guard), guardiansCoord); } // System.out.println(coordinatesVersGuardian); // A ce moment, coordinatesVersGuardian contient des ArrayList de coordonnees atteignables // comme clé, // et des ArrayList des guardiens qui peuvent les atteindre comme valeur // HashMap inverse de CoordinatesVersGuardians HashMap<ArrayList<Guardian>, ArrayList<Coordinate>> guardiansToCoordinates = new HashMap<ArrayList<Guardian>, ArrayList<Coordinate>>(); for (ArrayList<Coordinate> alCoord : coordinatesToGuardians.keySet()) { guardiansToCoordinates.put(coordinatesToGuardians.get(alCoord), alCoord); } // initialisation des coordonnes a visiter pour effectuer la patrouille (checkpoint) // ne represente pas l'itineraire // ne garde que quelques coordonnes cles ArrayList<Coordinate> patrolCoordinates = new ArrayList<Coordinate>(validCoordinates); // calculer si un ensemble d'ArrayList de coordonnees ne contiendrait pas par hasard toutes les // coordonnees visibles depuis une certaine coordonnee // calculer si le fait de supprimer une coordonnee enleve des cases visibles a l'ArrayList for (int i = 0; i < patrolCoordinates.size(); i++) { ArrayList<Coordinate> coordinatesMinusOne = new ArrayList<Coordinate>(); ArrayList<Coordinate> unsortedVisibleCoordinatesMinusOne = new ArrayList<Coordinate>(); ArrayList<Coordinate> sortedVisibleCoordinatesMinusOne = new ArrayList<Coordinate>(); for (Coordinate coordTest : patrolCoordinates) { coordinatesMinusOne.add(coordTest); } Coordinate coordReference = patrolCoordinates.get(i); coordinatesMinusOne.remove(coordReference); for (Coordinate coordTemp : coordinatesMinusOne) { unsortedVisibleCoordinatesMinusOne.addAll(visible.get(coordTemp)); } Set<Coordinate> mySet = new HashSet<Coordinate>(unsortedVisibleCoordinatesMinusOne); sortedVisibleCoordinatesMinusOne.addAll(mySet); if (sortedVisibleCoordinatesMinusOne.containsAll(validCoordinates)) { patrolCoordinates.remove(coordReference); i--; } } return patrolCoordinates; }
/** * Calculates patrol routes (depending on reachable <b>Coordinates</b> by <b>Guardian</b>) to see * all the <b>Grid</b>.</br> A patrol route is then assigned to each <b>Guardian</b> (If several * <b>Guardians</b> have access to the same <b>Coordinates</b>, their patrol will be the same). * * @param guardians : a list of <b>Guardians</b> in order to directly assign their patrol route. * @return a list containing all the <b>Coordinates</b> of all the patrols routes. (Debug) */ public ArrayList<Coordinate> patrolRouteCalculation(ArrayList<Guardian> guardians) { // long debut = System.currentTimeMillis(); int dimension = grid.getDimension(); // ArrayList de coordonnees pour l'itineraire de patrouille ArrayList<Coordinate> validCoordinates = new ArrayList<Coordinate>(); // ArrayList de coordonnees pour l'itineraire de patrouille // HashMap de coordonnees, et de l'ArrayList contenant le champ de vision a partir de cette // coordoneee HashMap<Coordinate, ArrayList<Coordinate>> visible = new HashMap<Coordinate, ArrayList<Coordinate>>(); // init ArrayList, tableau et HashMap for (int i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) { Coordinate coordTemp = new Coordinate(i, j); // System.out.println(grid); if (grid.isValid(coordTemp) && grid.isDirectlyAccessible(coordTemp)) { validCoordinates.add(coordTemp); visible.put(coordTemp, visualFieldCalculation(coordTemp)); } } } // Remplissage d'une HashMap avec les gardians pour Cle, et une ArrayList de coordonnees // atteignables en Valeur HashMap<Guardian, ArrayList<Coordinate>> guardianToCoordinates = new HashMap<Guardian, ArrayList<Coordinate>>(); for (Guardian guard : guardians) { ArrayList<Coordinate> accessibleCoordinatesGuardian = new ArrayList<Coordinate>(); for (Coordinate coord : validCoordinates) { ArrayList<Coordinate> itineraireTemp = routeCalculation(guard.getPosition(), coord, false); if (itineraireTemp.size() > 2 || areAdjacent(guard.getPosition(), coord)) // Coord accessible accessibleCoordinatesGuardian.add(coord); } accessibleCoordinatesGuardian.add(guard.getPosition()); Collections.sort(accessibleCoordinatesGuardian, new Tri.SortByCoordinate()); guardianToCoordinates.put(guard, accessibleCoordinatesGuardian); } // System.out.println(guardianVersCoordinates); // System.out.println(); // System.out.println(); // Fusion en ArrayList si plusieurs gardiens ont les mêmes coordonnees atteignables HashMap<ArrayList<Coordinate>, ArrayList<Guardian>> coordinatesToGuardians = new HashMap<ArrayList<Coordinate>, ArrayList<Guardian>>(); for (Guardian guard : guardians) { ArrayList<Guardian> guardiansCoord = coordinatesToGuardians.get(guardianToCoordinates.get(guard)); if (guardiansCoord == null) { guardiansCoord = new ArrayList<Guardian>(); } if (!guardiansCoord.contains(guard)) guardiansCoord.add(guard); coordinatesToGuardians.put(guardianToCoordinates.get(guard), guardiansCoord); } // System.out.println(coordinatesVersGuardian); // A ce moment, coordinatesVersGuardian contient des ArrayList de coordonnees atteignables // comme clé, // et des ArrayList des guardiens qui peuvent les atteindre comme valeur // HashMap inverse de CoordinatesVersGuardians HashMap<ArrayList<Guardian>, ArrayList<Coordinate>> guardiansToCoordinates = new HashMap<ArrayList<Guardian>, ArrayList<Coordinate>>(); for (ArrayList<Coordinate> alCoord : coordinatesToGuardians.keySet()) { guardiansToCoordinates.put(coordinatesToGuardians.get(alCoord), alCoord); } // initialisation des coordonnes a visiter pour effectuer la patrouille (checkpoint) // ne represente pas l'itineraire // ne garde que quelques coordonnes cles ArrayList<Coordinate> globalPatrolCoordinates = new ArrayList<Coordinate>(validCoordinates); // calculer si un ensemble d'ArrayList de coordonnees ne contiendrait pas par hasard toutes les // coordonnees visibles depuis une certaine coordonnee // calculer si le fait de supprimer une coordonnee enleve des cases visibles a l'ArrayList for (int i = 0; i < globalPatrolCoordinates.size(); i++) { ArrayList<Coordinate> coordinatesMinusOne = new ArrayList<Coordinate>(); ArrayList<Coordinate> unsortedVisibleCoordinatesMinusOne = new ArrayList<Coordinate>(); ArrayList<Coordinate> sortedVisibleCoordinatesMinusOne = new ArrayList<Coordinate>(); for (Coordinate coordTest : globalPatrolCoordinates) { coordinatesMinusOne.add(coordTest); } Coordinate coordReference = globalPatrolCoordinates.get(i); coordinatesMinusOne.remove(coordReference); for (Coordinate coordTemp : coordinatesMinusOne) { unsortedVisibleCoordinatesMinusOne.addAll(visible.get(coordTemp)); } Set<Coordinate> mySet = new HashSet<Coordinate>(unsortedVisibleCoordinatesMinusOne); sortedVisibleCoordinatesMinusOne.addAll(mySet); if (sortedVisibleCoordinatesMinusOne.containsAll(validCoordinates)) { globalPatrolCoordinates.remove(coordReference); i--; } } ArrayList<Coordinate> allPatrolsRoutes = new ArrayList<Coordinate>(); // debut boucle for (ArrayList<Guardian> alGuardian : coordinatesToGuardians.values()) { // On ne garde que les coordonnees atteignables par le groupe de gardiens ArrayList<Coordinate> groupPatrolCoordinates = new ArrayList<Coordinate>(globalPatrolCoordinates); // for(Coordinates coord : coordinatesPatrouilleGroupe) { // if(!guardiansVersCoordinates.get(alGuardian).contains(coord)) // coordinatesPatrouilleGroupe.remove(coord); // } for (int i = 0; i < groupPatrolCoordinates.size(); i++) { Coordinate coord = groupPatrolCoordinates.get(i); if (!guardiansToCoordinates.get(alGuardian).contains(coord)) { groupPatrolCoordinates.remove(coord); i--; } } TreeMap<Integer, Coordinate> patrolRoute = new TreeMap<Integer, Coordinate>(); // Si aucun checkpoint accessible if (groupPatrolCoordinates.size() == 0) { for (Guardian guardTemp : alGuardian) { guardTemp.setPatrolPosition(-2); } } else { ArrayList<Coordinate> routeFinal = new ArrayList<Coordinate>(); ArrayList<Coordinate> routeTemp = new ArrayList<Coordinate>(); Coordinate coordSource = groupPatrolCoordinates.get(0); Coordinate coordSourceTemp = coordSource; Coordinate coordTemp = null; int index = 0; while (groupPatrolCoordinates.size() > 0) { groupPatrolCoordinates.remove(coordSourceTemp); routeFinal.clear(); routeTemp.clear(); for (Coordinate coordDestinationTemp : groupPatrolCoordinates) { routeTemp = routeCalculation(coordSourceTemp, coordDestinationTemp, false); // System.out.println("Itineraire " + coordSourceTemp + " vers " + coordDestinationTemp // + " : " + itineraireTemp); if (routeFinal.size() == 0 || (routeTemp.size() != 0 && routeTemp.size() < routeFinal.size())) { routeFinal = new ArrayList<Coordinate>(routeTemp); coordTemp = coordDestinationTemp; } } // System.out.println(itineraireFinal); coordSourceTemp = coordTemp; for (int i = 0; i < routeFinal.size() - 1; i++) { patrolRoute.put(index, routeFinal.get(i)); index++; } } // Ajout de l'itineraire pour aller e la fin de la patrouille vers le debut routeFinal = routeCalculation(coordTemp, coordSource, false); for (int i = 0; i < routeFinal.size() - 1; i++) { patrolRoute.put(index, routeFinal.get(i)); index++; } // affectation de la patrouille a tous les gardiens, a modifier for (Guardian guardTemp : alGuardian) { guardTemp.setPatrol(patrolRoute); guardTemp.setReachableCoordinates(guardiansToCoordinates.get(alGuardian)); } allPatrolsRoutes.addAll(patrolRoute.values()); } // fin boucle } // entre 100 et 1000ms en fonction de la taille (complexite lineaire) // System.out.println(System.currentTimeMillis() - debut); // System.out.println(itinerairePatrouille); return allPatrolsRoutes; }