[format] use google codestyle

This commit is contained in:
Mylloon 2024-04-28 15:58:22 +02:00
parent db471f41d1
commit 27a34f390e
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
40 changed files with 3037 additions and 2846 deletions

View file

@ -1,28 +1,37 @@
# Comment contribuer à ce projet # Comment contribuer à ce projet
2 cas sont possibles pour contribuer à ce projet: 2 cas sont possibles pour contribuer à ce projet:
- Vous ête un étudiant et l'utilisez pour créer votre projet, dans ce cas reportez vous à [la section étudiant](#etudiant)
- Vous êtes un enseignant améliorant ce modèle, dans ce cas reportez vous à [la section enseignant](#enseignant) - Vous ête un étudiant et l'utilisez pour créer votre projet, dans ce cas reportez vous
à [la section étudiant](#etudiant)
- Vous êtes un enseignant améliorant ce modèle, dans ce cas reportez vous
à [la section enseignant](#enseignant)
## Etudiant ## Etudiant
Vous ne devez pas contribuer directement à ce projet mais devez en effectuer un fork. Une fois cela effectué vous devez: Vous ne devez pas contribuer directement à ce projet mais devez en effectuer un fork. Une fois cela
- [X] Ajouter votre identifiant de groupe au champs `groupId` du fichier [pom.xml](pom.xml) sous la forme de `fr.u-paris.gla.votreequipe` effectué vous devez:
- [x] Ajouter votre identifiant de groupe au champs `groupId` du fichier [pom.xml](pom.xml) sous la
forme de `fr.u-paris.gla.votreequipe`
- [ ] Modifier le package principal afin de refleter le nouveau nom de groupe. - [ ] Modifier le package principal afin de refleter le nouveau nom de groupe.
- [ ] Adapter le fichier [README](README.md) au contenu de votre projet specifique - [ ] Adapter le fichier [README](README.md) au contenu de votre projet specifique
- [ ] Adapter ce fichier (CONTRIBUTING.md) à vos propres instructions de contribution, notamment: - [ ] Adapter ce fichier (CONTRIBUTING.md) à vos propres instructions de contribution, notamment:
- [ ] Convention de style de codage - [ ] Convention de style de codage
- [ ] Convention d'utilisation de git - [ ] Convention d'utilisation de git
- [ ] Lien avec d'autres projets et d'autres dépôts. - [ ] Lien avec d'autres projets et d'autres dépôts.
- [X] Modifier le fichier `application.properties` au besoin. - [x] Modifier le fichier `application.properties` au besoin.
## Enseignant ## Enseignant
Ce dépôt suit la convention de gitflow. Les modifications doivent être effectuées dans des branches séparées, Ce dépôt suit la convention de gitflow. Les modifications doivent être effectuées dans des branches
séparées,
intégrées dans la branche dev une fois terminée. intégrées dans la branche dev une fois terminée.
La branche main ne doit contenir que des versions stables de ce modèle. La branche main ne doit contenir que des versions stables de ce modèle.
Le code est écrit en Java, manipulé par l'outils de construction maven et doit suivre les conventions usuelles du langage et de l'outils. Le code est écrit en Java, manipulé par l'outils de construction maven et doit suivre les
conventions usuelles du langage et de l'outils.
Le package principal du code Java est `fr.u_paris.gla.project` Le package principal du code Java est `fr.u_paris.gla.project`
Le fichier de properties `application.properties` permet d'accéder depuis le code Java aux diverses informations inscrite dans maven. Le fichier de properties `application.properties` permet d'accéder depuis le code Java aux diverses
informations inscrite dans maven.

View file

@ -6,7 +6,8 @@ Version 2024
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).
Il s'agit d'un projet Java. Ce dépôt définit un système de build et une application simple. Il est nécessaire de consulter le fichier [CONTRIBUTING.md](CONTRIBUTING.md) pour utiliser ce dépôt. Il s'agit d'un projet Java. Ce dépôt définit un système de build et une application simple. Il est
nécessaire de consulter le fichier [CONTRIBUTING.md](CONTRIBUTING.md) pour utiliser ce dépôt.
## Lancement du programme ## Lancement du programme
@ -27,9 +28,11 @@ mvn clean jacoco:prepare-agent install jacoco:report
Par la suite, `mvn jacoco:report` suffit. 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 --info
@ -37,7 +40,8 @@ java -jar target/project-2024.1.0.0-SNAPSHOT.jar --info
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.
## Tests JaCoCo ## Tests JaCoCo

View file

@ -8,107 +8,123 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.Properties; import java.util.Properties;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.WindowConstants; import javax.swing.WindowConstants;
/** Simple application model. /**
* Simple application model.
* *
* @author Emmanuel Bigeon */ * @author Emmanuel Bigeon
*/
public class App { public class App {
/**
*
*/
private static final String UNSPECIFIED = "Unspecified"; //$NON-NLS-1$
/** The logo image name. */
private static final String LOGO_NAME = "uparis_logo_rvb.png"; //$NON-NLS-1$
/** Image height. */
private static final int HEIGHT = 256;
/** Image width. */
private static final int WIDTH = HEIGHT;
/** Resizes an image. /**
* *
* @param src source image */
* @param w width private static final String UNSPECIFIED = "Unspecified"; //$NON-NLS-1$
* @param h height /**
* @return the resized image */ * The logo image name.
private static Image getScaledImage(Image src, int w, int h) { */
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); private static final String LOGO_NAME = "uparis_logo_rvb.png"; //$NON-NLS-1$
Graphics2D g2d = resizedImg.createGraphics(); /**
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, * Image height.
RenderingHints.VALUE_INTERPOLATION_BILINEAR); */
g2d.drawImage(src, 0, 0, w, h, null); private static final int HEIGHT = 256;
g2d.dispose(); /**
return resizedImg; * Image width.
*/
private static final int WIDTH = HEIGHT;
/**
* Resizes an image.
*
* @param src source image
* @param w width
* @param h height
* @return the resized image
*/
private static Image getScaledImage(Image src, int w, int h) {
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = resizedImg.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(src, 0, 0, w, h, null);
g2d.dispose();
return resizedImg;
}
/**
* Application entry point.
*
* @param args launching arguments
*/
public static void main(String[] args) {
for (String string : args) {
if ("--info".equals(string)) { //$NON-NLS-1$
printAppInfos(System.out);
return;
}
if ("--gui".equals(string)) { //$NON-NLS-1$
showLogo();
}
}
}
/**
* @param out the output stream
*/
public static void printAppInfos(PrintStream out) {
Properties props = readApplicationProperties();
out.println(
"Application: " + props.getProperty("app.name", UNSPECIFIED)); //$NON-NLS-1$ //$NON-NLS-2$
out.println(
"Version: " + props.getProperty("app.version", UNSPECIFIED)); //$NON-NLS-1$ //$NON-NLS-2$
out.println("By: " + props.getProperty("app.team", UNSPECIFIED)); //$NON-NLS-1$ //$NON-NLS-2$
}
private static Properties readApplicationProperties() {
Properties props = new Properties();
try (InputStream is = App.class.getResourceAsStream("application.properties")) { //$NON-NLS-1$
props.load(is);
} catch (IOException e) {
throw new RuntimeException("Unable to read application informations", e); //$NON-NLS-1$
}
return props;
}
/**
* Shows the logo in an image.
*/
public static void showLogo() {
Properties props = readApplicationProperties();
JFrame frame = new JFrame(props.getProperty("app.name")); //$NON-NLS-1$
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JLabel container = new JLabel();
try (InputStream is = App.class.getResourceAsStream(LOGO_NAME)) {
if (is == null) {
container.setText("Image Not Found");
} else {
BufferedImage img = ImageIO.read(is);
ImageIcon icon = new ImageIcon(img);
ImageIcon resized = new ImageIcon(
getScaledImage(icon.getImage(), WIDTH, HEIGHT));
container.setIcon(resized);
}
} catch (IOException e) {
container.setText("Image Not Read: " + e.getLocalizedMessage());
} }
/** Application entry point. frame.getContentPane().add(container);
*
* @param args launching arguments */
public static void main(String[] args) {
if (args.length > 0) {
for (String string : args) {
if ("--info".equals(string)) { //$NON-NLS-1$
printAppInfos(System.out);
return;
}
if ("--gui".equals(string)) { //$NON-NLS-1$
showLogo();
}
}
}
}
/** @param out the output stream */ frame.pack();
public static void printAppInfos(PrintStream out) { frame.setVisible(true);
Properties props = readApplicationProperties(); }
out.println("Application: " + props.getProperty("app.name", UNSPECIFIED)); //$NON-NLS-1$ //$NON-NLS-2$
out.println("Version: " + props.getProperty("app.version", UNSPECIFIED)); //$NON-NLS-1$ //$NON-NLS-2$
out.println("By: " + props.getProperty("app.team", UNSPECIFIED)); //$NON-NLS-1$ //$NON-NLS-2$
}
private static Properties readApplicationProperties() {
Properties props = new Properties();
try (InputStream is = App.class.getResourceAsStream("application.properties")) { //$NON-NLS-1$
props.load(is);
} catch (IOException e) {
throw new RuntimeException("Unable to read application informations", e); //$NON-NLS-1$
}
return props;
}
/** Shows the logo in an image. */
public static void showLogo() {
Properties props = readApplicationProperties();
JFrame frame = new JFrame(props.getProperty("app.name")); //$NON-NLS-1$
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JLabel container = new JLabel();
try (InputStream is = App.class.getResourceAsStream(LOGO_NAME)) {
if (is == null) {
container.setText("Image Not Found");
} else {
BufferedImage img = ImageIO.read(is);
ImageIcon icon = new ImageIcon(img);
ImageIcon resized = new ImageIcon(
getScaledImage(icon.getImage(), WIDTH, HEIGHT));
container.setIcon(resized);
}
} catch (IOException e) {
container.setText("Image Not Read: " + e.getLocalizedMessage());
}
frame.getContentPane().add(container);
frame.pack();
frame.setVisible(true);
}
} }

View file

@ -1,363 +1,357 @@
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.itinerary.Stop;
import java.awt.CardLayout;
import javax.swing.*; import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
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.event.*;
import java.util.ArrayList;
public class View extends JFrame { public class View extends JFrame {
private JPanel CardPanel;
private JMenuItem Home;
private JMenuItem Network;
private JMenuItem Favorites;
private JPanel NetworkPanel;
private JTextField TextLocation; private final JPanel CardPanel;
private JButton ButtonLocation; private final JMenuItem Home;
private JPanel HomePanel; private final JMenuItem Network;
private JPanel MainPanel; private final JPanel NetworkPanel;
private DefaultTableModel modelStops; private final JTextField TextLocation;
private final JButton ButtonLocation;
private final JPanel HomePanel;
private final JPanel MainPanel;
private final DefaultTableModel modelStops;
private final JTable tableStops;
private final JTable tableItinerary;
private final DefaultTableModel modelItinerary;
private final JScrollPane paneStops;
private final JScrollPane paneItinerary;
private final JPanel ItineraryPanel;
private final JMenuItem Itinerary;
private final JPanel stationsPanel;
private final JLabel departText;
private final JLabel arrText;
private final JTextField TextCoord;
private final JButton ButtonCoord;
private final JPanel SearchCoordPanel;
private final JPanel SearchLocationPanel;
private final JLabel NetworkLabel;
private final JMenuBar ButtonBar;
private final ArrayList<Stop> StopList;
private JMenuItem Favorites;
private JLabel FavLabel;
private String departureCur;
private JTable tableStops; private String arrivalCur;
private JTable tableItinerary; private String searchLocation;
private DefaultTableModel modelItinerary; private String searchCoord;
private JScrollPane paneStops; private ArrayList<Stop> searchRes;
private JScrollPane paneItinerary; private int count = 0;
private JPanel ItineraryPanel;
private JMenuItem Itinerary;
private JPanel stationsPanel;
private JLabel departText;
private JLabel arrText;
private JTextField TextCoord;
private JButton ButtonCoord;
private JPanel SearchCoordPanel;
private JPanel SearchLocationPanel;
private JLabel NetworkLabel;
private JLabel FavLabel;
private JMenuBar ButtonBar;
private ArrayList<Stop> StopList;
private String departureCur;
private String arrivalCur;
private String searchLocation;
private String searchCoord;
private ArrayList<Stop> searchRes;
private int count = 0;
public View(ArrayList<Stop> s) throws HeadlessException { public View(ArrayList<Stop> s) throws HeadlessException {
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);
CardLayout CardLay = new CardLayout(); CardLayout CardLay = new CardLayout();
CardPanel = new JPanel(CardLay); CardPanel = new JPanel(CardLay);
HomePanel = new JPanel(); HomePanel = new JPanel();
CardPanel.add(HomePanel);
SearchCoordPanel = new JPanel();
SearchLocationPanel = new JPanel();
GridLayout SearchLayout = new GridLayout(1, 2);
HomePanel.setLayout(SearchLayout);
HomePanel.add(SearchCoordPanel);
HomePanel.add(SearchLocationPanel);
GridLayout SearchCoordLayout = new GridLayout(2, 1);
GridLayout SearchLocationLayout = new GridLayout(2, 1);
SearchCoordPanel.setLayout(SearchCoordLayout);
SearchLocationPanel.setLayout(SearchLocationLayout);
TextCoord = new JTextField();
ButtonCoord = new JButton("Look for coords");
SearchCoordPanel.add(TextCoord);
SearchCoordPanel.add(ButtonCoord);
TextLocation = new JTextField();
ButtonLocation = new JButton("Look for string");
SearchLocationPanel.add(TextLocation);
SearchLocationPanel.add(ButtonLocation);
NetworkPanel = new JPanel();
CardPanel.add(NetworkPanel);
GridLayout NetworkLayout = new GridLayout(3, 1);
NetworkPanel.setLayout(NetworkLayout);
NetworkLabel = new JLabel("Network");
NetworkPanel.add(NetworkLabel);
stationsPanel = new JPanel();
NetworkPanel.add(stationsPanel);
GridLayout StationsLayout = new GridLayout(2, 1);
departText = new JLabel("Départ: ");
arrText = new JLabel("Arivée: ");
stationsPanel.setLayout(StationsLayout);
stationsPanel.add(departText);
stationsPanel.add(arrText);
paneStops = new JScrollPane();
tableStops = new JTable();
paneStops.add(tableStops);
NetworkPanel.add(paneStops);
ItineraryPanel = new JPanel();
CardPanel.add(ItineraryPanel);
GridLayout ItineraryLayout = new GridLayout(2, 1);
ItineraryPanel.setLayout(ItineraryLayout);
paneItinerary = new JScrollPane();
tableItinerary = new JTable();
paneItinerary.add(tableItinerary);
ItineraryPanel.add(paneItinerary);
ButtonBar = new JMenuBar();
GridLayout ButtonLayout = new GridLayout(3, 1);
ButtonBar.setLayout(ButtonLayout);
Home = new JMenuItem("Home");
ButtonBar.add(Home);
Network = new JMenuItem("Network");
ButtonBar.add(Network);
Itinerary = new JMenuItem("Itinerary");
ButtonBar.add(Itinerary);
ButtonBar.setPreferredSize(new Dimension(50, 500));
MainPanel.add(ButtonBar);
MainPanel.add(CardPanel);
modelStops = (DefaultTableModel) tableStops.getModel();
modelStops.setColumnCount(2);
modelStops.setColumnIdentifiers(new Object[]{"Line", "Stop"});
modelItinerary = (DefaultTableModel) tableItinerary.getModel();
modelItinerary.setColumnCount(3);
modelItinerary.setColumnIdentifiers(new Object[]{"Line", "Stop", "Time"});
this.StopList = s;
setContentPane(MainPanel);
setTitle("app");
setExtendedState(JFrame.MAXIMIZED_BOTH);
//setUndecorated(true);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Home.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
CardPanel.removeAll();
CardPanel.add(HomePanel); CardPanel.add(HomePanel);
SearchCoordPanel = new JPanel(); CardPanel.repaint();
SearchLocationPanel = new JPanel(); CardPanel.revalidate();
GridLayout SearchLayout = new GridLayout(1, 2); }
HomePanel.setLayout(SearchLayout); });
HomePanel.add(SearchCoordPanel);
HomePanel.add(SearchLocationPanel);
GridLayout SearchCoordLayout = new GridLayout(2, 1);
GridLayout SearchLocationLayout = new GridLayout(2, 1);
SearchCoordPanel.setLayout(SearchCoordLayout);
SearchLocationPanel.setLayout(SearchLocationLayout);
TextCoord = new JTextField();
ButtonCoord = new JButton("Look for coords");
SearchCoordPanel.add(TextCoord);
SearchCoordPanel.add(ButtonCoord);
TextLocation = new JTextField();
ButtonLocation = new JButton("Look for string");
SearchLocationPanel.add(TextLocation);
SearchLocationPanel.add(ButtonLocation);
NetworkPanel = new JPanel(); Network.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
LoadSearchResult(s, modelStops);
CardPanel.removeAll();
CardPanel.add(NetworkPanel); CardPanel.add(NetworkPanel);
GridLayout NetworkLayout = new GridLayout(3, 1);
NetworkPanel.setLayout(NetworkLayout);
NetworkLabel = new JLabel("Network");
NetworkPanel.add(NetworkLabel);
stationsPanel = new JPanel();
NetworkPanel.add(stationsPanel);
GridLayout StationsLayout = new GridLayout(2, 1);
departText = new JLabel("Départ: ");
arrText = new JLabel("Arivée: ");
stationsPanel.setLayout(StationsLayout);
stationsPanel.add(departText);
stationsPanel.add(arrText);
paneStops = new JScrollPane();
tableStops = new JTable();
paneStops.add(tableStops);
NetworkPanel.add(paneStops);
CardPanel.repaint();
CardPanel.revalidate();
}
});
Itinerary.addActionListener(new ActionListener() {
ItineraryPanel = new JPanel(); @Override
public void actionPerformed(ActionEvent e) {
LoadSearchResult(s, modelItinerary);
CardPanel.removeAll();
CardPanel.add(ItineraryPanel); CardPanel.add(ItineraryPanel);
GridLayout ItineraryLayout = new GridLayout(2, 1);
ItineraryPanel.setLayout(ItineraryLayout);
paneItinerary = new JScrollPane();
tableItinerary = new JTable();
paneItinerary.add(tableItinerary);
ItineraryPanel.add(paneItinerary);
CardPanel.repaint();
CardPanel.revalidate();
}
});
ButtonBar = new JMenuBar(); TextLocation.addKeyListener(new KeyAdapter() {
GridLayout ButtonLayout = new GridLayout(3, 1); @Override
ButtonBar.setLayout(ButtonLayout); public void keyReleased(KeyEvent e) {
Home = new JMenuItem("Home"); super.keyReleased(e);
ButtonBar.add(Home); if (e.getKeyCode() == KeyEvent.VK_ENTER) {
Network = new JMenuItem("Network");
ButtonBar.add(Network);
Itinerary = new JMenuItem("Itinerary"); searchLocation = TextLocation.getText();
ButtonBar.add(Itinerary); LoadSearchResult(s, modelStops);
ButtonBar.setPreferredSize(new Dimension(50, 500)); System.out.println("Enter key released with text " + searchLocation);
CardPanel.removeAll();
CardPanel.add(NetworkPanel);
MainPanel.add(ButtonBar); CardPanel.repaint();
MainPanel.add(CardPanel); CardPanel.revalidate();
modelStops = (DefaultTableModel) tableStops.getModel();
modelStops.setColumnCount(2);
modelStops.setColumnIdentifiers(new Object[]{"Line", "Stop"});
modelItinerary = (DefaultTableModel) tableItinerary.getModel();
modelItinerary.setColumnCount(3);
modelItinerary.setColumnIdentifiers(new Object[]{"Line", "Stop", "Time"});
this.StopList = s;
setContentPane(MainPanel);
setTitle("app");
setExtendedState(JFrame.MAXIMIZED_BOTH);
//setUndecorated(true);
setVisible(true);
;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Home.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
CardPanel.removeAll();
CardPanel.add(HomePanel);
CardPanel.repaint();
CardPanel.revalidate();
}
});
Network.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
LoadSearchResult(s, modelStops);
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() {
@Override
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
searchLocation = TextLocation.getText();
LoadSearchResult(s, modelStops);
System.out.println("Enter key released with text " + searchLocation);
CardPanel.removeAll();
CardPanel.add(NetworkPanel);
CardPanel.repaint();
CardPanel.revalidate();
}
}
});
ButtonLocation.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
CardPanel.removeAll();
searchLocation = TextLocation.getText();
LoadSearchResult(s, modelStops);
System.out.println("search location clicked with text " + searchLocation);
CardPanel.add(NetworkPanel);
CardPanel.repaint();
CardPanel.revalidate();
}
});
ButtonCoord.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
CardPanel.removeAll();
searchCoord = TextCoord.getText();
LoadSearchResult(s, modelStops);
System.out.println("search coord clicked with text " + searchCoord);
CardPanel.add(NetworkPanel);
CardPanel.repaint();
CardPanel.revalidate();
}
});
tableStops.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
System.out.println("MouseClick: " + e.getX() + ";" + e.getY());
showOptionsDialog(tableStops, e.getX(), e.getY());
}
});
paneStops.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
}
});
}
private void showOptionsDialog(JTable table, int x, int y) {
int selectedRow = table.rowAtPoint(new Point(x, y));
if (selectedRow != -1) { // If a row is selected
String stationSel = (String) table.getValueAt(selectedRow, 1);
// Options to set Departure, Arrival, or Cancel
Object[] options = {"Departure", "Arrival", "Cancel"};
int choice = JOptionPane.showOptionDialog(null, "What action would you like to perform for " + stationSel + "?", "Action Selection",
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[2]);
// Handling the choice
if (choice == 0) {
this.departureCur = stationSel;
this.departText.setText("Departure: " + stationSel);
} else if (choice == 1) {
this.arrivalCur = stationSel;
this.arrText.setText("Arrival: " + stationSel);
} else {
System.out.println("rien");
}
System.out.println("Départ: " + this.departureCur + "; Arrivée: " + this.arrivalCur);
} }
}
});
ButtonLocation.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
CardPanel.removeAll();
searchLocation = TextLocation.getText();
LoadSearchResult(s, modelStops);
System.out.println("search location clicked with text " + searchLocation);
CardPanel.add(NetworkPanel);
CardPanel.repaint();
CardPanel.revalidate();
}
});
ButtonCoord.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
CardPanel.removeAll();
searchCoord = TextCoord.getText();
LoadSearchResult(s, modelStops);
System.out.println("search coord clicked with text " + searchCoord);
CardPanel.add(NetworkPanel);
CardPanel.repaint();
CardPanel.revalidate();
}
});
tableStops.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
System.out.println("MouseClick: " + e.getX() + ";" + e.getY());
showOptionsDialog(tableStops, e.getX(), e.getY());
}
});
paneStops.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
}
});
}
public static void main(String[] args) {
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));
View v = new View(s);
}
private void showOptionsDialog(JTable table, int x, int y) {
int selectedRow = table.rowAtPoint(new Point(x, y));
if (selectedRow != -1) { // If a row is selected
String stationSel = (String) table.getValueAt(selectedRow, 1);
// Options to set Departure, Arrival, or Cancel
Object[] options = {"Departure", "Arrival", "Cancel"};
int choice = JOptionPane.showOptionDialog(null,
"What action would you like to perform for " + stationSel + "?", "Action Selection",
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options,
options[2]);
// Handling the choice
if (choice == 0) {
this.departureCur = stationSel;
this.departText.setText("Departure: " + stationSel);
} else if (choice == 1) {
this.arrivalCur = stationSel;
this.arrText.setText("Arrival: " + stationSel);
} else {
System.out.println("rien");
}
System.out.println("Départ: " + this.departureCur + "; Arrivée: " + this.arrivalCur);
}
}
public void LoadSearchResult(ArrayList<Stop> stops, 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;
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
model.addRow(new Object[]{String.join(",", stop.getLines()), stop.getName()});
++count;
} }
System.out.println(stops);
for (int i = 0; i < model.getRowCount(); i++) {
public static void main(String[] args) { for (int j = 0; j < model.getColumnCount(); j++) {
ArrayList<Stop> s = new ArrayList<>(); System.out.print("valeur at coord " + i + ";" + j + ": " + model.getValueAt(i, j) + "\t");
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();
View v = new View(s);
} }
System.out.println(count);
tableStops.revalidate();
tableStops.repaint();
tableItinerary.revalidate();
tableItinerary.repaint();
public void LoadSearchResult(ArrayList<Stop> stops, DefaultTableModel model) { paneStops.setViewportView(tableStops);
// Clear existing rows from the table paneStops.revalidate();
int cols = model.getColumnCount(); paneStops.repaint();
model.setRowCount(0);
model.setColumnCount(cols);
paneItinerary.setViewportView(tableItinerary);
paneItinerary.revalidate();
paneItinerary.repaint();
// Add new rows based on the search results NetworkPanel.revalidate();
count = 0; NetworkPanel.repaint();
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
model.addRow(new Object[]{String.join(",", stop.getLines()), stop.getName()}); ItineraryPanel.revalidate();
++count; ItineraryPanel.repaint();
this.displayTableValues(model);
}
public void displayTableValues(TableModel mod) {
for (int row = 0; row < mod.getRowCount(); row++) {
for (int column = 0; column < mod.getColumnCount(); column++) {
if (mod.getValueAt(row, column) != null) {
System.out.print(mod.getValueAt(row, column).toString() + " ");
} }
}
System.out.println(stops.toString()); System.out.print(";");
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.repaint();
tableItinerary.revalidate();
tableItinerary.repaint();
paneStops.setViewportView(tableStops);
paneStops.revalidate();
paneStops.repaint();
paneItinerary.setViewportView(tableItinerary);
paneItinerary.revalidate();
paneItinerary.repaint();
NetworkPanel.revalidate();
NetworkPanel.repaint();
ItineraryPanel.revalidate();
ItineraryPanel.repaint();
this.displayTableValues(model);
} }
System.out.println();
public void displayTableValues(TableModel mod) { }
for (int row = 0; row < mod.getRowCount(); row++) {
for (int column = 0; column < mod.getColumnCount(); column++) {
if (mod.getValueAt(row, column) != null) System.out.print(mod.getValueAt(row, column).toString() + " ");
}
System.out.print(";");
}
System.out.println();
}
} }

