diff --git a/pom.xml b/pom.xml
index 6eb663f..89cd54d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
true
${project.build.finalName}.lib/
- fr.u_paris.gla.project.idfm.IDFMNetworkExtractor
+ fr.u_paris.gla.project.itinerary.Main
diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/Connection.java b/src/main/java/fr/u_paris/gla/project/itinerary/Connection.java
new file mode 100644
index 0000000..ccc3bfd
--- /dev/null
+++ b/src/main/java/fr/u_paris/gla/project/itinerary/Connection.java
@@ -0,0 +1,35 @@
+package fr.u_paris.gla.project.itinerary;
+
+public class Connection{
+ private final Stop stop;
+
+ private final String lineName;
+
+ private final double distance;
+
+ private final int time;
+
+ public Connection(Stop stop, String lineName, double distance, int time){
+ this.stop = stop;
+ this.lineName=lineName;
+ this.distance = distance;
+ this.time = time;
+ }
+
+
+ public String getLineName() {
+ return lineName;
+ }
+
+ public double getDistance() {
+ return distance;
+ }
+
+ public int getTime() {
+ return time;
+ }
+
+ public Stop getStop() {
+ return stop;
+ }
+}
diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/Finder.java b/src/main/java/fr/u_paris/gla/project/itinerary/Finder.java
new file mode 100644
index 0000000..f91047d
--- /dev/null
+++ b/src/main/java/fr/u_paris/gla/project/itinerary/Finder.java
@@ -0,0 +1,91 @@
+package fr.u_paris.gla.project.itinerary;
+
+import java.util.*;
+
+public class Finder {
+ private Graph graph;
+ public Finder(Graph graph) {
+ this.graph = graph;
+ }
+
+ public List findPath(Stop startNode, Stop goalNode) {
+ PriorityQueue openSet = new PriorityQueue<>(Comparator.comparingDouble(GraphNode::getF));
+ HashSet closedSet = new HashSet<>();
+ HashMap cameFrom = new HashMap<>();
+ HashMap gScore = new HashMap<>();
+ HashMap fScore = new HashMap<>();
+
+ // Initialize scores for all nodes to infinity
+ for (Stop node : graph.getNodes()) {
+ gScore.put(node, Double.POSITIVE_INFINITY);
+ fScore.put(node, Double.POSITIVE_INFINITY);
+ }
+
+ // The cost of going from start to start is zero
+ gScore.put(startNode, 0.0);
+ // For the first node, fScore = gScore + heuristic
+ fScore.put(startNode, startNode.getHeuristicCost(goalNode));
+ openSet.add(startNode);
+
+ while (!openSet.isEmpty()) {
+ Stop current = openSet.poll();
+ //System.out.println(current);
+ //System.out.println(graph.getConnections(current));
+
+ if (current.equals(goalNode)) {
+ return reconstructPath(cameFrom, current);
+ }
+
+ closedSet.add(current);
+
+ if(graph.getConnections(current) == null) {
+ continue;
+ }
+
+ for (Connection connection : graph.getConnections(current) ) {
+ Stop neighbor = connection.getStop();
+ if (closedSet.contains(neighbor)) {
+ continue; // Ignore the neighbor which is already evaluated.
+ }
+
+ double tentativeGScore = gScore.get(current) + connection.getDistance();
+
+ if (!openSet.contains(neighbor)) {
+ openSet.add(neighbor);
+ } else if (tentativeGScore >= gScore.get(neighbor)) {
+ continue; // This is not a better path.
+ }
+
+ // This path is the best until now. Record it!
+ cameFrom.put(neighbor, current);
+ gScore.put(neighbor, tentativeGScore);
+ fScore.put(neighbor, tentativeGScore + neighbor.getHeuristicCost(goalNode));
+ neighbor.setF(fScore.get(neighbor));
+ }
+ }
+
+ // If we reach here, it means there's no path from start to goal
+ return null;
+ }
+
+ private List reconstructPath(HashMap cameFrom, Stop current) {
+ List totalPath = new ArrayList<>();
+ totalPath.add(current);
+
+ while (cameFrom.containsKey(current)) {
+ current = cameFrom.get(current);
+ totalPath.add(0, current); // Add to the beginning of the list to maintain order
+ }
+
+ return totalPath;
+ }
+
+ //TODO:
+ public List findPath(double longitude, double latitude){
+ return null;
+ }
+
+
+}
+
+
diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/Graph.java b/src/main/java/fr/u_paris/gla/project/itinerary/Graph.java
new file mode 100644
index 0000000..3025a04
--- /dev/null
+++ b/src/main/java/fr/u_paris/gla/project/itinerary/Graph.java
@@ -0,0 +1,29 @@
+package fr.u_paris.gla.project.itinerary;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class Graph{
+ private final Set nodes;
+
+ private final Map> connections;
+
+ public Graph(Set nodes, Map> connections) {
+ this.nodes = nodes;
+ this.connections = connections;
+ }
+
+ public Set getConnections(Stop node) {
+ return connections.get(node);
+ }
+
+ public Set getNodes() {
+ return nodes;
+ }
+
+
+ public Map> getConnections() {
+ return connections;
+ }
+}
diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/GraphNode.java b/src/main/java/fr/u_paris/gla/project/itinerary/GraphNode.java
new file mode 100644
index 0000000..175db6e
--- /dev/null
+++ b/src/main/java/fr/u_paris/gla/project/itinerary/GraphNode.java
@@ -0,0 +1,14 @@
+package fr.u_paris.gla.project.itinerary;
+
+import java.util.List;
+import java.util.Set;
+
+public interface GraphNode {
+ int getId();
+ double getHeuristicCost(Stop goalNode);
+
+ Set getNeighbors();
+ double getCost(Stop neighbor);
+ double getF();
+ void setF(double value);
+}
diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/Main.java b/src/main/java/fr/u_paris/gla/project/itinerary/Main.java
new file mode 100644
index 0000000..5a75b34
--- /dev/null
+++ b/src/main/java/fr/u_paris/gla/project/itinerary/Main.java
@@ -0,0 +1,137 @@
+package fr.u_paris.gla.project.itinerary;
+
+import fr.u_paris.gla.project.idfm.*;
+import fr.u_paris.gla.project.utils.CSVTools;
+import fr.u_paris.gla.project.utils.GPS;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class Main{
+ private static final Logger LOGGER = Logger
+ .getLogger(IDFMNetworkExtractor.class.getName());
+
+ // IDF mobilite generated file
+ private static final String TRACE_FILE_NAME = "./trace.csv";
+
+ private static final String HOURS_FILE_NAME = "./hours.csv";
+
+ // IDF mobilite file format
+
+ private static final int IDFM_TRACE_ID_INDEX = 0;
+
+ private static final int IDFM_TRACE_DERIV_INDEX = 1;
+
+ private static final int IDFM_TRACE_FROM_INDEX = 2;
+
+ private static final int IDFM_TRACE_FROM_GPS_INDEX = 3;
+
+ private static final int IDFM_TRACE_TO_INDEX= 4;
+
+ private static final int IDFM_TRACE_TO_GPS_INDEX = 5;
+
+ private static final int IDFM_TRACE_TIME_INDEX = 6;
+
+ private static final int IDFM_TRACE_DISTANCE_INDEX = 7;
+
+ private static final double MARGE_ERREUR = 1.;
+
+ // Parser helper values
+
+ /**
+ * Returns the coordinates from a String to a double array:
+ * "49.08, 3.07" -> {49.08, 3.07}
+ * @param gps the string representation
+ * @return the double array
+ */
+ private static double[] getCoords(String gps) {
+ String []stringCoords = gps.split(", ");
+ return new double[] {Double.parseDouble(stringCoords[0]), Double.parseDouble(stringCoords[1])};
+ }
+
+ private static Stop getOrCreateStop(HashSet nodes, HashMap> tmp, String name, String gps, String lineId) {
+ ArrayList stopList = tmp.get(name);
+ if (stopList != null) {
+ for(Stop stop : stopList) {
+ double[] coords = getCoords(gps);
+ double dist = GPS.distance(coords[0], coords[1], stop.getLatitude(), stop.getLongitude());
+ if(dist < MARGE_ERREUR) {
+ stop.addLine(lineId);
+ return stop;
+ }
+ }
+ }
+
+ double[] coords = getCoords(gps);
+ Stop newStop = new Stop(lineId, name, coords[0], coords[1]);
+ nodes.add(newStop);
+ stopList = stopList == null ? new ArrayList<>() : stopList;
+ stopList.add(newStop);
+ tmp.put(name, stopList);
+ return newStop;
+ }
+
+ public static int lineNB = 0;
+
+ private static void addLine(String[] line, HashSet nodes, HashMap> tmp, HashMap> connections) {
+ Stop fromStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_FROM_INDEX], line[IDFM_TRACE_FROM_GPS_INDEX], line[IDFM_TRACE_ID_INDEX]);
+ Stop toStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_TO_INDEX], line[IDFM_TRACE_TO_GPS_INDEX], line[IDFM_TRACE_ID_INDEX]);
+
+ String[] timeString = line[IDFM_TRACE_TIME_INDEX].split(":");
+ int time = Integer.parseInt(timeString[0]) * 60 + Integer.parseInt(timeString[1]);
+
+ Connection connection = new Connection(toStop, line[IDFM_TRACE_ID_INDEX], Double.parseDouble(line[IDFM_TRACE_DISTANCE_INDEX]), time);
+
+ connections.computeIfAbsent(fromStop, k -> new HashSet<>()).add(connection);
+ }
+
+ public static void find(Graph graph){
+
+
+ }
+
+ public static void main(String[] args){
+ if (args.length != 0) {
+ LOGGER.severe("Invalid command line. Target file names are in the main file for now.");
+ return;
+ }
+
+ try {
+ HashSet nodes = new HashSet<>();
+ HashMap> connections = new HashMap<>();
+ HashMap> tmp = new HashMap<>();
+ CSVTools.readCSVFromFile(TRACE_FILE_NAME,
+ (String[] line) -> addLine(line, nodes, tmp, connections));
+
+
+ Stop porteivry = tmp.get("Porte d'Ivry").get(0);
+ Stop repu = tmp.get("République").get(0);
+
+ Graph graph = new Graph(nodes, connections);
+ int cpt = 0;
+ for (Map.Entry> entry : graph.getConnections().entrySet()) {
+ if (entry.getValue() == null) cpt +=1;
+ }
+ Stop garenord = tmp.get("Gare du Nord").get(0);
+
+ Stop chatelet = tmp.get("Châtelet").get(0);
+ //System.out.println(graph.getConnections(garenord));
+ //System.out.println(cpt);
+ //System.out.println(graph.getConnections(porteivry));
+ Finder finder = new Finder(graph);
+
+ List res = finder.findPath(porteivry, chatelet);
+
+ for (Stop element : res) {
+ System.out.println(element);
+ }
+
+ } catch (IOException e) {
+ LOGGER.log(Level.SEVERE, "Error while reading the line paths", e);
+ }
+
+
+ }
+}
diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/Path.java b/src/main/java/fr/u_paris/gla/project/itinerary/Path.java
new file mode 100644
index 0000000..a492b99
--- /dev/null
+++ b/src/main/java/fr/u_paris/gla/project/itinerary/Path.java
@@ -0,0 +1,18 @@
+package fr.u_paris.gla.project.itinerary;
+
+public class Path {
+ private T current;
+
+ private T previous;
+
+ private double currentScore;
+
+ private final double targetScore;
+
+ public Path(T current, T previous, double currentScore, double targetScore) {
+ this.current = current;
+ this.previous = previous;
+ this.currentScore = currentScore;
+ this.targetScore = targetScore;
+ }
+}
diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/Stop.java b/src/main/java/fr/u_paris/gla/project/itinerary/Stop.java
new file mode 100644
index 0000000..240c9b0
--- /dev/null
+++ b/src/main/java/fr/u_paris/gla/project/itinerary/Stop.java
@@ -0,0 +1,86 @@
+package fr.u_paris.gla.project.itinerary;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class Stop implements GraphNode {
+ private static int counter = 0;
+
+ private final int id;
+
+ private final Set lines;
+
+ private final String name;
+
+ private final double latitude;
+
+ private final double longitude;
+
+ private double f;
+
+ public Stop(String line, String name, double latitude, double longitude) {
+ lines = new HashSet<>();
+ lines.add(line);
+ this.id = counter++;
+ this.name = name;
+ this.latitude = latitude;
+ this.longitude = longitude;
+ this.f = 0;
+ }
+
+ @Override
+ public String toString() {
+ return "Stop{" +
+ "id=" + id +
+ ", lines=" + lines +
+ ", name='" + name + '\'' +
+ ", latitude=" + latitude +
+ ", longitude=" + longitude +
+ '}';
+ }
+
+ @Override
+ public int getId(){
+ return id;
+ }
+
+ @Override
+ public double getHeuristicCost(Stop goalNode) {
+ return 0;
+ }
+
+ @Override
+ public Set getNeighbors() {
+ return null;
+ }
+
+ @Override
+ public double getCost(Stop neighbor) {
+ return 0;
+ }
+
+ @Override
+ public double getF() {
+ return f;
+ }
+
+ public void setF(double value) {
+ this.f = value;
+ }
+
+ public String getName(){
+ return name;
+ }
+
+ public double getLatitude(){
+ return latitude;
+ }
+
+ public double getLongitude(){
+ return longitude;
+ }
+
+ public void addLine(String s){
+ lines.add(s);
+ }
+}
diff --git a/src/main/java/fr/u_paris/gla/project/utils/CSVTools.java b/src/main/java/fr/u_paris/gla/project/utils/CSVTools.java
index b3194f9..7d50613 100644
--- a/src/main/java/fr/u_paris/gla/project/utils/CSVTools.java
+++ b/src/main/java/fr/u_paris/gla/project/utils/CSVTools.java
@@ -3,12 +3,7 @@
*/
package fr.u_paris.gla.project.utils;
-import java.io.BufferedReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
+import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
@@ -32,12 +27,11 @@ public final class CSVTools {
// Tool class
}
- public static void readCSVFromURL(String url, Consumer contentLineConsumer)
+ private static void readCSVFromInputStream(InputStream is, Consumer contentLineConsumer)
throws IOException {
ICSVParser parser = new CSVParserBuilder().withSeparator(';').build();
- try (InputStream is = new URL(url).openStream();
- Reader reader = new BufferedReader(
- new InputStreamReader(is, StandardCharsets.UTF_8))) {
+ try (Reader reader = new BufferedReader(
+ new InputStreamReader(is, StandardCharsets.UTF_8))) {
CSVReaderBuilder csvBuilder = new CSVReaderBuilder(reader)
.withCSVParser(parser);
try (CSVReader csv = csvBuilder.build()) {
@@ -52,6 +46,17 @@ public final class CSVTools {
}
}
+ public static void readCSVFromFile(String filename, Consumer contentLineConsumer)
+ throws IOException {
+ File file = new File(filename);
+ readCSVFromInputStream(new FileInputStream(file), contentLineConsumer);
+ }
+
+ public static void readCSVFromURL(String url, Consumer contentLineConsumer)
+ throws IOException {
+ readCSVFromInputStream(new URL(url).openStream(), contentLineConsumer);
+ }
+
public static void writeCSVToFile(String filename,
Stream contentLineConsumer) throws IOException {
try (FileWriter writer = new FileWriter(filename, StandardCharsets.UTF_8)) {
diff --git a/src/main/java/fr/u_paris/gla/project/utils/GPS.java b/src/main/java/fr/u_paris/gla/project/utils/GPS.java
index 1aaca79..0eb7130 100644
--- a/src/main/java/fr/u_paris/gla/project/utils/GPS.java
+++ b/src/main/java/fr/u_paris/gla/project/utils/GPS.java
@@ -30,14 +30,16 @@ public final class GPS {
* @param longitude1 the longitude of the first position
* @param latitude2 the latitude of the second position
* @param longitude2 the longitude of the second position
- * @return the flying distance */
+ * @return the flying distance in km*/
public static double distance(double latitude1, double longitude1, double latitude2,
double longitude2) {
- double deltaLatitude = degreeToRadian(latitude2 - latitude1);
+ latitude1 = degreeToRadian(latitude1);
+ latitude2 = degreeToRadian(latitude2);
+ double deltaLatitude = latitude2 - latitude1;
double deltaLongitude = degreeToRadian(longitude2 - longitude1);
double a = Math.pow(Math.sin(deltaLatitude / 2), 2)
- + Math.pow(Math.sin(deltaLongitude), 2) * Math.cos(latitude1)
+ + Math.pow(Math.sin(deltaLongitude / 2), 2) * Math.cos(latitude1)
* Math.cos(latitude2);
- return EARTH_RADIUS * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+ return 2 * EARTH_RADIUS * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}
}