Merge branch 'dev' into 'main'
Release 1.0 See merge request gla-groupe-3/projet!23
This commit is contained in:
commit
0953deabef
24 changed files with 759 additions and 2202 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -1,8 +1,10 @@
|
||||||
# Maven
|
# Maven
|
||||||
target/
|
target/
|
||||||
|
|
||||||
# Files
|
# Generated files
|
||||||
.csv
|
hours.csv
|
||||||
|
images.csv
|
||||||
|
trace.csv
|
||||||
|
|
||||||
# IDEs
|
# IDEs
|
||||||
# Eclipse
|
# Eclipse
|
||||||
|
|
24
README.md
24
README.md
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
Version 2024
|
Version 2024
|
||||||
|
|
||||||
|
## Lien vers la vidéo
|
||||||
|
https://youtu.be/eBVGWTBQfHg
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
Ceci est l'archétype de projet de Génie Logiciel Avancé (GLA).
|
Ceci est l'archétype de projet de Génie Logiciel Avancé (GLA).
|
||||||
|
@ -18,31 +21,28 @@ Afin de compiler et lancer les tests, exécutez simplement
|
||||||
mvn verify
|
mvn verify
|
||||||
```
|
```
|
||||||
|
|
||||||
Afin de vérifier les tests via JaCoCo.
|
|
||||||
Les résultats du test sont dans `target/site/jacoco/index.html`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mvn clean jacoco:prepare-agent install jacoco:report
|
|
||||||
```
|
|
||||||
|
|
||||||
Par la suite, `mvn jacoco:report` suffit.
|
|
||||||
|
|
||||||
Dans sa version initiale, le programme fournit est un simple code qui se lance en terminal ou en application graphique.
|
Dans sa version initiale, le programme fournit est un simple code qui se lance en terminal ou en application graphique.
|
||||||
|
|
||||||
Une fois le programme compilé, vous trouverez un jar executable dans le dossier target. Au nom de jar près (version changeante), vous pourrez l'exécuter avec:
|
Une fois le programme compilé, vous trouverez un jar executable dans le dossier target. Au nom de jar près (version changeante), vous pourrez l'exécuter avec:
|
||||||
|
|
||||||
```
|
```
|
||||||
java -jar target/project-2024.1.0.0-SNAPSHOT.jar --info
|
java -jar target/project-2024.1.0.0-SNAPSHOT.jar
|
||||||
```
|
```
|
||||||
|
|
||||||
L'option de lancement `--info` causera l'affichage dans la console d'informations de l'application.
|
L'option de lancement `--info` causera l'affichage dans la console d'informations de l'application.
|
||||||
|
|
||||||
L'option de lancement `--gui` causera l'ouverture d'une fenêtre affichant le logo de l'Université de Paris.
|
L'option de lancement `--gui` causera l'ouverture d'une fenêtre affichant le logo de l'Université de Paris.
|
||||||
|
|
||||||
|
Sans option, le programme Pathfinder sera lancé.
|
||||||
|
|
||||||
## Tests JaCoCo
|
## Tests JaCoCo
|
||||||
|
|
||||||
```
|
Afin de vérifier la couverture des tests via JaCoCo:
|
||||||
|
|
||||||
|
```bash
|
||||||
mvn clean jacoco:prepare-agent install jacoco:report
|
mvn clean jacoco:prepare-agent install jacoco:report
|
||||||
```
|
```
|
||||||
|
|
||||||
Puis ouvrir le fichier `./target/site/jacoco/index.html`.
|
Les résultats seront stockés dans `target/site/jacoco/index.html`.
|
||||||
|
|
||||||
|
Par la suite, ```mvn jacoco:report``` suffit.
|
||||||
|
|
4
pom.xml
4
pom.xml
|
@ -91,6 +91,10 @@
|
||||||
<directory>src/main/resources-filtered</directory>
|
<directory>src/main/resources-filtered</directory>
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -7,19 +7,15 @@ import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.*;
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.WindowConstants;
|
|
||||||
|
|
||||||
import fr.u_paris.gla.project.itinerary.Finder;
|
import fr.u_paris.gla.project.gui.View;
|
||||||
import fr.u_paris.gla.project.itinerary.Parse;
|
import fr.u_paris.gla.project.itinerary.*;
|
||||||
import fr.u_paris.gla.project.itinerary.Path;
|
|
||||||
import fr.u_paris.gla.project.itinerary.Stop;
|
|
||||||
|
|
||||||
/** Simple application model.
|
/** Simple application model.
|
||||||
*
|
*
|
||||||
|
@ -66,31 +62,26 @@ public class App {
|
||||||
showLogo();
|
showLogo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}
|
||||||
testRelease();
|
else {
|
||||||
|
run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void testRelease(){
|
public static void run() {
|
||||||
Parse parse = new Parse();
|
Parse parse = new Parse();
|
||||||
parse.parseFiles();
|
parse.parseFiles();
|
||||||
Stop source = parse.getTmp().get("Porte d'Ivry").get(0);
|
|
||||||
Stop destination = parse.getTmp().get("Châtelet").get(0);
|
|
||||||
System.out.println("Itinéraire de Porte d'Ivry à Châtelet");
|
|
||||||
List<Path> result = parse.getItinerary(source, destination, 43200);
|
|
||||||
for(Path element : result){
|
|
||||||
System.out.println(element.getCurrentStop());
|
|
||||||
}
|
|
||||||
System.out.println("°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°");
|
|
||||||
System.out.println("Itinéraire de Porte d'Ivry à Châtelet");
|
|
||||||
source = parse.getTmp().get("Saint-Jacques").get(0);
|
|
||||||
destination = parse.getTmp().get("Porte d'Ivry").get(0);
|
|
||||||
result = parse.getItinerary(source, destination, 43200);
|
|
||||||
for(Path element : result){
|
|
||||||
System.out.println(element.getCurrentStop());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Graph graph = parse.createGraph();
|
||||||
|
Finder finder = parse.createFinder(graph);
|
||||||
|
|
||||||
|
ArrayList<Stop> 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));
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater(() -> new View(graph, finder, s));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param out the output stream */
|
/** @param out the output stream */
|
||||||
public static void printAppInfos(PrintStream out) {
|
public static void printAppInfos(PrintStream out) {
|
||||||
Properties props = readApplicationProperties();
|
Properties props = readApplicationProperties();
|
||||||
|
|
|
@ -1,19 +1,33 @@
|
||||||
package fr.u_paris.gla.project.gui;
|
package fr.u_paris.gla.project.gui;
|
||||||
|
|
||||||
import fr.u_paris.gla.project.itinerary.Stop;
|
import fr.u_paris.gla.project.idfm.CSVImageProvider;
|
||||||
|
import fr.u_paris.gla.project.idfm.IDFMNetworkExtractor;
|
||||||
|
import fr.u_paris.gla.project.idfm.ImagePair;
|
||||||
|
import fr.u_paris.gla.project.itinerary.*;
|
||||||
|
import fr.u_paris.gla.project.utils.ApiUtils;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.Border;
|
||||||
import javax.swing.table.DefaultTableModel;
|
import javax.swing.table.DefaultTableModel;
|
||||||
import javax.swing.table.TableModel;
|
import javax.swing.table.TableModel;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
import java.util.ArrayList;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class View extends JFrame {
|
public class View extends JFrame {
|
||||||
|
private static final Logger LOGGER = Logger
|
||||||
|
.getLogger(IDFMNetworkExtractor.class.getName());
|
||||||
|
|
||||||
private JPanel CardPanel;
|
private JPanel CardPanel;
|
||||||
private JMenuItem Home;
|
private JMenuItem Home;
|
||||||
private JMenuItem Network;
|
private JMenuItem Network;
|
||||||
private JMenuItem Favorites;
|
|
||||||
private JPanel NetworkPanel;
|
private JPanel NetworkPanel;
|
||||||
|
|
||||||
private JTextField TextLocation;
|
private JTextField TextLocation;
|
||||||
|
@ -36,6 +50,20 @@ public class View extends JFrame {
|
||||||
private JPanel stationsPanel;
|
private JPanel stationsPanel;
|
||||||
private JLabel departText;
|
private JLabel departText;
|
||||||
private JLabel arrText;
|
private JLabel arrText;
|
||||||
|
|
||||||
|
private JMenuItem Lines;
|
||||||
|
private JPanel LinesPanel;
|
||||||
|
private JLabel LineLabel;
|
||||||
|
private JComboBox LinesComboBox;
|
||||||
|
private JButton ShowLineButton;
|
||||||
|
|
||||||
|
private JMenuItem Stops;
|
||||||
|
private JPanel StopsPanel;
|
||||||
|
private JLabel StopsLabel;
|
||||||
|
private JComboBox StopsComboBox;
|
||||||
|
private JComboBox StopsLinesComboBox;
|
||||||
|
private JButton SeeStopButton;
|
||||||
|
|
||||||
private JTextField TextCoord;
|
private JTextField TextCoord;
|
||||||
private JButton ButtonCoord;
|
private JButton ButtonCoord;
|
||||||
private JPanel SearchCoordPanel;
|
private JPanel SearchCoordPanel;
|
||||||
|
@ -56,10 +84,16 @@ public class View extends JFrame {
|
||||||
|
|
||||||
private ArrayList<Stop> searchRes;
|
private ArrayList<Stop> searchRes;
|
||||||
|
|
||||||
|
private ArrayList<Path> searchResPath;
|
||||||
|
|
||||||
private int count = 0;
|
private int count = 0;
|
||||||
|
|
||||||
|
private Finder finder;
|
||||||
|
|
||||||
public View(ArrayList<Stop> s) throws HeadlessException {
|
|
||||||
|
public View(Graph graph, Finder finder, ArrayList<Stop> s) throws HeadlessException {
|
||||||
|
this.finder = finder;
|
||||||
|
setSize(800, 600);
|
||||||
MainPanel = new JPanel();
|
MainPanel = new JPanel();
|
||||||
GridLayout MainLayout = new GridLayout(1, 2, 50, 0);
|
GridLayout MainLayout = new GridLayout(1, 2, 50, 0);
|
||||||
MainPanel.setLayout(MainLayout);
|
MainPanel.setLayout(MainLayout);
|
||||||
|
@ -106,8 +140,6 @@ public class View extends JFrame {
|
||||||
paneStops.add(tableStops);
|
paneStops.add(tableStops);
|
||||||
NetworkPanel.add(paneStops);
|
NetworkPanel.add(paneStops);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ItineraryPanel = new JPanel();
|
ItineraryPanel = new JPanel();
|
||||||
CardPanel.add(ItineraryPanel);
|
CardPanel.add(ItineraryPanel);
|
||||||
GridLayout ItineraryLayout = new GridLayout(2, 1);
|
GridLayout ItineraryLayout = new GridLayout(2, 1);
|
||||||
|
@ -117,23 +149,74 @@ public class View extends JFrame {
|
||||||
paneItinerary.add(tableItinerary);
|
paneItinerary.add(tableItinerary);
|
||||||
ItineraryPanel.add(paneItinerary);
|
ItineraryPanel.add(paneItinerary);
|
||||||
|
|
||||||
|
LinesComboBox = new JComboBox();
|
||||||
|
LinesComboBox.setMaximumSize(new Dimension(100, LinesComboBox.getPreferredSize().height));
|
||||||
|
LinesComboBox.setPreferredSize(LinesComboBox.getPreferredSize());
|
||||||
|
LineLabel = new JLabel("Show line");
|
||||||
|
LineLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
ShowLineButton = new JButton("Open");
|
||||||
|
ShowLineButton.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
|
||||||
|
LinesPanel = new JPanel();
|
||||||
|
LinesPanel.setBackground(new Color(214,173,153));
|
||||||
|
LinesPanel.setLayout(new BoxLayout(LinesPanel, BoxLayout.Y_AXIS));
|
||||||
|
LinesPanel.add(Box.createHorizontalGlue());
|
||||||
|
LinesPanel.add(Box.createHorizontalStrut(2));
|
||||||
|
LinesPanel.add(LineLabel);
|
||||||
|
LinesPanel.add(Box.createHorizontalStrut(10));
|
||||||
|
LinesPanel.add(LinesComboBox);
|
||||||
|
LinesPanel.add(Box.createHorizontalStrut(10));
|
||||||
|
LinesPanel.add(ShowLineButton);
|
||||||
|
LinesPanel.add(Box.createHorizontalStrut(2));
|
||||||
|
LinesPanel.add(Box.createHorizontalGlue());
|
||||||
|
|
||||||
|
StopsComboBox = new JComboBox();
|
||||||
|
StopsComboBox.setMaximumSize(new Dimension(200, StopsComboBox.getPreferredSize().height));
|
||||||
|
StopsComboBox.setPreferredSize(StopsComboBox.getPreferredSize());
|
||||||
|
StopsLinesComboBox = new JComboBox();
|
||||||
|
StopsLinesComboBox.setMaximumSize(new Dimension(200, StopsLinesComboBox.getPreferredSize().height));
|
||||||
|
StopsLinesComboBox.setPreferredSize(StopsComboBox.getPreferredSize());
|
||||||
|
StopsLabel = new JLabel("See stop schedules");
|
||||||
|
StopsLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
SeeStopButton = new JButton("See Schedule");
|
||||||
|
SeeStopButton.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
|
|
||||||
|
StopsPanel = new JPanel();
|
||||||
|
StopsPanel.setBackground(new Color(171,197,105));
|
||||||
|
StopsPanel.setLayout(new BoxLayout(StopsPanel, BoxLayout.Y_AXIS));
|
||||||
|
StopsPanel.add(Box.createHorizontalGlue());
|
||||||
|
StopsPanel.add(Box.createHorizontalStrut(2));
|
||||||
|
StopsPanel.add(StopsLabel);
|
||||||
|
StopsPanel.add(Box.createHorizontalStrut(10));
|
||||||
|
StopsPanel.add(StopsComboBox);
|
||||||
|
StopsPanel.add(Box.createHorizontalStrut(10));
|
||||||
|
StopsPanel.add(StopsLinesComboBox);
|
||||||
|
StopsPanel.add(Box.createHorizontalStrut(10));
|
||||||
|
StopsPanel.add(SeeStopButton);
|
||||||
|
StopsPanel.add(Box.createHorizontalStrut(2));
|
||||||
|
StopsPanel.add(Box.createHorizontalGlue());
|
||||||
|
|
||||||
|
JPanel buttonBarPanel = new JPanel(new BorderLayout());
|
||||||
ButtonBar = new JMenuBar();
|
ButtonBar = new JMenuBar();
|
||||||
GridLayout ButtonLayout = new GridLayout(3, 1);
|
GridLayout ButtonLayout = new GridLayout(5, 1);
|
||||||
ButtonBar.setLayout(ButtonLayout);
|
ButtonBar.setLayout(ButtonLayout);
|
||||||
Home = new JMenuItem("Home");
|
Home = new JMenuItem("Home");
|
||||||
ButtonBar.add(Home);
|
ButtonBar.add(Home);
|
||||||
Network = new JMenuItem("Network");
|
Network = new JMenuItem("Network");
|
||||||
ButtonBar.add(Network);
|
ButtonBar.add(Network);
|
||||||
|
|
||||||
Itinerary = new JMenuItem("Itinerary");
|
Itinerary = new JMenuItem("Itinerary");
|
||||||
ButtonBar.add(Itinerary);
|
ButtonBar.add(Itinerary);
|
||||||
ButtonBar.setPreferredSize(new Dimension(50, 500));
|
Lines = new JMenuItem("Lines");
|
||||||
|
ButtonBar.add(Lines);
|
||||||
|
Stops = new JMenuItem("Stops");
|
||||||
|
ButtonBar.add(Stops);
|
||||||
|
buttonBarPanel.add(ButtonBar, BorderLayout.CENTER);
|
||||||
|
buttonBarPanel.setVisible(true);
|
||||||
|
|
||||||
|
ButtonBar.setPreferredSize(new Dimension(50, MainPanel.getHeight()));
|
||||||
MainPanel.add(ButtonBar);
|
MainPanel.add(ButtonBar);
|
||||||
MainPanel.add(CardPanel);
|
MainPanel.add(CardPanel);
|
||||||
|
|
||||||
|
|
||||||
modelStops = (DefaultTableModel) tableStops.getModel();
|
modelStops = (DefaultTableModel) tableStops.getModel();
|
||||||
modelStops.setColumnCount(2);
|
modelStops.setColumnCount(2);
|
||||||
modelStops.setColumnIdentifiers(new Object[]{"Line", "Stop"});
|
modelStops.setColumnIdentifiers(new Object[]{"Line", "Stop"});
|
||||||
|
@ -143,63 +226,90 @@ public class View extends JFrame {
|
||||||
modelItinerary.setColumnIdentifiers(new Object[]{"Line", "Stop", "Time"});
|
modelItinerary.setColumnIdentifiers(new Object[]{"Line", "Stop", "Time"});
|
||||||
this.StopList = s;
|
this.StopList = s;
|
||||||
|
|
||||||
|
|
||||||
setContentPane(MainPanel);
|
setContentPane(MainPanel);
|
||||||
setTitle("app");
|
setTitle("Pathfinder");
|
||||||
setExtendedState(JFrame.MAXIMIZED_BOTH);
|
|
||||||
//setUndecorated(true);
|
//setUndecorated(true);
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
;
|
|
||||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
|
||||||
Home.addActionListener(new ActionListener() {
|
Home.addActionListener(e -> {
|
||||||
@Override
|
CardPanel.removeAll();
|
||||||
public void actionPerformed(ActionEvent e) {
|
CardPanel.add(HomePanel);
|
||||||
CardPanel.removeAll();
|
CardPanel.repaint();
|
||||||
CardPanel.add(HomePanel);
|
CardPanel.revalidate();
|
||||||
CardPanel.repaint();
|
});
|
||||||
CardPanel.revalidate();
|
|
||||||
|
Network.addActionListener(e -> {
|
||||||
|
LoadSearchResult(s, modelStops);
|
||||||
|
CardPanel.removeAll();
|
||||||
|
CardPanel.add(NetworkPanel);
|
||||||
|
|
||||||
|
CardPanel.repaint();
|
||||||
|
CardPanel.revalidate();
|
||||||
|
});
|
||||||
|
|
||||||
|
Itinerary.addActionListener(e -> {
|
||||||
|
LoadSearchResultItinerary(searchResPath, modelItinerary);
|
||||||
|
CardPanel.removeAll();
|
||||||
|
CardPanel.add(ItineraryPanel);
|
||||||
|
|
||||||
|
CardPanel.repaint();
|
||||||
|
CardPanel.revalidate();
|
||||||
|
});
|
||||||
|
|
||||||
|
Lines.addActionListener(e -> {
|
||||||
|
CardPanel.removeAll();
|
||||||
|
CardPanel.add(LinesPanel);
|
||||||
|
CardPanel.repaint();
|
||||||
|
CardPanel.revalidate();
|
||||||
|
});
|
||||||
|
|
||||||
|
Stops.addActionListener(e -> {
|
||||||
|
CardPanel.removeAll();
|
||||||
|
CardPanel.add(StopsPanel);
|
||||||
|
CardPanel.repaint();
|
||||||
|
CardPanel.revalidate();
|
||||||
|
});
|
||||||
|
|
||||||
|
CSVImageProvider.getLineImageMap().forEach(p -> LinesComboBox.addItem(p));
|
||||||
|
ShowLineButton.addActionListener(f -> {
|
||||||
|
ImagePair item = (ImagePair) LinesComboBox.getSelectedItem();
|
||||||
|
openWebpage(item.getValue());
|
||||||
|
});
|
||||||
|
|
||||||
|
Set<Stop> nodes = graph.getNodes();
|
||||||
|
List<Stop> nodesList = nodes.stream().sorted(Comparator.comparing(Stop::getName)).toList();
|
||||||
|
nodesList.forEach(stop -> StopsComboBox.addItem(stop));
|
||||||
|
StopsComboBox.addItemListener(e -> {
|
||||||
|
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||||
|
Stop stop = (Stop) StopsComboBox.getSelectedItem();
|
||||||
|
StopsLinesComboBox.removeAllItems();
|
||||||
|
graph.getConnections(stop).forEach(c -> {
|
||||||
|
if (!c.toString().equals("WALK"))
|
||||||
|
StopsLinesComboBox.addItem(c);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Network.addActionListener(new ActionListener() {
|
SeeStopButton.addActionListener(f -> {
|
||||||
@Override
|
Connection c;
|
||||||
public void actionPerformed(ActionEvent e) {
|
if ((c = (Connection) StopsLinesComboBox.getSelectedItem()) != null) {
|
||||||
LoadSearchResult(s, modelStops);
|
createHourWindow(c.getSchedules());
|
||||||
CardPanel.removeAll();
|
|
||||||
CardPanel.add(NetworkPanel);
|
|
||||||
|
|
||||||
CardPanel.repaint();
|
|
||||||
CardPanel.revalidate();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Itinerary.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
LoadSearchResult(s, modelItinerary);
|
|
||||||
CardPanel.removeAll();
|
|
||||||
CardPanel.add(ItineraryPanel);
|
|
||||||
|
|
||||||
CardPanel.repaint();
|
|
||||||
CardPanel.revalidate();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TextLocation.addKeyListener(new KeyAdapter() {
|
TextLocation.addKeyListener(new KeyAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void keyReleased(KeyEvent e) {
|
public void keyReleased(KeyEvent e) {
|
||||||
super.keyReleased(e);
|
super.keyReleased(e);
|
||||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||||
|
|
||||||
searchLocation = TextLocation.getText();
|
String cur = TextLocation.getText();
|
||||||
LoadSearchResult(s, modelStops);
|
LoadStringStops(cur);
|
||||||
System.out.println("Enter key released with text " + searchLocation);
|
LoadSearchResultItinerary(searchResPath, modelItinerary);
|
||||||
|
System.out.println("Enter key released with text " + cur);
|
||||||
CardPanel.removeAll();
|
CardPanel.removeAll();
|
||||||
CardPanel.add(NetworkPanel);
|
CardPanel.add(ItineraryPanel);
|
||||||
|
|
||||||
CardPanel.repaint();
|
CardPanel.repaint();
|
||||||
CardPanel.revalidate();
|
CardPanel.revalidate();
|
||||||
|
@ -207,45 +317,39 @@ public class View extends JFrame {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ButtonLocation.addActionListener(new ActionListener() {
|
ButtonLocation.addActionListener(e -> {
|
||||||
@Override
|
String cur = TextLocation.getText();
|
||||||
public void actionPerformed(ActionEvent e) {
|
if (!cur.isEmpty()) {
|
||||||
CardPanel.removeAll();
|
CardPanel.removeAll();
|
||||||
searchLocation = TextLocation.getText();
|
LoadStringStops(cur);
|
||||||
LoadSearchResult(s, modelStops);
|
LoadSearchResultItinerary(searchResPath, modelItinerary);
|
||||||
System.out.println("search location clicked with text " + searchLocation);
|
CardPanel.add(ItineraryPanel);
|
||||||
CardPanel.add(NetworkPanel);
|
|
||||||
|
|
||||||
CardPanel.repaint();
|
|
||||||
CardPanel.revalidate();
|
|
||||||
}
|
}
|
||||||
|
CardPanel.repaint();
|
||||||
|
CardPanel.revalidate();
|
||||||
});
|
});
|
||||||
|
|
||||||
ButtonCoord.addActionListener(new ActionListener() {
|
ButtonCoord.addActionListener(e -> {
|
||||||
@Override
|
String cur = TextCoord.getText();
|
||||||
public void actionPerformed(ActionEvent e) {
|
if (!cur.isEmpty()) {
|
||||||
CardPanel.removeAll();
|
CardPanel.removeAll();
|
||||||
searchCoord = TextCoord.getText();
|
LoadStringCoords(cur);
|
||||||
LoadSearchResult(s, modelStops);
|
LoadSearchResultItinerary(searchResPath, modelItinerary);
|
||||||
System.out.println("search coord clicked with text " + searchCoord);
|
CardPanel.add(ItineraryPanel);
|
||||||
CardPanel.add(NetworkPanel);
|
|
||||||
|
|
||||||
CardPanel.repaint();
|
|
||||||
CardPanel.revalidate();
|
|
||||||
}
|
}
|
||||||
|
CardPanel.repaint();
|
||||||
|
CardPanel.revalidate();
|
||||||
});
|
});
|
||||||
|
|
||||||
tableStops.addMouseListener(new MouseAdapter() {
|
tableStops.addMouseListener(new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseClicked(MouseEvent e) {
|
public void mouseClicked(MouseEvent e) {
|
||||||
super.mouseClicked(e);
|
super.mouseClicked(e);
|
||||||
System.out.println("MouseClick: " + e.getX() + ";" + e.getY());
|
System.out.println("MouseClick: " + e.getX() + ";" + e.getY());
|
||||||
showOptionsDialog(tableStops, e.getX(), e.getY());
|
showOptionsDialog(tableStops, e.getX(), e.getY());
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
paneStops.addMouseListener(new MouseAdapter() {
|
paneStops.addMouseListener(new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseClicked(MouseEvent e) {
|
public void mouseClicked(MouseEvent e) {
|
||||||
|
@ -254,6 +358,46 @@ public class View extends JFrame {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param schedules
|
||||||
|
*/
|
||||||
|
private void createHourWindow(ArrayList<Integer> schedules) {
|
||||||
|
JFrame frame = new JFrame("Schedule");
|
||||||
|
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||||
|
JPanel panel = new JPanel(new GridLayout(0, 1));
|
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||||
|
|
||||||
|
JScrollPane scrollPane = new JScrollPane(panel);
|
||||||
|
frame.getContentPane().add(scrollPane);
|
||||||
|
|
||||||
|
for (int time : schedules) {
|
||||||
|
int hours = time / 3600;
|
||||||
|
int minutes = (time % 3600) / 60;
|
||||||
|
JLabel label = new JLabel(String.format("%dh%d", hours, minutes));
|
||||||
|
label.setBorder(BorderFactory.createCompoundBorder(
|
||||||
|
BorderFactory.createLineBorder(Color.BLACK),
|
||||||
|
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
|
||||||
|
label.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
panel.add(label);
|
||||||
|
}
|
||||||
|
if (schedules.isEmpty()) {
|
||||||
|
panel.add(new JLabel("No time available"));
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollPane.repaint();
|
||||||
|
frame.repaint();
|
||||||
|
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||||
|
frame.setSize(200, 400);
|
||||||
|
frame.setLocationRelativeTo(null);
|
||||||
|
frame.setVisible(true);
|
||||||
|
frame.setResizable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Used to select a departure/arrival stop in the "Network" section, UNUSED
|
||||||
|
* @param table the table that displays the stops
|
||||||
|
* @param x x coordinate of mouse click
|
||||||
|
* @param y y coordinate of mouse click
|
||||||
|
*/
|
||||||
private void showOptionsDialog(JTable table, int x, int y) {
|
private void showOptionsDialog(JTable table, int x, int y) {
|
||||||
int selectedRow = table.rowAtPoint(new Point(x, y));
|
int selectedRow = table.rowAtPoint(new Point(x, y));
|
||||||
if (selectedRow != -1) { // If a row is selected
|
if (selectedRow != -1) { // If a row is selected
|
||||||
|
@ -279,85 +423,138 @@ public class View extends JFrame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Load all stops related to coordinates
|
||||||
|
* @param stops a String in format (x1,y1);(x2,y2)
|
||||||
|
*/
|
||||||
|
public void LoadStringCoords(String stops){
|
||||||
|
stops = stops.replaceAll("[()]", "").replaceAll(";", ",");
|
||||||
|
String[] stops_array = stops.split(",");
|
||||||
|
double[] coords = new double[4];
|
||||||
|
for (int i = 0; i < 4; i++){
|
||||||
|
coords[i] = Double.parseDouble(stops_array[i]);
|
||||||
|
}
|
||||||
|
searchResPath = (ArrayList<Path>) finder.findPath(coords[0], coords[1], coords[2], coords[3], LocalDateTime.now().toLocalTime().toSecondOfDay());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Load all stops related to locations
|
||||||
public static void main(String[] args) {
|
* @param stops a String in format name1;name2
|
||||||
ArrayList<Stop> s = new ArrayList<>();
|
*/
|
||||||
s.add(new Stop("M8", "Balard", 1.0315897, 3.0265513));
|
public void LoadStringStops(String stops){
|
||||||
s.add(new Stop("M14", "Gare de Lyon", 2.4658452681, 3.0265513));
|
String[] stops_array = stops.split(";");
|
||||||
View v = new View(s);
|
double[] coords = new double[4];
|
||||||
|
int j = 0;
|
||||||
|
for (String stop: stops_array) {
|
||||||
|
double[] cur = ApiUtils.getGPSLocation(stop);
|
||||||
|
for (int i = 0; i < 2;i++){
|
||||||
|
coords[j] = cur[i];
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
searchResPath = (ArrayList<Path>) finder.findPath(coords[0], coords[1], coords[2], coords[3], LocalDateTime.now().toLocalTime().toSecondOfDay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Load a list of stops to display (used for selecting a departure and arrival stop, W.I.P)
|
||||||
|
* @param stops the stops list
|
||||||
|
* @param model the JTable model that will store them
|
||||||
|
*/
|
||||||
public void LoadSearchResult(ArrayList<Stop> stops, DefaultTableModel model) {
|
public void LoadSearchResult(ArrayList<Stop> stops, DefaultTableModel model) {
|
||||||
// Clear existing rows from the table
|
// Clear existing rows from the table
|
||||||
int cols = model.getColumnCount();
|
int cols = model.getColumnCount();
|
||||||
model.setRowCount(0);
|
model.setRowCount(0);
|
||||||
model.setColumnCount(cols);
|
model.setColumnCount(cols);
|
||||||
|
|
||||||
|
|
||||||
// Add new rows based on the search results
|
// Add new rows based on the search results
|
||||||
count = 0;
|
count = 0;
|
||||||
for (Stop stop : stops) {
|
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
|
// Add a row to the table with Stop's line in the first column and Stop's name in the second column
|
||||||
|
|
||||||
model.addRow(new Object[]{String.join(",", stop.getLines()), stop.getName()});
|
model.addRow(new Object[]{String.join(",", stop.getLines()), stop.getName()});
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println(stops.toString());
|
|
||||||
for (int i = 0; i < model.getRowCount(); i++) {
|
|
||||||
for (int j = 0; j < model.getColumnCount(); j++) {
|
|
||||||
System.out.print("valeur at coord " + i +";" + j +": " + model.getValueAt(i, j) + "\t");
|
|
||||||
}
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println(count);
|
|
||||||
|
|
||||||
tableStops.revalidate();
|
tableStops.revalidate();
|
||||||
tableStops.repaint();
|
tableStops.repaint();
|
||||||
|
|
||||||
tableItinerary.revalidate();
|
|
||||||
tableItinerary.repaint();
|
|
||||||
|
|
||||||
paneStops.setViewportView(tableStops);
|
paneStops.setViewportView(tableStops);
|
||||||
paneStops.revalidate();
|
paneStops.revalidate();
|
||||||
paneStops.repaint();
|
paneStops.repaint();
|
||||||
|
NetworkPanel.revalidate();
|
||||||
|
NetworkPanel.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that takes a list of paths and displays it in a JTabke
|
||||||
|
* @param paths the list of paths (from one stop to another)
|
||||||
|
* @param model the TableModel that stores the Table's data
|
||||||
|
*/
|
||||||
|
public void LoadSearchResultItinerary(ArrayList<Path> paths, DefaultTableModel model){
|
||||||
|
// Clear existing rows from the table
|
||||||
|
int cols = model.getColumnCount();
|
||||||
|
model.setRowCount(0);
|
||||||
|
model.setColumnCount(cols);
|
||||||
|
|
||||||
|
// Add new rows based on the search results
|
||||||
|
count = 0;
|
||||||
|
Path last = null;
|
||||||
|
if (paths != null) {
|
||||||
|
for (Path path : paths) {
|
||||||
|
// Add a row to the table with Stop's line in the first column and Stop's name in the second column
|
||||||
|
double time = path.getStartTime();
|
||||||
|
int hours = (int) (time / 3600);
|
||||||
|
int minutes = (int) ((time % 3600) / 60);
|
||||||
|
|
||||||
|
model.addRow(new Object[]{path.getLine(), path.getCurrentStop(), String.format("%02d:%02d", hours, minutes)});
|
||||||
|
|
||||||
|
++count;
|
||||||
|
last = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (last != null)
|
||||||
|
model.addRow(new Object[]{last.getLine(), last.getNextStop()});
|
||||||
|
|
||||||
|
tableItinerary.revalidate();
|
||||||
|
tableItinerary.repaint();
|
||||||
paneItinerary.setViewportView(tableItinerary);
|
paneItinerary.setViewportView(tableItinerary);
|
||||||
paneItinerary.revalidate();
|
paneItinerary.revalidate();
|
||||||
paneItinerary.repaint();
|
paneItinerary.repaint();
|
||||||
|
|
||||||
|
|
||||||
NetworkPanel.revalidate();
|
|
||||||
NetworkPanel.repaint();
|
|
||||||
|
|
||||||
ItineraryPanel.revalidate();
|
ItineraryPanel.revalidate();
|
||||||
ItineraryPanel.repaint();
|
ItineraryPanel.repaint();
|
||||||
|
|
||||||
|
|
||||||
this.displayTableValues(model);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Takes a table's data as argument and displays it
|
||||||
|
* @param mod the table's data
|
||||||
|
*/
|
||||||
public void displayTableValues(TableModel mod) {
|
public void displayTableValues(TableModel mod) {
|
||||||
|
|
||||||
for (int row = 0; row < mod.getRowCount(); row++) {
|
for (int row = 0; row < mod.getRowCount(); row++) {
|
||||||
for (int column = 0; column < mod.getColumnCount(); column++) {
|
for (int column = 0; column < mod.getColumnCount(); column++) {
|
||||||
|
|
||||||
if (mod.getValueAt(row, column) != null) System.out.print(mod.getValueAt(row, column).toString() + " ");
|
if (mod.getValueAt(row, column) != null) System.out.print(mod.getValueAt(row, column).toString() + " ");
|
||||||
}
|
}
|
||||||
System.out.print(";");
|
System.out.print(";");
|
||||||
|
|
||||||
}
|
}
|
||||||
System.out.println();
|
System.out.println();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** open a URL in browser
|
||||||
|
* @param uri
|
||||||
|
*/
|
||||||
|
private void openWebpage(URI uri) {
|
||||||
|
Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
|
||||||
|
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
|
||||||
|
try {
|
||||||
|
desktop.browse(uri);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.severe("Error opening browser");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** open a URL (taken from a String) in browser
|
||||||
|
* @param url the url String
|
||||||
|
*/
|
||||||
|
private void openWebpage(String url) {
|
||||||
|
try {
|
||||||
|
openWebpage(new URL(url).toURI());
|
||||||
|
} catch (URISyntaxException|MalformedURLException e) {
|
||||||
|
LOGGER.severe("Default desktop browser not set");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,33 +3,39 @@
|
||||||
*/
|
*/
|
||||||
package fr.u_paris.gla.project.idfm;
|
package fr.u_paris.gla.project.idfm;
|
||||||
|
|
||||||
import fr.u_paris.gla.project.io.ScheduleFormat;
|
import java.io.IOException;
|
||||||
import java.text.MessageFormat;
|
import java.io.InputStream;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
import java.util.logging.Logger;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import fr.u_paris.gla.project.io.ImageFormat;
|
import fr.u_paris.gla.project.io.ImageFormat;
|
||||||
import fr.u_paris.gla.project.utils.GPS;
|
import fr.u_paris.gla.project.utils.CSVTools;
|
||||||
|
|
||||||
public final class CSVImageProvider {
|
public final class CSVImageProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger for information on the process
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = Logger
|
||||||
|
.getLogger(IDFMNetworkExtractor.class.getName());
|
||||||
|
|
||||||
private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat
|
private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat
|
||||||
.getInstance(Locale.ENGLISH);
|
.getInstance(Locale.ENGLISH);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
MINUTES_SECOND_FORMATTER.setMinimumIntegerDigits(2);
|
MINUTES_SECOND_FORMATTER.setMinimumIntegerDigits(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String[] line = new String[ImageFormat.NUMBER_COLUMNS];
|
private final String[] line = new String[ImageFormat.NUMBER_COLUMNS];
|
||||||
|
|
||||||
private final Iterator<Transport> current;
|
private final Iterator<Transport> current;
|
||||||
|
|
||||||
|
private static ArrayList<ImagePair> lineImageMap;
|
||||||
|
|
||||||
|
public static final String FILE_NAME = IDFMNetworkExtractor.IMAGES_FILE_NAME;
|
||||||
|
|
||||||
|
|
||||||
/** Create the stream provider */
|
/** Create the stream provider */
|
||||||
public CSVImageProvider(Iterator<Transport> traces) {
|
public CSVImageProvider(Iterator<Transport> traces) {
|
||||||
this.current = traces;
|
this.current = traces;
|
||||||
|
@ -48,8 +54,37 @@ public final class CSVImageProvider {
|
||||||
|
|
||||||
Transport element = this.current.next();
|
Transport element = this.current.next();
|
||||||
this.line[ImageFormat.LINE_INDEX] = element.name;
|
this.line[ImageFormat.LINE_INDEX] = element.name;
|
||||||
|
this.line[ImageFormat.LINE_DETAIL_INDEX] = element.type;
|
||||||
this.line[ImageFormat.IMAGE_URL_INDEX] = element.image_url;
|
this.line[ImageFormat.IMAGE_URL_INDEX] = element.image_url;
|
||||||
|
|
||||||
return Arrays.copyOf(this.line, this.line.length);
|
return Arrays.copyOf(this.line, this.line.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns a list of ImagePair, which represents the name of the line and the link to the
|
||||||
|
* image of the line details.
|
||||||
|
* The list is created once and then store in a static variable.
|
||||||
|
* @return an ArrayList of ImagePair
|
||||||
|
*/
|
||||||
|
public static ArrayList<ImagePair> getLineImageMap() {
|
||||||
|
if (lineImageMap != null)
|
||||||
|
return lineImageMap;
|
||||||
|
lineImageMap = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
CSVTools.readCSVFromFile(FILE_NAME,
|
||||||
|
(String[] line) ->
|
||||||
|
{
|
||||||
|
String label = line[ImageFormat.LINE_INDEX];
|
||||||
|
String detail = line[ImageFormat.LINE_DETAIL_INDEX];
|
||||||
|
String imageUrl = line[ImageFormat.IMAGE_URL_INDEX];
|
||||||
|
|
||||||
|
lineImageMap.add(new ImagePair(label, detail, imageUrl));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch(IOException e){
|
||||||
|
LOGGER.severe("File is not generated yet");
|
||||||
|
}
|
||||||
|
lineImageMap.sort(Comparator.comparing(ImagePair::getLabel));
|
||||||
|
return lineImageMap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ public class CSVSchedulesProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move to the the nextDescription of a Transport line
|
* Move to the nextDescription of a Transport line
|
||||||
*/
|
*/
|
||||||
private void skipToNextDescription() {
|
private void skipToNextDescription() {
|
||||||
if (this.currentDescription.hasNext()) {
|
if (this.currentDescription.hasNext()) {
|
||||||
|
|
|
@ -202,7 +202,7 @@ public final class CSVStreamProvider {
|
||||||
} while (currentSegmentStart == null);
|
} while (currentSegmentStart == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Store current trace' data as a String array
|
/** Store current trace data as a String array
|
||||||
* @return The newly generated line of text
|
* @return The newly generated line of text
|
||||||
*/
|
*/
|
||||||
public String[] next() {
|
public String[] next() {
|
||||||
|
@ -271,7 +271,7 @@ public final class CSVStreamProvider {
|
||||||
Double max_speed = max_speed_by_type.get(type);
|
Double max_speed = max_speed_by_type.get(type);
|
||||||
Double two_acc_distance = two_acceleration_distance_by_type.get(type);
|
Double two_acc_distance = two_acceleration_distance_by_type.get(type);
|
||||||
return Math.max(0, distance - two_acc_distance) / max_speed
|
return Math.max(0, distance - two_acc_distance) / max_speed
|
||||||
+ Math.pow(Math.min(distance, two_acc_distance) / max_speed, 2);
|
+ 2 * Math.sqrt(Math.min(distance, two_acc_distance) * two_acc_distance)/max_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillTransports(int bif) {
|
private void fillTransports(int bif) {
|
||||||
|
@ -283,7 +283,7 @@ public final class CSVStreamProvider {
|
||||||
|
|
||||||
Transport transp = null;
|
Transport transp = null;
|
||||||
if(!transports.containsKey(traceId)){
|
if(!transports.containsKey(traceId)){
|
||||||
transp = new Transport(nameTransport,traceType, url_image);
|
transp = new Transport(nameTransport, traceType, url_image);
|
||||||
transports.put(traceId, transp);
|
transports.put(traceId, transp);
|
||||||
}else{
|
}else{
|
||||||
transp = transports.get(traceId);
|
transp = transports.get(traceId);
|
||||||
|
|
|
@ -18,6 +18,7 @@ import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Code of an extractor for the data from IDF mobilite.
|
* Code of an extractor for the data from IDF mobilite.
|
||||||
*
|
*
|
||||||
|
@ -84,7 +85,7 @@ public class IDFMNetworkExtractor {
|
||||||
|
|
||||||
private static final String HOURS_FILE_NAME = "hours.csv";
|
private static final String HOURS_FILE_NAME = "hours.csv";
|
||||||
|
|
||||||
private static final String IMAGES_FILE_NAME = "./images.csv";
|
public static final String IMAGES_FILE_NAME = "images.csv";
|
||||||
|
|
||||||
// Magically chosen values
|
// Magically chosen values
|
||||||
/**
|
/**
|
||||||
|
@ -101,18 +102,17 @@ public class IDFMNetworkExtractor {
|
||||||
public static boolean checkFileExistence(String filePath) {
|
public static boolean checkFileExistence(String filePath) {
|
||||||
File file = new File(filePath);
|
File file = new File(filePath);
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
LOGGER.severe(filePath+ " already exists.");
|
LOGGER.log(Level.INFO, filePath+ " already exists.");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
LOGGER.severe(filePath + " does not exist.");
|
LOGGER.log(Level.INFO, filePath + " does not exist.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void buildFiles() {
|
public static void buildFiles() {
|
||||||
|
if (checkFileExistence("./"+HOURS_FILE_NAME) && checkFileExistence("./"+TRACE_FILE_NAME) && checkFileExistence(("./"+IMAGES_FILE_NAME))) {
|
||||||
if (checkFileExistence("./"+HOURS_FILE_NAME) && checkFileExistence("./"+TRACE_FILE_NAME)) {
|
LOGGER.log(Level.INFO, "Files already exists.");
|
||||||
LOGGER.severe("Files already exists.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ public class IDFMNetworkExtractor {
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
for (Transport entry : transports.values()) {
|
for (Transport entry : transports.values()) {
|
||||||
entry.buildBifurcationOptimzed();
|
entry.buildBifurcationOptimized();
|
||||||
}
|
}
|
||||||
|
|
||||||
long endTime = System.currentTimeMillis();
|
long endTime = System.currentTimeMillis();
|
||||||
|
@ -160,7 +160,7 @@ public class IDFMNetworkExtractor {
|
||||||
long seconds = (tempsPasse / 1000) % 60;
|
long seconds = (tempsPasse / 1000) % 60;
|
||||||
long milliseconds = tempsPasse % 1000;
|
long milliseconds = tempsPasse % 1000;
|
||||||
|
|
||||||
System.out.println("Temps écoulé : " + minutes + " minutess, " + seconds + " secndes et " + milliseconds + " millis");
|
System.out.println("Temps écoulé : " + minutes + " minutes, " + seconds + " secndes et " + milliseconds + " millis");
|
||||||
|
|
||||||
System.out.println("******************Fin Building bifurcations ************************");
|
System.out.println("******************Fin Building bifurcations ************************");
|
||||||
|
|
||||||
|
|
45
src/main/java/fr/u_paris/gla/project/idfm/ImagePair.java
Normal file
45
src/main/java/fr/u_paris/gla/project/idfm/ImagePair.java
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
package fr.u_paris.gla.project.idfm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is made specific to store a Pair of Name/Link to be used in a Swing ComboBox
|
||||||
|
* These getters ables a ComboBox to show the label returned by toString, and get a specific value when the object is returned
|
||||||
|
*/
|
||||||
|
public class ImagePair {
|
||||||
|
/**
|
||||||
|
* The name of the line
|
||||||
|
*/
|
||||||
|
private final String line;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The label that will be shown in the ComboBox
|
||||||
|
*/
|
||||||
|
private final String label;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The link of the line details
|
||||||
|
*/
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
public ImagePair(String label, String label_detail, String value){
|
||||||
|
this.line = label;
|
||||||
|
this.label = label + " - " + label_detail;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLabel(){
|
||||||
|
return this.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLine(){
|
||||||
|
return this.line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue(){
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,7 +55,7 @@ public class Transport {
|
||||||
/**
|
/**
|
||||||
* Build the bifurcation for all the descriptions but optimized
|
* Build the bifurcation for all the descriptions but optimized
|
||||||
*/
|
*/
|
||||||
public void buildBifurcationOptimzed() {
|
public void buildBifurcationOptimized() {
|
||||||
// int found = 0;
|
// int found = 0;
|
||||||
for (TraceDescription d : descriptions) {
|
for (TraceDescription d : descriptions) {
|
||||||
Stop debut = stopsMap.get(d.from);
|
Stop debut = stopsMap.get(d.from);
|
||||||
|
@ -92,7 +92,7 @@ public class Transport {
|
||||||
* @param currentStop the current stop we are visiting
|
* @param currentStop the current stop we are visiting
|
||||||
* @param last The last stop we are trying to go to
|
* @param last The last stop we are trying to go to
|
||||||
* @param alreadyVisited All the stop we already have visisted
|
* @param alreadyVisited All the stop we already have visisted
|
||||||
* @param bif All the bifurcation encountered from the first stop to the current
|
* @param bifurcation All the bifurcation encountered from the first stop to the current
|
||||||
* one
|
* one
|
||||||
* @return True and the bifurcation if we found our road to the last stop and
|
* @return True and the bifurcation if we found our road to the last stop and
|
||||||
* false if we didn't
|
* false if we didn't
|
||||||
|
@ -138,7 +138,7 @@ public class Transport {
|
||||||
* @param currentStop the current stop we are visiting
|
* @param currentStop the current stop we are visiting
|
||||||
* @param last The last stop we are trying to go to
|
* @param last The last stop we are trying to go to
|
||||||
* @param alreadyVisited All the stop we already have visisted
|
* @param alreadyVisited All the stop we already have visisted
|
||||||
* @param bif All the bifurcation encountered from the first stop to the current
|
* @param bifurcation All the bifurcation encountered from the first stop to the current
|
||||||
* one
|
* one
|
||||||
* @return True and the bifurcation if we found our road to the last stop and
|
* @return True and the bifurcation if we found our road to the last stop and
|
||||||
* false if we didn't
|
* false if we didn't
|
||||||
|
|
|
@ -3,19 +3,15 @@
|
||||||
*/
|
*/
|
||||||
package fr.u_paris.gla.project.io;
|
package fr.u_paris.gla.project.io;
|
||||||
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.time.format.ResolverStyle;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A tool class for the Image format.
|
* A tool class for the Image format.
|
||||||
*/
|
*/
|
||||||
public final class ImageFormat {
|
public final class ImageFormat {
|
||||||
public static final int NUMBER_COLUMNS = 2;
|
public static final int NUMBER_COLUMNS = 3;
|
||||||
|
|
||||||
public static final int LINE_INDEX = 0;
|
public static final int LINE_INDEX = 0;
|
||||||
public static final int IMAGE_URL_INDEX = 1;
|
public static final int LINE_DETAIL_INDEX = 1;
|
||||||
|
public static final int IMAGE_URL_INDEX = 2;
|
||||||
|
|
||||||
/** Hidden constructor for tool class */
|
/** Hidden constructor for tool class */
|
||||||
private ImageFormat() {
|
private ImageFormat() {
|
||||||
|
|
|
@ -3,6 +3,10 @@ package fr.u_paris.gla.project.itinerary;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representation of a connection to another stop.
|
||||||
|
* Corresponds to a graph edge for the algorithm.
|
||||||
|
*/
|
||||||
public class Connection{
|
public class Connection{
|
||||||
// Destination of the connection between the two stops
|
// Destination of the connection between the two stops
|
||||||
private final Stop stop;
|
private final Stop stop;
|
||||||
|
@ -20,6 +24,13 @@ public class Connection{
|
||||||
|
|
||||||
private final int bifurcation;
|
private final int bifurcation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param stop the stop where the connection is going.
|
||||||
|
* @param lineName the name of the line used by the connection
|
||||||
|
* @param distance the distance of the connection in km
|
||||||
|
* @param time the travel time in s
|
||||||
|
* @param bifurcation the bifurcation used
|
||||||
|
*/
|
||||||
public Connection(Stop stop, String lineName, double distance, int time, int bifurcation){
|
public Connection(Stop stop, String lineName, double distance, int time, int bifurcation){
|
||||||
this.stop = stop;
|
this.stop = stop;
|
||||||
this.lineName=lineName;
|
this.lineName=lineName;
|
||||||
|
@ -29,39 +40,78 @@ public class Connection{
|
||||||
this.bifurcation = bifurcation;
|
this.bifurcation = bifurcation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param stop the stop where the connection is going.
|
||||||
|
* @param lineName the name of the line used by the connection
|
||||||
|
* @param distance the distance of the connection in km
|
||||||
|
* @param time the travel time in s
|
||||||
|
*/
|
||||||
public Connection(Stop stop, String lineName, double distance, int time){
|
public Connection(Stop stop, String lineName, double distance, int time){
|
||||||
this(stop, lineName, distance, time, 0);
|
this(stop, lineName, distance, time, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the line name of the connection
|
||||||
|
* @return the line name of the connection
|
||||||
|
*/
|
||||||
public String getLineName() {
|
public String getLineName() {
|
||||||
return lineName;
|
return lineName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the distance between the two connection stops.
|
||||||
|
* @return distance in km
|
||||||
|
*/
|
||||||
public double getDistance() {
|
public double getDistance() {
|
||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the travel time between the two stops.
|
||||||
|
* @return time in s
|
||||||
|
*/
|
||||||
public int getTime() {
|
public int getTime() {
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the stop to which the connection is going.
|
||||||
|
* @return the destination stop
|
||||||
|
*/
|
||||||
public Stop getStop() {
|
public Stop getStop() {
|
||||||
return stop;
|
return stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a schedule for the connection.
|
||||||
|
* @param hours passage time in s from 00:00
|
||||||
|
*/
|
||||||
public void addSchedule(int hours) {
|
public void addSchedule(int hours) {
|
||||||
this.schedules.add(hours);
|
this.schedules.add(hours);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort schedules.
|
||||||
|
* Necessary to get the right passage time.
|
||||||
|
*/
|
||||||
public void sortSchedule() {
|
public void sortSchedule() {
|
||||||
Collections.sort(this.schedules);
|
Collections.sort(this.schedules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return to the schedule list
|
||||||
|
* @return the schedule list
|
||||||
|
*/
|
||||||
public ArrayList<Integer> getSchedules() {
|
public ArrayList<Integer> getSchedules() {
|
||||||
return this.schedules;
|
return this.schedules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bifurcation of the connection
|
||||||
|
* @return the bifurcation
|
||||||
|
*/
|
||||||
public int getBifurcation() {
|
public int getBifurcation() {
|
||||||
return this.bifurcation;
|
return this.bifurcation;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +120,11 @@ public class Connection{
|
||||||
return this.time;
|
return this.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the time of the next passage.
|
||||||
|
* @param currentTime the current time
|
||||||
|
* @return the time of the next passage
|
||||||
|
*/
|
||||||
public double getNextTime(double currentTime) {
|
public double getNextTime(double currentTime) {
|
||||||
if(this.schedules.size() == 0) {
|
if(this.schedules.size() == 0) {
|
||||||
return currentTime;
|
return currentTime;
|
||||||
|
@ -85,9 +140,15 @@ public class Connection{
|
||||||
return this.schedules.get(0);
|
return this.schedules.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the time before you can reach the next stop with this connection.
|
||||||
|
* Corresponds to the sum of time to next stop and travel time.
|
||||||
|
* @param currentTime the current time
|
||||||
|
* @return time to reach the next stop
|
||||||
|
*/
|
||||||
public double getCost(double currentTime) {
|
public double getCost(double currentTime) {
|
||||||
if(this.schedules.size() == 0) {
|
if(this.schedules.size() == 0) {
|
||||||
if(this.lineName.equals("WALK")) {
|
if(this.lineName.equals("WALK") || this.lineName.equals("")) {
|
||||||
return this.time;
|
return this.time;
|
||||||
}
|
}
|
||||||
return this.time + 900;
|
return this.time + 900;
|
||||||
|
@ -96,4 +157,9 @@ public class Connection{
|
||||||
if(nextTime < currentTime) { nextTime += 86400;}
|
if(nextTime < currentTime) { nextTime += 86400;}
|
||||||
return nextTime - currentTime + this.time;
|
return nextTime - currentTime + this.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return lineName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,60 @@
|
||||||
package fr.u_paris.gla.project.itinerary;
|
package fr.u_paris.gla.project.itinerary;
|
||||||
|
|
||||||
|
import fr.u_paris.gla.project.utils.GPS;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path finder algorithm.
|
||||||
|
* The algorithm is based on an A* algorithm,
|
||||||
|
* adapted to our case of path finding in a public transport network.
|
||||||
|
*/
|
||||||
public class Finder {
|
public class Finder {
|
||||||
|
|
||||||
private Graph graph;
|
private Graph graph;
|
||||||
|
|
||||||
public Finder(Graph graph) {
|
public Finder(Graph graph) {
|
||||||
this.graph = graph;
|
this.graph = graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param from_x the latitude of the starting point in decimal degrees (DD)
|
||||||
|
* @param from_y the longitude of the starting point
|
||||||
|
* @param to_x the latitude of the arrival point
|
||||||
|
* @param to_y the longitude of the arrival point
|
||||||
|
* @param startTime the departure time
|
||||||
|
* @return the optimal path found by the algorithm
|
||||||
|
*/
|
||||||
|
public List<Path> findPath(double from_x, double from_y, double to_x, double to_y, double startTime) {
|
||||||
|
Stop fromNode = new Stop("", "tmp_from", from_x, from_y);
|
||||||
|
Stop toNode = new Stop("", "tmp_to", to_x, to_y);
|
||||||
|
|
||||||
|
for (Stop node : graph.getNodes()) {
|
||||||
|
double from_dst = GPS.distance(from_x, from_y, node.getLatitude(), node.getLongitude());
|
||||||
|
double to_dst = GPS.distance(to_x, to_y, node.getLatitude(), node.getLongitude());
|
||||||
|
Connection from_c = new Connection(node, "", from_dst, (int) ((from_dst * 1000) / Parse.WALK_SPEED));
|
||||||
|
Connection to_c = new Connection(toNode, "", to_dst, (int) ((to_dst * 1000) / Parse.WALK_SPEED));
|
||||||
|
graph.addConnection(fromNode, from_c);
|
||||||
|
graph.addConnection(node, to_c);
|
||||||
|
}
|
||||||
|
graph.addNode(fromNode);
|
||||||
|
graph.addNode(toNode);
|
||||||
|
|
||||||
|
List<Path> result = findPath(fromNode, toNode, startTime);
|
||||||
|
|
||||||
|
graph.removeNode(fromNode);
|
||||||
|
graph.removeNode(toNode);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return a path from startNode to goalNode using A* algorithm
|
* return a path from startNode to goalNode using A* algorithm
|
||||||
* @param startNode
|
* @param startNode
|
||||||
* @param goalNode
|
* @param goalNode
|
||||||
*/
|
*/
|
||||||
public List<Path> findPath(Stop startNode, Stop goalNode, double startTime) {
|
public List<Path> findPath(Stop startNode, Stop goalNode, double startTime) {
|
||||||
|
PriorityQueue<Stop> openSet = new PriorityQueue<>(Comparator.comparingDouble(Stop::getF));
|
||||||
PriorityQueue<Stop> openSet = new PriorityQueue<>(Comparator.comparingDouble(GraphNode::getF));
|
|
||||||
HashSet<Stop> closedSet = new HashSet<>();
|
HashSet<Stop> closedSet = new HashSet<>();
|
||||||
HashMap<Stop, Path> cameFrom = new HashMap<>();
|
HashMap<Stop, Path> cameFrom = new HashMap<>();
|
||||||
HashMap<Stop, Double> gScore = new HashMap<>();
|
HashMap<Stop, Double> gScore = new HashMap<>();
|
||||||
|
@ -111,6 +148,5 @@ public class Finder {
|
||||||
node.setF(newF);
|
node.setF(newF);
|
||||||
openSet.add(node);
|
openSet.add(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,99 @@
|
||||||
package fr.u_paris.gla.project.itinerary;
|
package fr.u_paris.gla.project.itinerary;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class Graph{
|
/**
|
||||||
|
* A representation of a graph
|
||||||
|
* for our path-finding algorithm
|
||||||
|
*/
|
||||||
|
public class Graph {
|
||||||
private final Set<Stop> nodes;
|
private final Set<Stop> nodes;
|
||||||
|
|
||||||
private final Map<Stop, Set<Connection>> connections;
|
private final Map<Stop, Set<Connection>> connections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nodes the set of graph nodes
|
||||||
|
* @param connections the map of all nodes to their edges
|
||||||
|
*/
|
||||||
public Graph(Set<Stop> nodes, Map<Stop, Set<Connection>> connections) {
|
public Graph(Set<Stop> nodes, Map<Stop, Set<Connection>> connections) {
|
||||||
this.nodes = nodes;
|
this.nodes = nodes;
|
||||||
this.connections = connections;
|
this.connections = connections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the set of edges of a node
|
||||||
|
* @param node the node from which we want to get the edges
|
||||||
|
* @return the sets of the edges for the given node
|
||||||
|
*/
|
||||||
public Set<Connection> getConnections(Stop node) {
|
public Set<Connection> getConnections(Stop node) {
|
||||||
return connections.get(node);
|
return connections.get(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the set of graph nodes
|
||||||
|
* @return the set of nodes
|
||||||
|
*/
|
||||||
public Set<Stop> getNodes() {
|
public Set<Stop> getNodes() {
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the map of all nodes to their edges in the graph
|
||||||
|
* @return the map of all nodes to their edges
|
||||||
|
*/
|
||||||
public Map<Stop, Set<Connection>> getConnections() {
|
public Map<Stop, Set<Connection>> getConnections() {
|
||||||
return connections;
|
return connections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a node to the graph
|
||||||
|
* @param s the node to add
|
||||||
|
*/
|
||||||
|
public void addNode(Stop s) {
|
||||||
|
nodes.add(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a connection to the graph
|
||||||
|
* @param stop the node from which the connection starts
|
||||||
|
* @param con the connection to add
|
||||||
|
*/
|
||||||
|
public void addConnection(Stop stop, Connection con) {
|
||||||
|
Set<Connection> currentConnections = connections.get(stop);
|
||||||
|
if (currentConnections == null) {
|
||||||
|
HashSet<Connection> set = new HashSet<>();
|
||||||
|
set.add(con);
|
||||||
|
connections.put(stop, set);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentConnections.add(con);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a node from the graph.
|
||||||
|
* This also removes all connections to and from this node.
|
||||||
|
* @param s the node to be removed
|
||||||
|
*/
|
||||||
|
public void removeNode(Stop s) {
|
||||||
|
for(Stop stop : nodes) {
|
||||||
|
if(getConnections(stop) == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ArrayList<Connection> toRemove = new ArrayList<>();
|
||||||
|
for(Connection c : getConnections(stop)) {
|
||||||
|
if(c.getStop() == s) {
|
||||||
|
toRemove.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(Connection c : toRemove) {
|
||||||
|
getConnections(stop).remove(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodes.remove(s);
|
||||||
|
connections.remove(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
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<Stop> getNeighbors();
|
|
||||||
double getCost(Stop neighbor);
|
|
||||||
double getF();
|
|
||||||
void setF(double value);
|
|
||||||
}
|
|
|
@ -9,6 +9,9 @@ import java.util.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSV file parser to generate the network graph
|
||||||
|
*/
|
||||||
public class Parse {
|
public class Parse {
|
||||||
private static final Logger LOGGER = Logger
|
private static final Logger LOGGER = Logger
|
||||||
.getLogger(IDFMNetworkExtractor.class.getName());
|
.getLogger(IDFMNetworkExtractor.class.getName());
|
||||||
|
@ -42,7 +45,7 @@ public class Parse {
|
||||||
private static final int STOP_TIME = 30;
|
private static final int STOP_TIME = 30;
|
||||||
|
|
||||||
//Walking speed in m/s
|
//Walking speed in m/s
|
||||||
private static final double WALK_SPEED = 1.;
|
public static final double WALK_SPEED = 1.;
|
||||||
|
|
||||||
private HashSet<Stop> nodes = new HashSet<>();
|
private HashSet<Stop> nodes = new HashSet<>();
|
||||||
private HashMap<Stop, Set<Connection>> connections = new HashMap<>();
|
private HashMap<Stop, Set<Connection>> connections = new HashMap<>();
|
||||||
|
@ -182,6 +185,13 @@ public class Parse {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds schedules to graph stops, parsed from a CSV line
|
||||||
|
* @param input the current line we want to parse
|
||||||
|
* @param stopsHashSet the map of stop names to their objects
|
||||||
|
* @param connections the map of stops to their connections
|
||||||
|
*/
|
||||||
private static void addSchedule(String[] input, HashMap<String, ArrayList<Stop>> stopsHashSet, HashMap<Stop, Set<Connection>> connections) {
|
private static void addSchedule(String[] input, HashMap<String, ArrayList<Stop>> stopsHashSet, HashMap<Stop, Set<Connection>> connections) {
|
||||||
|
|
||||||
String line = input[0];
|
String line = input[0];
|
||||||
|
@ -211,12 +221,13 @@ public class Parse {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse CSV files to build the network graph
|
||||||
|
*/
|
||||||
public void parseFiles(){
|
public void parseFiles(){
|
||||||
|
|
||||||
IDFMNetworkExtractor.buildFiles();
|
IDFMNetworkExtractor.buildFiles();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
CSVTools.readCSVFromFile(TRACE_FILE_NAME,
|
CSVTools.readCSVFromFile(TRACE_FILE_NAME,
|
||||||
(String[] line) -> addLine(line, nodes, tmp, connections));
|
(String[] line) -> addLine(line, nodes, tmp, connections));
|
||||||
|
|
||||||
|
@ -228,17 +239,27 @@ public class Parse {
|
||||||
c.sortSchedule();
|
c.sortSchedule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
catch (IOException e) {
|
||||||
LOGGER.log(Level.SEVERE, "Error while reading the line paths", e);
|
LOGGER.log(Level.SEVERE, "Error while reading the line paths", e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns network graph from parsed CSV files
|
||||||
|
* @return the graphe of the network
|
||||||
|
*/
|
||||||
|
public Graph createGraph() {
|
||||||
|
return new Graph(nodes, connections);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Finder createFinder(Graph graph) {
|
||||||
|
return new Finder(graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Path> getItinerary(Stop src, Stop dst, double startTime ){
|
public List<Path> getItinerary(Stop src, Stop dst, double startTime ){
|
||||||
Graph graph = new Graph(nodes, connections);
|
Graph graph = new Graph(nodes, connections);
|
||||||
Finder finder = new Finder(graph);
|
Finder finder = new Finder(graph);
|
||||||
return finder.findPath(src, dst, startTime);
|
return finder.findPath(src, dst, startTime);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package fr.u_paris.gla.project.itinerary;
|
package fr.u_paris.gla.project.itinerary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representation of a path
|
||||||
|
*/
|
||||||
public class Path {
|
public class Path {
|
||||||
private Stop current;
|
private Stop current;
|
||||||
|
|
||||||
|
@ -15,6 +18,11 @@ public class Path {
|
||||||
|
|
||||||
private Connection connection;
|
private Connection connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param current the start stop
|
||||||
|
* @param connection the connection to the next stop
|
||||||
|
* @param startTime departure time from node current
|
||||||
|
*/
|
||||||
public Path(Stop current, Connection connection, double startTime) {
|
public Path(Stop current, Connection connection, double startTime) {
|
||||||
this.current = current;
|
this.current = current;
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
|
@ -24,26 +32,50 @@ public class Path {
|
||||||
this.line = connection.getLineName();
|
this.line = connection.getLineName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the connection used by the path
|
||||||
|
* @return the connection used
|
||||||
|
*/
|
||||||
public Connection getConnection(){
|
public Connection getConnection(){
|
||||||
return this.connection;
|
return this.connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the start stop
|
||||||
|
* @return the start stop
|
||||||
|
*/
|
||||||
public Stop getCurrentStop() {
|
public Stop getCurrentStop() {
|
||||||
return this.current;
|
return this.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next stop
|
||||||
|
* @return the next stop
|
||||||
|
*/
|
||||||
public Stop getNextStop() {
|
public Stop getNextStop() {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns stop start time
|
||||||
|
* @return the time in s
|
||||||
|
*/
|
||||||
public double getStartTime() {
|
public double getStartTime() {
|
||||||
return this.startTime;
|
return this.startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the travel time between the two stops.
|
||||||
|
* @return the travel time in s
|
||||||
|
*/
|
||||||
public double travelTime() {
|
public double travelTime() {
|
||||||
return this.travelTime;
|
return this.travelTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the line taken.
|
||||||
|
* @return the name of the line
|
||||||
|
*/
|
||||||
public String getLine() {
|
public String getLine() {
|
||||||
return this.line;
|
return this.line;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
package fr.u_paris.gla.project.itinerary;
|
package fr.u_paris.gla.project.itinerary;
|
||||||
|
|
||||||
|
import fr.u_paris.gla.project.utils.GPS;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class Stop implements GraphNode {
|
/**
|
||||||
|
* A representation of a stop used as a node
|
||||||
|
* for the path-finding algorithm.
|
||||||
|
*/
|
||||||
|
public class Stop {
|
||||||
// The total number of stops
|
// The total number of stops
|
||||||
private static int counter = 0;
|
private static int counter = 0;
|
||||||
|
|
||||||
|
@ -20,6 +26,15 @@ public class Stop implements GraphNode {
|
||||||
|
|
||||||
private double f;
|
private double f;
|
||||||
|
|
||||||
|
//Maximal speed in m/s
|
||||||
|
private final double MAX_SPEED = 14.;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param line the line passing through the stop
|
||||||
|
* @param name the name of the stop
|
||||||
|
* @param latitude the latitude of the stop in decimal degrees (DD)
|
||||||
|
* @param longitude the longitude of the stop in DD
|
||||||
|
*/
|
||||||
public Stop(String line, String name, double latitude, double longitude) {
|
public Stop(String line, String name, double latitude, double longitude) {
|
||||||
lines = new HashSet<>();
|
lines = new HashSet<>();
|
||||||
lines.add(line);
|
lines.add(line);
|
||||||
|
@ -32,36 +47,31 @@ public class Stop implements GraphNode {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Stop{" +
|
return name;
|
||||||
"id=" + id +
|
|
||||||
", lines=" + lines +
|
|
||||||
", name='" + name + '\'' +
|
|
||||||
", latitude=" + latitude +
|
|
||||||
", longitude=" + longitude +
|
|
||||||
'}';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId(){
|
public int getId(){
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Computes the heuristic cost of the node relative to the goal node
|
||||||
|
* @param goalNode the node we're trying to reach
|
||||||
|
* @return the heuristic cost
|
||||||
|
*/
|
||||||
public double getHeuristicCost(Stop goalNode) {
|
public double getHeuristicCost(Stop goalNode) {
|
||||||
return 0;
|
double distance = GPS.distance(this.latitude, this.longitude, goalNode.latitude, goalNode.longitude);
|
||||||
|
return distance/MAX_SPEED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Stop> getNeighbors() {
|
public Set<Stop> getNeighbors() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getCost(Stop neighbor) {
|
public double getCost(Stop neighbor) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getF() {
|
public double getF() {
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
@ -70,21 +80,41 @@ public class Stop implements GraphNode {
|
||||||
this.f = value;
|
this.f = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the stop
|
||||||
|
* @return the name of the stop
|
||||||
|
*/
|
||||||
public String getName(){
|
public String getName(){
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns latitude of the stop
|
||||||
|
* @return stop latitude in DD
|
||||||
|
*/
|
||||||
public double getLatitude(){
|
public double getLatitude(){
|
||||||
return latitude;
|
return latitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns longitude of the stop
|
||||||
|
* @return stop longitude in DD
|
||||||
|
*/
|
||||||
public double getLongitude(){
|
public double getLongitude(){
|
||||||
return longitude;
|
return longitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a transport line to the stop
|
||||||
|
* @param s the line to add
|
||||||
|
*/
|
||||||
public void addLine(String s){
|
public void addLine(String s){
|
||||||
lines.add(s);
|
lines.add(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the lines
|
||||||
|
* @return all transport lines passing through this stop.
|
||||||
|
*/
|
||||||
public Set<String> getLines() { return this.lines; }
|
public Set<String> getLines() { return this.lines; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,17 @@ public class ApiUtils {
|
||||||
private static final Logger LOGGER = Logger
|
private static final Logger LOGGER = Logger
|
||||||
.getLogger(IDFMNetworkExtractor.class.getName());
|
.getLogger(IDFMNetworkExtractor.class.getName());
|
||||||
|
|
||||||
// OpenStreetMap API URL
|
/**
|
||||||
|
* OpenStreetMap API URL
|
||||||
|
*/
|
||||||
private static final String OSM_URL = "https://nominatim.openstreetmap.org/search";
|
private static final String OSM_URL = "https://nominatim.openstreetmap.org/search";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns the GPS location of a string, using OSM API.
|
||||||
|
* The string can be anything, and adress, a street, a place.
|
||||||
|
* @param term the term to search
|
||||||
|
* @return the GPS location, (0,0) if not result
|
||||||
|
*/
|
||||||
public static double[] getGPSLocation(String term) {
|
public static double[] getGPSLocation(String term) {
|
||||||
try {
|
try {
|
||||||
String urlString = String.format("%s?q=%s&format=json", OSM_URL, URLEncoder.encode(term, StandardCharsets.UTF_8));
|
String urlString = String.format("%s?q=%s&format=json", OSM_URL, URLEncoder.encode(term, StandardCharsets.UTF_8));
|
||||||
|
|
|
@ -6,7 +6,6 @@ package fr.u_paris.gla.project.utils;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@ -33,7 +32,7 @@ public final class CSVTools {
|
||||||
* @param contentLineConsumer the variable used to store the data
|
* @param contentLineConsumer the variable used to store the data
|
||||||
* @throws IOException if it's impossible to download the file
|
* @throws IOException if it's impossible to download the file
|
||||||
*/
|
*/
|
||||||
private static void readCSVFromInputStream(InputStream is, Consumer<String[]> contentLineConsumer)
|
public static void readCSVFromInputStream(InputStream is, Consumer<String[]> contentLineConsumer)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
ICSVParser parser = new CSVParserBuilder().withSeparator(';').build();
|
ICSVParser parser = new CSVParserBuilder().withSeparator(';').build();
|
||||||
try (Reader reader = new BufferedReader(
|
try (Reader reader = new BufferedReader(
|
||||||
|
@ -75,8 +74,8 @@ public final class CSVTools {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Save our current CSV variable's data into an actual file
|
/** Save our current CSV variable's data into an actual file
|
||||||
* @param filename the saved file's name and path
|
* @param filename saved file's name and path
|
||||||
* @param contentLineConsumer our data variable
|
* @param contentLinesConsumer our data variable
|
||||||
* @throws IOException if we can't write the data into the file
|
* @throws IOException if we can't write the data into the file
|
||||||
*/
|
*/
|
||||||
public static void writeCSVToFile(String filename,
|
public static void writeCSVToFile(String filename,
|
||||||
|
@ -88,20 +87,4 @@ public final class CSVTools {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// /** Save our current CSV variable's data into an actual file
|
|
||||||
// * @param filename the saved file's name and path
|
|
||||||
// * @param contentLineConsumer our data variable
|
|
||||||
// * @throws IOException if we can't write the data into the file
|
|
||||||
// */
|
|
||||||
// public static void writeCSVToFile(String filename,
|
|
||||||
// Stream<String[][]> contentLinesConsumer) throws IOException {
|
|
||||||
// try (FileWriter writer = new FileWriter(filename, StandardCharsets.UTF_8)) {
|
|
||||||
// CSVWriterBuilder wBuilder = new CSVWriterBuilder(writer).withSeparator(';');
|
|
||||||
// try (ICSVWriter csv = wBuilder.build()) {
|
|
||||||
// contentLinesConsumer.forEachOrdered(line -> Arrays.stream(line).forEach(csv::writeNext));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,22 +99,22 @@ public class CSVStreamProviderTest {
|
||||||
@Test
|
@Test
|
||||||
public void testDistanceToTime() throws Exception {
|
public void testDistanceToTime() throws Exception {
|
||||||
// Valeurs fictives pour TWO_ACCELERATION_DISTANCE et MAX_SPEED
|
// Valeurs fictives pour TWO_ACCELERATION_DISTANCE et MAX_SPEED
|
||||||
final double TWO_ACCELERATION_DISTANCE = 0.2; // Par exemple
|
final double TWO_ACCELERATION_DISTANCE = 0.1;
|
||||||
final double MAX_SPEED = 5.0; // Par exemple
|
final double MAX_SPEED = 10.0;
|
||||||
|
|
||||||
// Exemple de distance à tester
|
// Exemple de distance à tester
|
||||||
double distanceExample = 1.0; // 1 km
|
double distanceExample = 1.0; // 1 km
|
||||||
|
|
||||||
// Calcul attendu basé sur la formule fournie
|
// Calcul attendu basé sur la formule fournie
|
||||||
double expected = Math.max(0, distanceExample - TWO_ACCELERATION_DISTANCE) / MAX_SPEED
|
double expected = Math.max(0, distanceExample - TWO_ACCELERATION_DISTANCE) / MAX_SPEED
|
||||||
+ Math.pow(Math.min(distanceExample, TWO_ACCELERATION_DISTANCE) / MAX_SPEED, 2);
|
+ (2 * Math.sqrt(Math.min(distanceExample, TWO_ACCELERATION_DISTANCE) * TWO_ACCELERATION_DISTANCE) / MAX_SPEED);
|
||||||
|
|
||||||
// Accès à la méthode distanceToTime via la réflexion
|
// Accès à la méthode distanceToTime via la réflexion
|
||||||
Method method = CSVStreamProvider.class.getDeclaredMethod("distanceToTime", double.class);
|
Method method = CSVStreamProvider.class.getDeclaredMethod("distanceToTime", double.class, String.class);
|
||||||
method.setAccessible(true);
|
method.setAccessible(true);
|
||||||
|
|
||||||
// Invocation de la méthode distanceToTime et stockage du résultat
|
// Invocation de la méthode distanceToTime et stockage du résultat
|
||||||
double result = (Double) method.invoke(null, distanceExample);
|
double result = (Double) method.invoke(null, distanceExample, "Bus");
|
||||||
|
|
||||||
// Assertion pour vérifier si le résultat est conforme à l'attendu
|
// Assertion pour vérifier si le résultat est conforme à l'attendu
|
||||||
assertEquals(expected, result, "Le calcul du temps à partir de la distance devrait être conforme à l'attendu.");
|
assertEquals(expected, result, "Le calcul du temps à partir de la distance devrait être conforme à l'attendu.");
|
||||||
|
|
|
@ -15,6 +15,7 @@ public class StopEntryTest {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
//Si le le test testToString du haut ne marche pas essayer celui du bas
|
//Si le le test testToString du haut ne marche pas essayer celui du bas
|
||||||
@Test
|
@Test
|
||||||
public void testToString() {
|
public void testToString() {
|
||||||
|
@ -23,6 +24,7 @@ public class StopEntryTest {
|
||||||
String expected = "Chatelet [2.346, 48.853]";
|
String expected = "Chatelet [2.346, 48.853]";
|
||||||
assertEquals(expected, stop.toString());
|
assertEquals(expected, stop.toString());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
//Test de compareTo
|
//Test de compareTo
|
||||||
|
|
Reference in a new issue