View file

@ -1,18 +1,18 @@
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
/** /**
* A representation of a stop with the bifurcation that is needed. All stops * A representation of a stop with the bifurcation that is needed. All stops have a list of bifstop
* have a list of bifstop called connected. BifStop is just composed of a * called connected. BifStop is just composed of a connected stop and the bifurcation used to go
* connected stop and the bifurcation used to go from the first stop to the * from the first stop to the connected one.
* connected one.
*/ */
public class BifStop { public class BifStop {
// The bifurcation
public int bifurc;
public Stop stop;
public BifStop(int bif, Stop stop){ // The bifurcation
bifurc = bif; public int bifurc;
this.stop = stop; public Stop stop;
}
public BifStop(int bif, Stop stop) {
bifurc = bif;
this.stop = stop;
}
} }

View file

@ -3,53 +3,50 @@
*/ */
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import fr.u_paris.gla.project.io.ScheduleFormat;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
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 java.text.NumberFormat;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Locale;
public final class CSVImageProvider { public final class CSVImageProvider {
private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat
.getInstance(Locale.ENGLISH); private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat
static { .getInstance(Locale.ENGLISH);
MINUTES_SECOND_FORMATTER.setMinimumIntegerDigits(2);
static {
MINUTES_SECOND_FORMATTER.setMinimumIntegerDigits(2);
}
private final String[] line = new String[ImageFormat.NUMBER_COLUMNS];
private final Iterator<Transport> current;
/**
* Create the stream provider
*/
public CSVImageProvider(Iterator<Transport> traces) {
this.current = traces;
}
/**
* Check if next exists
*/
public boolean hasNext() {
return this.current.hasNext();
}
/**
* Get Next element
*/
public String[] next() {
if (!this.hasNext()) {
return null;
} }
private final String[] line = new String[ImageFormat.NUMBER_COLUMNS]; Transport element = this.current.next();
private final Iterator<Transport> current; this.line[ImageFormat.LINE_INDEX] = element.name;
this.line[ImageFormat.IMAGE_URL_INDEX] = element.image_url;
/** Create the stream provider */ return Arrays.copyOf(this.line, this.line.length);
public CSVImageProvider(Iterator<Transport> traces) { }
this.current = traces;
}
/** Check if next exists */
public boolean hasNext() {
return this.current.hasNext();
}
/** Get Next element */
public String[] next() {
if (!this.hasNext()) {
return null;
}
Transport element = this.current.next();
this.line[ImageFormat.LINE_INDEX] = element.name;
this.line[ImageFormat.IMAGE_URL_INDEX] = element.image_url;
return Arrays.copyOf(this.line, this.line.length);
}
} }

View file

@ -1,160 +1,155 @@
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import fr.u_paris.gla.project.io.ScheduleFormat; import fr.u_paris.gla.project.io.ScheduleFormat;
import java.text.NumberFormat;
import java.time.LocalDateTime;
import java.time.LocalTime; import java.time.LocalTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.Duration; import java.util.Arrays;
import java.time.LocalDateTime; import java.util.Collections;
// import java.time.format.ResolverStyle; import java.util.HashMap;
import java.text.NumberFormat; import java.util.Iterator;
import java.util.*; import java.util.Locale;
import java.util.Random;
public class CSVSchedulesProvider { public class CSVSchedulesProvider {
private static final DateTimeFormatter HOUR_MINUTE_FORMATTER = ScheduleFormat.getTimeFormatter();
private static final HashMap<String, int[]> timings = new HashMap<String, int[]>(){{ private static final DateTimeFormatter HOUR_MINUTE_FORMATTER = ScheduleFormat.getTimeFormatter();
put("Bus", new int[]{11, 8, 7});
put("Funicular", new int[]{15, 25, 20});
put("Tram", new int[]{6, 7, 8, 9});
put("Rail", new int[]{10, 11,15,12,20});
put("Subway", new int[]{4, 2, 6,3,3,4});
}};
private static final HashMap<String, int[]> timings = new HashMap<String, int[]>() {{
put("Bus", new int[]{11, 8, 7});
put("Funicular", new int[]{15, 25, 20});
put("Tram", new int[]{6, 7, 8, 9});
put("Rail", new int[]{10, 11, 15, 12, 20});
put("Subway", new int[]{4, 2, 6, 3, 3, 4});
}};
private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat
.getInstance(Locale.ENGLISH);
// Time between 2 passages for the transports with a new type we don't know yet
private static final int DEFAULT_TIMING = 6;
// Time between 2 passages for the transports with a new type we don't know yet static {
private static int DEFAULT_TIMING = 6; MINUTES_SECOND_FORMATTER.setMinimumIntegerDigits(2);
private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat }
.getInstance(Locale.ENGLISH);
static { private final String[] line = new String[ScheduleFormat.NUMBER_COLUMNS];
MINUTES_SECOND_FORMATTER.setMinimumIntegerDigits(2); private final Iterator<Transport> currentTransport;
private Iterator<TraceDescription> currentDescription = Collections.emptyIterator();
private String current_tansport_type = "";
private LocalDateTime currentHour = null;
private LocalDateTime lastHour = null;
/**
* Create the stream provider
*/
public CSVSchedulesProvider(Iterator<Transport> transports) {
this.currentTransport = transports;
}
/**
* @param transportType the type of a transport
* @return a random minute depending on the type of the transport
*/
public static int pickMinute(String transportType) {
if (!timings.containsKey(transportType)) {
return DEFAULT_TIMING;
}
int[] temps = timings.get(transportType);
Random random = new Random();
int indexAleatoire = random.nextInt(temps.length);
return temps[indexAleatoire];
}
/**
* @param hourMinute hour and minute representation. Ex: "14:03"
* @return a datetime of today but using hourMinute
*/
public static LocalDateTime convertIntoLocalDateTime(String hourMinute) {
LocalDateTime aujourdHui = LocalDateTime.now();
LocalTime time = LocalTime.parse(hourMinute, HOUR_MINUTE_FORMATTER);
return aujourdHui.withHour(time.getHour()).withMinute(time.getMinute()).withSecond(0)
.withNano(0);
}
public boolean hasNext() {
return currentTransport.hasNext() || currentDescription.hasNext();
}
private void skipToNext() {
if (currentHour == null || lastHour == null) {
skipToNextTransport();
} else if (currentHour.isBefore(lastHour)) {
// System.out.println("**Skip: Le current hour est plus petit "+currentHour+"|||"+lastHour);
addRandomMinutes();
} else if (!currentHour.isBefore(lastHour)) {
// System.out.println("**Skip: Le current hour est plus grand "+currentHour+"|||"+lastHour);
skipToNextDescription();
} else if (!this.currentDescription.hasNext()) {
skipToNextTransport();
} }
private final String[] line = new String[ScheduleFormat.NUMBER_COLUMNS]; }
private final Iterator<Transport> currentTransport;
private Iterator<TraceDescription> currentDescription = Collections.emptyIterator();
private String current_tansport_type = ""; /**
private LocalDateTime currentHour = null; * Move to the the nextDescription of a Transport line
private LocalDateTime lastHour = null; */
private void skipToNextDescription() {
if (this.currentDescription.hasNext()) {
TraceDescription description = this.currentDescription.next();
currentHour = convertIntoLocalDateTime(description.first);
lastHour = convertIntoLocalDateTime(description.last);
if (!lastHour.isAfter(currentHour)) {
lastHour = lastHour.plusDays(1);
}
this.line[ScheduleFormat.TERMINUS_INDEX] = description.from;
this.line[ScheduleFormat.TRIP_SEQUENCE_INDEX] = description.bifurcation.toString();
this.line[ScheduleFormat.TIME_INDEX] = currentHour.format(HOUR_MINUTE_FORMATTER);
} else {
/** skipToNextTransport();
* Create the stream provider
*/
public CSVSchedulesProvider(Iterator<Transport> transports) {
this.currentTransport = transports;
} }
}
public boolean hasNext() { /**
return currentTransport.hasNext() || currentDescription.hasNext(); * Move to the next Transport line
*/
private void skipToNextTransport() {
if (this.currentTransport.hasNext()) {
Transport transport = this.currentTransport.next();
this.line[ScheduleFormat.LINE_INDEX] = transport.name;
current_tansport_type = transport.type;
this.currentDescription = transport.descriptions.iterator();
skipToNextDescription();
} }
}
private void skipToNext() { public String[] next() {
if(currentHour == null || lastHour == null){ if (!hasNext()) {
skipToNextTransport(); return null;
}else if(currentHour.compareTo(lastHour) < 0){
// System.out.println("**Skip: Le current hour est plus petit "+currentHour+"|||"+lastHour);
addRandomMinutes();
}else if (currentHour.compareTo(lastHour) >= 0) {
// System.out.println("**Skip: Le current hour est plus grand "+currentHour+"|||"+lastHour);
skipToNextDescription();
}
else if (!this.currentDescription.hasNext()) {
skipToNextTransport();
}
} }
skipToNext();
return Arrays.copyOf(this.line, this.line.length);
/** // return new String[][]{Arrays.copyOf(this.line, this.line.length)};
* Move to the the nextDescription of a Transport line
*/
private void skipToNextDescription() {
if (this.currentDescription.hasNext()) {
TraceDescription description = this.currentDescription.next();
currentHour = convertIntoLocalDateTime(description.first); }
lastHour = convertIntoLocalDateTime(description.last);
if(lastHour.compareTo(currentHour) <= 0){ /**
lastHour = lastHour.plusDays(1); * Add random minutes for the next passage of a transport. The random minutes depends on the type
} * of the transport
this.line[ScheduleFormat.TERMINUS_INDEX] = description.from; */
this.line[ScheduleFormat.TRIP_SEQUENCE_INDEX] = description.bifurcation.toString(); private void addRandomMinutes() {
this.line[ScheduleFormat.TIME_INDEX] = currentHour.format(HOUR_MINUTE_FORMATTER); // System.out.println("** addM: AVANT: "+currentHour);
currentHour = currentHour.plusMinutes(pickMinute(current_tansport_type));
}else{ this.line[ScheduleFormat.TIME_INDEX] = currentHour.format(HOUR_MINUTE_FORMATTER);
skipToNextTransport(); // System.out.println("** addM: APRES: "+currentHour);
} // debut ++;
} // if(debut == 7) throw new IllegalArgumentException();
}
/**
* Move to the next Transport line
*/
private void skipToNextTransport() {
if (this.currentTransport.hasNext()) {
Transport transport = this.currentTransport.next();
this.line[ScheduleFormat.LINE_INDEX] = transport.name;
current_tansport_type = transport.type;
this.currentDescription = transport.descriptions.iterator();
skipToNextDescription();
}
}
public String[] next() {
if (!hasNext()) {
return null;
}
skipToNext();
return Arrays.copyOf(this.line, this.line.length);
// return new String[][]{Arrays.copyOf(this.line, this.line.length)};
}
/**
* Add random minutes for the next passage of a transport.
* The random minutes depends on the type of the transport
*/
private void addRandomMinutes() {
// System.out.println("** addM: AVANT: "+currentHour);
currentHour = currentHour.plusMinutes(pickMinute(current_tansport_type));
this.line[ScheduleFormat.TIME_INDEX] = currentHour.format(HOUR_MINUTE_FORMATTER);
// System.out.println("** addM: APRES: "+currentHour);
// debut ++;
// if(debut == 7) throw new IllegalArgumentException();
}
/**
*
* @param transportType the type of a transport
* @return a random minute depending on the type of the transport
*/
public static int pickMinute(String transportType) {
if (!timings.containsKey(transportType)) {
return DEFAULT_TIMING;
}
int[] temps = timings.get(transportType);
Random random = new Random();
int indexAleatoire = random.nextInt(temps.length);
return temps[indexAleatoire];
}
/**
*
* @param hourMinute hour and minute representation. Ex: "14:03"
* @return a datetime of today but using hourMinute
*/
public static LocalDateTime convertIntoLocalDateTime(String hourMinute) {
LocalDateTime aujourdHui = LocalDateTime.now();
LocalTime time = LocalTime.parse(hourMinute, HOUR_MINUTE_FORMATTER);
return aujourdHui.withHour(time.getHour()).withMinute(time.getMinute()).withSecond(0).withNano(0);
}
} }

View file

