From 9514d5d254428a20fd027884e303eba5e3eb96bf Mon Sep 17 00:00:00 2001 From: Lucas Date: Mon, 8 Apr 2024 14:19:44 +0200 Subject: [PATCH] [feat] Result table for stops list WIP --- pom.xml | 19 ++- .../java/fr/u_paris/gla/project/gui/View.form | 12 +- .../java/fr/u_paris/gla/project/gui/View.java | 95 +++++++++++- .../gla/project/itinerary/Connection.java | 37 +++++ .../u_paris/gla/project/itinerary/Graph.java | 28 ++++ .../itinerary/ItineraryCalculator.java | 146 ++++++++++++++++++ .../u_paris/gla/project/itinerary/Stop.java | 98 ++++++++++++ 7 files changed, 430 insertions(+), 5 deletions(-) create mode 100644 src/main/java/fr/u_paris/gla/project/itinerary/Connection.java create mode 100644 src/main/java/fr/u_paris/gla/project/itinerary/Graph.java create mode 100644 src/main/java/fr/u_paris/gla/project/itinerary/ItineraryCalculator.java create mode 100644 src/main/java/fr/u_paris/gla/project/itinerary/Stop.java diff --git a/pom.xml b/pom.xml index 787e8a2..61d26c4 100644 --- a/pom.xml +++ b/pom.xml @@ -37,6 +37,22 @@ + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/${project.build.finalName}.lib + + + + org.apache.maven.plugins maven-jar-plugin @@ -45,7 +61,8 @@ true - fr.u_paris.gla.project.App + ${project.build.finalName}.lib/ + fr.u_paris.gla.project.itinerary.ItineraryCalculator diff --git a/src/main/java/fr/u_paris/gla/project/gui/View.form b/src/main/java/fr/u_paris/gla/project/gui/View.form index 0d5e3d8..703d5bc 100644 --- a/src/main/java/fr/u_paris/gla/project/gui/View.form +++ b/src/main/java/fr/u_paris/gla/project/gui/View.form @@ -37,7 +37,7 @@ - + @@ -83,7 +83,7 @@ - + @@ -103,6 +103,14 @@ + + + + + + + + diff --git a/src/main/java/fr/u_paris/gla/project/gui/View.java b/src/main/java/fr/u_paris/gla/project/gui/View.java index 52be130..7fc0831 100644 --- a/src/main/java/fr/u_paris/gla/project/gui/View.java +++ b/src/main/java/fr/u_paris/gla/project/gui/View.java @@ -1,9 +1,15 @@ package fr.u_paris.gla.project.gui; +import fr.u_paris.gla.project.itinerary.Stop; + import javax.swing.*; +import javax.swing.table.DefaultTableModel; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.ArrayList; public class View extends JFrame{ private JPanel Cardpanel; @@ -16,8 +22,23 @@ public class View extends JFrame{ private JButton searchButton; private JPanel HomePanel; private JPanel MainPanel; + private DefaultTableModel dtm; + + private JTable table; + + private JScrollPane mypane; + + private ArrayList StopList; + + private Stop StopCur; + + private ArrayList searchRes; + + public View(ArrayList s) throws HeadlessException { + this.createUIComponents(); + this.StopList = s; + this.StopCur = StopList.get(0); - public View() throws HeadlessException { setContentPane(MainPanel); setTitle("app"); setExtendedState(JFrame.MAXIMIZED_BOTH); @@ -56,11 +77,81 @@ public class View extends JFrame{ }); + textField1.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + super.keyReleased(e); + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + System.out.println("Enter key released"); + } + } + }); + } + + + public static void main(String[] args) { - View v = new View(); + ArrayList s = new ArrayList<>(); + s.add(new Stop("M8", "Balard", 1.0315897, 3.0265513)); + s.add(new Stop("M14", "Gare de Lyon", 2.4658452681, 3.0265513)); + System.out.println(s.toString()); + View v = new View(s); + v.showSearch(s); } + + + private void createUIComponents() { + // TODO: place custom component creation code here + + table = new JTable(); + dtm = new DefaultTableModel(0, 0); + + String[] header = new String[] { "Line", "Stop" }; + dtm.setColumnIdentifiers(header); + table.setModel(dtm); + mypane = new JScrollPane(table); + + + } + + private void showSearch(ArrayList stops) { + // Clear existing rows from the table + dtm.setRowCount(0); + + // Add new rows based on the search results + for (Stop stop : stops) { + // Add a row to the table with Stop's line in the first column and Stop's name in the second column + + dtm.addRow(new Object[]{stop.getLines(), stop.getName()}); + } + this.displayTableValues(); + dtm.fireTableDataChanged(); + table.repaint(); + table.revalidate(); + Cardpanel.repaint(); + Cardpanel.revalidate(); + + } + + private void displayTableValues() { + int rowCount = dtm.getRowCount(); + int columnCount = dtm.getColumnCount(); + + // Iterate over each row + for (int row = 0; row < rowCount; row++) { + // Iterate over each column + for (int col = 0; col < columnCount; col++) { + // Get the value at the current cell + Object value = dtm.getValueAt(row, col); + // Display the value + System.out.println("Value at row " + row + ", column " + col + ": " + value); + } + } + } + + } 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..1cafbec --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/itinerary/Connection.java @@ -0,0 +1,37 @@ +package fr.u_paris.gla.project.itinerary; + +public class Connection{ + // Destination of the connection between the two stops + private final Stop stop; + + // The line used for this connection + 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/Graph.java b/src/main/java/fr/u_paris/gla/project/itinerary/Graph.java new file mode 100644 index 0000000..795add9 --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/itinerary/Graph.java @@ -0,0 +1,28 @@ +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/ItineraryCalculator.java b/src/main/java/fr/u_paris/gla/project/itinerary/ItineraryCalculator.java new file mode 100644 index 0000000..5391c19 --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/itinerary/ItineraryCalculator.java @@ -0,0 +1,146 @@ +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 ItineraryCalculator { + 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 ERROR_MARGIN = 1.; + + + /** + * 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])}; + } + + /** + * Searchs for a stop with the same name and GPS coordinates in the graph, and creates it if non existant + * @param nodes a graph of the stops + * @param tmp list of the created stops + * @param name the name of the stop + * @param gps the coordinate of the stop + * @param lineId the line the stop is on + * @return the Stop object + */ + private static Stop getOrCreateStop(HashSet nodes, HashMap> tmp, String name, String gps, String lineId) { + ArrayList stopList = tmp.get(name); + // First we search by name, and then compare the coordinates since multiple stations can have the same name. A margin of error is necessary since stops can have multiple GPS coordinates + 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 < ERROR_MARGIN) { + 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; + } + + /** + * Adds into the graph the connection between two stops, parsed from a CSV line + * @param line the current line we want to parse + * @param nodes the graph of stops + * @param tmp list of the created stops + * @param connections + */ + 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 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/Stop.java b/src/main/java/fr/u_paris/gla/project/itinerary/Stop.java new file mode 100644 index 0000000..80526a4 --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/itinerary/Stop.java @@ -0,0 +1,98 @@ +package fr.u_paris.gla.project.itinerary; + +import java.util.HashSet; +import java.util.Set; + +public class Stop implements GraphNode { + // The total number of stops + private static int counter = 0; + + private final int id; + + + + // The set of all the lines the stop is on + 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); + } + + public Set getLines() { + return lines; + } + + +}