diff --git a/be-graphes-model/src/main/java/org/insa/graphs/model/Path.java b/be-graphes-model/src/main/java/org/insa/graphs/model/Path.java index 6ebdb73..7ad0901 100644 --- a/be-graphes-model/src/main/java/org/insa/graphs/model/Path.java +++ b/be-graphes-model/src/main/java/org/insa/graphs/model/Path.java @@ -18,231 +18,340 @@ import java.util.List; */ public class Path { - /** - * Create a new path that goes through the given list of nodes (in order), - * choosing the fastest route if multiple are available. - * - * @param graph Graph containing the nodes in the list. - * @param nodes List of nodes to build the path. - * - * @return A path that goes through the given list of nodes. - * - * @throws IllegalArgumentException If the list of nodes is not valid, i.e. two - * consecutive nodes in the list are not connected in the graph. - * - * @deprecated Need to be implemented. - */ - public static Path createFastestPathFromNodes(Graph graph, List nodes) - throws IllegalArgumentException { - List arcs = new ArrayList(); - // TODO: - return new Path(graph, arcs); - } + /** + * Create a new path that goes through the given list of nodes (in order), + * choosing the fastest route if multiple are available. + * + * @param graph Graph containing the nodes in the list. + * @param nodes List of nodes to build the path. + * + * @return A path that goes through the given list of nodes. + * + * @throws IllegalArgumentException If the list of nodes is not valid, i.e. two + * consecutive nodes in the list are not connected in the graph. + * + */ + public static Path createFastestPathFromNodes(Graph graph, List nodes) + throws IllegalArgumentException { + int nodeListSize = nodes.size(); - /** - * Create a new path that goes through the given list of nodes (in order), - * choosing the shortest route if multiple are available. - * - * @param graph Graph containing the nodes in the list. - * @param nodes List of nodes to build the path. - * - * @return A path that goes through the given list of nodes. - * - * @throws IllegalArgumentException If the list of nodes is not valid, i.e. two - * consecutive nodes in the list are not connected in the graph. - * - * @deprecated Need to be implemented. - */ - public static Path createShortestPathFromNodes(Graph graph, List nodes) - throws IllegalArgumentException { - List arcs = new ArrayList(); - // TODO: - return new Path(graph, arcs); - } + List arcs = new ArrayList(nodeListSize); - /** - * Concatenate the given paths. - * - * @param paths Array of paths to concatenate. - * - * @return Concatenated path. - * - * @throws IllegalArgumentException if the paths cannot be concatenated (IDs of - * map do not match, or the end of a path is not the beginning of the - * next). - */ - public static Path concatenate(Path... paths) throws IllegalArgumentException { - if (paths.length == 0) { - throw new IllegalArgumentException("Cannot concatenate an empty list of paths."); - } - final String mapId = paths[0].getGraph().getMapId(); - for (int i = 1; i < paths.length; ++i) { - if (!paths[i].getGraph().getMapId().equals(mapId)) { - throw new IllegalArgumentException( - "Cannot concatenate paths from different graphs."); - } - } - ArrayList arcs = new ArrayList<>(); - for (Path path: paths) { - arcs.addAll(path.getArcs()); - } - Path path = new Path(paths[0].getGraph(), arcs); - if (!path.isValid()) { - throw new IllegalArgumentException( - "Cannot concatenate paths that do not form a single path."); - } - return path; - } + if(nodeListSize > 1) { + //nodes.size() - 1 because we look at i and i+1 + for(int i=0;i neighbourhood = nodes.get(i).getSuccessors(); - // Origin of the path - private final Node origin; + Arc fastestPath = null; - // List of arcs in this path. - private final List arcs; + for(Arc nextArc : neighbourhood) { + if(nextArc.getDestination().compareTo(nodes.get(i+1)) == 0) { + //here we find a path between i and i+1, now we need to see if it's the fastest one + if(fastestPath == null) { + fastestPath = nextArc; + } + else if(fastestPath.getMinimumTravelTime() > nextArc.getMinimumTravelTime()) { + fastestPath = nextArc; + } + } + } - /** - * Create an empty path corresponding to the given graph. - * - * @param graph Graph containing the path. - */ - public Path(Graph graph) { - this.graph = graph; - this.origin = null; - this.arcs = new ArrayList<>(); - } + if(fastestPath == null) { + throw new IllegalArgumentException(); + } - /** - * Create a new path containing a single node. - * - * @param graph Graph containing the path. - * @param node Single node of the path. - */ - public Path(Graph graph, Node node) { - this.graph = graph; - this.origin = node; - this.arcs = new ArrayList<>(); - } + arcs.add(fastestPath); + } + } + else if (nodeListSize == 1) { + return new Path(graph, nodes.get(0)); + } + else { + //nodeListSize == 0 + return new Path(graph); + } - /** - * Create a new path with the given list of arcs. - * - * @param graph Graph containing the path. - * @param arcs Arcs to construct the path. - */ - public Path(Graph graph, List arcs) { - this.graph = graph; - this.arcs = arcs; - this.origin = arcs.size() > 0 ? arcs.get(0).getOrigin() : null; - } + return new Path(graph, arcs); + } - /** - * @return Graph containing the path. - */ - public Graph getGraph() { - return graph; - } + /** + * Create a new path that goes through the given list of nodes (in order), + * choosing the shortest route if multiple are available. + * + * @param graph Graph containing the nodes in the list. + * @param nodes List of nodes to build the path. + * + * @return A path that goes through the given list of nodes. + * + * @throws IllegalArgumentException If the list of nodes is not valid, i.e. two + * consecutive nodes in the list are not connected in the graph. + * + * + */ + public static Path createShortestPathFromNodes(Graph graph, List nodes) + throws IllegalArgumentException { - /** - * @return First node of the path. - */ - public Node getOrigin() { - return origin; - } + int nodeListSize = nodes.size(); - /** - * @return Last node of the path. - */ - public Node getDestination() { - return arcs.get(arcs.size() - 1).getDestination(); - } + List arcs = new ArrayList(nodeListSize); - /** - * @return List of arcs in the path. - */ - public List getArcs() { - return Collections.unmodifiableList(arcs); - } + if(nodeListSize > 1) { + //nodes.size() - 1 because we look at i and i+1 + for(int i=0;i neighbourhood = nodes.get(i).getSuccessors(); - /** - * Get the number of nodes in this path. - * - * @return Number of nodes in this path. - */ - public int size() { - return isEmpty() ? 0 : 1 + this.arcs.size(); - } + Arc shortestPath = null; - /** - * Check if this path is valid. - * - * A path is valid if any of the following is true: - *
    - *
  • it is empty;
  • - *
  • it contains a single node (without arcs);
  • - *
  • the first arc has for origin the origin of the path and, for two - * consecutive arcs, the destination of the first one is the origin of the - * second one.
  • - *
- * - * @return true if the path is valid, false otherwise. - * - * @deprecated Need to be implemented. - */ - public boolean isValid() { - // TODO: - return false; - } + for(Arc nextArc : neighbourhood) { + if(nextArc.getDestination().compareTo(nodes.get(i+1)) == 0) { + //here we find a path between i and i+1, now we need to see if it's the shortest one + if(shortestPath == null) { + shortestPath = nextArc; + } + else if(shortestPath.getLength() > nextArc.getLength()) { + shortestPath = nextArc; + } + } + } - /** - * Compute the length of this path (in meters). - * - * @return Total length of the path (in meters). - * - * @deprecated Need to be implemented. - */ - public float getLength() { - // TODO: - return 0; - } + if(shortestPath == null) { + throw new IllegalArgumentException(); + } - /** - * Compute the time required to travel this path if moving at the given speed. - * - * @param speed Speed to compute the travel time. - * - * @return Time (in seconds) required to travel this path at the given speed (in - * kilometers-per-hour). - * - * @deprecated Need to be implemented. - */ - public double getTravelTime(double speed) { - // TODO: - return 0; - } + arcs.add(shortestPath); + } + } + else if (nodeListSize == 1) { + return new Path(graph, nodes.get(0)); + } + else { + //nodeListSize == 0 + return new Path(graph); + } - /** - * Compute the time to travel this path if moving at the maximum allowed speed - * on every arc. - * - * @return Minimum travel time to travel this path (in seconds). - * - * @deprecated Need to be implemented. - */ - public double getMinimumTravelTime() { - // TODO: - return 0; - } + return new Path(graph, arcs); + } + + /** + * Concatenate the given paths. + * + * @param paths Array of paths to concatenate. + * + * @return Concatenated path. + * + * @throws IllegalArgumentException if the paths cannot be concatenated (IDs of + * map do not match, or the end of a path is not the beginning of the + * next). + */ + public static Path concatenate(Path... paths) throws IllegalArgumentException { + if (paths.length == 0) { + throw new IllegalArgumentException("Cannot concatenate an empty list of paths."); + } + final String mapId = paths[0].getGraph().getMapId(); + for (int i = 1; i < paths.length; ++i) { + if (!paths[i].getGraph().getMapId().equals(mapId)) { + throw new IllegalArgumentException( + "Cannot concatenate paths from different graphs."); + } + } + ArrayList arcs = new ArrayList<>(); + for (Path path: paths) { + arcs.addAll(path.getArcs()); + } + Path path = new Path(paths[0].getGraph(), arcs); + if (!path.isValid()) { + throw new IllegalArgumentException( + "Cannot concatenate paths that do not form a single path."); + } + return path; + } + + // Graph containing this path. + private final Graph graph; + + // Origin of the path + private final Node origin; + + // List of arcs in this path. + private final List arcs; + + /** + * Create an empty path corresponding to the given graph. + * + * @param graph Graph containing the path. + */ + public Path(Graph graph) { + this.graph = graph; + this.origin = null; + this.arcs = new ArrayList<>(); + } + + /** + * Create a new path containing a single node. + * + * @param graph Graph containing the path. + * @param node Single node of the path. + */ + public Path(Graph graph, Node node) { + this.graph = graph; + this.origin = node; + this.arcs = new ArrayList<>(); + } + + /** + * Create a new path with the given list of arcs. + * + * @param graph Graph containing the path. + * @param arcs Arcs to construct the path. + */ + public Path(Graph graph, List arcs) { + this.graph = graph; + this.arcs = arcs; + this.origin = arcs.size() > 0 ? arcs.get(0).getOrigin() : null; + } + + /** + * @return Graph containing the path. + */ + public Graph getGraph() { + return graph; + } + + /** + * @return First node of the path. + */ + public Node getOrigin() { + return origin; + } + + /** + * @return Last node of the path. + */ + public Node getDestination() { + return arcs.get(arcs.size() - 1).getDestination(); + } + + /** + * @return List of arcs in the path. + */ + public List getArcs() { + return Collections.unmodifiableList(arcs); + } + + /** + * Check if this path is empty (it does not contain any node). + * + * @return true if this path is empty, false otherwise. + */ + public boolean isEmpty() { + return this.origin == null; + } + + /** + * Get the number of nodes in this path. + * + * @return Number of nodes in this path. + */ + public int size() { + return isEmpty() ? 0 : 1 + this.arcs.size(); + } + + /** + * Check if this path is valid. + * + * A path is valid if any of the following is true: + *
    + *
  • it is empty;
  • + *
  • it contains a single node (without arcs);
  • + *
  • the first arc has for origin the origin of the path and, for two + * consecutive arcs, the destination of the first one is the origin of the + * second one.
  • + *
+ * + * @return true if the path is valid, false otherwise. + * + */ + public boolean isValid() { + + if((this.isEmpty() && arcs.isEmpty()) || this.size() == 1) { + return true; + } + + //the first arc has for origin the origin of the path + if(this.arcs.get(0).getOrigin() != this.origin) { + return false; + } + + //for two consecutive arcs, the destination of the first one is the origin of the second one + for(int i = 0 ; i < arcs.size() - 1 ;i++) { + if(arcs.get(i).getDestination().compareTo(arcs.get(i+1).getOrigin()) != 0) { + return false; + } + } + + return true; + } + + /** + * Compute the length of this path (in meters). + * + * @return Total length of the path (in meters). + * + */ + public float getLength() { + + float totalLength = 0.0f; + + for(Arc arc : arcs) { + totalLength += arc.getLength(); + } + + + return totalLength; + } + + /** + * Compute the time required to travel this path if moving at the given speed. + * + * @param speed Speed to compute the travel time. + * + * @return Time (in seconds) required to travel this path at the given speed (in + * kilometers-per-hour). + * + * + */ + public double getTravelTime(double speed) { + double totalTime = 0.0d; + + for(Arc arc : arcs) { + totalTime += arc.getTravelTime(speed); + } + + + return totalTime; + } + + /** + * Compute the time to travel this path if moving at the maximum allowed speed + * on every arc. + * + * @return Minimum travel time to travel this path (in seconds). + * + * + */ + public double getMinimumTravelTime() { + double totalTime = 0.0d; + + for(Arc arc : arcs) { + totalTime += arc.getMinimumTravelTime(); + } + + + return totalTime; + } }