@ -3,6 +3,8 @@
*/ */
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import fr.u_paris.gla.project.io.NetworkFormat;
import fr.u_paris.gla.project.utils.GPS;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
@ -16,285 +18,304 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import fr.u_paris.gla.project.io.NetworkFormat;
import fr.u_paris.gla.project.utils.GPS;
/** /**
* CSV Stream Provider class * CSV Stream Provider class
*/ */
public final class CSVStreamProvider { public final class CSVStreamProvider {
private static final HashMap<String, Double> two_acceleration_distance_by_type = new HashMap<String, Double>(){{ private static final HashMap<String, Double> two_acceleration_distance_by_type = new HashMap<String, Double>() {{
put("Bus", 0.1); put("Bus", 0.1);
put("Funicular", 0.1); put("Funicular", 0.1);
put("Tram", 0.1); put("Tram", 0.1);
put("Rail", 0.2); put("Rail", 0.2);
put("Subway", 0.1); put("Subway", 0.1);
}}; }};
private static final HashMap<String, Double> max_speed_by_type = new HashMap<String, Double>(){{ private static final HashMap<String, Double> max_speed_by_type = new HashMap<String, Double>() {{
put("Bus", 10.0); put("Bus", 10.0);
put("Funicular", 5.0); put("Funicular", 5.0);
put("Tram", 20.0); put("Tram", 20.0);
put("Rail", 50.0); put("Rail", 50.0);
put("Subway", 30.0); put("Subway", 30.0);
}}; }};
/** /**
* Formatter from numbers into GPS Coordinates * Formatter from numbers into GPS Coordinates
*/ */
private static final NumberFormat GPS_FORMATTER = NetworkFormat private static final NumberFormat GPS_FORMATTER = NetworkFormat
.getGPSFormatter(); .getGPSFormatter();
/** /**
* Formatter from numbers into MM:SS * Formatter from numbers into MM:SS
*/ */
private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat
.getInstance(Locale.ENGLISH); .getInstance(Locale.ENGLISH);
static { /**
MINUTES_SECOND_FORMATTER.setMinimumIntegerDigits(2); * Number of seconds in a minute.
*/
private static final int SECONDS_IN_MINUTES = 60;
/**
* Number of seconds in an hour
*/
private static final long SECONDS_IN_HOURS = 3_600;
/**
* Maximal speed in km/h
*/
private static final double MAX_SPEED = 5;
// Magically chosen values
/**
* Distance to reach maximal speed in km
*/
private static final double TWO_ACCELERATION_DISTANCE = 0.2;
static {
MINUTES_SECOND_FORMATTER.setMinimumIntegerDigits(2);
}
/**
* Current CSV Line
*/
private final String[] line = new String[NetworkFormat.NUMBER_COLUMNS];
/**
* Current CSV transport line iterator
*/
private final Iterator<TraceEntry> currentTrace;
// The transport id with its value
private final Map<String, Transport> transports;
/**
* HashMap of the current line's segments
*/
Map<StopEntry, Set<StopEntry>> lineSegments = new HashMap<>();
List<TraceDescription> descriptions = new ArrayList<>();
/**
* Current Stop path iterator
*/
private Iterator<List<StopEntry>> currentPath = Collections.emptyIterator();
/**
* current iterator for the begin of the line
*/
private Iterator<StopEntry> currentSegmentStart = Collections.emptyIterator();
/**
* current iterator for the end of the line
*/
private Iterator<StopEntry> currentSegmentEnd = Collections.emptyIterator();
/**
* current begin of line
*/
private StopEntry start = null;
/**
* current end of line
*/
private StopEntry end = null;
/**
* csv stream iterator checker
*/
private boolean hasNext = false;
/**
* tells if we're already on the next
*/
private boolean onNext = false;
private String traceId = "";
private String traceType = "";
private String url_image = "";
/**
* Create the stream provider
*
* @param traces an iterator of the possible traces
* @param t map of transports
*/
public CSVStreamProvider(Iterator<TraceEntry> traces, Map<String, Transport> t) {
this.currentTrace = traces;
transports = t;
}
/**
* creates adds a station into the next line String
*
* @param stop the stop
* @param nextLine the next line
* @param index the stop index in the next line
*/
private static void fillStation(StopEntry stop, String[] nextLine, int index) {
nextLine[index] = stop.lname;
nextLine[index + 1] = MessageFormat.format("{0}, {1}", //$NON-NLS-1$
GPS_FORMATTER.format(stop.latitude),
GPS_FORMATTER.format(stop.longitude));
}
/**
* turns a number into a formatted time string
*
* @param time the time value
* @return the time as a String
*/
private static String formatTime(long time) {
return MessageFormat.format("{0}:{1}", //$NON-NLS-1$
MINUTES_SECOND_FORMATTER.format(time / SECONDS_IN_MINUTES),
MINUTES_SECOND_FORMATTER.format(time % SECONDS_IN_MINUTES));
}
/**
* A tool method to give a delay to go through a certain distance.
* <p>
* This is a model with an linear acceleration and deceleration periods and a constant speed in
* between.
*
* @param distance the distance (in km)
* @return the duration of the trip (in hours)
*/
private static double distanceToTime(double distance, String type) {
Double max_speed = max_speed_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
+ Math.pow(Math.min(distance, two_acc_distance) / max_speed, 2);
}
/**
* Method that tells if we have segments or paths to go through
*
* @return if there are next elements or not
*/
public boolean hasNext() {
if (!this.onNext) {
skipToNext();
} }
/** Number of seconds in a minute. */ return this.hasNext;
private static final int SECONDS_IN_MINUTES = 60; }
/**
* Number of seconds in an hour
*/
private static final long SECONDS_IN_HOURS = 3_600;
// Magically chosen values
/** Maximal speed in km/h */
private static final double MAX_SPEED = 5;
/** Distance to reach maximal speed in km */
private static final double TWO_ACCELERATION_DISTANCE = 0.2;
/** /**
* Current CSV Line * Skip to either the next segment or the next path
*/ */
private final String[] line = new String[NetworkFormat.NUMBER_COLUMNS]; private void skipToNext() {
if (this.onNext) {
/** return;
* Current CSV transport line iterator
*/
private final Iterator<TraceEntry> currentTrace;
/**
* Current Stop path iterator
*/
private Iterator<List<StopEntry>> currentPath = Collections.emptyIterator();
/**
* current iterator for the begin of the line
*/
private Iterator<StopEntry> currentSegmentStart = Collections.emptyIterator();
/**
* current iterator for the end of the line
*/
private Iterator<StopEntry> currentSegmentEnd = Collections.emptyIterator();
/**
* HashMap of the current line's segments
*/
Map<StopEntry, Set<StopEntry>> lineSegments = new HashMap<>();
// The transport id with its value
private final Map<String, Transport> transports;
List <TraceDescription> descriptions = new ArrayList<>();
/**
* current begin of line
*/
private StopEntry start = null;
/**
* current end of line
*/
private StopEntry end = null;
/**
* csv stream iterator checker
*/
private boolean hasNext = false;
/**
* tells if we're already on the next
*/
private boolean onNext = false;
private String traceId = "";
private String traceType = "";
private String url_image = "";
/** Create the stream provider
* @param traces an iterator of the possible traces
* @param t map of transports */
public CSVStreamProvider(Iterator<TraceEntry> traces, Map<String, Transport> t) {
this.currentTrace = traces;
transports = t;
} }
while (!this.onNext) {
if (!this.currentSegmentEnd.hasNext()) {
skipToNextCandidatePath();
}
if (this.onNext) {
return;
}
skipToNextNewSegment();
}
}
/** Method that tells if we have segments or paths to go through /**
* @return if there are next elements or not * Skips to the next segment
*/ */
public boolean hasNext() { private void skipToNextNewSegment() {
if (!this.onNext) { do {
skipToNext(); this.start = this.currentSegmentStart.next();
this.lineSegments.putIfAbsent(this.start, new HashSet<>());
this.end = this.currentSegmentEnd.next();
} while (this.lineSegments.get(this.start).contains(this.end)
&& this.currentSegmentEnd.hasNext());
if (!this.lineSegments.get(this.start).contains(this.end)) {
this.lineSegments.get(this.start).add(this.end);
this.onNext = true;
this.hasNext = true;
}
}
/**
* Move the reading head of path to the next one that has at least two elements
*/
private void skipToNextCandidatePath() {
currentSegmentStart = null;
do {
while (!this.currentPath.hasNext()) {
if (!this.currentTrace.hasNext()) {
this.hasNext = false;
this.onNext = true;
return;
} }
return this.hasNext; TraceEntry trace = this.currentTrace.next();
this.traceId = trace.id;
this.traceType = trace.type;
this.url_image = trace.url;
this.descriptions.clear();
this.descriptions.addAll(trace.descriptions);
this.currentPath = trace.getPaths().iterator();
this.line[NetworkFormat.LINE_INDEX] = trace.lname;
this.lineSegments.clear();
}
List<StopEntry> path = this.currentPath.next();
this.currentSegmentEnd = path.iterator();
if (this.currentSegmentEnd.hasNext()) {
this.currentSegmentEnd.next();
this.currentSegmentStart = path.iterator();
}
} while (currentSegmentStart == null);
}
// /** A tool method to give a delay to go through a certain distance.
// * <p>
// * This is a model with an linear acceleration and deceleration periods and a
// * constant speed in between.
// *
// * @param distance the distance (in km)
// * @return the duration of the trip (in hours) */
// private static double distanceToTime(double distance) {
// return Math.max(0, distance - TWO_ACCELERATION_DISTANCE) / MAX_SPEED
// + Math.pow(Math.min(distance, TWO_ACCELERATION_DISTANCE) / MAX_SPEED, 2);
// }
/**
* Store current trace' data as a String array
*
* @return The newly generated line of text
*/
public String[] next() {
if (!this.onNext) {
skipToNext();
}
this.onNext = false;
fillStation(this.start, this.line, NetworkFormat.START_INDEX);
fillStation(this.end, this.line, NetworkFormat.STOP_INDEX);
double distance = GPS.distance(this.start.latitude, this.start.longitude,
this.end.latitude, this.end.longitude);
this.line[NetworkFormat.DISTANCE_INDEX] = NumberFormat.getInstance(Locale.ENGLISH)
.format(distance);
this.line[NetworkFormat.DURATION_INDEX] = formatTime(
(long) Math.ceil(distanceToTime(distance, this.traceType) * SECONDS_IN_HOURS));
int bifurcation = this.lineSegments.get(this.start).size() - 1;
this.line[NetworkFormat.VARIANT_INDEX] = Integer
.toString(bifurcation);
fillTransports(bifurcation);
return Arrays.copyOf(this.line, this.line.length);
// return new String[][]{Arrays.copyOf(this.line, this.line.length)};
}
private void fillTransports(int bif) {
if (transports != null) {
String nameTransport = this.line[NetworkFormat.LINE_INDEX];
String start_p = this.line[NetworkFormat.START_INDEX];
String end_p = this.line[NetworkFormat.STOP_INDEX];
// String bifurcation = this.line[NetworkFormat.VARIANT_INDEX];
Transport transp = null;
if (!transports.containsKey(traceId)) {
transp = new Transport(nameTransport, traceType, url_image);
transports.put(traceId, transp);
} else {
transp = transports.get(traceId);
}
transp.addStop(start_p, end_p, bif);
if (transp.descriptions.isEmpty()) {
transp.addDescriptions(descriptions);
}
} }
/** }
* Skip to either the next segment or the next path
*/
private void skipToNext() {
if (this.onNext) {
return;
}
while (!this.onNext) {
if (!this.currentSegmentEnd.hasNext()) {
skipToNextCandidatePath();
}
if (this.onNext) {
return;
}
skipToNextNewSegment();
}
}
/**
* Skips to the next segment
*/
private void skipToNextNewSegment() {
do {
this.start = this.currentSegmentStart.next();
this.lineSegments.putIfAbsent(this.start, new HashSet<>());
this.end = this.currentSegmentEnd.next();
} while (this.lineSegments.get(this.start).contains(this.end)
&& this.currentSegmentEnd.hasNext());
if (!this.lineSegments.get(this.start).contains(this.end)) {
this.lineSegments.get(this.start).add(this.end);
this.onNext = true;
this.hasNext = true;
}
}
/** Move the reading head of path to the next one that has at least two
* elements */
private void skipToNextCandidatePath() {
currentSegmentStart = null;
do {
while (!this.currentPath.hasNext()) {
if (!this.currentTrace.hasNext()) {
this.hasNext = false;
this.onNext = true;
return;
}
TraceEntry trace = this.currentTrace.next();
this.traceId = trace.id;
this.traceType = trace.type;
this.url_image = trace.url;
this.descriptions.clear();
this.descriptions.addAll(trace.descriptions);
this.currentPath = trace.getPaths().iterator();
this.line[NetworkFormat.LINE_INDEX] = trace.lname;
this.lineSegments.clear();
}
List<StopEntry> path = this.currentPath.next();
this.currentSegmentEnd = path.iterator();
if (this.currentSegmentEnd.hasNext()) {
this.currentSegmentEnd.next();
this.currentSegmentStart = path.iterator();
}
} while (currentSegmentStart == null);
}
/** Store current trace' data as a String array
* @return The newly generated line of text
*/
public String[] next() {
if (!this.onNext) {
skipToNext();
}
this.onNext = false;
fillStation(this.start, this.line, NetworkFormat.START_INDEX);
fillStation(this.end, this.line, NetworkFormat.STOP_INDEX);
double distance = GPS.distance(this.start.latitude, this.start.longitude,
this.end.latitude, this.end.longitude);
this.line[NetworkFormat.DISTANCE_INDEX] = NumberFormat.getInstance(Locale.ENGLISH)
.format(distance);
this.line[NetworkFormat.DURATION_INDEX] = formatTime(
(long) Math.ceil(distanceToTime(distance,this.traceType) * SECONDS_IN_HOURS));
int bifurcation = this.lineSegments.get(this.start).size() - 1;
this.line[NetworkFormat.VARIANT_INDEX] = Integer
.toString(bifurcation);
fillTransports(bifurcation);
return Arrays.copyOf(this.line, this.line.length);
// return new String[][]{Arrays.copyOf(this.line, this.line.length)};
}
/** creates adds a station into the next line String
* @param stop the stop
* @param nextLine the next line
* @param index the stop index in the next line */
private static void fillStation(StopEntry stop, String[] nextLine, int index) {
nextLine[index] = stop.lname;
nextLine[index + 1] = MessageFormat.format("{0}, {1}", //$NON-NLS-1$
GPS_FORMATTER.format(stop.latitude),
GPS_FORMATTER.format(stop.longitude));
}
/** turns a number into a formatted time string
* @param time the time value
* @return the time as a String */
private static String formatTime(long time) {
return MessageFormat.format("{0}:{1}", //$NON-NLS-1$
MINUTES_SECOND_FORMATTER.format(time / SECONDS_IN_MINUTES), MINUTES_SECOND_FORMATTER.format(time % SECONDS_IN_MINUTES));
}
// /** A tool method to give a delay to go through a certain distance.
// * <p>
// * This is a model with an linear acceleration and deceleration periods and a
// * constant speed in between.
// *
// * @param distance the distance (in km)
// * @return the duration of the trip (in hours) */
// private static double distanceToTime(double distance) {
// return Math.max(0, distance - TWO_ACCELERATION_DISTANCE) / MAX_SPEED
// + Math.pow(Math.min(distance, TWO_ACCELERATION_DISTANCE) / MAX_SPEED, 2);
// }
/** A tool method to give a delay to go through a certain distance.
* <p>
* This is a model with an linear acceleration and deceleration periods and a
* constant speed in between.
*
* @param distance the distance (in km)
* @return the duration of the trip (in hours) */
private static double distanceToTime(double distance, String type) {
Double max_speed = max_speed_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
+ Math.pow(Math.min(distance, two_acc_distance) / max_speed, 2);
}
private void fillTransports(int bif) {
if(transports != null){
String nameTransport = this.line[NetworkFormat.LINE_INDEX];
String start_p = this.line[NetworkFormat.START_INDEX];
String end_p = this.line[NetworkFormat.STOP_INDEX];
// String bifurcation = this.line[NetworkFormat.VARIANT_INDEX];
Transport transp = null;
if(!transports.containsKey(traceId)){
transp = new Transport(nameTransport,traceType, url_image);
transports.put(traceId, transp);
}else{
transp = transports.get(traceId);
}
transp.addStop(start_p, end_p, bif);
if(transp.descriptions.isEmpty()){
transp.addDescriptions(descriptions);
}
}
}
} }

View file

@ -5,18 +5,22 @@ package fr.u_paris.gla.project.idfm;
import fr.u_paris.gla.project.utils.CSVTools; import fr.u_paris.gla.project.utils.CSVTools;
import fr.u_paris.gla.project.utils.GPS; import fr.u_paris.gla.project.utils.GPS;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level; 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;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/** /**
* Code of an extractor for the data from IDF mobilite. * Code of an extractor for the data from IDF mobilite.
@ -25,345 +29,364 @@ import java.util.stream.Stream;
*/ */
public class IDFMNetworkExtractor { public class IDFMNetworkExtractor {
/** /**
* The logger for information on the process * The logger for information on the process
*/ */
private static final Logger LOGGER = Logger private static final Logger LOGGER = Logger
.getLogger(IDFMNetworkExtractor.class.getName()); .getLogger(IDFMNetworkExtractor.class.getName());
/** /**
* the URL of the Trace CSV * the URL of the Trace CSV
*/ */
// IDF mobilite API URLs // IDF mobilite API URLs
private static final String TRACE_FILE_URL = "https://data.iledefrance-mobilites.fr/api/explore/v2.1/catalog/datasets/traces-des-lignes-de-transport-en-commun-idfm/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B"; private static final String TRACE_FILE_URL = "https://data.iledefrance-mobilites.fr/api/explore/v2.1/catalog/datasets/traces-des-lignes-de-transport-en-commun-idfm/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B";
/** /**
* The URL of the Stops CSV * The URL of the Stops CSV
*/ */
private static final String STOPS_FILE_URL = "https://data.iledefrance-mobilites.fr/api/explore/v2.1/catalog/datasets/arrets-lignes/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B"; private static final String STOPS_FILE_URL = "https://data.iledefrance-mobilites.fr/api/explore/v2.1/catalog/datasets/arrets-lignes/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B";
private static final String TRACE_FILE_DOWNLOADED_NAME = "./trace_idfm.csv"; private static final String TRACE_FILE_DOWNLOADED_NAME = "./trace_idfm.csv";
private static final String STOPS_FILE_DOWNLOADED_NAME = "./arret_idfm.csv"; private static final String STOPS_FILE_DOWNLOADED_NAME = "./arret_idfm.csv";
/** /**
* the index in the CSV of a Trace's ID * the index in the CSV of a Trace's ID
*/ */
// IDF mobilite csv formats // IDF mobilite csv formats
private static final int IDFM_TRACE_ID_INDEX = 0; private static final int IDFM_TRACE_ID_INDEX = 0;
/** /**
* the index in the CSV of a Trace's Name * the index in the CSV of a Trace's Name
*/ */
private static final int IDFM_TRACE_SNAME_INDEX = 1; private static final int IDFM_TRACE_SNAME_INDEX = 1;
/** /**
* the index in the CSV of a Trace's shape * the index in the CSV of a Trace's shape
*/ */
private static final int IDFM_TRACE_SHAPE_INDEX = 6; private static final int IDFM_TRACE_SHAPE_INDEX = 6;
private static final int IDFM_TRACE_TYPE_INDEX = 3; private static final int IDFM_TRACE_TYPE_INDEX = 3;
/** /**
* The index in the CSV of the Stops' id * The index in the CSV of the Stops' id
*/ */
private static final int IDFM_STOPS_RID_INDEX = 0; private static final int IDFM_STOPS_RID_INDEX = 0;
/** /**
* The index in the CSV of the Stops' schedules * The index in the CSV of the Stops' schedules
*/ */
private static final int IDFM_STOPS_SCHEDULES_INDEX = 3; private static final int IDFM_STOPS_SCHEDULES_INDEX = 3;
/** /**
* The index in the CSV of the Stops' names * The index in the CSV of the Stops' names
*/ */
private static final int IDFM_STOPS_NAME_INDEX = 5; private static final int IDFM_STOPS_NAME_INDEX = 5;
/** /**
* The index in the CSV of the Stops' longitude * The index in the CSV of the Stops' longitude
*/ */
private static final int IDFM_STOPS_LON_INDEX = 6; private static final int IDFM_STOPS_LON_INDEX = 6;
/** /**
* The index in the CSV of the Stops' latitude * The index in the CSV of the Stops' latitude
*/ */
private static final int IDFM_STOPS_LAT_INDEX = 7; private static final int IDFM_STOPS_LAT_INDEX = 7;
private static final int IDFM_URL_INDEX = 10; private static final int IDFM_URL_INDEX = 10;
private static final String TRACE_FILE_NAME = "trace.csv"; private static final String TRACE_FILE_NAME = "trace.csv";
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"; private static final String IMAGES_FILE_NAME = "./images.csv";
// Magically chosen values // Magically chosen values
/** /**
* A number of stops on each line * A number of stops on each line
*/ */
private static final int GUESS_STOPS_BY_LINE = 5; private static final int GUESS_STOPS_BY_LINE = 5;
/** /**
* The quarter of a kilometer as a static value * The quarter of a kilometer as a static value
*/ */
// Well named constants // Well named constants
private static final double QUARTER_KILOMETER = .25; private static final double QUARTER_KILOMETER = .25;
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.severe(filePath + " already exists.");
return true; return true;
} else { } else {
LOGGER.severe(filePath + " does not exist."); LOGGER.severe(filePath + " does not exist.");
return false; return false;
} }
}
public static void buildFiles() {
if (checkFileExistence("./" + HOURS_FILE_NAME) && checkFileExistence("./" + TRACE_FILE_NAME)) {
LOGGER.severe("Files already exists.");
return;
} }
public static void buildFiles() { Map<String, TraceEntry> traces = new HashMap<>();
try {
if (checkFileExistence("./"+HOURS_FILE_NAME) && checkFileExistence("./"+TRACE_FILE_NAME)) { CSVTools.readCSVFromFile(TRACE_FILE_DOWNLOADED_NAME,
LOGGER.severe("Files already exists."); (String[] line) -> addLine(line, traces));
return; } catch (IOException e) {
} LOGGER.log(Level.SEVERE, "Error while reading the line paths", e);
Map<String, TraceEntry> traces = new HashMap<>();
try {
CSVTools.readCSVFromFile(TRACE_FILE_DOWNLOADED_NAME,
(String[] line) -> addLine(line, traces));
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Error while reading the line paths", e);
}
List<StopEntry> stops = new ArrayList<>(traces.size() * GUESS_STOPS_BY_LINE);
try {
CSVTools.readCSVFromFile(STOPS_FILE_DOWNLOADED_NAME,
(String[] line) -> addStop(line, traces, stops));
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Error while reading the stops", e);
}
cleanTraces(traces);
Map<String, Transport> transports = new HashMap<>();
CSVStreamProvider provider = new CSVStreamProvider(traces.values().iterator(), transports);
// Write into args[0]
try {
CSVTools.writeCSVToFile(TRACE_FILE_NAME, Stream.iterate(provider.next(),
t -> provider.hasNext(), t -> provider.next()));
} catch (IOException e) {
LOGGER.log(Level.SEVERE, e,
() -> MessageFormat.format("Could not write in file {0}", TRACE_FILE_NAME));
}
System.out.println("******************Building bifurcations ************************");
long startTime = System.currentTimeMillis();
for (Transport entry : transports.values()) {
entry.buildBifurcationOptimzed();
}
long endTime = System.currentTimeMillis();
long tempsPasse = endTime - startTime;
long minutes = (tempsPasse / 1000) / 60;
long seconds = (tempsPasse / 1000) % 60;
long milliseconds = tempsPasse % 1000;
System.out.println("Temps écoulé : " + minutes + " minutess, " + seconds + " secndes et " + milliseconds + " millis");
System.out.println("******************Fin Building bifurcations ************************");
CSVSchedulesProvider providerschedules = new CSVSchedulesProvider(transports.values().iterator());
try {
CSVTools.writeCSVToFile(HOURS_FILE_NAME, Stream.iterate(providerschedules.next(),
t -> providerschedules.hasNext(), t -> providerschedules.next()));
} catch (IOException e) {
LOGGER.log(Level.SEVERE, e,
() -> MessageFormat.format("Could not write in file {0}", HOURS_FILE_NAME));
}
CSVImageProvider providerimage = new CSVImageProvider(transports.values().iterator());
try {
CSVTools.writeCSVToFile(IMAGES_FILE_NAME, Stream.iterate(providerimage.next(),
t -> providerimage.hasNext(), t -> providerimage.next()));
} catch (IOException e) {
LOGGER.log(Level.SEVERE, e,
() -> MessageFormat.format("Could not write in file {0}", IMAGES_FILE_NAME));
}
} }
List<StopEntry> stops = new ArrayList<>(traces.size() * GUESS_STOPS_BY_LINE);
/** Clean the traces/remove the unresolved lines try {
* @param traces the traces to clean CSVTools.readCSVFromFile(STOPS_FILE_DOWNLOADED_NAME,
*/ (String[] line) -> addStop(line, traces, stops));
private static void cleanTraces(Map<String, TraceEntry> traces) { } catch (IOException e) {
Set<String> toRemove = new HashSet<>(); LOGGER.log(Level.SEVERE, "Error while reading the stops", e);
for (Entry<String, TraceEntry> traceEntry : traces.entrySet()) {
TraceEntry trace = traceEntry.getValue();
if (!cleanLine(trace.getPaths())) {
LOGGER.severe(() -> MessageFormat.format(
"Missing stop for line {0}. Line will be removed", trace.lname));
toRemove.add(traceEntry.getKey());
}
}
for (String string : toRemove) {
traces.remove(string);
}
} }
/** Tells if the current trasport line has all its stops entries resolved cleanTraces(traces);
* @param stops the stops list
* @return if the line is "clean"*/ Map<String, Transport> transports = new HashMap<>();
private static boolean cleanLine(List<List<StopEntry>> stops) { CSVStreamProvider provider = new CSVStreamProvider(traces.values().iterator(), transports);
for (List<StopEntry> path : stops) {
for (int i = 0; i < path.size(); i++) { // Write into args[0]
StopEntry stop = path.get(i); try {
if (!(stop instanceof UnidentifiedStopEntry unidentified)) { CSVTools.writeCSVToFile(TRACE_FILE_NAME, Stream.iterate(provider.next(),
continue; t -> provider.hasNext(), t -> provider.next()));
} } catch (IOException e) {
StopEntry stopResolution = unidentified.resolve(); LOGGER.log(Level.SEVERE, e,
if (stopResolution == null) { () -> MessageFormat.format("Could not write in file {0}", TRACE_FILE_NAME));
return false;
}
path.set(i, stopResolution);
}
}
return true;
} }
/** adds a stop to all related variables System.out.println("******************Building bifurcations ************************");
* @param line the transport line involved with the new stop long startTime = System.currentTimeMillis();
* @param traces the traces related to it
* @param stops the general stops list
*/
private static void addStop(String[] line, Map<String, TraceEntry> traces,
List<StopEntry> stops) {
StopEntry entry = new StopEntry(line[IDFM_STOPS_NAME_INDEX],
Double.parseDouble(line[IDFM_STOPS_LON_INDEX]),
Double.parseDouble(line[IDFM_STOPS_LAT_INDEX]));
String rid = line[IDFM_STOPS_RID_INDEX];
//Add traces description if it's empty for (Transport entry : transports.values()) {
if (traces.containsKey(rid)) { entry.buildBifurcationOptimzed();
TraceEntry tmp = traces.get(rid);
if (tmp.isDescriptionEmpty()) {
List<TraceDescription> descriptions = extractDescription(line[IDFM_STOPS_SCHEDULES_INDEX]);
tmp.addDescriptions(descriptions);
}
}
// Add terminus to the traces
if (traces.containsKey(rid)) {
extractTerminus(line[IDFM_STOPS_SCHEDULES_INDEX]).forEach(t -> traces.get(rid).addTerminus(t));
}
traces.computeIfPresent(rid,
(String k, TraceEntry trace) -> addCandidate(trace, entry));
stops.add(entry);
} }
/** add a line to the related list of traces long endTime = System.currentTimeMillis();
* @param line the line as a string long tempsPasse = endTime - startTime;
* @param traces the traces
*/ long minutes = (tempsPasse / 1000) / 60;
private static void addLine(String[] line, Map<String, TraceEntry> traces) { long seconds = (tempsPasse / 1000) % 60;
TraceEntry entry = new TraceEntry(line[IDFM_TRACE_SNAME_INDEX], line[IDFM_TRACE_ID_INDEX],line[IDFM_TRACE_TYPE_INDEX], line[IDFM_URL_INDEX]); long milliseconds = tempsPasse % 1000;
List<List<StopEntry>> buildPaths = buildPaths(line[IDFM_TRACE_SHAPE_INDEX]);
entry.getPaths().addAll(buildPaths); System.out.println(
if (buildPaths.isEmpty()) { "Temps écoulé : " + minutes + " minutess, " + seconds + " secndes et " + milliseconds
LOGGER.severe(() -> MessageFormat.format( + " millis");
"Line {0} has no provided itinerary and was ignored", entry.lname));
} else { System.out.println("******************Fin Building bifurcations ************************");
traces.put(line[IDFM_TRACE_ID_INDEX], entry);
} CSVSchedulesProvider providerschedules = new CSVSchedulesProvider(
transports.values().iterator());
try {
CSVTools.writeCSVToFile(HOURS_FILE_NAME, Stream.iterate(providerschedules.next(),
t -> providerschedules.hasNext(), t -> providerschedules.next()));
} catch (IOException e) {
LOGGER.log(Level.SEVERE, e,
() -> MessageFormat.format("Could not write in file {0}", HOURS_FILE_NAME));
} }
/** add a new entry as a candidate to a trace CSVImageProvider providerimage = new CSVImageProvider(transports.values().iterator());
* @param trace the trace try {
* @param entry the entry CSVTools.writeCSVToFile(IMAGES_FILE_NAME, Stream.iterate(providerimage.next(),
* @return the trace in question t -> providerimage.hasNext(), t -> providerimage.next()));
*/ } catch (IOException e) {
private static TraceEntry addCandidate(TraceEntry trace, StopEntry entry) { LOGGER.log(Level.SEVERE, e,
for (List<StopEntry> path : trace.getPaths()) { () -> MessageFormat.format("Could not write in file {0}", IMAGES_FILE_NAME));
for (StopEntry stopEntry : path) { }
if (stopEntry instanceof UnidentifiedStopEntry unidentified }
&& GPS.distance(entry.latitude, entry.longitude,
stopEntry.latitude,
stopEntry.longitude) < QUARTER_KILOMETER) { /**
unidentified.addCandidate(entry); * Clean the traces/remove the unresolved lines
} *
} * @param traces the traces to clean
*/
private static void cleanTraces(Map<String, TraceEntry> traces) {
Set<String> toRemove = new HashSet<>();
for (Entry<String, TraceEntry> traceEntry : traces.entrySet()) {
TraceEntry trace = traceEntry.getValue();
if (!cleanLine(trace.getPaths())) {
LOGGER.severe(() -> MessageFormat.format(
"Missing stop for line {0}. Line will be removed", trace.lname));
toRemove.add(traceEntry.getKey());
}
}
for (String string : toRemove) {
traces.remove(string);
}
}
/**
* Tells if the current trasport line has all its stops entries resolved
*
* @param stops the stops list
* @return if the line is "clean"
*/
private static boolean cleanLine(List<List<StopEntry>> stops) {
for (List<StopEntry> path : stops) {
for (int i = 0; i < path.size(); i++) {
StopEntry stop = path.get(i);
if (!(stop instanceof UnidentifiedStopEntry unidentified)) {
continue;
} }
return trace; StopEntry stopResolution = unidentified.resolve();
if (stopResolution == null) {
return false;
}
path.set(i, stopResolution);
}
}
return true;
}
/**
* adds a stop to all related variables
*
* @param line the transport line involved with the new stop
* @param traces the traces related to it
* @param stops the general stops list
*/
private static void addStop(String[] line, Map<String, TraceEntry> traces,
List<StopEntry> stops) {
StopEntry entry = new StopEntry(line[IDFM_STOPS_NAME_INDEX],
Double.parseDouble(line[IDFM_STOPS_LON_INDEX]),
Double.parseDouble(line[IDFM_STOPS_LAT_INDEX]));
String rid = line[IDFM_STOPS_RID_INDEX];
//Add traces description if it's empty
if (traces.containsKey(rid)) {
TraceEntry tmp = traces.get(rid);
if (tmp.isDescriptionEmpty()) {
List<TraceDescription> descriptions = extractDescription(line[IDFM_STOPS_SCHEDULES_INDEX]);
tmp.addDescriptions(descriptions);
}
} }
/** turn a JSON list of stops into a list of paths // Add terminus to the traces
* @param pathsJSON the JSON String of all paths if (traces.containsKey(rid)) {
* @return the paths as a List of StopEntries extractTerminus(line[IDFM_STOPS_SCHEDULES_INDEX]).forEach(
*/ t -> traces.get(rid).addTerminus(t));
private static List<List<StopEntry>> buildPaths(String pathsJSON) {
List<List<StopEntry>> all = new ArrayList<>();
try {
JSONObject json = new JSONObject(pathsJSON);
JSONArray paths = json.getJSONArray("coordinates");
for (int i = 0; i < paths.length(); i++) {
JSONArray path = paths.getJSONArray(i);
List<StopEntry> stopsPath = new ArrayList<>();
for (int j = 0; j < path.length(); j++) {
JSONArray coordinates = path.getJSONArray(j);
StopEntry entry = new UnidentifiedStopEntry(coordinates.getDouble(0),
coordinates.getDouble(1));
stopsPath.add(entry);
}
all.add(stopsPath);
}
} catch (JSONException e) {
// Ignoring invalid element!
LOGGER.log(Level.FINE, e,
() -> MessageFormat.format("Invalid json element {0}", pathsJSON)); //$NON-NLS-1$
}
return all;
} }
/** extract the terminus out of a JSON file traces.computeIfPresent(rid,
* @param JSON the JSON (String k, TraceEntry trace) -> addCandidate(trace, entry));
* @return a list of strings related to the terminus stops.add(entry);
*/ }
private static List<String> extractTerminus(String JSON) {
List<String> all = new ArrayList<>();
try {
JSONArray schedules = new JSONArray(JSON);
for (int i = 0; i < schedules.length(); i++) {
JSONObject stop = schedules.getJSONObject(i);
String terminus = stop.getString("from");
all.add(terminus);
}
} catch (
JSONException e) { /**
// Ignoring invalid element! * add a line to the related list of traces
LOGGER.log(Level.FINE, e, *
() -> MessageFormat.format("Invalid json element {0}", JSON)); //$NON-NLS-1$ * @param line the line as a string
* @param traces the traces
*/
private static void addLine(String[] line, Map<String, TraceEntry> traces) {
TraceEntry entry = new TraceEntry(line[IDFM_TRACE_SNAME_INDEX], line[IDFM_TRACE_ID_INDEX],
line[IDFM_TRACE_TYPE_INDEX], line[IDFM_URL_INDEX]);
List<List<StopEntry>> buildPaths = buildPaths(line[IDFM_TRACE_SHAPE_INDEX]);
entry.getPaths().addAll(buildPaths);
if (buildPaths.isEmpty()) {
LOGGER.severe(() -> MessageFormat.format(
"Line {0} has no provided itinerary and was ignored", entry.lname));
} else {
traces.put(line[IDFM_TRACE_ID_INDEX], entry);
}
}
/**
* add a new entry as a candidate to a trace
*
* @param trace the trace
* @param entry the entry
* @return the trace in question
*/
private static TraceEntry addCandidate(TraceEntry trace, StopEntry entry) {
for (List<StopEntry> path : trace.getPaths()) {
for (StopEntry stopEntry : path) {
if (stopEntry instanceof UnidentifiedStopEntry unidentified
&& GPS.distance(entry.latitude, entry.longitude,
stopEntry.latitude,
stopEntry.longitude) < QUARTER_KILOMETER) {
unidentified.addCandidate(entry);
}
}
}
return trace;
}
/**
* turn a JSON list of stops into a list of paths
*
* @param pathsJSON the JSON String of all paths
* @return the paths as a List of StopEntries
*/
private static List<List<StopEntry>> buildPaths(String pathsJSON) {
List<List<StopEntry>> all = new ArrayList<>();
try {
JSONObject json = new JSONObject(pathsJSON);
JSONArray paths = json.getJSONArray("coordinates");
for (int i = 0; i < paths.length(); i++) {
JSONArray path = paths.getJSONArray(i);
List<StopEntry> stopsPath = new ArrayList<>();
for (int j = 0; j < path.length(); j++) {
JSONArray coordinates = path.getJSONArray(j);
StopEntry entry = new UnidentifiedStopEntry(coordinates.getDouble(0),
coordinates.getDouble(1));
stopsPath.add(entry);
} }
return all; all.add(stopsPath);
}
} catch (JSONException e) {
// Ignoring invalid element!
LOGGER.log(Level.FINE, e,
() -> MessageFormat.format("Invalid json element {0}", pathsJSON)); //$NON-NLS-1$
}
return all;
}
/**
* extract the terminus out of a JSON file
*
* @param JSON the JSON
* @return a list of strings related to the terminus
*/
private static List<String> extractTerminus(String JSON) {
List<String> all = new ArrayList<>();
try {
JSONArray schedules = new JSONArray(JSON);
for (int i = 0; i < schedules.length(); i++) {
JSONObject stop = schedules.getJSONObject(i);
String terminus = stop.getString("from");
all.add(terminus);
}
} catch (
JSONException e) {
// Ignoring invalid element!
LOGGER.log(Level.FINE, e,
() -> MessageFormat.format("Invalid json element {0}", JSON)); //$NON-NLS-1$
} }
private static List<TraceDescription> extractDescription(String JSON) { return all;
List<TraceDescription> all = new ArrayList<>(); }
try {
JSONArray schedules = new JSONArray(JSON);
for (int i = 0; i < schedules.length(); i++) {
JSONObject stop = schedules.getJSONObject(i);
String from = stop.getString("from");
String to = stop.getString("to");
String first = stop.getString("first");
String last = stop.getString("last");
//We skip the lines where from equals to
// if(from.compareTo(to) != 0){
all.add(new TraceDescription(from, to, first, last));
// }
}
} catch (JSONException e) {
// Ignoring invalid element!
// e.printStackTrace();
}
return all; private static List<TraceDescription> extractDescription(String JSON) {
List<TraceDescription> all = new ArrayList<>();
try {
JSONArray schedules = new JSONArray(JSON);
for (int i = 0; i < schedules.length(); i++) {
JSONObject stop = schedules.getJSONObject(i);
String from = stop.getString("from");
String to = stop.getString("to");
String first = stop.getString("first");
String last = stop.getString("last");
//We skip the lines where from equals to
// if(from.compareTo(to) != 0){
all.add(new TraceDescription(from, to, first, last));
// }
}
} catch (JSONException e) {
// Ignoring invalid element!
// e.printStackTrace();
} }
return all;
}
} }

View file

@ -1,48 +1,49 @@
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
/** /**
* A representation of a stop with its connected stop and which bifurcation * A representation of a stop with its connected stop and which bifurcation is needed to go to each
* is needed to go to each connected stop * connected stop
*/ */
public class Stop { public class Stop {
Map<String, BifStop> connected = new HashMap<>(); public String name;
public String name; Map<String, BifStop> connected = new HashMap<>();
public Stop(String name){ public Stop(String name) {
this.name = name; this.name = name;
} }
/** /**
* Checks is stopName is connected to this one * Checks is stopName is connected to this one
* @param stopName *
* @return True if stopName is connected to the current stop * @param stopName
*/ * @return True if stopName is connected to the current stop
public boolean isStopConnected(String stopName) { */
return connected.containsKey(stopName); public boolean isStopConnected(String stopName) {
} return connected.containsKey(stopName);
}
/** /**
* Add Connected stop * Add Connected stop
* @param stop connected stop with the bifurcation needed *
*/ * @param stop connected stop with the bifurcation needed
public void addConnectedStop(BifStop stop) { */
connected.put(stop.stop.name, stop); public void addConnectedStop(BifStop stop) {
} connected.put(stop.stop.name, stop);
}
/** /**
* Return the connected stop with the name : stopName * Return the connected stop with the name : stopName
* @param stopName *
* @return the connected stop with the name : stopName * @param stopName
*/ * @return the connected stop with the name : stopName
public BifStop getConnectedStop(String stopName) { */
return connected.get(stopName); public BifStop getConnectedStop(String stopName) {
} return connected.get(stopName);
}
} }

View file

@ -1,5 +1,5 @@
/** /**
* *
*/ */
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
@ -7,65 +7,69 @@ import java.text.MessageFormat;
import java.util.Objects; import java.util.Objects;
/** A transport stop data. /** A transport stop data.
* *
* @author Emmanuel Bigeon */ * @author Emmanuel Bigeon */
public class StopEntry implements Comparable<StopEntry> { public class StopEntry implements Comparable<StopEntry> {
public final String lname;
public final double longitude;
public final double latitude;
/** Create the stop public final String lname;
* public final double longitude;
* @param lname public final double latitude;
* @param longitude
* @param latitude */
public StopEntry(String lname, double longitude, double latitude) {
super();
this.lname = lname;
this.longitude = longitude;
this.latitude = latitude;
}
@Override /** Create the stop
public String toString() { *
return MessageFormat.format("{0} [{1}, {2}]", this.lname, this.longitude, //$NON-NLS-1$ * @param lname
this.latitude); * @param longitude
} * @param latitude */
public StopEntry(String lname, double longitude, double latitude) {
super();
this.lname = lname;
this.longitude = longitude;
this.latitude = latitude;
}
@Override @Override
public int compareTo(StopEntry o) { public String toString() {
if (latitude < o.latitude) { return MessageFormat.format("{0} [{1}, {2}]", this.lname, this.longitude, //$NON-NLS-1$
return -1; this.latitude);
} }
if (latitude > o.latitude) {
return 1;
}
if (longitude < o.longitude) {
return -1;
}
if (longitude > o.longitude) {
return 1;
}
return lname.compareTo(o.lname);
}
@Override @Override
public int hashCode() { public int compareTo(StopEntry o) {
return Objects.hash(latitude, lname, longitude); if (latitude < o.latitude) {
return -1;
} }
if (latitude > o.latitude) {
return 1;
}
if (longitude < o.longitude) {
return -1;
}
if (longitude > o.longitude) {
return 1;
}
return lname.compareTo(o.lname);
}
@Override @Override
public boolean equals(Object obj) { public int hashCode() {
if (this == obj) return Objects.hash(latitude, lname, longitude);
return true; }
if (obj == null)
return false; @Override
if (getClass() != obj.getClass()) public boolean equals(Object obj) {
return false; if (this == obj) {
StopEntry other = (StopEntry) obj; return true;
return Double.doubleToLongBits(latitude) == Double }
.doubleToLongBits(other.latitude) && Objects.equals(lname, other.lname) if (obj == null) {
&& Double.doubleToLongBits(longitude) == Double return false;
.doubleToLongBits(other.longitude); }
} if (getClass() != obj.getClass()) {
return false;
}
StopEntry other = (StopEntry) obj;
return Double.doubleToLongBits(latitude) == Double
.doubleToLongBits(other.latitude) && Objects.equals(lname, other.lname)
&& Double.doubleToLongBits(longitude) == Double
.doubleToLongBits(other.longitude);
}
} }

View file

@ -1,29 +1,31 @@
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/** /**
* A representation of a transport description encompansing its first and last * A representation of a transport description encompansing its first and last stop in all of its
* stop in all of its direction, the first and last schedule and all the * direction, the first and last schedule and all the bifurcation that direction takes. The
* bifurcation that direction takes. The description comes from the fourth column * of the stop csv file. * description comes from the fourth column * of the stop csv file.
*/ */
public class TraceDescription { public class TraceDescription {
public String from;
public String to;
public String first;
public String last;
List<Integer> bifurcation = new ArrayList<>();
public TraceDescription(String from,String to, String first, String last){ public String from;
this.from = from; public String to;
this.to = to; public String first;
this.first = first; public String last;
this.last = last; List<Integer> bifurcation = new ArrayList<>();
}
@Override public TraceDescription(String from, String to, String first, String last) {
public String toString() { this.from = from;
return "From: " + from + ", To: " + to + ", First: " + first + ", Last: " + last + ", Bifurcation: " + bifurcation; this.to = to;
} this.first = first;
this.last = last;
}
@Override
public String toString() {
return "From: " + from + ", To: " + to + ", First: " + first + ", Last: " + last
+ ", Bifurcation: " + bifurcation;
}
} }

View file

@ -12,60 +12,64 @@ import java.util.List;
* @author Emmanuel Bigeon * @author Emmanuel Bigeon
*/ */
public final class TraceEntry { public final class TraceEntry {
public final String lname;
public final String id; public final String lname;
public final String type; public final String id;
public final String url; public final String type;
public final String url;
private final List<String> terminus = new ArrayList<>();
private final List<List<StopEntry>> paths = new ArrayList<>();
List<TraceDescription> descriptions = new ArrayList<>();
private List<String> terminus = new ArrayList<>(); /**
private List<List<StopEntry>> paths = new ArrayList<>(); * Create a transport line.
List <TraceDescription> descriptions = new ArrayList<>(); *
* @param lname the name of the line
*/
public TraceEntry(String lname, String ident, String t_type, String img_url) {
super();
this.lname = lname;
this.id = ident;
this.type = t_type;
this.url = img_url;
}
/** // FIXME list of lists are bad practice in direct access...
* Create a transport line.
*
* @param lname the name of the line
*/
public TraceEntry(String lname,String ident,String t_type, String img_url) {
super();
this.lname = lname;
this.id = ident;
this.type = t_type;
this.url = img_url;
}
// FIXME list of lists are bad practice in direct access... /**
/** @return the list of paths */ * @return the list of paths
public List<List<StopEntry>> getPaths() { */
// TODO Ne pas retourner directement la liste public List<List<StopEntry>> getPaths() {
return paths; // TODO Ne pas retourner directement la liste
} return paths;
}
/** @return the list of terminus */ /**
public List<String> getTerminus() { * @return the list of terminus
return terminus; */
} public List<String> getTerminus() {
return terminus;
}
public void addPath(List<StopEntry> path) { public void addPath(List<StopEntry> path) {
paths.add(new ArrayList<>(path)); paths.add(new ArrayList<>(path));
} }
public void addTerminus(String term) { public void addTerminus(String term) {
terminus.add(term); terminus.add(term);
} }
public boolean isDescriptionEmpty(){ public boolean isDescriptionEmpty() {
return descriptions.isEmpty(); return descriptions.isEmpty();
} }
/** /**
* Add all the description to the current one * Add all the description to the current one
* @param desctipt *
*/ * @param desctipt
public void addDescriptions(List<TraceDescription> desctipt){ */
descriptions.addAll(desctipt); public void addDescriptions(List<TraceDescription> desctipt) {
} descriptions.addAll(desctipt);
}
} }

View file

@ -1,226 +1,232 @@
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import java.util.List; import java.util.AbstractMap.SimpleEntry;
import java.util.Map;
import java.util.Set;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.List;
import java.util.AbstractMap.SimpleEntry; import java.util.Map;
import java.util.Set;
/** /**
* Representation of a line with its description and stops * Representation of a line with its description and stops
*/ */
public class Transport { public class Transport {
//All the stops of the line
Map<String, Stop> stopsMap = new HashMap<>();
public String name;
public String type;
public String image_url;
//All the line descriptions (directions and schedules) public String name;
List <TraceDescription> descriptions = new ArrayList<>(); public String type;
public String image_url;
//All the stops of the line
Map<String, Stop> stopsMap = new HashMap<>();
//All the line descriptions (directions and schedules)
List<TraceDescription> descriptions = new ArrayList<>();
public Transport(String name,String type, String url){ public Transport(String name, String type, String url) {
this.name = name; this.name = name;
this.type = type; this.type = type;
this.image_url = url; this.image_url = url;
}
/**
* Build the bifurcation for all the descriptions
*/
public void buildBifurcation() {
// int found = 0;
for (TraceDescription d : descriptions) {
// System.out.println("Debut est "+d.first);
Stop debut = stopsMap.get(d.from);
Stop fin = stopsMap.get(d.to);
if (debut != null && fin != null) {
SimpleEntry<Boolean, List<Integer>> sol = roadToLast(debut.name, fin.name,
new ArrayList<String>(), new ArrayList<Integer>());
if (sol.getKey()) {
// found++;
d.bifurcation = sol.getValue();
}
}
} }
// System.out.println("J'en ai trouvé "+found);
}
/** /**
* Build the bifurcation for all the descriptions * Build the bifurcation for all the descriptions but optimized
*/ */
public void buildBifurcation(){ public void buildBifurcationOptimzed() {
// int found = 0; // int found = 0;
for(TraceDescription d : descriptions){ for (TraceDescription d : descriptions) {
// System.out.println("Debut est "+d.first); Stop debut = stopsMap.get(d.from);
Stop fin = stopsMap.get(d.to);
Stop debut = stopsMap.get(d.from); if (debut != null && fin != null) {
Stop fin = stopsMap.get(d.to); Set<String> alreadyVisited = new HashSet<>();
if (debut != null && fin != null) { SimpleEntry<Boolean, List<Integer>> sol = roadToLastOptimized(debut.name, fin.name,
SimpleEntry<Boolean, List<Integer>> sol = roadToLast(debut.name, fin.name, new ArrayList<String>(), new ArrayList<Integer>()); alreadyVisited, new ArrayList<Integer>());
if (sol.getKey()) { if (sol.getKey()) {
// found++; // found++;
d.bifurcation = sol.getValue(); d.bifurcation = sol.getValue();
}
}
} }
// System.out.println("J'en ai trouvé "+found); }
} }
// System.out.println("J'en ai trouvé " + found);
}
/** /**
* Build the bifurcation for all the descriptions but optimized * Check if the stop is a terminus
*/ *
public void buildBifurcationOptimzed() { * @param stop the name of a Stop
// int found = 0; * @return True if the stop is a terminus
for (TraceDescription d : descriptions) { */
Stop debut = stopsMap.get(d.from); public boolean isTerminus(String stop) {
Stop fin = stopsMap.get(d.to); for (TraceDescription t : descriptions) {
if (debut != null && fin != null) { if (stop.equals(t.first) || stop.equals(t.last)) {
Set<String> alreadyVisited = new HashSet<>(); return true;
SimpleEntry<Boolean, List<Integer>> sol = roadToLastOptimized(debut.name, fin.name, alreadyVisited, new ArrayList<Integer>());
if (sol.getKey()) {
// found++;
d.bifurcation = sol.getValue();
}
}
}
// System.out.println("J'en ai trouvé " + found);
}
/**
* Check if the stop is a terminus
* @param stop the name of a Stop
* @return True if the stop is a terminus
*/
public boolean isTerminus(String stop){
for(TraceDescription t: descriptions){
if(stop.equals(t.first) || stop.equals(t.last))
return true;
}
return false;
}
/**
* Find the road from the currentStop to the last stop
* @param currentStop the current stop we are visiting
* @param last The last stop we are trying to go to
* @param alreadyVisited All the stop we already have visisted
* @param bif All the bifurcation encountered from the first stop to the current
* one
* @return True and the bifurcation if we found our road to the last stop and
* false if we didn't
*/
public SimpleEntry<Boolean,List<Integer> > roadToLast(String currentStop, String last, List<String> alreadyVisited, List<Integer> bifurcation){
if(currentStop.equals(last)){
return new SimpleEntry<>(true,bifurcation);
}
//Checker if the current stop is the bad terminus
if(isTerminus(currentStop)){
return new SimpleEntry<>(false,null);
}
List<String> visitedCopy = new ArrayList<>(alreadyVisited);
visitedCopy.add(currentStop);
Stop current = stopsMap.get(currentStop);
List <SimpleEntry<Boolean,List<Integer>> > solutions = new ArrayList<>();
for(BifStop b: current.connected.values()){
if(!visitedCopy.contains(b.stop.name)){
List<Integer> bifCopy = new ArrayList<>(bifurcation);
if(b.bifurc!= 0)
bifCopy.add(b.bifurc);
solutions.add(roadToLast(b.stop.name, last, visitedCopy, bifCopy));
}
}
//TODo: Send a list on list of integer in case there is a lot of path for the same direction
List<Integer> bifSol = new ArrayList<>();
boolean trouve = false;
for(SimpleEntry<Boolean,List<Integer>> se: solutions){
if(se.getKey()){
trouve = true;
bifSol = se.getValue();
}
}
return new SimpleEntry<>(trouve,bifSol) ;
}
/**
* Find the road from the currentStop to the last stop
* @param currentStop the current stop we are visiting
* @param last The last stop we are trying to go to
* @param alreadyVisited All the stop we already have visisted
* @param bif All the bifurcation encountered from the first stop to the current
* one
* @return True and the bifurcation if we found our road to the last stop and
* false if we didn't
*/
public SimpleEntry<Boolean, List<Integer>> roadToLastOptimized(String currentStop, String last, Set<String> alreadyVisited, List<Integer> bifurcation) {
if (currentStop.equals(last)) {
return new SimpleEntry<>(true, bifurcation);
}
// Checker if the current stop is the bad terminus
if (isTerminus(currentStop)) {
return new SimpleEntry<>(false, null);
}
alreadyVisited.add(currentStop);
Stop current = stopsMap.get(currentStop);
List<SimpleEntry<Boolean, List<Integer>>> solutions = new ArrayList<>();
for (BifStop b : current.connected.values()) {
if (!alreadyVisited.contains(b.stop.name)) {
List<Integer> bifCopy = new ArrayList<>(bifurcation);
if (b.bifurc != 0) {
bifCopy.add(b.bifurc);
}
solutions.add(roadToLastOptimized(b.stop.name, last, alreadyVisited, bifCopy));
}
}
// Todo: Send a list on list of integer in case there is a lot of path for the same direction
List<Integer> bifSol = new ArrayList<>();
boolean trouve = false;
for (SimpleEntry<Boolean, List<Integer>> se : solutions) {
if (se.getKey()) {
trouve = true;
bifSol = se.getValue();
break; // Exit loop if a solution is found
}
}
alreadyVisited.remove(currentStop); // Remove current stop from visited after processing
return new SimpleEntry<>(trouve, bifSol);
}
/**
* Connect 2 stops (start, end) and add them in stopMap if they are not already in
* @param start The name of a stop
* @param end The name of the stop connected to the start
* @param bifurcation The bifurcation taken to go from start stop to end stop
*/
public void addStop(String start, String end, int bifurcation){
Stop startStop = stopsMap.computeIfAbsent(start, Stop::new);
Stop endStop = stopsMap.computeIfAbsent(end, Stop::new);
BifStop connectedStop = new BifStop(bifurcation, endStop);
startStop.addConnectedStop(connectedStop);
}
/**
* Print every stops of the line and its connections
*/
public void printAllConnectionStops() {
System.out.println("Affichage des couples (stop, next du stop):");
for (Map.Entry<String, Stop> entry : stopsMap.entrySet()) {
Stop stop = entry.getValue();
System.out.println("Stop: " + stop.name);
System.out.println("Next:");
for (BifStop nextEntry : stop.connected.values()) {
System.out.println(nextEntry.bifurc + ": " + nextEntry.stop.name);
}
} }
} }
return false;
}
/** /**
* Add all the description to the current one * Find the road from the currentStop to the last stop
* @param desctipt *
*/ * @param currentStop the current stop we are visiting
public void addDescriptions(List<TraceDescription> desctipt){ * @param last The last stop we are trying to go to
descriptions.addAll(desctipt); * @param alreadyVisited All the stop we already have visisted
* @param bif All the bifurcation encountered from the first stop to the current one
* @return True and the bifurcation if we found our road to the last stop and false if we didn't
*/
public SimpleEntry<Boolean, List<Integer>> roadToLast(String currentStop, String last,
List<String> alreadyVisited, List<Integer> bifurcation) {
if (currentStop.equals(last)) {
return new SimpleEntry<>(true, bifurcation);
} }
//Checker if the current stop is the bad terminus
if (isTerminus(currentStop)) {
return new SimpleEntry<>(false, null);
}
List<String> visitedCopy = new ArrayList<>(alreadyVisited);
visitedCopy.add(currentStop);
Stop current = stopsMap.get(currentStop);
List<SimpleEntry<Boolean, List<Integer>>> solutions = new ArrayList<>();
for (BifStop b : current.connected.values()) {
if (!visitedCopy.contains(b.stop.name)) {
List<Integer> bifCopy = new ArrayList<>(bifurcation);
if (b.bifurc != 0) {
bifCopy.add(b.bifurc);
}
solutions.add(roadToLast(b.stop.name, last, visitedCopy, bifCopy));
}
}
//TODo: Send a list on list of integer in case there is a lot of path for the same direction
List<Integer> bifSol = new ArrayList<>();
boolean trouve = false;
for (SimpleEntry<Boolean, List<Integer>> se : solutions) {
if (se.getKey()) {
trouve = true;
bifSol = se.getValue();
}
}
return new SimpleEntry<>(trouve, bifSol);
}
/**
* Find the road from the currentStop to the last stop
*
* @param currentStop the current stop we are visiting
* @param last The last stop we are trying to go to
* @param alreadyVisited All the stop we already have visisted
* @param bif All the bifurcation encountered from the first stop to the current one
* @return True and the bifurcation if we found our road to the last stop and false if we didn't
*/
public SimpleEntry<Boolean, List<Integer>> roadToLastOptimized(String currentStop, String last,
Set<String> alreadyVisited, List<Integer> bifurcation) {
if (currentStop.equals(last)) {
return new SimpleEntry<>(true, bifurcation);
}
// Checker if the current stop is the bad terminus
if (isTerminus(currentStop)) {
return new SimpleEntry<>(false, null);
}
alreadyVisited.add(currentStop);
Stop current = stopsMap.get(currentStop);
List<SimpleEntry<Boolean, List<Integer>>> solutions = new ArrayList<>();
for (BifStop b : current.connected.values()) {
if (!alreadyVisited.contains(b.stop.name)) {
List<Integer> bifCopy = new ArrayList<>(bifurcation);
if (b.bifurc != 0) {
bifCopy.add(b.bifurc);
}
solutions.add(roadToLastOptimized(b.stop.name, last, alreadyVisited, bifCopy));
}
}
// Todo: Send a list on list of integer in case there is a lot of path for the same direction
List<Integer> bifSol = new ArrayList<>();
boolean trouve = false;
for (SimpleEntry<Boolean, List<Integer>> se : solutions) {
if (se.getKey()) {
trouve = true;
bifSol = se.getValue();
break; // Exit loop if a solution is found
}
}
alreadyVisited.remove(currentStop); // Remove current stop from visited after processing
return new SimpleEntry<>(trouve, bifSol);
}
/**
* Connect 2 stops (start, end) and add them in stopMap if they are not already in
*
* @param start The name of a stop
* @param end The name of the stop connected to the start
* @param bifurcation The bifurcation taken to go from start stop to end stop
*/
public void addStop(String start, String end, int bifurcation) {
Stop startStop = stopsMap.computeIfAbsent(start, Stop::new);
Stop endStop = stopsMap.computeIfAbsent(end, Stop::new);
BifStop connectedStop = new BifStop(bifurcation, endStop);
startStop.addConnectedStop(connectedStop);
}
/**
* Print every stops of the line and its connections
*/
public void printAllConnectionStops() {
System.out.println("Affichage des couples (stop, next du stop):");
for (Map.Entry<String, Stop> entry : stopsMap.entrySet()) {
Stop stop = entry.getValue();
System.out.println("Stop: " + stop.name);
System.out.println("Next:");
for (BifStop nextEntry : stop.connected.values()) {
System.out.println(nextEntry.bifurc + ": " + nextEntry.stop.name);
}
}
}
/**
* Add all the description to the current one
*
* @param desctipt
*/
public void addDescriptions(List<TraceDescription> desctipt) {
descriptions.addAll(desctipt);
}
} }

View file

@ -1,8 +1,9 @@
/** /**
* *
*/ */
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import fr.u_paris.gla.project.utils.GPS;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -10,63 +11,72 @@ import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import fr.u_paris.gla.project.utils.GPS; /**
* A transport stop with unidentified name and potential candidates as to their real value.
/** A transport stop with unidentified name and potential candidates as to their *
* real value. * @author Emmanuel Bigeon
* */
* @author Emmanuel Bigeon */
public final class UnidentifiedStopEntry extends StopEntry { public final class UnidentifiedStopEntry extends StopEntry {
private List<StopEntry> candidates = new ArrayList<>();
/** Create the stop private final List<StopEntry> candidates = new ArrayList<>();
*
* @param longitude /**
* @param latitude */ * Create the stop
public UnidentifiedStopEntry(double longitude, double latitude) { *
super("Unidentified", longitude, latitude); //$NON-NLS-1$ * @param longitude
* @param latitude
*/
public UnidentifiedStopEntry(double longitude, double latitude) {
super("Unidentified", longitude, latitude); //$NON-NLS-1$
}
@Override
public String toString() {
return MessageFormat.format("UnidentifiedStop [candidates={0}]", this.candidates); //$NON-NLS-1$
}
/**
* Get the most likely choice for the stop
*
* @return the most likely candidate
*/
public StopEntry resolve() {
if (candidates.isEmpty()) {
return null;
} }
if (candidates.size() == 1) {
@Override return candidates.get(0);
public String toString() {
return MessageFormat.format("UnidentifiedStop [candidates={0}]", this.candidates); //$NON-NLS-1$
} }
Collections.sort(candidates, (Comparator<? super StopEntry>) (StopEntry s1,
StopEntry s2) -> (int) Math.signum((GPS.distance(latitude, longitude,
s1.latitude, s1.longitude)
- GPS.distance(latitude, longitude, s2.latitude, s2.longitude))));
/** Get the most likely choice for the stop return candidates.get(0);
* }
* @return the most likely candidate */
public StopEntry resolve() {
if (candidates.isEmpty()) {
return null;
}
if (candidates.size() == 1) {
return candidates.get(0);
}
Collections.sort(candidates, (Comparator<? super StopEntry>) (StopEntry s1,
StopEntry s2) -> (int) Math.signum((GPS.distance(latitude, longitude,
s1.latitude, s1.longitude)
- GPS.distance(latitude, longitude, s2.latitude, s2.longitude))));
return candidates.get(0); /**
* Add a candidate.
*
* @param entry the candidate
*/
public void addCandidate(StopEntry entry) {
candidates.add(entry);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
} }
if (!super.equals(obj)) {
/** Add a candidate. return false;
*
* @param entry the candidate */
public void addCandidate(StopEntry entry) {
candidates.add(entry);
} }
if (getClass() != obj.getClass()) {
@Override return false;
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
UnidentifiedStopEntry other = (UnidentifiedStopEntry) obj;
return Objects.equals(candidates, other.candidates);
} }
UnidentifiedStopEntry other = (UnidentifiedStopEntry) obj;
return Objects.equals(candidates, other.candidates);
}
} }

View file

@ -3,22 +3,20 @@
*/ */
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 LINE_INDEX = 0; public static final int NUMBER_COLUMNS = 2;
public static final int IMAGE_URL_INDEX = 1;
/** Hidden constructor for tool class */ public static final int LINE_INDEX = 0;
private ImageFormat() { public static final int IMAGE_URL_INDEX = 1;
// Tool class
} /**
* Hidden constructor for tool class
*/
private ImageFormat() {
// Tool class
}
} }

View file

@ -1,5 +1,5 @@
/** /**
* *
*/ */
package fr.u_paris.gla.project.io; package fr.u_paris.gla.project.io;
@ -11,66 +11,68 @@ import java.time.temporal.Temporal;
import java.util.Locale; import java.util.Locale;
/** Definition of the formats of files for this project. /** Definition of the formats of files for this project.
* *
* @author Emmanuel Bigeon */ * @author Emmanuel Bigeon */
public final class NetworkFormat { public final class NetworkFormat {
/** The amount of columns in the CSV file */
public static final int NUMBER_COLUMNS = 8;
/** The amount of decimal places in the GPS' coordinates */ /** The amount of columns in the CSV file */
public static final int GPS_PRECISION = 18; public static final int NUMBER_COLUMNS = 8;
/** The index of the line name in the network format */ /** The amount of decimal places in the GPS' coordinates */
public static final int LINE_INDEX = 0; public static final int GPS_PRECISION = 18;
/** The index of the variant number of the segment in the network format */
public static final int VARIANT_INDEX = 1;
/** The index of the segment trip duration in the network format */
public static final int DURATION_INDEX = 6;
/** The index of the segment distance in the network format */
public static final int DISTANCE_INDEX = 7;
/** The index of the segment end stop name in the network format */
public static final int STOP_INDEX = 4;
/** The index of the segment starting stop name in the network format */
public static final int START_INDEX = 2;
private static final DateTimeFormatter DURATION_FORMATTER = DateTimeFormatter /** The index of the line name in the network format */
.ofPattern("HH:mm:ss"); public static final int LINE_INDEX = 0;
private static final NumberFormat DURATION_INDIVIDUAL_FORMATTER = NumberFormat /** The index of the variant number of the segment in the network format */
.getIntegerInstance(Locale.ENGLISH); public static final int VARIANT_INDEX = 1;
static { /** The index of the segment trip duration in the network format */
DURATION_INDIVIDUAL_FORMATTER.setMinimumIntegerDigits(2); public static final int DURATION_INDEX = 6;
} /** The index of the segment distance in the network format */
private static final Temporal ZERO = LocalTime.parse("00:00:00"); public static final int DISTANCE_INDEX = 7;
/** The index of the segment end stop name in the network format */
public static final int STOP_INDEX = 4;
/** The index of the segment starting stop name in the network format */
public static final int START_INDEX = 2;
/** Hidden constructor for utility class */ private static final DateTimeFormatter DURATION_FORMATTER = DateTimeFormatter
private NetworkFormat() { .ofPattern("HH:mm:ss");
// Tool class private static final NumberFormat DURATION_INDIVIDUAL_FORMATTER = NumberFormat
} .getIntegerInstance(Locale.ENGLISH);
private static final Temporal ZERO = LocalTime.parse("00:00:00");
/** Convert a {@link java.lang.String} into a {@link java.time.Duration} static {
* @param duration the {@link java.lang.String} DURATION_INDIVIDUAL_FORMATTER.setMinimumIntegerDigits(2);
* @return the {@link java.time.Duration} object }
*/
public static Duration parseDuration(String duration) {
LocalTime time = LocalTime.parse("00:" + duration, DURATION_FORMATTER);
return Duration.between(time, ZERO);
}
/** Format a {@link java.time.Duration} into a {@link java.lang.String} /** Hidden constructor for utility class */
* @param duration an object of type {@link java.time.Duration} private NetworkFormat() {
* @return a String that depicts the duration in format MM:SS // Tool class
*/ }
public static String formatDuration(Duration duration) {
return DURATION_INDIVIDUAL_FORMATTER.format(duration.toMinutes()) + ":"
+ DURATION_INDIVIDUAL_FORMATTER.format(duration.toSecondsPart());
}
/** Get a formatter for the numbers in a GPS coordinate pair /** Convert a {@link java.lang.String} into a {@link java.time.Duration}
* * @param duration the {@link java.lang.String}
* @return the {@link java.text.NumberFormat} formatter for numbers in a GPS coordinate pair */ * @return the {@link java.time.Duration} object
public static NumberFormat getGPSFormatter() { */
NumberFormat instance = NumberFormat.getNumberInstance(Locale.ENGLISH); public static Duration parseDuration(String duration) {
instance.setMaximumFractionDigits(GPS_PRECISION); LocalTime time = LocalTime.parse("00:" + duration, DURATION_FORMATTER);
return instance; return Duration.between(time, ZERO);
} }
/** Format a {@link java.time.Duration} into a {@link java.lang.String}
* @param duration an object of type {@link java.time.Duration}
* @return a String that depicts the duration in format MM:SS
*/
public static String formatDuration(Duration duration) {
return DURATION_INDIVIDUAL_FORMATTER.format(duration.toMinutes()) + ":"
+ DURATION_INDIVIDUAL_FORMATTER.format(duration.toSecondsPart());
}
/** Get a formatter for the numbers in a GPS coordinate pair
*
* @return the {@link java.text.NumberFormat} formatter for numbers in a GPS coordinate pair */
public static NumberFormat getGPSFormatter() {
NumberFormat instance = NumberFormat.getNumberInstance(Locale.ENGLISH);
instance.setMaximumFractionDigits(GPS_PRECISION);
return instance;
}
} }

View file

@ -14,42 +14,58 @@ import java.util.List;
* @author Emmanuel Bigeon * @author Emmanuel Bigeon
*/ */
public final class ScheduleFormat { public final class ScheduleFormat {
/** The amount of columns in the CSV file */
public static final int NUMBER_COLUMNS = 4;
/** The index of the line name in the schedule format */ /**
public static final int LINE_INDEX = 0; * The amount of columns in the CSV file
/** The index of the trip sequence in the schedule format */ */
public static final int TRIP_SEQUENCE_INDEX = 1; public static final int NUMBER_COLUMNS = 4;
/** The index of the terminus name in the schedule format */
public static final int TERMINUS_INDEX = 2;
/** The index of the time in the schedule format */
public static final int TIME_INDEX = 3;
/** Hidden constructor for tool class */ /**
private ScheduleFormat() { * The index of the line name in the schedule format
// Tool class */
} public static final int LINE_INDEX = 0;
/**
* The index of the trip sequence in the schedule format
*/
public static final int TRIP_SEQUENCE_INDEX = 1;
/**
* The index of the terminus name in the schedule format
*/
public static final int TERMINUS_INDEX = 2;
/**
* The index of the time in the schedule format
*/
public static final int TIME_INDEX = 3;
/** /**
* Read a trip sequence from its string representation * Hidden constructor for tool class
* */
* @param representation the representation private ScheduleFormat() {
* @return the sequence of branching // Tool class
*/ }
public static List<Integer> getTripSequence(String representation) {
List<Integer> l = new ArrayList<>(); /**
for(String s : representation.split(",")) * Read a trip sequence from its string representation
l.add(Integer.parseInt(s)); *
return l; * @param representation the representation
} * @return the sequence of branching
*/
public static List<Integer> getTripSequence(String representation) {
List<Integer> l = new ArrayList<>();
for (String s : representation.split(",")) {
l.add(Integer.parseInt(s));
}
return l;
}
/** Create a {@link java.time.format.DateTimeFormatter} object used to format Dates /**
* @return the formatter * Create a {@link java.time.format.DateTimeFormatter} object used to format Dates
*/ *
public static DateTimeFormatter getTimeFormatter() { * @return the formatter
return DateTimeFormatter.ofPattern("HH:mm").withResolverStyle(ResolverStyle.LENIENT); */
} public static DateTimeFormatter getTimeFormatter() {
return DateTimeFormatter.ofPattern("HH:mm").withResolverStyle(ResolverStyle.LENIENT);
}
} }

View file

@ -3,97 +3,100 @@ package fr.u_paris.gla.project.itinerary;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
public class Connection{ public class Connection {
// Destination of the connection between the two stops
private final Stop stop;
// The line used for this connection // Destination of the connection between the two stops
private final String lineName; private final Stop stop;
//Distance between the two stops // The line used for this connection
private final double distance; private final String lineName;
//Travel time between the two stops //Distance between the two stops
private final int time; private final double distance;
private final ArrayList<Integer> schedules; //Travel time between the two stops
private final int time;
private final int bifurcation; private final ArrayList<Integer> schedules;
public Connection(Stop stop, String lineName, double distance, int time, int bifurcation){ private final int bifurcation;
this.stop = stop;
this.lineName=lineName; public Connection(Stop stop, String lineName, double distance, int time, int bifurcation) {
this.distance = distance; this.stop = stop;
this.time = time; this.lineName = lineName;
this.schedules = new ArrayList<>(); this.distance = distance;
this.bifurcation = bifurcation; this.time = time;
this.schedules = new ArrayList<>();
this.bifurcation = bifurcation;
}
public Connection(Stop stop, String lineName, double distance, int time) {
this(stop, lineName, distance, time, 0);
}
public String getLineName() {
return lineName;
}
public double getDistance() {
return distance;
}
public int getTime() {
return time;
}
public Stop getStop() {
return stop;
}
public void addSchedule(int hours) {
this.schedules.add(hours);
}
public void sortSchedule() {
Collections.sort(this.schedules);
}
public ArrayList<Integer> getSchedules() {
return this.schedules;
}
public int getBifurcation() {
return this.bifurcation;
}
public double getCost() {
return this.time;
}
public double getNextTime(double currentTime) {
if (this.schedules.size() == 0) {
return currentTime;
} }
public Connection(Stop stop, String lineName, double distance, int time){ int i = 0;
this(stop, lineName, distance, time, 0); while (i < this.schedules.size() && this.schedules.get(i) < currentTime) {
i++;
} }
if (i < this.schedules.size()) {
return this.schedules.get(i);
public String getLineName() {
return lineName;
} }
return this.schedules.get(0);
}
public double getDistance() { public double getCost(double currentTime) {
return distance; if (this.schedules.size() == 0) {
} if (this.lineName.equals("WALK")) {
public int getTime() {
return time;
}
public Stop getStop() {
return stop;
}
public void addSchedule(int hours) {
this.schedules.add(hours);
}
public void sortSchedule() {
Collections.sort(this.schedules);
}
public ArrayList<Integer> getSchedules() {
return this.schedules;
}
public int getBifurcation() {
return this.bifurcation;
}
public double getCost() {
return this.time; return this.time;
}
return this.time + 900;
} }
double nextTime = this.getNextTime(currentTime);
public double getNextTime(double currentTime) { if (nextTime < currentTime) {
if(this.schedules.size() == 0) { nextTime += 86400;
return currentTime;
}
int i = 0;
while(i < this.schedules.size() && this.schedules.get(i) < currentTime) {
i++;
}
if(i < this.schedules.size()) {
return this.schedules.get(i);
}
return this.schedules.get(0);
}
public double getCost(double currentTime) {
if(this.schedules.size() == 0) {
if(this.lineName.equals("WALK")) {
return this.time;
}
return this.time + 900;
}
double nextTime = this.getNextTime(currentTime);
if(nextTime < currentTime) { nextTime += 86400;}
return nextTime - currentTime + this.time;
} }
return nextTime - currentTime + this.time;
}
} }

View file

@ -1,116 +1,125 @@
package fr.u_paris.gla.project.itinerary; package fr.u_paris.gla.project.itinerary;
import java.util.*; import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.PriorityQueue;
public class Finder { public class Finder {
private Graph graph; private final Graph graph;
public Finder(Graph graph) {
this.graph = graph; public Finder(Graph graph) {
this.graph = graph;
}
/**
* return a path from startNode to goalNode using A* algorithm
*
* @param startNode
* @param goalNode
*/
public List<Path> findPath(Stop startNode, Stop goalNode, double startTime) {
PriorityQueue<Stop> openSet = new PriorityQueue<>(Comparator.comparingDouble(GraphNode::getF));
HashSet<Stop> closedSet = new HashSet<>();
HashMap<Stop, Path> cameFrom = new HashMap<>();
HashMap<Stop, Double> gScore = new HashMap<>();
HashMap<Stop, Double> fScore = new HashMap<>();
// Initialize scores for all nodes to infinity
for (Stop node : graph.getNodes()) {
gScore.put(node, Double.POSITIVE_INFINITY);
fScore.put(node, Double.POSITIVE_INFINITY);
} }
/** // The cost of going from start to start is the start time
* return a path from startNode to goalNode using A* algorithm gScore.put(startNode, startTime);
* @param startNode // For the first node, fScore = gScore + heuristic
* @param goalNode fScore.put(startNode, startNode.getHeuristicCost(goalNode));
*/ openSet.add(startNode);
public List<Path> findPath(Stop startNode, Stop goalNode, double startTime) {
PriorityQueue<Stop> openSet = new PriorityQueue<>(Comparator.comparingDouble(GraphNode::getF)); while (!openSet.isEmpty()) {
HashSet<Stop> closedSet = new HashSet<>(); Stop current = openSet.poll();
HashMap<Stop, Path> cameFrom = new HashMap<>(); double currentTime = gScore.get(current);
HashMap<Stop, Double> gScore = new HashMap<>();
HashMap<Stop, Double> fScore = new HashMap<>();
// Initialize scores for all nodes to infinity if (current.equals(goalNode)) {
for (Stop node : graph.getNodes()) { return reconstructPath(cameFrom, current);
gScore.put(node, Double.POSITIVE_INFINITY); }
fScore.put(node, Double.POSITIVE_INFINITY);
closedSet.add(current);
if (graph.getConnections(current) == null) {
continue;
}
for (Connection connection : graph.getConnections(current)) {
Stop neighbor = connection.getStop();
if (closedSet.contains(neighbor)) {
continue; // Ignore the neighbor which is already evaluated.
} }
// The cost of going from start to start is the start time double tentativeGScore = currentTime + connection.getCost(currentTime);
gScore.put(startNode, startTime);
// For the first node, fScore = gScore + heuristic
fScore.put(startNode, startNode.getHeuristicCost(goalNode));
openSet.add(startNode);
while (!openSet.isEmpty()) { if (tentativeGScore >= gScore.get(neighbor)) {
Stop current = openSet.poll(); continue; // This is not a better path.
double currentTime = gScore.get(current);
if (current.equals(goalNode)) {
return reconstructPath(cameFrom, current);
}
closedSet.add(current);
if(graph.getConnections(current) == null) {
continue;
}
for (Connection connection : graph.getConnections(current)) {
Stop neighbor = connection.getStop();
if (closedSet.contains(neighbor)) {
continue; // Ignore the neighbor which is already evaluated.
}
double tentativeGScore = currentTime + connection.getCost(currentTime);
if (tentativeGScore >= gScore.get(neighbor)) {
continue; // This is not a better path.
}
// This path is the best until now. Record it!
cameFrom.put(neighbor, new Path(current, connection, currentTime));
gScore.put(neighbor, tentativeGScore);
fScore.put(neighbor, tentativeGScore + neighbor.getHeuristicCost(goalNode));
if (!openSet.contains(neighbor)) {
neighbor.setF(fScore.get(neighbor));
openSet.add(neighbor);
}
else {
updatePriority(openSet, neighbor, fScore.get(neighbor));
}
}
} }
// If we reach here, it means there's no path from start to goal // This path is the best until now. Record it!
return null; cameFrom.put(neighbor, new Path(current, connection, currentTime));
} gScore.put(neighbor, tentativeGScore);
fScore.put(neighbor, tentativeGScore + neighbor.getHeuristicCost(goalNode));
/** if (!openSet.contains(neighbor)) {
* Once we found the destination we reconstruct the path neighbor.setF(fScore.get(neighbor));
* @param cameFrom openSet.add(neighbor);
* @param current } else {
* @return path updatePriority(openSet, neighbor, fScore.get(neighbor));
*/
private List<Path> reconstructPath(HashMap<Stop, Path> cameFrom, Stop current) {
List<Path> totalPath = new ArrayList<>();
totalPath.add(cameFrom.get(current));
while (cameFrom.containsKey(current)) {
current = cameFrom.get(current).getCurrentStop();
if(cameFrom.get(current) != null) {
totalPath.add(0, cameFrom.get(current)); // Add to the beginning of the list to maintain order
}
} }
}
return totalPath;
} }
/** // If we reach here, it means there's no path from start to goal
* Update the priority queue return null;
* @param openSet }
* @param node
* @param newF /**
*/ * Once we found the destination we reconstruct the path
public void updatePriority(PriorityQueue<Stop> openSet, Stop node, double newF) { *
openSet.remove(node); * @param cameFrom
node.setF(newF); * @param current
openSet.add(node); * @return path
*/
private List<Path> reconstructPath(HashMap<Stop, Path> cameFrom, Stop current) {
List<Path> totalPath = new ArrayList<>();
totalPath.add(cameFrom.get(current));
while (cameFrom.containsKey(current)) {
current = cameFrom.get(current).getCurrentStop();
if (cameFrom.get(current) != null) {
totalPath.add(0,
cameFrom.get(current)); // Add to the beginning of the list to maintain order
}
} }
return totalPath;
}
/**
* Update the priority queue
*
* @param openSet
* @param node
* @param newF
*/
public void updatePriority(PriorityQueue<Stop> openSet, Stop node, double newF) {
openSet.remove(node);
node.setF(newF);
openSet.add(node);
}
} }

View file

@ -1,28 +1,28 @@
package fr.u_paris.gla.project.itinerary; package fr.u_paris.gla.project.itinerary;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
public class Graph{ public class Graph {
private final Set<Stop> nodes;
private final Map<Stop, Set<Connection>> connections; private final Set<Stop> nodes;
public Graph(Set<Stop> nodes, Map<Stop, Set<Connection>> connections) { private final Map<Stop, Set<Connection>> connections;
this.nodes = nodes;
this.connections = connections;
}
public Set<Connection> getConnections(Stop node) { public Graph(Set<Stop> nodes, Map<Stop, Set<Connection>> connections) {
return connections.get(node); this.nodes = nodes;
} this.connections = connections;
}
public Set<Stop> getNodes() { public Set<Connection> getConnections(Stop node) {
return nodes; return connections.get(node);
} }
public Map<Stop, Set<Connection>> getConnections() { public Set<Stop> getNodes() {
return connections; return nodes;
} }
public Map<Stop, Set<Connection>> getConnections() {
return connections;
}
} }

View file

@ -1,14 +1,18 @@
package fr.u_paris.gla.project.itinerary; package fr.u_paris.gla.project.itinerary;
import java.util.List;
import java.util.Set; import java.util.Set;
public interface GraphNode { public interface GraphNode {
int getId();
double getHeuristicCost(Stop goalNode);
Set<Stop> getNeighbors(); int getId();
double getCost(Stop neighbor);
double getF(); double getHeuristicCost(Stop goalNode);
void setF(double value);
Set<Stop> getNeighbors();
double getCost(Stop neighbor);
double getF();
void setF(double value);
} }

View file

@ -1,241 +1,266 @@
package fr.u_paris.gla.project.itinerary; package fr.u_paris.gla.project.itinerary;
import fr.u_paris.gla.project.idfm.*; import fr.u_paris.gla.project.idfm.IDFMNetworkExtractor;
import fr.u_paris.gla.project.utils.CSVTools; import fr.u_paris.gla.project.utils.CSVTools;
import fr.u_paris.gla.project.utils.GPS; import fr.u_paris.gla.project.utils.GPS;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
public class Parse { public class Parse {
private static final Logger LOGGER = Logger
.getLogger(IDFMNetworkExtractor.class.getName());
// IDF mobilite generated file private static final Logger LOGGER = Logger
private static final String TRACE_FILE_NAME = "./trace.csv"; .getLogger(IDFMNetworkExtractor.class.getName());
private static final String HOURS_FILE_NAME = "./hours.csv"; // IDF mobilite generated file
private static final String TRACE_FILE_NAME = "./trace.csv";
// IDF mobilite file format private static final String HOURS_FILE_NAME = "./hours.csv";
private static final int IDFM_TRACE_ID_INDEX = 0; // IDF mobilite file format
private static final int IDFM_TRACE_DERIV_INDEX = 1; private static final int IDFM_TRACE_ID_INDEX = 0;
private static final int IDFM_TRACE_FROM_INDEX = 2; private static final int IDFM_TRACE_DERIV_INDEX = 1;
private static final int IDFM_TRACE_FROM_GPS_INDEX = 3; private static final int IDFM_TRACE_FROM_INDEX = 2;
private static final int IDFM_TRACE_TO_INDEX= 4; private static final int IDFM_TRACE_FROM_GPS_INDEX = 3;
private static final int IDFM_TRACE_TO_GPS_INDEX = 5; private static final int IDFM_TRACE_TO_INDEX = 4;
private static final int IDFM_TRACE_TIME_INDEX = 6; private static final int IDFM_TRACE_TO_GPS_INDEX = 5;
private static final int IDFM_TRACE_DISTANCE_INDEX = 7; private static final int IDFM_TRACE_TIME_INDEX = 6;
private static final double ERROR_MARGIN = 1.; private static final int IDFM_TRACE_DISTANCE_INDEX = 7;
//The time public vehicles spend at each stop in seconds. private static final double ERROR_MARGIN = 1.;
private static final int STOP_TIME = 30;
//Walking speed in m/s //The time public vehicles spend at each stop in seconds.
private static final double WALK_SPEED = 1.; private static final int STOP_TIME = 30;
private HashSet<Stop> nodes = new HashSet<>(); //Walking speed in m/s
private HashMap<Stop, Set<Connection>> connections = new HashMap<>(); private static final double WALK_SPEED = 1.;
private HashMap<String, ArrayList<Stop>> tmp = new HashMap<>();
/** private final HashSet<Stop> nodes = new HashSet<>();
* Returns the coordinates from a String to a double array: private final HashMap<Stop, Set<Connection>> connections = new HashMap<>();
* "49.08, 3.07" -> {49.08, 3.07} private final HashMap<String, ArrayList<Stop>> tmp = new HashMap<>();
* @param gps the string representation
* @return the double array /**
*/ * Returns the coordinates from a String to a double array: "49.08, 3.07" -> {49.08, 3.07}
private static double[] getCoords(String gps) { *
String []stringCoords = gps.split(", "); * @param gps the string representation
return new double[] {Double.parseDouble(stringCoords[0]), Double.parseDouble(stringCoords[1])}; * @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<Stop> nodes, HashMap<String, ArrayList<Stop>> tmp,
String name, String gps, String lineId, HashMap<Stop, Set<Connection>> connections) {
ArrayList<Stop> stopList = tmp.get(name);
double[] coords = getCoords(gps);
// 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
ArrayList<Stop> lineChanges = new ArrayList<>();
if (stopList != null) {
for (Stop stop : stopList) {
double dist = GPS.distance(coords[0], coords[1], stop.getLatitude(), stop.getLongitude());
if (dist == 0) {
stop.addLine(lineId);
return stop;
}
if (dist < ERROR_MARGIN) {
lineChanges.add(stop);
}
}
} }
/** Stop newStop = new Stop(lineId, name, coords[0], coords[1]);
* Searchs for a stop with the same name and GPS coordinates in the graph, and creates it if non existant nodes.add(newStop);
* @param nodes a graph of the stops stopList = stopList == null ? new ArrayList<>() : stopList;
* @param tmp list of the created stops stopList.add(newStop);
* @param name the name of the stop tmp.put(name, stopList);
* @param gps the coordinate of the stop for (Stop s : lineChanges) {
* @param lineId the line the stop is on double dist = GPS.distance(coords[0], coords[1], s.getLatitude(), s.getLongitude());
* @return the Stop object int time = (int) (dist * 1000 / WALK_SPEED);
*/ Connection c1 = new Connection(s, "WALK", dist, time);
private static Stop getOrCreateStop(HashSet<Stop> nodes, HashMap<String, ArrayList<Stop>> tmp, String name, String gps, String lineId, HashMap<Stop, Set<Connection>> connections) { connections.computeIfAbsent(newStop, k -> new HashSet<>()).add(c1);
ArrayList<Stop> stopList = tmp.get(name);
double[] coords = getCoords(gps);
// 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 Connection c2 = new Connection(newStop, "WALK", dist, time);
ArrayList<Stop> lineChanges = new ArrayList<>(); connections.computeIfAbsent(s, k -> new HashSet<>()).add(c2);
if (stopList != null) { }
for(Stop stop : stopList) { return newStop;
}
double dist = GPS.distance(coords[0], coords[1], stop.getLatitude(), stop.getLongitude()); /**
if(dist == 0) { * Adds into the graph the connection between two stops, parsed from a CSV line
stop.addLine(lineId); *
return stop; * @param line the current line we want to parse
} * @param nodes the graph of stops
if(dist < ERROR_MARGIN) { * @param tmp list of the created stops
lineChanges.add(stop); * @param connections
} */
} private static void addLine(String[] line, HashSet<Stop> nodes,
} HashMap<String, ArrayList<Stop>> tmp, HashMap<Stop, Set<Connection>> connections) {
Stop fromStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_FROM_INDEX],
line[IDFM_TRACE_FROM_GPS_INDEX], line[IDFM_TRACE_ID_INDEX], connections);
Stop toStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_TO_INDEX],
line[IDFM_TRACE_TO_GPS_INDEX], line[IDFM_TRACE_ID_INDEX], connections);
Stop newStop = new Stop(lineId, name, coords[0], coords[1]); String[] timeString = line[IDFM_TRACE_TIME_INDEX].split(":");
nodes.add(newStop); String time0WithoutComma = timeString[0].replace(",", "");
stopList = stopList == null ? new ArrayList<>() : stopList; int time = Integer.parseInt(time0WithoutComma) * 60 + Integer.parseInt(timeString[1]);
stopList.add(newStop);
tmp.put(name, stopList);
for(Stop s : lineChanges) {
double dist = GPS.distance(coords[0], coords[1], s.getLatitude(), s.getLongitude());
int time = (int) (dist*1000/WALK_SPEED);
Connection c1 = new Connection(s, "WALK", dist, time);
connections.computeIfAbsent(newStop, k -> new HashSet<>()).add(c1);
Connection c2 = new Connection(newStop, "WALK", dist, time); Connection connection = new Connection(toStop, line[IDFM_TRACE_ID_INDEX],
connections.computeIfAbsent(s, k -> new HashSet<>()).add(c2); Double.parseDouble(line[IDFM_TRACE_DISTANCE_INDEX]), time,
} Integer.parseInt(line[IDFM_TRACE_DERIV_INDEX]));
return newStop;
connections.computeIfAbsent(fromStop, k -> new HashSet<>()).add(connection);
}
private static void addScheduleRec(Stop current, Stop previous, String line,
ArrayList<Integer> bifurcations, int time, HashMap<String, ArrayList<Stop>> stopsHashSet,
HashMap<Stop, Set<Connection>> connections, HashSet<Stop> processed) {
time = time % 86400;
//If the stop has already been processed, it is not reprocessed.
if (processed.contains(current)) {
return;
}
processed.add(current);
Set<Connection> neighborhood = connections.get(current);
if (neighborhood == null) {
return;
} }
/** ArrayList<Connection> directions = new ArrayList<>();
* Adds into the graph the connection between two stops, parsed from a CSV line for (Connection n : neighborhood) {
* @param line the current line we want to parse if (n.getLineName().equals(line)
* @param nodes the graph of stops && (previous == null || !n.getStop().getName().equals(previous.getName()))
* @param tmp list of the created stops ) {
* @param connections directions.add(n);
*/ }
private static void addLine(String[] line, HashSet<Stop> nodes, HashMap<String, ArrayList<Stop>> tmp, HashMap<Stop, Set<Connection>> connections) {
Stop fromStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_FROM_INDEX], line[IDFM_TRACE_FROM_GPS_INDEX], line[IDFM_TRACE_ID_INDEX], connections);
Stop toStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_TO_INDEX], line[IDFM_TRACE_TO_GPS_INDEX], line[IDFM_TRACE_ID_INDEX], connections);
String[] timeString = line[IDFM_TRACE_TIME_INDEX].split(":");
String time0WithoutComma = timeString[0].replace(",", "");
int time = Integer.parseInt(time0WithoutComma) * 60 + Integer.parseInt(timeString[1]);
Connection connection = new Connection(toStop, line[IDFM_TRACE_ID_INDEX], Double.parseDouble(line[IDFM_TRACE_DISTANCE_INDEX]), time, Integer.parseInt(line[IDFM_TRACE_DERIV_INDEX]));
connections.computeIfAbsent(fromStop, k -> new HashSet<>()).add(connection);
} }
private static void addScheduleRec(Stop current, Stop previous, String line, ArrayList<Integer> bifurcations, int time, HashMap<String, ArrayList<Stop>> stopsHashSet, HashMap<Stop, Set<Connection>> connections, HashSet<Stop> processed){ if (directions.size() == 0) {
time = time%86400; return;
//If the stop has already been processed, it is not reprocessed.
if(processed.contains(current)) {return;}
processed.add(current);
Set<Connection> neighborhood = connections.get(current);
if(neighborhood == null) {return;}
ArrayList<Connection> directions = new ArrayList<>();
for(Connection n : neighborhood) {
if(n.getLineName().equals(line)
&& (previous == null || !n.getStop().getName().equals(previous.getName()))
) {
directions.add(n);
}
}
if(directions.size() == 0) {return;}
Stop next_stop = null;
if(directions.size() > 1) {
int bifurcation = bifurcations.size() == 0 ? 0 : bifurcations.get(0);
if(bifurcations.size() > 0) {bifurcations.remove(0);}
for(Connection d : directions) {
if(d.getBifurcation() == bifurcation) {
next_stop = d.getStop();
break;
}
}
if(next_stop == null) {
return;
}
}
else {
next_stop = directions.get(0).getStop();
if(directions.get(0).getBifurcation() != 0) {
if(bifurcations.size() > 0 && directions.get(0).getBifurcation() == bifurcations.get(0)){
bifurcations.remove(0);
}
}
}
for(Connection n : directions) {
if(n.getStop() == next_stop) {
n.addSchedule(time);
time += n.getTime() + STOP_TIME;
addScheduleRec(next_stop, current, line, bifurcations, time, stopsHashSet, connections, processed);
return;
}
}
} }
private static void addSchedule(String[] input, HashMap<String, ArrayList<Stop>> stopsHashSet, HashMap<Stop, Set<Connection>> connections) { Stop next_stop = null;
if (directions.size() > 1) {
String line = input[0]; int bifurcation = bifurcations.size() == 0 ? 0 : bifurcations.get(0);
if (bifurcations.size() > 0) {
ArrayList<Integer> bifurcations = new ArrayList<>(); bifurcations.remove(0);
if(!input[1].equals("[]")) { }
String[] b = input[1].substring(1, input[1].length()-1).split(","); for (Connection d : directions) {
bifurcations = new ArrayList<>(); if (d.getBifurcation() == bifurcation) {
for(String n : b){ next_stop = d.getStop();
bifurcations.add(Integer.parseInt(n.trim())); break;
}
} }
}
String name = input[2]; if (next_stop == null) {
return;
String[] timeString = input[3].split(":"); }
int time = Integer.parseInt(timeString[0]) * 3600 + Integer.parseInt(timeString[1])*60; } else {
next_stop = directions.get(0).getStop();
if (directions.get(0).getBifurcation() != 0) {
ArrayList<Stop> stops = stopsHashSet.get(name); if (bifurcations.size() > 0 && directions.get(0).getBifurcation() == bifurcations.get(0)) {
if(stops == null) {return;} bifurcations.remove(0);
for(Stop stop : stops) {
if(stop.getLines().contains(line)) {
addScheduleRec(stop, null, line, bifurcations, time, stopsHashSet, connections, new HashSet<>());
}
} }
}
} }
public void parseFiles(){ for (Connection n : directions) {
if (n.getStop() == next_stop) {
n.addSchedule(time);
time += n.getTime() + STOP_TIME;
addScheduleRec(next_stop, current, line, bifurcations, time, stopsHashSet, connections,
processed);
return;
}
}
}
IDFMNetworkExtractor.buildFiles(); private static void addSchedule(String[] input, HashMap<String, ArrayList<Stop>> stopsHashSet,
HashMap<Stop, Set<Connection>> connections) {
try { String line = input[0];
CSVTools.readCSVFromFile(TRACE_FILE_NAME, ArrayList<Integer> bifurcations = new ArrayList<>();
(String[] line) -> addLine(line, nodes, tmp, connections)); if (!input[1].equals("[]")) {
String[] b = input[1].substring(1, input[1].length() - 1).split(",");
bifurcations = new ArrayList<>();
for (String n : b) {
bifurcations.add(Integer.parseInt(n.trim()));
}
}
CSVTools.readCSVFromFile(HOURS_FILE_NAME, String name = input[2];
(String[] line) -> addSchedule(line, tmp, connections));
for(Set<Connection> set : connections.values()) { String[] timeString = input[3].split(":");
for(Connection c : set) { int time = Integer.parseInt(timeString[0]) * 3600 + Integer.parseInt(timeString[1]) * 60;
c.sortSchedule();
}
}
} catch (IOException e) { ArrayList<Stop> stops = stopsHashSet.get(name);
LOGGER.log(Level.SEVERE, "Error while reading the line paths", e); if (stops == null) {
return;
}
for (Stop stop : stops) {
if (stop.getLines().contains(line)) {
addScheduleRec(stop, null, line, bifurcations, time, stopsHashSet, connections,
new HashSet<>());
}
}
}
public void parseFiles() {
IDFMNetworkExtractor.buildFiles();
try {
CSVTools.readCSVFromFile(TRACE_FILE_NAME,
(String[] line) -> addLine(line, nodes, tmp, connections));
CSVTools.readCSVFromFile(HOURS_FILE_NAME,
(String[] line) -> addSchedule(line, tmp, connections));
for (Set<Connection> set : connections.values()) {
for (Connection c : set) {
c.sortSchedule();
} }
}
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Error while reading the line paths", e);
} }
public List<Path> getItinerary(Stop src, Stop dst, double startTime ){ }
Graph graph = new Graph(nodes, connections);
Finder finder = new Finder(graph);
return finder.findPath(src, dst, startTime);
} public List<Path> getItinerary(Stop src, Stop dst, double startTime) {
Graph graph = new Graph(nodes, connections);
Finder finder = new Finder(graph);
return finder.findPath(src, dst, startTime);
}
} }

View file

@ -1,50 +1,48 @@
package fr.u_paris.gla.project.itinerary; package fr.u_paris.gla.project.itinerary;
public class Path { public class Path {
private Stop current;
private Stop next; private final Stop current;
private double startTime; private final Stop next;
private double travelTime; private final double startTime;
private double distance; private final double travelTime;
private final String line;
private final Connection connection;
private double distance;
private String line; public Path(Stop current, Connection connection, double startTime) {
this.current = current;
this.connection = connection;
this.next = connection.getStop();
this.startTime = startTime;
this.travelTime = connection.getTime();
this.line = connection.getLineName();
}
private Connection connection; public Connection getConnection() {
return this.connection;
}
public Path(Stop current, Connection connection, double startTime) { public Stop getCurrentStop() {
this.current = current; return this.current;
this.connection = connection; }
this.next = connection.getStop();
this.startTime = startTime;
this.travelTime = connection.getTime();
this.line = connection.getLineName();
}
public Connection getConnection(){ public Stop getNextStop() {
return this.connection; return next;
} }
public Stop getCurrentStop() { public double getStartTime() {
return this.current; return this.startTime;
} }
public Stop getNextStop() { public double travelTime() {
return next; return this.travelTime;
} }
public double getStartTime() { public String getLine() {
return this.startTime; return this.line;
} }
public double travelTime() {
return this.travelTime;
}
public String getLine() {
return this.line;
}
} }

View file

@ -4,87 +4,90 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
public class Stop implements GraphNode { public class Stop implements GraphNode {
// The total number of stops
private static int counter = 0;
private final int id; // The total number of stops
private static int counter = 0;
// The set of all the lines the stop is on private final int id;
private final Set<String> lines;
private final String name; // The set of all the lines the stop is on
private final Set<String> lines;
private final double latitude; private final String name;
private final double longitude; private final double latitude;
private double f; private final double longitude;
public Stop(String line, String name, double latitude, double longitude) { private double f;
lines = new HashSet<>();
lines.add(line);
this.id = counter++;
this.name = name;
this.latitude = latitude;
this.longitude = longitude;
this.f = 0;
}
@Override public Stop(String line, String name, double latitude, double longitude) {
public String toString() { lines = new HashSet<>();
return "Stop{" + lines.add(line);
"id=" + id + this.id = counter++;
", lines=" + lines + this.name = name;
", name='" + name + '\'' + this.latitude = latitude;
", latitude=" + latitude + this.longitude = longitude;
", longitude=" + longitude + this.f = 0;
'}'; }
}
@Override @Override
public int getId(){ public String toString() {
return id; return "Stop{" +
} "id=" + id +
", lines=" + lines +
", name='" + name + '\'' +
", latitude=" + latitude +
", longitude=" + longitude +
'}';
}
@Override @Override
public double getHeuristicCost(Stop goalNode) { public int getId() {
return 0; return id;
} }
@Override @Override
public Set<Stop> getNeighbors() { public double getHeuristicCost(Stop goalNode) {
return null; return 0;
} }
@Override @Override
public double getCost(Stop neighbor) { public Set<Stop> getNeighbors() {
return 0; return null;
} }
@Override @Override
public double getF() { public double getCost(Stop neighbor) {
return f; return 0;
} }
public void setF(double value) { @Override
this.f = value; public double getF() {
} return f;
}
public String getName(){ public void setF(double value) {
return name; this.f = value;
} }
public double getLatitude(){ public String getName() {
return latitude; return name;
} }
public double getLongitude(){ public double getLatitude() {
return longitude; return latitude;
} }
public void addLine(String s){ public double getLongitude() {
lines.add(s); return longitude;
} }
public Set<String> getLines() { return this.lines; } public void addLine(String s) {
lines.add(s);
}
public Set<String> getLines() {
return this.lines;
}
} }

View file

@ -1,54 +1,58 @@
package fr.u_paris.gla.project.utils; package fr.u_paris.gla.project.utils;
import fr.u_paris.gla.project.idfm.IDFMNetworkExtractor; import fr.u_paris.gla.project.idfm.IDFMNetworkExtractor;
import org.json.JSONArray; import java.io.BufferedReader;
import org.json.JSONObject; import java.io.IOException;
import java.io.InputStreamReader;
import java.io.*;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.json.JSONArray;
import org.json.JSONObject;
public class ApiUtils { public class ApiUtils {
/** The logger for information on the process */
private static final Logger LOGGER = Logger
.getLogger(IDFMNetworkExtractor.class.getName());
// OpenStreetMap API URL /**
private static final String OSM_URL = "https://nominatim.openstreetmap.org/search"; * The logger for information on the process
*/
private static final Logger LOGGER = Logger
.getLogger(IDFMNetworkExtractor.class.getName());
public static double[] getGPSLocation(String term) { // OpenStreetMap API URL
try { private static final String OSM_URL = "https://nominatim.openstreetmap.org/search";
String urlString = String.format("%s?q=%s&format=json", OSM_URL, URLEncoder.encode(term, StandardCharsets.UTF_8));
HttpURLConnection connection = (HttpURLConnection) new URL(urlString).openConnection();
connection.setRequestMethod("GET"); public static double[] getGPSLocation(String term) {
try {
String urlString = String.format("%s?q=%s&format=json", OSM_URL,
URLEncoder.encode(term, StandardCharsets.UTF_8));
HttpURLConnection connection = (HttpURLConnection) new URL(urlString).openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); connection.setRequestMethod("GET");
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) { BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
response.append(inputLine); String inputLine;
} StringBuilder response = new StringBuilder();
JSONArray jsonArray = new JSONArray(response.toString()); while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
if (!jsonArray.isEmpty()) { JSONArray jsonArray = new JSONArray(response.toString());
JSONObject firstResult = jsonArray.getJSONObject(0);
double lat = firstResult.getDouble("lat"); if (!jsonArray.isEmpty()) {
double lon = firstResult.getDouble("lon"); JSONObject firstResult = jsonArray.getJSONObject(0);
return new double[]{lat, lon};
} double lat = firstResult.getDouble("lat");
} double lon = firstResult.getDouble("lon");
catch (IOException e) { return new double[]{lat, lon};
LOGGER.log(Level.SEVERE, e, }
() -> "Error accessing the API"); } catch (IOException e) {
} LOGGER.log(Level.SEVERE, e,
return new double[]{0, 0}; () -> "Error accessing the API");
} }
return new double[]{0, 0};
}
} }

View file

@ -3,13 +3,6 @@
*/ */
package fr.u_paris.gla.project.utils; package fr.u_paris.gla.project.utils;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.function.Consumer;
import java.util.stream.Stream;
import com.opencsv.CSVParserBuilder; import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReader; import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder; import com.opencsv.CSVReaderBuilder;
@ -17,91 +10,115 @@ import com.opencsv.CSVWriterBuilder;
import com.opencsv.ICSVParser; import com.opencsv.ICSVParser;
import com.opencsv.ICSVWriter; import com.opencsv.ICSVWriter;
import com.opencsv.exceptions.CsvValidationException; import com.opencsv.exceptions.CsvValidationException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
import java.util.stream.Stream;
/** A CSV tool class. /**
* A CSV tool class.
* *
* @author Emmanuel Bigeon */ * @author Emmanuel Bigeon
*/
public final class CSVTools { public final class CSVTools {
/** Hidden constructor of tool class */ /**
private CSVTools() { * Hidden constructor of tool class
// Tool class */
} private CSVTools() {
// Tool class
}
/** get a CSV file from a URL, download and parse it, and keep values in memory /**
* @param is the address of the CSV file * get a CSV file from a URL, download and parse it, and keep values in memory
* @param contentLineConsumer the variable used to store the data *
* @throws IOException if it's impossible to download the file * @param is the address of the CSV file
*/ * @param contentLineConsumer the variable used to store the data
private static void readCSVFromInputStream(InputStream is, Consumer<String[]> contentLineConsumer) * @throws IOException if it's impossible to download the file
throws IOException { */
ICSVParser parser = new CSVParserBuilder().withSeparator(';').build(); private static void readCSVFromInputStream(InputStream is, Consumer<String[]> contentLineConsumer)
try (Reader reader = new BufferedReader( throws IOException {
new InputStreamReader(is, StandardCharsets.UTF_8))) { ICSVParser parser = new CSVParserBuilder().withSeparator(';').build();
CSVReaderBuilder csvBuilder = new CSVReaderBuilder(reader) try (Reader reader = new BufferedReader(
.withCSVParser(parser); new InputStreamReader(is, StandardCharsets.UTF_8))) {
try (CSVReader csv = csvBuilder.build()) { CSVReaderBuilder csvBuilder = new CSVReaderBuilder(reader)
String[] line = csv.readNextSilently(); // Eliminate header .withCSVParser(parser);
while (csv.peek() != null) { try (CSVReader csv = csvBuilder.build()) {
line = csv.readNext(); String[] line = csv.readNextSilently(); // Eliminate header
contentLineConsumer.accept(line); while (csv.peek() != null) {
} line = csv.readNext();
} contentLineConsumer.accept(line);
} catch (CsvValidationException e) {
throw new IOException("Invalid csv file", e); //$NON-NLS-1$
} }
}
} catch (CsvValidationException e) {
throw new IOException("Invalid csv file", e); //$NON-NLS-1$
} }
}
/** get a CSV file from a file and parse it, keeping values in memory /**
* @param filename the saved file's name and path * get a CSV file from a file and parse it, keeping values in memory
* @param contentLineConsumer the variable used to store the data *
* @throws IOException if it's impossible to read the file * @param filename the saved file's name and path
*/ * @param contentLineConsumer the variable used to store the data
public static void readCSVFromFile(String filename, Consumer<String[]> contentLineConsumer) * @throws IOException if it's impossible to read the file
throws IOException { */
File file = new File(filename); public static void readCSVFromFile(String filename, Consumer<String[]> contentLineConsumer)
readCSVFromInputStream(new FileInputStream(file), contentLineConsumer); throws IOException {
File file = new File(filename);
readCSVFromInputStream(new FileInputStream(file), contentLineConsumer);
}
/**
* get a CSV file from a URL, download and parse it, and keep values in memory
*
* @param url the address of the CSV file
* @param contentLineConsumer the variable used to store the data
* @throws IOException if it's impossible to download the file
*/
public static void readCSVFromURL(String url, Consumer<String[]> contentLineConsumer)
throws IOException {
readCSVFromInputStream(new URL(url).openStream(), contentLineConsumer);
}
/**
* 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(csv::writeNext);
}
} }
}
/** get a CSV file from a URL, download and parse it, and keep values in memory // /** Save our current CSV variable's data into an actual file
* @param url the address of the CSV file // * @param filename the saved file's name and path
* @param contentLineConsumer the variable used to store the data // * @param contentLineConsumer our data variable
* @throws IOException if it's impossible to download the file // * @throws IOException if we can't write the data into the file
*/ // */
public static void readCSVFromURL(String url, Consumer<String[]> contentLineConsumer) // public static void writeCSVToFile(String filename,
throws IOException { // Stream<String[][]> contentLinesConsumer) throws IOException {
readCSVFromInputStream(new URL(url).openStream(), contentLineConsumer); // try (FileWriter writer = new FileWriter(filename, StandardCharsets.UTF_8)) {
} // CSVWriterBuilder wBuilder = new CSVWriterBuilder(writer).withSeparator(';');
// try (ICSVWriter csv = wBuilder.build()) {
/** Save our current CSV variable's data into an actual file // contentLinesConsumer.forEachOrdered(line -> Arrays.stream(line).forEach(csv::writeNext));
* @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(csv::writeNext);
}
}
}
// /** 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));
// }
// }
// }
} }

View file

@ -1,47 +1,47 @@
/** /**
* *
*/ */
package fr.u_paris.gla.project.utils; package fr.u_paris.gla.project.utils;
/** A utility class for computations related to GPS. /** A utility class for computations related to GPS.
* *
* @author Emmanuel Bigeon */ * @author Emmanuel Bigeon */
public final class GPS { public final class GPS {
/** The value of a flat angle, in degrees. */ /** The value of a flat angle, in degrees. */
private static final int FLAT_ANGLE_DEGREE = 180; private static final int FLAT_ANGLE_DEGREE = 180;
/** The (approximated) earth radius in km. */ /** The (approximated) earth radius in km. */
private static final double EARTH_RADIUS = 6_370.0; private static final double EARTH_RADIUS = 6_370.0;
/** Hidden constructor for tool class */ /** Hidden constructor for tool class */
private GPS() { private GPS() {
// Tool class // Tool class
} }
/** Convert a degree angle value in a radian angle one. /** Convert a degree angle value in a radian angle one.
* *
* @param degree the degree value * @param degree the degree value
* @return the radian value */ * @return the radian value */
private static double degreeToRadian(double degree) { private static double degreeToRadian(double degree) {
return degree / FLAT_ANGLE_DEGREE * Math.PI; return degree / FLAT_ANGLE_DEGREE * Math.PI;
} }
/** Compute the flying distance between two GPS positions. /** Compute the flying distance between two GPS positions.
* *
* @param latitude1 the latitude of the first position * @param latitude1 the latitude of the first position
* @param longitude1 the longitude of the first position * @param longitude1 the longitude of the first position
* @param latitude2 the latitude of the second position * @param latitude2 the latitude of the second position
* @param longitude2 the longitude of the second position * @param longitude2 the longitude of the second position
* @return the flying distance in km*/ * @return the flying distance in km*/
public static double distance(double latitude1, double longitude1, double latitude2, public static double distance(double latitude1, double longitude1, double latitude2,
double longitude2) { double longitude2) {
latitude1 = degreeToRadian(latitude1); latitude1 = degreeToRadian(latitude1);
latitude2 = degreeToRadian(latitude2); latitude2 = degreeToRadian(latitude2);
double deltaLatitude = latitude2 - latitude1; double deltaLatitude = latitude2 - latitude1;
double deltaLongitude = degreeToRadian(longitude2 - longitude1); double deltaLongitude = degreeToRadian(longitude2 - longitude1);
double a = Math.pow(Math.sin(deltaLatitude / 2), 2) double a = Math.pow(Math.sin(deltaLatitude / 2), 2)
+ Math.pow(Math.sin(deltaLongitude / 2), 2) * Math.cos(latitude1) + Math.pow(Math.sin(deltaLongitude / 2), 2) * Math.cos(latitude1)
* Math.cos(latitude2); * Math.cos(latitude2);
return 2 * EARTH_RADIUS * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return 2 * EARTH_RADIUS * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
} }
} }

View file

@ -4,11 +4,16 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** Unit test for simple App. */ /**
* Unit test for simple App.
*/
class AppTest { class AppTest {
/** Rigorous Test :-) */
@Test /**
public void testPlaceholder() { * Rigorous Test :-)
assertTrue(true, "It should be true that true is true..."); */
} @Test
public void testPlaceholder() {
assertTrue(true, "It should be true that true is true...");
}
} }

View file

@ -4,6 +4,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import fr.u_paris.gla.project.io.NetworkFormat;
import fr.u_paris.gla.project.utils.GPS;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.text.NumberFormat; import java.text.NumberFormat;
@ -12,111 +15,119 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import fr.u_paris.gla.project.io.NetworkFormat;
import fr.u_paris.gla.project.utils.GPS;
public class CSVStreamProviderTest { public class CSVStreamProviderTest {
//Test de hasNext, pour le cas ou il y'a un trace et cas ou il n'y en a pas //Test de hasNext, pour le cas ou il y'a un trace et cas ou il n'y en a pas
@Test @Test
public void testHasNext() { public void testHasNext() {
// Scénario sans Trace // Scénario sans Trace
CSVStreamProvider providerWithoutTrace = new CSVStreamProvider(Collections.emptyIterator(),null); CSVStreamProvider providerWithoutTrace = new CSVStreamProvider(Collections.emptyIterator(),
assertFalse(providerWithoutTrace.hasNext(), "hasNext should return false when no traces are provided"); null);
assertFalse(providerWithoutTrace.hasNext(),
"hasNext should return false when no traces are provided");
// Scénario avec Trace // Scénario avec Trace
StopEntry stop1 = new StopEntry("Stop1", 2.3522, 48.8566); StopEntry stop1 = new StopEntry("Stop1", 2.3522, 48.8566);
StopEntry stop2 = new StopEntry("Stop2", 2.295, 48.8738); StopEntry stop2 = new StopEntry("Stop2", 2.295, 48.8738);
List<StopEntry> path = Arrays.asList(stop1, stop2); List<StopEntry> path = Arrays.asList(stop1, stop2);
TraceEntry trace = new TraceEntry("Ligne1","IDFM:03434","Bus", "dummy_url"); TraceEntry trace = new TraceEntry("Ligne1", "IDFM:03434", "Bus", "dummy_url");
trace.addPath(path); trace.addPath(path);
CSVStreamProvider providerWithTrace = new CSVStreamProvider(Arrays.asList(trace).iterator(),null); CSVStreamProvider providerWithTrace = new CSVStreamProvider(List.of(trace).iterator(),
assertTrue(providerWithTrace.hasNext(), "hasNext should return true when traces are provided"); null);
} assertTrue(providerWithTrace.hasNext(), "hasNext should return true when traces are provided");
}
//Test de la methode next()
@Test
public void testNext() {
// Initialisation des données d'exemple directement dans le test
StopEntry start = new StopEntry("Début", 2.3522, 48.8566); // Paris
StopEntry end = new StopEntry("Fin", 2.295, 48.8738); // Proche de Paris
//Test de la methode next() TraceEntry traceEntry = new TraceEntry("Ligne1", "IDFM:03434", "Bus", "dummy_url");
@Test traceEntry.addPath(Arrays.asList(start, end)); // Ajout d'un chemin à la trace
public void testNext() {
// Initialisation des données d'exemple directement dans le test
StopEntry start = new StopEntry("Début", 2.3522, 48.8566); // Paris
StopEntry end = new StopEntry("Fin", 2.295, 48.8738); // Proche de Paris
TraceEntry traceEntry = new TraceEntry("Ligne1","IDFM:03434","Bus", "dummy_url");
traceEntry.addPath(Arrays.asList(start, end)); // Ajout d'un chemin à la trace
CSVStreamProvider provider = new CSVStreamProvider(Collections.singletonList(traceEntry).iterator(),null);
assertTrue(provider.hasNext(), "Doit avoir un prochain élément"); CSVStreamProvider provider = new CSVStreamProvider(
Collections.singletonList(traceEntry).iterator(), null);
String[] result = provider.next(); assertTrue(provider.hasNext(), "Doit avoir un prochain élément");
assertNotNull(result, "Le résultat ne doit pas être null");
// Vérifications spécifiques sur le format des données de sortie String[] result = provider.next();
assertEquals(start.lname, result[NetworkFormat.START_INDEX], "Le nom de l'arrêt de départ doit correspondre"); assertNotNull(result, "Le résultat ne doit pas être null");
assertEquals(end.lname, result[NetworkFormat.STOP_INDEX], "Le nom de l'arrêt d'arrivée doit correspondre");
// Calcul et vérification de la distance attendue // Vérifications spécifiques sur le format des données de sortie
double expectedDistance = GPS.distance(start.latitude, start.longitude, end.latitude, end.longitude); assertEquals(start.lname, result[NetworkFormat.START_INDEX],
String expectedDistanceFormatted = NumberFormat.getInstance(Locale.ENGLISH).format(expectedDistance); "Le nom de l'arrêt de départ doit correspondre");
assertEquals(expectedDistanceFormatted, result[NetworkFormat.DISTANCE_INDEX], "La distance doit correspondre"); assertEquals(end.lname, result[NetworkFormat.STOP_INDEX],
} "Le nom de l'arrêt d'arrivée doit correspondre");
// Calcul et vérification de la distance attendue
double expectedDistance = GPS.distance(start.latitude, start.longitude, end.latitude,
end.longitude);
String expectedDistanceFormatted = NumberFormat.getInstance(Locale.ENGLISH)
.format(expectedDistance);
assertEquals(expectedDistanceFormatted, result[NetworkFormat.DISTANCE_INDEX],
"La distance doit correspondre");
}
//Test de la methode private fillStation avec la réflexion
@Test
public void testFillStation() throws Exception {
// Initialisation des données de test
StopEntry stop = new StopEntry("StopName", 2.3522,
48.8566); // Exemple de coordonnées pour Paris
String[] nextLine = new String[NetworkFormat.NUMBER_COLUMNS];
//Test de la methode private fillStation avec la réflexion // Accès à la méthode fillStation via la réflexion
@Test Method fillStationMethod = CSVStreamProvider.class.getDeclaredMethod("fillStation",
public void testFillStation() throws Exception { StopEntry.class, String[].class, int.class);
// Initialisation des données de test fillStationMethod.setAccessible(true);
StopEntry stop = new StopEntry("StopName", 2.3522, 48.8566); // Exemple de coordonnées pour Paris
String[] nextLine = new String[NetworkFormat.NUMBER_COLUMNS];
// Accès à la méthode fillStation via la réflexion // Invocation de la méthode fillStation
Method fillStationMethod = CSVStreamProvider.class.getDeclaredMethod("fillStation", StopEntry.class, String[].class, int.class); fillStationMethod.invoke(null, stop, nextLine, NetworkFormat.START_INDEX);
fillStationMethod.setAccessible(true);
// Invocation de la méthode fillStation // Format attendu pour la latitude et la longitude
fillStationMethod.invoke(null, stop, nextLine, NetworkFormat.START_INDEX); NumberFormat gpsFormatter = NetworkFormat.getGPSFormatter();
String expectedLatitudeLongitude = MessageFormat.format("{0}, {1}",
gpsFormatter.format(stop.latitude),
gpsFormatter.format(stop.longitude));
// Format attendu pour la latitude et la longitude // Vérifications
NumberFormat gpsFormatter = NetworkFormat.getGPSFormatter(); assertEquals(stop.lname, nextLine[NetworkFormat.START_INDEX],
String expectedLatitudeLongitude = MessageFormat.format("{0}, {1}", "Le nom de l'arrêt doit correspondre.");
gpsFormatter.format(stop.latitude), assertEquals(expectedLatitudeLongitude, nextLine[NetworkFormat.START_INDEX + 1],
gpsFormatter.format(stop.longitude)); "Les coordonnées GPS doivent correspondre.");
}
// Vérifications
assertEquals(stop.lname, nextLine[NetworkFormat.START_INDEX], "Le nom de l'arrêt doit correspondre.");
assertEquals(expectedLatitudeLongitude, nextLine[NetworkFormat.START_INDEX + 1], "Les coordonnées GPS doivent correspondre.");
}
//Test de la méthode static private distanceToTime()
@Test
public void testDistanceToTime() throws Exception {
// Valeurs fictives pour TWO_ACCELERATION_DISTANCE et MAX_SPEED
final double TWO_ACCELERATION_DISTANCE = 0.2; // Par exemple
final double MAX_SPEED = 5.0; // Par exemple
// Exemple de distance à tester
double distanceExample = 1.0; // 1 km
//Test de la méthode static private distanceToTime() // Calcul attendu basé sur la formule fournie
@Test double expected = Math.max(0, distanceExample - TWO_ACCELERATION_DISTANCE) / MAX_SPEED
public void testDistanceToTime() throws Exception { + Math.pow(Math.min(distanceExample, TWO_ACCELERATION_DISTANCE) / MAX_SPEED, 2);
// Valeurs fictives pour TWO_ACCELERATION_DISTANCE et MAX_SPEED
final double TWO_ACCELERATION_DISTANCE = 0.2; // Par exemple // Accès à la méthode distanceToTime via la réflexion
final double MAX_SPEED = 5.0; // Par exemple Method method = CSVStreamProvider.class.getDeclaredMethod("distanceToTime", double.class);
method.setAccessible(true);
// Exemple de distance à tester
double distanceExample = 1.0; // 1 km // Invocation de la méthode distanceToTime et stockage du résultat
double result = (Double) method.invoke(null, distanceExample);
// Calcul attendu basé sur la formule fournie
double expected = Math.max(0, distanceExample - TWO_ACCELERATION_DISTANCE) / MAX_SPEED // Assertion pour vérifier si le résultat est conforme à l'attendu
+ Math.pow(Math.min(distanceExample, TWO_ACCELERATION_DISTANCE) / MAX_SPEED, 2); assertEquals(expected, result,
"Le calcul du temps à partir de la distance devrait être conforme à l'attendu.");
// Accès à la méthode distanceToTime via la réflexion }
Method method = CSVStreamProvider.class.getDeclaredMethod("distanceToTime", double.class);
method.setAccessible(true);
// Invocation de la méthode distanceToTime et stockage du résultat
double result = (Double) method.invoke(null, distanceExample);
// 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.");
}
} }

View file

@ -1,59 +1,67 @@
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test;
class IDFMNetworkExtractorTest { class IDFMNetworkExtractorTest {
//Test de clenLine de ma classe IDFMNetworkExtractor //Test de clenLine de ma classe IDFMNetworkExtractor
@Test @Test
public void testCleanLine() throws Exception { public void testCleanLine() throws Exception {
// Création d'un arrêt non identifié avec des coordonnées spécifiques // Création d'un arrêt non identifié avec des coordonnées spécifiques
UnidentifiedStopEntry unidentifiedStop = new UnidentifiedStopEntry(2.3522, 48.8566); // Coordonnées pour Paris UnidentifiedStopEntry unidentifiedStop = new UnidentifiedStopEntry(2.3522,
48.8566); // Coordonnées pour Paris
// Création d'un arrêt candidat proche de l'arrêt non identifié
StopEntry closeCandidate = new StopEntry("Proche Candidat", 2.3523, 48.8567); // Coordonnées proches de Paris // Création d'un arrêt candidat proche de l'arrêt non identifié
StopEntry closeCandidate = new StopEntry("Proche Candidat", 2.3523,
// Ajout du candidat à l'arrêt non identifié 48.8567); // Coordonnées proches de Paris
unidentifiedStop.addCandidate(closeCandidate);
// Ajout du candidat à l'arrêt non identifié
// Liste des chemins contenant l'arrêt non identifié unidentifiedStop.addCandidate(closeCandidate);
List<List<StopEntry>> paths = new ArrayList<>(Arrays.asList(Arrays.asList(unidentifiedStop)));
// Liste des chemins contenant l'arrêt non identifié
// Accès à la méthode cleanLine via la réflexion List<List<StopEntry>> paths = new ArrayList<>(List.of(List.of(unidentifiedStop)));
Method cleanLineMethod = IDFMNetworkExtractor.class.getDeclaredMethod("cleanLine", List.class);
cleanLineMethod.setAccessible(true); // Accès à la méthode cleanLine via la réflexion
Method cleanLineMethod = IDFMNetworkExtractor.class.getDeclaredMethod("cleanLine", List.class);
// Invocation de la méthode cleanLine cleanLineMethod.setAccessible(true);
boolean result = (Boolean) cleanLineMethod.invoke(null, paths);
// Invocation de la méthode cleanLine
// Vérifications boolean result = (Boolean) cleanLineMethod.invoke(null, paths);
assertTrue(result, "La méthode cleanLine devrait retourner true si le nettoyage a réussi.");
assertNotEquals("Unidentified", paths.get(0).get(0).lname, "L'arrêt non identifié devrait avoir été résolu."); // Vérifications
assertEquals(closeCandidate.lname, paths.get(0).get(0).lname, "L'arrêt devrait être résolu au candidat le plus proche."); assertTrue(result, "La méthode cleanLine devrait retourner true si le nettoyage a réussi.");
} assertNotEquals("Unidentified", paths.get(0).get(0).lname,
"L'arrêt non identifié devrait avoir été résolu.");
assertEquals(closeCandidate.lname, paths.get(0).get(0).lname,
"L'arrêt devrait être résolu au candidat le plus proche.");
}
@Test
public void testAddCandidate() throws Exception {
UnidentifiedStopEntry unidentifiedStop = new UnidentifiedStopEntry(2.3522,
48.8566); // Coordonnées pour Paris
List<StopEntry> path = new ArrayList<>(List.of(unidentifiedStop));
TraceEntry trace = new TraceEntry("Ligne1", "IDFM:03434", "Bus", "dummy_url");
trace.addPath(path);
@Test StopEntry candidate = new StopEntry("Proche Candidat", 2.3523, 48.8567); // Coordonnées proches
public void testAddCandidate() throws Exception {
UnidentifiedStopEntry unidentifiedStop = new UnidentifiedStopEntry(2.3522, 48.8566); // Coordonnées pour Paris
List<StopEntry> path = new ArrayList<>(Arrays.asList(unidentifiedStop));
TraceEntry trace = new TraceEntry("Ligne1","IDFM:03434","Bus", "dummy_url");
trace.addPath(path);
StopEntry candidate = new StopEntry("Proche Candidat", 2.3523, 48.8567); // Coordonnées proches Method method = IDFMNetworkExtractor.class.getDeclaredMethod("addCandidate", TraceEntry.class,
StopEntry.class);
method.setAccessible(true);
Method method = IDFMNetworkExtractor.class.getDeclaredMethod("addCandidate", TraceEntry.class, StopEntry.class); method.invoke(null, trace, candidate);
method.setAccessible(true);
method.invoke(null, trace, candidate); //L'appel c'est derouler correctement
assertTrue(true, "L'appel de addCandidate s'est déroulé sans erreur.");
//L'appel c'est derouler correctement }
assertTrue(true, "L'appel de addCandidate s'est déroulé sans erreur.");
}
} }

View file

@ -1,10 +1,14 @@
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class StopEntryTest { public class StopEntryTest {
//Test de toString //Test de toString
/* /*
@Test @Test
public void testToString() { public void testToString() {
@ -15,49 +19,49 @@ public class StopEntryTest {
} }
*/ */
//Si le le test testToString du haut ne marche pas essayer celui du bas //Si le test testToString du haut ne marche pas essayer celui du bas
@Test @Test
public void testToString() { public void testToString() {
StopEntry stop = new StopEntry("Chatelet", 2.346, 48.853); StopEntry stop = new StopEntry("Chatelet", 2.346, 48.853);
// Mise à jour de la valeur attendue pour correspondre au formatage réel // Mise à jour de la valeur attendue pour correspondre au formatage réel
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
public void testCompareTo() {
StopEntry stop1 = new StopEntry("Chatelet", 2.3467, 48.8534);
StopEntry stop2 = new StopEntry("Louvre", 2.3360, 48.8606);
assertTrue(stop1.compareTo(stop2) < 0); //
assertTrue(stop2.compareTo(stop1) > 0); //
// Test avec la même latitude et longitude mais des noms différents
StopEntry stop3 = new StopEntry("Chatelet", 2.3467, 48.8534);
assertEquals(0, stop1.compareTo(stop3));
// Test avec le même nom mais des emplacements différents
StopEntry stop4 = new StopEntry("Chatelet", 2.3500, 48.8500);
assertTrue(stop1.compareTo(stop4) > 0);
}
//Test de hashCode //Test de compareTo
@Test @Test
public void testHashCode() { public void testCompareTo() {
StopEntry stop1 = new StopEntry("Chatelet", 2.3467, 48.8534); StopEntry stop1 = new StopEntry("Chatelet", 2.3467, 48.8534);
StopEntry stop2 = new StopEntry("Chatelet", 2.3467, 48.8534); StopEntry stop2 = new StopEntry("Louvre", 2.3360, 48.8606);
assertEquals(stop1.hashCode(), stop2.hashCode()); assertTrue(stop1.compareTo(stop2) < 0); //
} assertTrue(stop2.compareTo(stop1) > 0); //
//Test de equals // Test avec la même latitude et longitude, mais des noms différents
@Test StopEntry stop3 = new StopEntry("Chatelet", 2.3467, 48.8534);
public void testEquals() { assertEquals(0, stop1.compareTo(stop3));
StopEntry stop1 = new StopEntry("Chatelet", 2.3467, 48.8534);
StopEntry stop2 = new StopEntry("Chatelet", 2.3467, 48.8534); // Test avec le même nom, mais des emplacements différents
StopEntry stop3 = new StopEntry("Louvre", 2.3360, 48.8606); StopEntry stop4 = new StopEntry("Chatelet", 2.3500, 48.8500);
assertTrue(stop1.compareTo(stop4) > 0);
assertEquals(stop1, stop2); }
assertNotEquals(stop1, stop3);
} //Test de hashCode
@Test
public void testHashCode() {
StopEntry stop1 = new StopEntry("Chatelet", 2.3467, 48.8534);
StopEntry stop2 = new StopEntry("Chatelet", 2.3467, 48.8534);
assertEquals(stop1.hashCode(), stop2.hashCode());
}
//Test de equals
@Test
public void testEquals() {
StopEntry stop1 = new StopEntry("Chatelet", 2.3467, 48.8534);
StopEntry stop2 = new StopEntry("Chatelet", 2.3467, 48.8534);
StopEntry stop3 = new StopEntry("Louvre", 2.3360, 48.8606);
assertEquals(stop1, stop2);
assertNotEquals(stop1, stop3);
}
} }

View file

@ -1,68 +1,72 @@
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class StopTest { public class StopTest {
@Test @Test
public void testIsStopConnected() { public void testIsStopConnected() {
Stop stop = new Stop("Stop1"); Stop stop = new Stop("Stop1");
BifStop bifStop1 = new BifStop(1, new Stop("Stop2")); BifStop bifStop1 = new BifStop(1, new Stop("Stop2"));
// Initially, no stops are connected // Initially, no stops are connected
assertFalse(stop.isStopConnected("Stop2")); assertFalse(stop.isStopConnected("Stop2"));
// Add a connected stop // Add a connected stop
stop.addConnectedStop(bifStop1); stop.addConnectedStop(bifStop1);
// Now, Stop2 should be connected // Now, Stop2 should be connected
assertTrue(stop.isStopConnected("Stop2")); assertTrue(stop.isStopConnected("Stop2"));
} }
@Test @Test
public void testGetConnectedStop() { public void testGetConnectedStop() {
Stop stop = new Stop("Stop1"); Stop stop = new Stop("Stop1");
BifStop bifStop1 = new BifStop(1, new Stop("Stop2")); BifStop bifStop1 = new BifStop(1, new Stop("Stop2"));
BifStop bifStop2 = new BifStop(2, new Stop("Stop3")); BifStop bifStop2 = new BifStop(2, new Stop("Stop3"));
// Add two connected stops // Add two connected stops
stop.addConnectedStop(bifStop1); stop.addConnectedStop(bifStop1);
stop.addConnectedStop(bifStop2); stop.addConnectedStop(bifStop2);
// Retrieve the connected stops // Retrieve the connected stops
BifStop retrievedStop1 = stop.getConnectedStop("Stop2"); BifStop retrievedStop1 = stop.getConnectedStop("Stop2");
BifStop retrievedStop2 = stop.getConnectedStop("Stop3"); BifStop retrievedStop2 = stop.getConnectedStop("Stop3");
// Check if the correct stops were retrieved // Check if the correct stops were retrieved
assertEquals(bifStop1, retrievedStop1); assertEquals(bifStop1, retrievedStop1);
assertEquals(bifStop2, retrievedStop2); assertEquals(bifStop2, retrievedStop2);
} }
@Test @Test
public void testAddConnectedStop() { public void testAddConnectedStop() {
Stop stop = new Stop("Stop1"); Stop stop = new Stop("Stop1");
BifStop bifStop1 = new BifStop(1, new Stop("Stop2")); BifStop bifStop1 = new BifStop(1, new Stop("Stop2"));
// Add a connected stop // Add a connected stop
stop.addConnectedStop(bifStop1); stop.addConnectedStop(bifStop1);
// Check if the stop was added // Check if the stop was added
assertTrue(stop.isStopConnected("Stop2")); assertTrue(stop.isStopConnected("Stop2"));
} }
@Test @Test
public void testSHJH(){ public void testSHJH() {
Stop stop = new Stop("Stop2323"); Stop stop = new Stop("Stop2323");
BifStop bifStop1 = new BifStop(1, new Stop("Stop2323")); BifStop bifStop1 = new BifStop(1, new Stop("Stop2323"));
// Add a connected stop // Add a connected stop
stop.addConnectedStop(bifStop1); stop.addConnectedStop(bifStop1);
// Check if the stop was added // Check if the stop was added
assertTrue(stop.isStopConnected("Stop2323")); assertTrue(stop.isStopConnected("Stop2323"));
} }
} }

View file

@ -1,48 +1,54 @@
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import org.junit.jupiter.api.Test;
public class TraceEntryTest { public class TraceEntryTest {
//addTerminus
@Test
public void testAddTerminus() {
TraceEntry traceEntry = new TraceEntry("Ligne 1","IDFM:03434","Bus", "dummy_url");
String terminus1 = "Terminus A";
String terminus2 = "Terminus B";
//Ajouter des arrêt sur la ligne //addTerminus
traceEntry.addTerminus(terminus1); @Test
traceEntry.addTerminus(terminus2); public void testAddTerminus() {
List<String> terminusList = traceEntry.getTerminus(); TraceEntry traceEntry = new TraceEntry("Ligne 1", "IDFM:03434", "Bus", "dummy_url");
String terminus1 = "Terminus A";
assertEquals(2, terminusList.size(), "La liste des terminus doit contenir deux éléments."); String terminus2 = "Terminus B";
assertTrue(terminusList.contains(terminus1), "La liste des terminus doit contenir le terminus A.");
assertTrue(terminusList.contains(terminus2), "La liste des terminus doit contenir le terminus B.");
}
//addPath //Ajouter des arrêt sur la ligne
@Test traceEntry.addTerminus(terminus1);
public void testAddPath() { traceEntry.addTerminus(terminus2);
TraceEntry traceEntry = new TraceEntry("Ligne 1","IDFM:03434","Bus", "dummy_url"); List<String> terminusList = traceEntry.getTerminus();
StopEntry stop1 = new StopEntry("Station 1", 2.300, 48.850);
StopEntry stop2 = new StopEntry("Station 2", 2.310, 48.855); assertEquals(2, terminusList.size(), "La liste des terminus doit contenir deux éléments.");
List<StopEntry> path = Arrays.asList(stop1, stop2); assertTrue(terminusList.contains(terminus1),
traceEntry.addPath(path); "La liste des terminus doit contenir le terminus A.");
List<List<StopEntry>> paths = traceEntry.getPaths(); assertTrue(terminusList.contains(terminus2),
"La liste des terminus doit contenir le terminus B.");
assertEquals(1, paths.size(), "Il doit y avoir un chemin dans la liste des chemins."); }
assertEquals(2, paths.get(0).size(), "Le chemin ajouté doit contenir deux arrêts.");
assertTrue(paths.get(0).containsAll(path), "Le chemin ajouté doit contenir les arrêts spécifiés."); //addPath
} @Test
public void testAddPath() {
TraceEntry traceEntry = new TraceEntry("Ligne 1", "IDFM:03434", "Bus", "dummy_url");
StopEntry stop1 = new StopEntry("Station 1", 2.300, 48.850);
StopEntry stop2 = new StopEntry("Station 2", 2.310, 48.855);
List<StopEntry> path = Arrays.asList(stop1, stop2);
traceEntry.addPath(path);
List<List<StopEntry>> paths = traceEntry.getPaths();
assertEquals(1, paths.size(), "Il doit y avoir un chemin dans la liste des chemins.");
assertEquals(2, paths.get(0).size(), "Le chemin ajouté doit contenir deux arrêts.");
assertTrue(paths.get(0).containsAll(path),
"Le chemin ajouté doit contenir les arrêts spécifiés.");
}
//Verfier si le nom de la ligne lname est correctement initialiser //Verfier si le nom de la ligne lname est correctement initialiser
@Test @Test
public void testTraceEntryName() { public void testTraceEntryName() {
TraceEntry traceEntry = new TraceEntry("Ligne 1","IDFM:03434","Bus", "dummy_url"); TraceEntry traceEntry = new TraceEntry("Ligne 1", "IDFM:03434", "Bus", "dummy_url");
assertEquals("Ligne 1", traceEntry.lname, "Le nom de la ligne doit être 'Ligne 1'."); assertEquals("Ligne 1", traceEntry.lname, "Le nom de la ligne doit être 'Ligne 1'.");
} }
} }

View file

@ -1,12 +1,10 @@
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import org.junit.jupiter.api.BeforeAll; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeEach; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.AbstractMap.SimpleEntry;
import java.util.List;
import java.util.ArrayList;
import static org.junit.jupiter.api.Assertions.*;
public class TransportTest { public class TransportTest {
@ -33,32 +31,32 @@ public class TransportTest {
assertEquals(List.of(1, 2, 3), result.getValue()); assertEquals(List.of(1, 2, 3), result.getValue());
}*/ }*/
@Test @Test
public void testIsTerminus() { public void testIsTerminus() {
Transport transport = new Transport("Test Line", "Bus", "dummy_url"); Transport transport = new Transport("Test Line", "Bus", "dummy_url");
transport.addStop("A", "B", 1); transport.addStop("A", "B", 1);
transport.addStop("B", "C", 2); transport.addStop("B", "C", 2);
transport.addStop("C", "D", 3); transport.addStop("C", "D", 3);
TraceDescription td = new TraceDescription("A", "D", "A", "D"); TraceDescription td = new TraceDescription("A", "D", "A", "D");
transport.descriptions.add(td); transport.descriptions.add(td);
assertTrue(transport.isTerminus("A")); assertTrue(transport.isTerminus("A"));
assertTrue(transport.isTerminus("D")); assertTrue(transport.isTerminus("D"));
assertFalse(transport.isTerminus("B")); assertFalse(transport.isTerminus("B"));
} }
@Test @Test
public void testAddStop() { public void testAddStop() {
Transport transport = new Transport("Test Line", "Bus", "dummy_url"); Transport transport = new Transport("Test Line", "Bus", "dummy_url");
transport.addStop("A", "B", 1); transport.addStop("A", "B", 1);
transport.addStop("B", "C", 2); transport.addStop("B", "C", 2);
transport.addStop("C", "D", 3); transport.addStop("C", "D", 3);
TraceDescription td = new TraceDescription("A", "D", "A", "D"); TraceDescription td = new TraceDescription("A", "D", "A", "D");
transport.descriptions.add(td); transport.descriptions.add(td);
transport.addStop("D", "E", 4); transport.addStop("D", "E", 4);
assertTrue(transport.stopsMap.containsKey("E")); assertTrue(transport.stopsMap.containsKey("E"));
assertEquals("E", transport.stopsMap.get("E").name); assertEquals("E", transport.stopsMap.get("E").name);
assertTrue(transport.stopsMap.get("D").isStopConnected("E")); assertTrue(transport.stopsMap.get("D").isStopConnected("E"));
} }
} }

View file

@ -1,84 +1,85 @@
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
public class UnidentifiedStopEntryTest { public class UnidentifiedStopEntryTest {
// Test de la méthode resolve de la classe UnidentifiedStopEntry // Test de la méthode resolve de la classe UnidentifiedStopEntry
@Test @Test
public void testResolve() { public void testResolve() {
// Création d'un UnidentifiedStopEntry avec des coordonnées arbitraires (0,0) // Création d'un UnidentifiedStopEntry avec des coordonnées arbitraires (0,0)
UnidentifiedStopEntry unidentifiedStopEntry = new UnidentifiedStopEntry(0, 0); UnidentifiedStopEntry unidentifiedStopEntry = new UnidentifiedStopEntry(0, 0);
// Test lorsque la liste des candidats est vide // Test lorsque la liste des candidats est vide
assertNull(unidentifiedStopEntry.resolve()); assertNull(unidentifiedStopEntry.resolve());
// Test lorsque la liste des candidats contient un seul StopEntry // Test lorsque la liste des candidats contient un seul StopEntry
StopEntry stopEntry1 = new StopEntry("Stop1", 10.0, 20.0); StopEntry stopEntry1 = new StopEntry("Stop1", 10.0, 20.0);
unidentifiedStopEntry.addCandidate(stopEntry1); unidentifiedStopEntry.addCandidate(stopEntry1);
assertEquals(stopEntry1, unidentifiedStopEntry.resolve()); assertEquals(stopEntry1, unidentifiedStopEntry.resolve());
// Test lorsque la liste des candidats contient plusieurs StopEntries // Test lorsque la liste des candidats contient plusieurs StopEntries
StopEntry stopEntry2 = new StopEntry("Stop2", 30.0, 40.0); StopEntry stopEntry2 = new StopEntry("Stop2", 30.0, 40.0);
unidentifiedStopEntry.addCandidate(stopEntry2); unidentifiedStopEntry.addCandidate(stopEntry2);
// En supposant que la méthode GPS.distance fonctionne correctement, stopEntry1 devrait être plus proche // En supposant que la méthode GPS.distance fonctionne correctement, stopEntry1 devrait être plus proche
assertEquals(stopEntry1, unidentifiedStopEntry.resolve()); assertEquals(stopEntry1, unidentifiedStopEntry.resolve());
// Test lorsque la liste des candidats contient plusieurs StopEntries et que le plus proche change // Test lorsque la liste des candidats contient plusieurs StopEntries et que le plus proche change
UnidentifiedStopEntry unidentifiedStopEntry2 = new UnidentifiedStopEntry(35.0, 45.0); UnidentifiedStopEntry unidentifiedStopEntry2 = new UnidentifiedStopEntry(35.0, 45.0);
unidentifiedStopEntry2.addCandidate(stopEntry1); unidentifiedStopEntry2.addCandidate(stopEntry1);
unidentifiedStopEntry2.addCandidate(stopEntry2); unidentifiedStopEntry2.addCandidate(stopEntry2);
// Maintenant, stopEntry1 devrait être plus proche // Maintenant, stopEntry1 devrait être plus proche
assertEquals(stopEntry2, unidentifiedStopEntry2.resolve()); assertEquals(stopEntry2, unidentifiedStopEntry2.resolve());
} }
// Test de la méthode addCandidate de la classe UnidentifiedStopEntry // Test de la méthode addCandidate de la classe UnidentifiedStopEntry
@Test @Test
public void testAddCandidate() { public void testAddCandidate() {
// Création d'un UnidentifiedStopEntry avec des coordonnées arbitraires (0,0) // Création d'un UnidentifiedStopEntry avec des coordonnées arbitraires (0,0)
UnidentifiedStopEntry unidentifiedStopEntry = new UnidentifiedStopEntry(0, 0); UnidentifiedStopEntry unidentifiedStopEntry = new UnidentifiedStopEntry(0, 0);
// Test lorsque nous ajoutons un StopEntry à la liste des candidats // Test lorsque nous ajoutons un StopEntry à la liste des candidats
StopEntry stopEntry1 = new StopEntry("Stop1", 10.0, 20.0); StopEntry stopEntry1 = new StopEntry("Stop1", 10.0, 20.0);
unidentifiedStopEntry.addCandidate(stopEntry1); unidentifiedStopEntry.addCandidate(stopEntry1);
assertEquals(stopEntry1, unidentifiedStopEntry.resolve()); assertEquals(stopEntry1, unidentifiedStopEntry.resolve());
// Test lorsque nous ajoutons un autre StopEntry à la liste des candidats // Test lorsque nous ajoutons un autre StopEntry à la liste des candidats
StopEntry stopEntry2 = new StopEntry("Stop2", 30.0, 40.0); StopEntry stopEntry2 = new StopEntry("Stop2", 30.0, 40.0);
unidentifiedStopEntry.addCandidate(stopEntry2); unidentifiedStopEntry.addCandidate(stopEntry2);
// En supposant que la méthode GPS.distance fonctionne correctement, stopEntry1 devrait être plus proche // En supposant que la méthode GPS.distance fonctionne correctement, stopEntry1 devrait être plus proche
assertEquals(stopEntry1, unidentifiedStopEntry.resolve()); assertEquals(stopEntry1, unidentifiedStopEntry.resolve());
} }
// Test de la méthode equals de la classe UnidentifiedStopEntry // Test de la méthode equals de la classe UnidentifiedStopEntry
@Test @Test
public void testEquals() { public void testEquals() {
// Création de deux UnidentifiedStopEntry avec les mêmes coordonnées // Création de deux UnidentifiedStopEntry avec les mêmes coordonnées
UnidentifiedStopEntry unidentifiedStopEntry1 = new UnidentifiedStopEntry(0, 0); UnidentifiedStopEntry unidentifiedStopEntry1 = new UnidentifiedStopEntry(0, 0);
UnidentifiedStopEntry unidentifiedStopEntry2 = new UnidentifiedStopEntry(0, 0); UnidentifiedStopEntry unidentifiedStopEntry2 = new UnidentifiedStopEntry(0, 0);
// Test lorsque nous comparons un UnidentifiedStopEntry avec lui-même // Test lorsque nous comparons un UnidentifiedStopEntry avec lui-même
assertTrue(unidentifiedStopEntry1.equals(unidentifiedStopEntry1)); assertEquals(unidentifiedStopEntry1, unidentifiedStopEntry1);
// Test lorsque nous comparons deux UnidentifiedStopEntry qui n'ont pas de candidats // Test lorsque nous comparons deux UnidentifiedStopEntry qui n'ont pas de candidats
assertTrue(unidentifiedStopEntry1.equals(unidentifiedStopEntry2)); assertEquals(unidentifiedStopEntry1, unidentifiedStopEntry2);
// Test lorsque nous ajoutons le même StopEntry aux deux UnidentifiedStopEntry // Test lorsque nous ajoutons le même StopEntry aux deux UnidentifiedStopEntry
StopEntry stopEntry = new StopEntry("Stop1", 10.0, 20.0); StopEntry stopEntry = new StopEntry("Stop1", 10.0, 20.0);
unidentifiedStopEntry1.addCandidate(stopEntry); unidentifiedStopEntry1.addCandidate(stopEntry);
unidentifiedStopEntry2.addCandidate(stopEntry); unidentifiedStopEntry2.addCandidate(stopEntry);
assertTrue(unidentifiedStopEntry1.equals(unidentifiedStopEntry2)); assertEquals(unidentifiedStopEntry1, unidentifiedStopEntry2);
// Test lorsque nous ajoutons un autre StopEntry à l'un des UnidentifiedStopEntry // Test lorsque nous ajoutons un autre StopEntry à l'un des UnidentifiedStopEntry
StopEntry stopEntry2 = new StopEntry("Stop2", 30.0, 40.0); StopEntry stopEntry2 = new StopEntry("Stop2", 30.0, 40.0);
unidentifiedStopEntry1.addCandidate(stopEntry2); unidentifiedStopEntry1.addCandidate(stopEntry2);
assertFalse(unidentifiedStopEntry1.equals(unidentifiedStopEntry2)); assertNotEquals(unidentifiedStopEntry1, unidentifiedStopEntry2);
} }
} }

View file

@ -1,80 +1,77 @@
package fr.u_paris.gla.project.io; package fr.u_paris.gla.project.io;
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.time.Duration; import java.time.Duration;
import java.time.LocalTime;
import java.time.format.DateTimeParseException; import java.time.format.DateTimeParseException;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class NetworkFormatTest { class NetworkFormatTest {
String t = "00:00";
NumberFormat GPS_test = NetworkFormat.getGPSFormatter();
@Test
public void testParseDurationEqual() {
assertEquals(Duration.ZERO, NetworkFormat.parseDuration(t));
}
@Test
public void testParseDurationTooBig() {
String y = "119:00";
assertThrows(DateTimeParseException.class, () -> NetworkFormat.parseDuration(y));
}
@Test
public void formatDuration() {
assertEquals(t, NetworkFormat.formatDuration(Duration.ZERO));
}
@Test
public void parseThenFormatDuration() {
String t = "00:00"; String t = "00:00";
NumberFormat GPS_test = NetworkFormat.getGPSFormatter(); assertEquals(t, NetworkFormat.formatDuration(NetworkFormat.parseDuration(t)));
}
@Test @Test
public void testParseDurationEqual() { public void getGPSFormatterPos() {
double GPS_pos = 1.456489615649813;
assertEquals(Duration.ZERO, NetworkFormat.parseDuration(t)); assertEquals(String.valueOf(GPS_pos), GPS_test.format(GPS_pos));
}
@Test
public void testParseDurationTooBig() {
String y = "119:00";
assertThrows(DateTimeParseException.class, () -> NetworkFormat.parseDuration(y));
}
@Test
public void formatDuration() {
assertEquals(t, NetworkFormat.formatDuration(Duration.ZERO));
}
@Test
public void parseThenFormatDuration(){
String t = "00:00";
assertEquals(t, NetworkFormat.formatDuration(NetworkFormat.parseDuration(t)));
}
@Test
public void getGPSFormatterPos() {
double GPS_pos = 1.456489615649813;
assertEquals(String.valueOf(GPS_pos), GPS_test.format(GPS_pos));
} }
@Test @Test
public void getGPSFormatterNeg() { public void getGPSFormatterNeg() {
double GPS_neg = -1.456489615649813; double GPS_neg = -1.456489615649813;
assertEquals(String.valueOf(GPS_neg), GPS_test.format(GPS_neg)); assertEquals(String.valueOf(GPS_neg), GPS_test.format(GPS_neg));
} }
@Test
public void getGPSFormatterNul() { @Test
int GPS_nul = 0; public void getGPSFormatterNul() {
assertEquals(String.valueOf(GPS_nul), GPS_test.format(GPS_nul)); int GPS_nul = 0;
assertEquals(String.valueOf(GPS_nul), GPS_test.format(GPS_nul));
} }
@Test @Test
public void getGPSFormatterBig() { public void getGPSFormatterBig() {
String string_int = "4565156498156489"; String string_int = "4565156498156489";
String string_float = "5675747274674276474267479751262167"; String string_float = "5675747274674276474267479751262167";
BigDecimal GPS_big = new BigDecimal(string_int + "." + string_float); BigDecimal GPS_big = new BigDecimal(string_int + "." + string_float);
assertEquals(string_int + "." + string_float.substring(0, NetworkFormat.GPS_PRECISION),
GPS_test.format(GPS_big).replace(",", "").replace(" ", ""));
assertEquals(string_int + "." + string_float.substring(0, NetworkFormat.GPS_PRECISION), }
GPS_test.format(GPS_big).replace(",", "").replace(" ",""));
}
} }

View file

@ -1,33 +1,31 @@
package fr.u_paris.gla.project.io; package fr.u_paris.gla.project.io;
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class ScheduleFormatTest { class ScheduleFormatTest {
@Test @Test
public void getTripSequence() { public void getTripSequence() {
String rpz = "4,5,19,21"; String rpz = "4,5,19,21";
List<Integer> test = Arrays.asList(4, 5, 19, 21); List<Integer> test = Arrays.asList(4, 5, 19, 21);
assertEquals(test, ScheduleFormat.getTripSequence(rpz)); assertEquals(test, ScheduleFormat.getTripSequence(rpz));
} }
@Test @Test
public void getTimeFormatter() { public void getTimeFormatter() {
DateTimeFormatter formatter = ScheduleFormat.getTimeFormatter(); DateTimeFormatter formatter = ScheduleFormat.getTimeFormatter();
LocalDateTime date = LocalDateTime.now(); LocalDateTime date = LocalDateTime.now();
String test = date.format(formatter); String test = date.format(formatter);
//format date: YYYY-MM-DDTHH:MM:SS.DECIMAL //format date: YYYY-MM-DDTHH:MM:SS.DECIMAL
assertEquals(date.toString().substring(11, 16), test); assertEquals(date.toString().substring(11, 16), test);
} }
} }

View file

@ -1,88 +1,80 @@
package fr.u_paris.gla.project.utils; package fr.u_paris.gla.project.utils;
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class CSVToolsTest { class CSVToolsTest {
@Test
public void readCSVFromURL_invalid() {
// TODO Fix the exception thrown
/* assertThrows(IOException.class,() -> {
Consumer<String[]> test = s -> System.out.println(Arrays.toString(s));
CSVTools.readCSVFromURL("https://google.fr",
test);
}
); */
}
@Test
public void testReadCSVFromURL_valid() {
assertDoesNotThrow(() -> {
Consumer<String[]> test = s -> System.out.println(Arrays.toString(s));
CSVTools.readCSVFromURL("https://people.sc.fsu.edu/~jburkardt/data/csv/addresses.csv",
test);
}
);
}
@Test String randomUniqueFilename() {
public void readCSVFromURL_invalid() { String prefix = "file_";
// TODO Fix the exception thrown String randomString = UUID.randomUUID().toString().substring(0, 8);
/** return prefix + randomString + ".csv";
assertThrows(IOException.class,() -> { }
Consumer<String[]> test = s -> System.out.println(Arrays.toString(s));
CSVTools.readCSVFromURL("https://google.fr",
test);
} @Test
); void writeCSVToFile() {
*/ String fileName = randomUniqueFilename();
} assertDoesNotThrow(() -> {
String[] stuff = {"jsqdsqdsqsqffdfgzava", "pfezegrrbeebn", "dfbsduifzegbczi", "sdfsdfcy"};
String[][] t = {stuff, stuff};
Stream<String[]> test = Arrays.stream(t);
CSVTools.writeCSVToFile(fileName, test);
File tmp = new File(fileName);
tmp.delete();
});
}
@Test @Test
public void testreadCSVFromURL_valid() { void writeCSVToFile_specialName() {
assertDoesNotThrow(() -> { String fileName = randomUniqueFilename();
Consumer<String[]> test = s -> System.out.println(Arrays.toString(s)); assertDoesNotThrow(() -> {
CSVTools.readCSVFromURL("https://people.sc.fsu.edu/~jburkardt/data/csv/addresses.csv", String[] stuff = {"jsqdsqdsqsqffdfgzava", "pfezegrrbeebn", "dfbsduifzegbczi", "sdfsdfcy"};
test); String[][] t = {stuff, stuff};
Stream<String[]> test = Arrays.stream(t);
CSVTools.writeCSVToFile(fileName, test);
File tmp = new File(fileName);
tmp.delete();
});
}
} @Test
); void writeCSVToFile_invalidName() {
} assertThrows(IOException.class, () -> {
String[] stuff = {"jsqdsqdsqsqffdfgzava", "pfezegrrbeebn", "dfbsduifzegbczi", "sdfsdfcy"};
String randomUniqueFilename() { String[][] t = {stuff, stuff};
String prefix = "file_"; Stream<String[]> test = Arrays.stream(t);
String randomString = UUID.randomUUID().toString().substring(0, 8); CSVTools.writeCSVToFile(".", test);
return prefix + randomString + ".csv"; });
} }
@Test
void writeCSVToFile() {
String fileName = randomUniqueFilename();
assertDoesNotThrow(() -> {
String[] stuff = {"jsqdsqdsqsqffdfgzava", "pfezegrrbeebn", "dfbsduifzegbczi", "sdfsdfcy"};
String[][] t = {stuff, stuff};
Stream<String[]> test = Arrays.stream(t);
CSVTools.writeCSVToFile(fileName, test);
File tmp = new File(fileName);
tmp.delete();
});
}
@Test
void writeCSVToFile_specialName() {
String fileName = randomUniqueFilename();
assertDoesNotThrow(() -> {
String[] stuff = {"jsqdsqdsqsqffdfgzava", "pfezegrrbeebn", "dfbsduifzegbczi", "sdfsdfcy"};
String[][] t = {stuff, stuff};
Stream<String[]> test = Arrays.stream(t);
CSVTools.writeCSVToFile(fileName, test);
File tmp = new File(fileName);
tmp.delete();
});
}
@Test
void writeCSVToFile_invalidName() {
assertThrows( IOException.class ,() -> {
String[] stuff = {"jsqdsqdsqsqffdfgzava", "pfezegrrbeebn", "dfbsduifzegbczi", "sdfsdfcy"};
String[][] t = {stuff, stuff};
Stream<String[]> test = Arrays.stream(t);
CSVTools.writeCSVToFile(".", test);
});
}
} }

View file

@ -1,39 +1,41 @@
package fr.u_paris.gla.project.utils; package fr.u_paris.gla.project.utils;
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test;
class GPSTest { class GPSTest {
@Test @Test
public void testDistance_SameLat(){ public void testDistance_SameLat() {
assertDoesNotThrow( assertDoesNotThrow(
() -> { () -> {
GPS.distance(5, 3, 5, 11); GPS.distance(5, 3, 5, 11);
} }
); );
} }
@Test @Test
public void distance_SameLon(){ public void distance_SameLon() {
assertDoesNotThrow( assertDoesNotThrow(
() -> { () -> {
GPS.distance(5, 3, 7, 3); GPS.distance(5, 3, 7, 3);
} }
); );
} }
@Test @Test
public void distance_SamePoint() { public void distance_SamePoint() {
assertEquals(0.0, GPS.distance(5, 3, 5, 3) ); assertEquals(0.0, GPS.distance(5, 3, 5, 3));
} }
@Test @Test
public void distance_NegativePoint(){ public void distance_NegativePoint() {
assertNotEquals(0.0, GPS.distance(-5, 7, -13, 4)); assertNotEquals(0.0, GPS.distance(-5, 7, -13, 4));
} }
} }