Merge branch 'dev' into 'main'

Release 1.0

See merge request gla-groupe-3/projet!23
This commit is contained in:
KOUE-HEMAZRO KANKOE ANGE HERMAN 2024-05-05 22:10:47 +02:00
commit 0953deabef
24 changed files with 759 additions and 2202 deletions

6
.gitignore vendored
View file

@ -1,8 +1,10 @@
# Maven
target/
# Files
.csv
# Generated files
hours.csv
images.csv
trace.csv
# IDEs
# Eclipse

View file

@ -2,6 +2,9 @@
Version 2024
## Lien vers la vidéo
https://youtu.be/eBVGWTBQfHg
## Description
Ceci est l'archétype de projet de Génie Logiciel Avancé (GLA).
@ -18,31 +21,28 @@ Afin de compiler et lancer les tests, exécutez simplement
mvn verify
```
Afin de vérifier les tests via JaCoCo.
Les résultats du test sont dans `target/site/jacoco/index.html`.
```bash
mvn clean jacoco:prepare-agent install jacoco:report
```
Par la suite, `mvn jacoco:report` suffit.
Dans sa version initiale, le programme fournit est un simple code qui se lance en terminal ou en application graphique.
Une fois le programme compilé, vous trouverez un jar executable dans le dossier target. Au nom de jar près (version changeante), vous pourrez l'exécuter avec:
```
java -jar target/project-2024.1.0.0-SNAPSHOT.jar --info
java -jar target/project-2024.1.0.0-SNAPSHOT.jar
```
L'option de lancement `--info` causera l'affichage dans la console d'informations de l'application.
L'option de lancement `--gui` causera l'ouverture d'une fenêtre affichant le logo de l'Université de Paris.
Sans option, le programme Pathfinder sera lancé.
## Tests JaCoCo
```
Afin de vérifier la couverture des tests via JaCoCo:
```bash
mvn clean jacoco:prepare-agent install jacoco:report
```
Puis ouvrir le fichier `./target/site/jacoco/index.html`.
Les résultats seront stockés dans `target/site/jacoco/index.html`.
Par la suite, ```mvn jacoco:report``` suffit.

1948
image.csv

File diff suppressed because it is too large Load diff

View file

@ -91,6 +91,10 @@
<directory>src/main/resources-filtered</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

View file

@ -7,19 +7,15 @@ import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;
import javax.swing.*;
import fr.u_paris.gla.project.itinerary.Finder;
import fr.u_paris.gla.project.itinerary.Parse;
import fr.u_paris.gla.project.itinerary.Path;
import fr.u_paris.gla.project.itinerary.Stop;
import fr.u_paris.gla.project.gui.View;
import fr.u_paris.gla.project.itinerary.*;
/** Simple application model.
*
@ -66,31 +62,26 @@ public class App {
showLogo();
}
}
}else{
testRelease();
}
else {
run();
}
}
public static void testRelease(){
public static void run() {
Parse parse = new Parse();
parse.parseFiles();
Stop source = parse.getTmp().get("Porte d'Ivry").get(0);
Stop destination = parse.getTmp().get("Châtelet").get(0);
System.out.println("Itinéraire de Porte d'Ivry à Châtelet");
List<Path> result = parse.getItinerary(source, destination, 43200);
for(Path element : result){
System.out.println(element.getCurrentStop());
}
System.out.println("°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°");
System.out.println("Itinéraire de Porte d'Ivry à Châtelet");
source = parse.getTmp().get("Saint-Jacques").get(0);
destination = parse.getTmp().get("Porte d'Ivry").get(0);
result = parse.getItinerary(source, destination, 43200);
for(Path element : result){
System.out.println(element.getCurrentStop());
}
Graph graph = parse.createGraph();
Finder finder = parse.createFinder(graph);
ArrayList<Stop> s = new ArrayList<>();
s.add(new Stop("M8", "Balard", 1.0315897, 3.0265513));
s.add(new Stop("M14", "Gare de Lyon", 2.4658452681, 3.0265513));
SwingUtilities.invokeLater(() -> new View(graph, finder, s));
}
/** @param out the output stream */
public static void printAppInfos(PrintStream out) {
Properties props = readApplicationProperties();

View file

@ -1,19 +1,33 @@
package fr.u_paris.gla.project.gui;
import fr.u_paris.gla.project.itinerary.Stop;
import fr.u_paris.gla.project.idfm.CSVImageProvider;
import fr.u_paris.gla.project.idfm.IDFMNetworkExtractor;
import fr.u_paris.gla.project.idfm.ImagePair;
import fr.u_paris.gla.project.itinerary.*;
import fr.u_paris.gla.project.utils.ApiUtils;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.*;
import java.util.List;
import java.util.logging.Logger;
public class View extends JFrame {
private static final Logger LOGGER = Logger
.getLogger(IDFMNetworkExtractor.class.getName());
private JPanel CardPanel;
private JMenuItem Home;
private JMenuItem Network;
private JMenuItem Favorites;
private JPanel NetworkPanel;
private JTextField TextLocation;
@ -36,6 +50,20 @@ public class View extends JFrame {
private JPanel stationsPanel;
private JLabel departText;
private JLabel arrText;
private JMenuItem Lines;
private JPanel LinesPanel;
private JLabel LineLabel;
private JComboBox LinesComboBox;
private JButton ShowLineButton;
private JMenuItem Stops;
private JPanel StopsPanel;
private JLabel StopsLabel;
private JComboBox StopsComboBox;
private JComboBox StopsLinesComboBox;
private JButton SeeStopButton;
private JTextField TextCoord;
private JButton ButtonCoord;
private JPanel SearchCoordPanel;
@ -56,10 +84,16 @@ public class View extends JFrame {
private ArrayList<Stop> searchRes;
private ArrayList<Path> searchResPath;
private int count = 0;
private Finder finder;
public View(ArrayList<Stop> s) throws HeadlessException {
public View(Graph graph, Finder finder, ArrayList<Stop> s) throws HeadlessException {
this.finder = finder;
setSize(800, 600);
MainPanel = new JPanel();
GridLayout MainLayout = new GridLayout(1, 2, 50, 0);
MainPanel.setLayout(MainLayout);
@ -106,8 +140,6 @@ public class View extends JFrame {
paneStops.add(tableStops);
NetworkPanel.add(paneStops);
ItineraryPanel = new JPanel();
CardPanel.add(ItineraryPanel);
GridLayout ItineraryLayout = new GridLayout(2, 1);
@ -117,23 +149,74 @@ public class View extends JFrame {
paneItinerary.add(tableItinerary);
ItineraryPanel.add(paneItinerary);
LinesComboBox = new JComboBox();
LinesComboBox.setMaximumSize(new Dimension(100, LinesComboBox.getPreferredSize().height));
LinesComboBox.setPreferredSize(LinesComboBox.getPreferredSize());
LineLabel = new JLabel("Show line");
LineLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
ShowLineButton = new JButton("Open");
ShowLineButton.setAlignmentX(Component.CENTER_ALIGNMENT);
LinesPanel = new JPanel();
LinesPanel.setBackground(new Color(214,173,153));
LinesPanel.setLayout(new BoxLayout(LinesPanel, BoxLayout.Y_AXIS));
LinesPanel.add(Box.createHorizontalGlue());
LinesPanel.add(Box.createHorizontalStrut(2));
LinesPanel.add(LineLabel);
LinesPanel.add(Box.createHorizontalStrut(10));
LinesPanel.add(LinesComboBox);
LinesPanel.add(Box.createHorizontalStrut(10));
LinesPanel.add(ShowLineButton);
LinesPanel.add(Box.createHorizontalStrut(2));
LinesPanel.add(Box.createHorizontalGlue());
StopsComboBox = new JComboBox();
StopsComboBox.setMaximumSize(new Dimension(200, StopsComboBox.getPreferredSize().height));
StopsComboBox.setPreferredSize(StopsComboBox.getPreferredSize());
StopsLinesComboBox = new JComboBox();
StopsLinesComboBox.setMaximumSize(new Dimension(200, StopsLinesComboBox.getPreferredSize().height));
StopsLinesComboBox.setPreferredSize(StopsComboBox.getPreferredSize());
StopsLabel = new JLabel("See stop schedules");
StopsLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
SeeStopButton = new JButton("See Schedule");
SeeStopButton.setAlignmentX(Component.CENTER_ALIGNMENT);
StopsPanel = new JPanel();
StopsPanel.setBackground(new Color(171,197,105));
StopsPanel.setLayout(new BoxLayout(StopsPanel, BoxLayout.Y_AXIS));
StopsPanel.add(Box.createHorizontalGlue());
StopsPanel.add(Box.createHorizontalStrut(2));
StopsPanel.add(StopsLabel);
StopsPanel.add(Box.createHorizontalStrut(10));
StopsPanel.add(StopsComboBox);
StopsPanel.add(Box.createHorizontalStrut(10));
StopsPanel.add(StopsLinesComboBox);
StopsPanel.add(Box.createHorizontalStrut(10));
StopsPanel.add(SeeStopButton);
StopsPanel.add(Box.createHorizontalStrut(2));
StopsPanel.add(Box.createHorizontalGlue());
JPanel buttonBarPanel = new JPanel(new BorderLayout());
ButtonBar = new JMenuBar();
GridLayout ButtonLayout = new GridLayout(3, 1);
GridLayout ButtonLayout = new GridLayout(5, 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));
Lines = new JMenuItem("Lines");
ButtonBar.add(Lines);
Stops = new JMenuItem("Stops");
ButtonBar.add(Stops);
buttonBarPanel.add(ButtonBar, BorderLayout.CENTER);
buttonBarPanel.setVisible(true);
ButtonBar.setPreferredSize(new Dimension(50, MainPanel.getHeight()));
MainPanel.add(ButtonBar);
MainPanel.add(CardPanel);
modelStops = (DefaultTableModel) tableStops.getModel();
modelStops.setColumnCount(2);
modelStops.setColumnIdentifiers(new Object[]{"Line", "Stop"});
@ -143,63 +226,90 @@ public class View extends JFrame {
modelItinerary.setColumnIdentifiers(new Object[]{"Line", "Stop", "Time"});
this.StopList = s;
setContentPane(MainPanel);
setTitle("app");
setExtendedState(JFrame.MAXIMIZED_BOTH);
setTitle("Pathfinder");
//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();
Home.addActionListener(e -> {
CardPanel.removeAll();
CardPanel.add(HomePanel);
CardPanel.repaint();
CardPanel.revalidate();
});
Network.addActionListener(e -> {
LoadSearchResult(s, modelStops);
CardPanel.removeAll();
CardPanel.add(NetworkPanel);
CardPanel.repaint();
CardPanel.revalidate();
});
Itinerary.addActionListener(e -> {
LoadSearchResultItinerary(searchResPath, modelItinerary);
CardPanel.removeAll();
CardPanel.add(ItineraryPanel);
CardPanel.repaint();
CardPanel.revalidate();
});
Lines.addActionListener(e -> {
CardPanel.removeAll();
CardPanel.add(LinesPanel);
CardPanel.repaint();
CardPanel.revalidate();
});
Stops.addActionListener(e -> {
CardPanel.removeAll();
CardPanel.add(StopsPanel);
CardPanel.repaint();
CardPanel.revalidate();
});
CSVImageProvider.getLineImageMap().forEach(p -> LinesComboBox.addItem(p));
ShowLineButton.addActionListener(f -> {
ImagePair item = (ImagePair) LinesComboBox.getSelectedItem();
openWebpage(item.getValue());
});
Set<Stop> nodes = graph.getNodes();
List<Stop> nodesList = nodes.stream().sorted(Comparator.comparing(Stop::getName)).toList();
nodesList.forEach(stop -> StopsComboBox.addItem(stop));
StopsComboBox.addItemListener(e -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
Stop stop = (Stop) StopsComboBox.getSelectedItem();
StopsLinesComboBox.removeAllItems();
graph.getConnections(stop).forEach(c -> {
if (!c.toString().equals("WALK"))
StopsLinesComboBox.addItem(c);
});
}
});
Network.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
LoadSearchResult(s, modelStops);
CardPanel.removeAll();
CardPanel.add(NetworkPanel);
CardPanel.repaint();
CardPanel.revalidate();
SeeStopButton.addActionListener(f -> {
Connection c;
if ((c = (Connection) StopsLinesComboBox.getSelectedItem()) != null) {
createHourWindow(c.getSchedules());
}
});
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);
String cur = TextLocation.getText();
LoadStringStops(cur);
LoadSearchResultItinerary(searchResPath, modelItinerary);
System.out.println("Enter key released with text " + cur);
CardPanel.removeAll();
CardPanel.add(NetworkPanel);
CardPanel.add(ItineraryPanel);
CardPanel.repaint();
CardPanel.revalidate();
@ -207,45 +317,39 @@ public class View extends JFrame {
}
});
ButtonLocation.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ButtonLocation.addActionListener(e -> {
String cur = TextLocation.getText();
if (!cur.isEmpty()) {
CardPanel.removeAll();
searchLocation = TextLocation.getText();
LoadSearchResult(s, modelStops);
System.out.println("search location clicked with text " + searchLocation);
CardPanel.add(NetworkPanel);
CardPanel.repaint();
CardPanel.revalidate();
LoadStringStops(cur);
LoadSearchResultItinerary(searchResPath, modelItinerary);
CardPanel.add(ItineraryPanel);
}
CardPanel.repaint();
CardPanel.revalidate();
});
ButtonCoord.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ButtonCoord.addActionListener(e -> {
String cur = TextCoord.getText();
if (!cur.isEmpty()) {
CardPanel.removeAll();
searchCoord = TextCoord.getText();
LoadSearchResult(s, modelStops);
System.out.println("search coord clicked with text " + searchCoord);
CardPanel.add(NetworkPanel);
CardPanel.repaint();
CardPanel.revalidate();
LoadStringCoords(cur);
LoadSearchResultItinerary(searchResPath, modelItinerary);
CardPanel.add(ItineraryPanel);
}
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) {
@ -254,6 +358,46 @@ public class View extends JFrame {
});
}
/**
* @param schedules
*/
private void createHourWindow(ArrayList<Integer> schedules) {
JFrame frame = new JFrame("Schedule");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel panel = new JPanel(new GridLayout(0, 1));
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JScrollPane scrollPane = new JScrollPane(panel);
frame.getContentPane().add(scrollPane);
for (int time : schedules) {
int hours = time / 3600;
int minutes = (time % 3600) / 60;
JLabel label = new JLabel(String.format("%dh%d", hours, minutes));
label.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.BLACK),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
label.setHorizontalAlignment(SwingConstants.CENTER);
panel.add(label);
}
if (schedules.isEmpty()) {
panel.add(new JLabel("No time available"));
}
scrollPane.repaint();
frame.repaint();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(200, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setResizable(false);
}
/** Used to select a departure/arrival stop in the "Network" section, UNUSED
* @param table the table that displays the stops
* @param x x coordinate of mouse click
* @param y y coordinate of mouse click
*/
private void showOptionsDialog(JTable table, int x, int y) {
int selectedRow = table.rowAtPoint(new Point(x, y));
if (selectedRow != -1) { // If a row is selected
@ -279,85 +423,138 @@ public class View extends JFrame {
}
}
/** Load all stops related to coordinates
* @param stops a String in format (x1,y1);(x2,y2)
*/
public void LoadStringCoords(String stops){
stops = stops.replaceAll("[()]", "").replaceAll(";", ",");
String[] stops_array = stops.split(",");
double[] coords = new double[4];
for (int i = 0; i < 4; i++){
coords[i] = Double.parseDouble(stops_array[i]);
}
searchResPath = (ArrayList<Path>) finder.findPath(coords[0], coords[1], coords[2], coords[3], LocalDateTime.now().toLocalTime().toSecondOfDay());
}
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);
/** Load all stops related to locations
* @param stops a String in format name1;name2
*/
public void LoadStringStops(String stops){
String[] stops_array = stops.split(";");
double[] coords = new double[4];
int j = 0;
for (String stop: stops_array) {
double[] cur = ApiUtils.getGPSLocation(stop);
for (int i = 0; i < 2;i++){
coords[j] = cur[i];
++j;
}
}
searchResPath = (ArrayList<Path>) finder.findPath(coords[0], coords[1], coords[2], coords[3], LocalDateTime.now().toLocalTime().toSecondOfDay());
}
/** Load a list of stops to display (used for selecting a departure and arrival stop, W.I.P)
* @param stops the stops list
* @param model the JTable model that will store them
*/
public void LoadSearchResult(ArrayList<Stop> stops, DefaultTableModel model) {
// 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.toString());
for (int i = 0; i < model.getRowCount(); i++) {
for (int j = 0; j < model.getColumnCount(); j++) {
System.out.print("valeur at coord " + i +";" + j +": " + model.getValueAt(i, j) + "\t");
}
System.out.println();
}
System.out.println(count);
tableStops.revalidate();
tableStops.repaint();
tableItinerary.revalidate();
tableItinerary.repaint();
paneStops.setViewportView(tableStops);
paneStops.revalidate();
paneStops.repaint();
NetworkPanel.revalidate();
NetworkPanel.repaint();
}
/**
* Function that takes a list of paths and displays it in a JTabke
* @param paths the list of paths (from one stop to another)
* @param model the TableModel that stores the Table's data
*/
public void LoadSearchResultItinerary(ArrayList<Path> paths, DefaultTableModel model){
// Clear existing rows from the table
int cols = model.getColumnCount();
model.setRowCount(0);
model.setColumnCount(cols);
// Add new rows based on the search results
count = 0;
Path last = null;
if (paths != null) {
for (Path path : paths) {
// Add a row to the table with Stop's line in the first column and Stop's name in the second column
double time = path.getStartTime();
int hours = (int) (time / 3600);
int minutes = (int) ((time % 3600) / 60);
model.addRow(new Object[]{path.getLine(), path.getCurrentStop(), String.format("%02d:%02d", hours, minutes)});
++count;
last = path;
}
}
if (last != null)
model.addRow(new Object[]{last.getLine(), last.getNextStop()});
tableItinerary.revalidate();
tableItinerary.repaint();
paneItinerary.setViewportView(tableItinerary);
paneItinerary.revalidate();
paneItinerary.repaint();
NetworkPanel.revalidate();
NetworkPanel.repaint();
ItineraryPanel.revalidate();
ItineraryPanel.repaint();
this.displayTableValues(model);
}
/** Takes a table's data as argument and displays it
* @param mod the table's data
*/
public void displayTableValues(TableModel mod) {
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();
}
/** open a URL in browser
* @param uri
*/
private void openWebpage(URI uri) {
Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
try {
desktop.browse(uri);
} catch (Exception e) {
LOGGER.severe("Error opening browser");
}
}
}
/** open a URL (taken from a String) in browser
* @param url the url String
*/
private void openWebpage(String url) {
try {
openWebpage(new URL(url).toURI());
} catch (URISyntaxException|MalformedURLException e) {
LOGGER.severe("Default desktop browser not set");
}
}
}

View file

@ -3,33 +3,39 @@
*/
package fr.u_paris.gla.project.idfm;
import fr.u_paris.gla.project.io.ScheduleFormat;
import java.text.MessageFormat;
import java.io.IOException;
import java.io.InputStream;
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 java.util.*;
import java.util.logging.Logger;
import fr.u_paris.gla.project.io.ImageFormat;
import fr.u_paris.gla.project.utils.GPS;
import fr.u_paris.gla.project.utils.CSVTools;
public final class CSVImageProvider {
/**
* The logger for information on the process
*/
private static final Logger LOGGER = Logger
.getLogger(IDFMNetworkExtractor.class.getName());
private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat
.getInstance(Locale.ENGLISH);
static {
MINUTES_SECOND_FORMATTER.setMinimumIntegerDigits(2);
}
private final String[] line = new String[ImageFormat.NUMBER_COLUMNS];
private final Iterator<Transport> current;
private static ArrayList<ImagePair> lineImageMap;
public static final String FILE_NAME = IDFMNetworkExtractor.IMAGES_FILE_NAME;
/** Create the stream provider */
public CSVImageProvider(Iterator<Transport> traces) {
this.current = traces;
@ -48,8 +54,37 @@ public final class CSVImageProvider {
Transport element = this.current.next();
this.line[ImageFormat.LINE_INDEX] = element.name;
this.line[ImageFormat.LINE_DETAIL_INDEX] = element.type;
this.line[ImageFormat.IMAGE_URL_INDEX] = element.image_url;
return Arrays.copyOf(this.line, this.line.length);
}
/**
* This function returns a list of ImagePair, which represents the name of the line and the link to the
* image of the line details.
* The list is created once and then store in a static variable.
* @return an ArrayList of ImagePair
*/
public static ArrayList<ImagePair> getLineImageMap() {
if (lineImageMap != null)
return lineImageMap;
lineImageMap = new ArrayList<>();
try {
CSVTools.readCSVFromFile(FILE_NAME,
(String[] line) ->
{
String label = line[ImageFormat.LINE_INDEX];
String detail = line[ImageFormat.LINE_DETAIL_INDEX];
String imageUrl = line[ImageFormat.IMAGE_URL_INDEX];
lineImageMap.add(new ImagePair(label, detail, imageUrl));
});
}
catch(IOException e){
LOGGER.severe("File is not generated yet");
}
lineImageMap.sort(Comparator.comparing(ImagePair::getLabel));
return lineImageMap;
}
}

View file

@ -71,7 +71,7 @@ public class CSVSchedulesProvider {
}
/**
* Move to the the nextDescription of a Transport line
* Move to the nextDescription of a Transport line
*/
private void skipToNextDescription() {
if (this.currentDescription.hasNext()) {

View file

@ -202,7 +202,7 @@ public final class CSVStreamProvider {
} while (currentSegmentStart == null);
}
/** Store current trace' data as a String array
/** Store current trace data as a String array
* @return The newly generated line of text
*/
public String[] next() {
@ -271,7 +271,7 @@ public final class CSVStreamProvider {
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);
+ 2 * Math.sqrt(Math.min(distance, two_acc_distance) * two_acc_distance)/max_speed;
}
private void fillTransports(int bif) {
@ -283,7 +283,7 @@ public final class CSVStreamProvider {
Transport transp = null;
if(!transports.containsKey(traceId)){
transp = new Transport(nameTransport,traceType, url_image);
transp = new Transport(nameTransport, traceType, url_image);
transports.put(traceId, transp);
}else{
transp = transports.get(traceId);

View file

@ -18,6 +18,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
/**
* Code of an extractor for the data from IDF mobilite.
*
@ -84,7 +85,7 @@ public class IDFMNetworkExtractor {
private static final String HOURS_FILE_NAME = "hours.csv";
private static final String IMAGES_FILE_NAME = "./images.csv";
public static final String IMAGES_FILE_NAME = "images.csv";
// Magically chosen values
/**
@ -101,18 +102,17 @@ public class IDFMNetworkExtractor {
public static boolean checkFileExistence(String filePath) {
File file = new File(filePath);
if (file.exists()) {
LOGGER.severe(filePath+ " already exists.");
LOGGER.log(Level.INFO, filePath+ " already exists.");
return true;
} else {
LOGGER.severe(filePath + " does not exist.");
LOGGER.log(Level.INFO, filePath + " does not exist.");
return false;
}
}
public static void buildFiles() {
if (checkFileExistence("./"+HOURS_FILE_NAME) && checkFileExistence("./"+TRACE_FILE_NAME)) {
LOGGER.severe("Files already exists.");
if (checkFileExistence("./"+HOURS_FILE_NAME) && checkFileExistence("./"+TRACE_FILE_NAME) && checkFileExistence(("./"+IMAGES_FILE_NAME))) {
LOGGER.log(Level.INFO, "Files already exists.");
return;
}
@ -150,7 +150,7 @@ public class IDFMNetworkExtractor {
long startTime = System.currentTimeMillis();
for (Transport entry : transports.values()) {
entry.buildBifurcationOptimzed();
entry.buildBifurcationOptimized();
}
long endTime = System.currentTimeMillis();
@ -160,7 +160,7 @@ public class IDFMNetworkExtractor {
long seconds = (tempsPasse / 1000) % 60;
long milliseconds = tempsPasse % 1000;
System.out.println("Temps écoulé : " + minutes + " minutess, " + seconds + " secndes et " + milliseconds + " millis");
System.out.println("Temps écoulé : " + minutes + " minutes, " + seconds + " secndes et " + milliseconds + " millis");
System.out.println("******************Fin Building bifurcations ************************");

View file

@ -0,0 +1,45 @@
package fr.u_paris.gla.project.idfm;
/**
* This class is made specific to store a Pair of Name/Link to be used in a Swing ComboBox
* These getters ables a ComboBox to show the label returned by toString, and get a specific value when the object is returned
*/
public class ImagePair {
/**
* The name of the line
*/
private final String line;
/**
* The label that will be shown in the ComboBox
*/
private final String label;
/**
* The link of the line details
*/
private final String value;
public ImagePair(String label, String label_detail, String value){
this.line = label;
this.label = label + " - " + label_detail;
this.value = value;
}
public String getLabel(){
return this.label;
}
public String getLine(){
return this.line;
}
public String getValue(){
return this.value;
}
@Override
public String toString(){
return label;
}
}

View file

@ -55,7 +55,7 @@ public class Transport {
/**
* Build the bifurcation for all the descriptions but optimized
*/
public void buildBifurcationOptimzed() {
public void buildBifurcationOptimized() {
// int found = 0;
for (TraceDescription d : descriptions) {
Stop debut = stopsMap.get(d.from);
@ -92,7 +92,7 @@ public class Transport {
* @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
* @param bifurcation 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
@ -138,7 +138,7 @@ public class Transport {
* @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
* @param bifurcation 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

View file

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

View file

@ -3,6 +3,10 @@ package fr.u_paris.gla.project.itinerary;
import java.util.ArrayList;
import java.util.Collections;
/**
* A representation of a connection to another stop.
* Corresponds to a graph edge for the algorithm.
*/
public class Connection{
// Destination of the connection between the two stops
private final Stop stop;
@ -20,6 +24,13 @@ public class Connection{
private final int bifurcation;
/**
* @param stop the stop where the connection is going.
* @param lineName the name of the line used by the connection
* @param distance the distance of the connection in km
* @param time the travel time in s
* @param bifurcation the bifurcation used
*/
public Connection(Stop stop, String lineName, double distance, int time, int bifurcation){
this.stop = stop;
this.lineName=lineName;
@ -29,39 +40,78 @@ public class Connection{
this.bifurcation = bifurcation;
}
/**
* @param stop the stop where the connection is going.
* @param lineName the name of the line used by the connection
* @param distance the distance of the connection in km
* @param time the travel time in s
*/
public Connection(Stop stop, String lineName, double distance, int time){
this(stop, lineName, distance, time, 0);
}
/**
* Returns the line name of the connection
* @return the line name of the connection
*/
public String getLineName() {
return lineName;
}
/**
* Returns the distance between the two connection stops.
* @return distance in km
*/
public double getDistance() {
return distance;
}
/**
* Returns the travel time between the two stops.
* @return time in s
*/
public int getTime() {
return time;
}
/**
* Returns the stop to which the connection is going.
* @return the destination stop
*/
public Stop getStop() {
return stop;
}
/**
* Adds a schedule for the connection.
* @param hours passage time in s from 00:00
*/
public void addSchedule(int hours) {
this.schedules.add(hours);
}
/**
* Sort schedules.
* Necessary to get the right passage time.
*/
public void sortSchedule() {
Collections.sort(this.schedules);
}
/**
* Return to the schedule list
* @return the schedule list
*/
public ArrayList<Integer> getSchedules() {
return this.schedules;
}
/**
* Returns the number of bifurcation of the connection
* @return the bifurcation
*/
public int getBifurcation() {
return this.bifurcation;
}
@ -70,6 +120,11 @@ public class Connection{
return this.time;
}
/**
* Returns the time of the next passage.
* @param currentTime the current time
* @return the time of the next passage
*/
public double getNextTime(double currentTime) {
if(this.schedules.size() == 0) {
return currentTime;
@ -85,9 +140,15 @@ public class Connection{
return this.schedules.get(0);
}
/**
* Returns the time before you can reach the next stop with this connection.
* Corresponds to the sum of time to next stop and travel time.
* @param currentTime the current time
* @return time to reach the next stop
*/
public double getCost(double currentTime) {
if(this.schedules.size() == 0) {
if(this.lineName.equals("WALK")) {
if(this.lineName.equals("WALK") || this.lineName.equals("")) {
return this.time;
}
return this.time + 900;
@ -96,4 +157,9 @@ public class Connection{
if(nextTime < currentTime) { nextTime += 86400;}
return nextTime - currentTime + this.time;
}
@Override
public String toString() {
return lineName;
}
}

View file

@ -1,23 +1,60 @@
package fr.u_paris.gla.project.itinerary;
import fr.u_paris.gla.project.utils.GPS;
import java.util.*;
/**
* Path finder algorithm.
* The algorithm is based on an A* algorithm,
* adapted to our case of path finding in a public transport network.
*/
public class Finder {
private Graph graph;
public Finder(Graph graph) {
this.graph = graph;
}
/**
*
* @param from_x the latitude of the starting point in decimal degrees (DD)
* @param from_y the longitude of the starting point
* @param to_x the latitude of the arrival point
* @param to_y the longitude of the arrival point
* @param startTime the departure time
* @return the optimal path found by the algorithm
*/
public List<Path> findPath(double from_x, double from_y, double to_x, double to_y, double startTime) {
Stop fromNode = new Stop("", "tmp_from", from_x, from_y);
Stop toNode = new Stop("", "tmp_to", to_x, to_y);
for (Stop node : graph.getNodes()) {
double from_dst = GPS.distance(from_x, from_y, node.getLatitude(), node.getLongitude());
double to_dst = GPS.distance(to_x, to_y, node.getLatitude(), node.getLongitude());
Connection from_c = new Connection(node, "", from_dst, (int) ((from_dst * 1000) / Parse.WALK_SPEED));
Connection to_c = new Connection(toNode, "", to_dst, (int) ((to_dst * 1000) / Parse.WALK_SPEED));
graph.addConnection(fromNode, from_c);
graph.addConnection(node, to_c);
}
graph.addNode(fromNode);
graph.addNode(toNode);
List<Path> result = findPath(fromNode, toNode, startTime);
graph.removeNode(fromNode);
graph.removeNode(toNode);
return result;
}
/**
* return a path from startNode to goalNode using A* algorithm
* @param startNode
* @param goalNode
*/
public List<Path> findPath(Stop startNode, Stop goalNode, double startTime) {
PriorityQueue<Stop> openSet = new PriorityQueue<>(Comparator.comparingDouble(GraphNode::getF));
PriorityQueue<Stop> openSet = new PriorityQueue<>(Comparator.comparingDouble(Stop::getF));
HashSet<Stop> closedSet = new HashSet<>();
HashMap<Stop, Path> cameFrom = new HashMap<>();
HashMap<Stop, Double> gScore = new HashMap<>();
@ -111,6 +148,5 @@ public class Finder {
node.setF(newF);
openSet.add(node);
}
}

View file

@ -1,28 +1,99 @@
package fr.u_paris.gla.project.itinerary;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class Graph{
/**
* A representation of a graph
* for our path-finding algorithm
*/
public class Graph {
private final Set<Stop> nodes;
private final Map<Stop, Set<Connection>> connections;
/**
* @param nodes the set of graph nodes
* @param connections the map of all nodes to their edges
*/
public Graph(Set<Stop> nodes, Map<Stop, Set<Connection>> connections) {
this.nodes = nodes;
this.connections = connections;
}
/**
* Returns the set of edges of a node
* @param node the node from which we want to get the edges
* @return the sets of the edges for the given node
*/
public Set<Connection> getConnections(Stop node) {
return connections.get(node);
}
/**
* Returns the set of graph nodes
* @return the set of nodes
*/
public Set<Stop> getNodes() {
return nodes;
}
/**
* Returns the map of all nodes to their edges in the graph
* @return the map of all nodes to their edges
*/
public Map<Stop, Set<Connection>> getConnections() {
return connections;
}
/**
* Add a node to the graph
* @param s the node to add
*/
public void addNode(Stop s) {
nodes.add(s);
}
/**
* Add a connection to the graph
* @param stop the node from which the connection starts
* @param con the connection to add
*/
public void addConnection(Stop stop, Connection con) {
Set<Connection> currentConnections = connections.get(stop);
if (currentConnections == null) {
HashSet<Connection> set = new HashSet<>();
set.add(con);
connections.put(stop, set);
}
else {
currentConnections.add(con);
}
}
/**
* Remove a node from the graph.
* This also removes all connections to and from this node.
* @param s the node to be removed
*/
public void removeNode(Stop s) {
for(Stop stop : nodes) {
if(getConnections(stop) == null) {
continue;
}
ArrayList<Connection> toRemove = new ArrayList<>();
for(Connection c : getConnections(stop)) {
if(c.getStop() == s) {
toRemove.add(c);
}
}
for(Connection c : toRemove) {
getConnections(stop).remove(c);
}
}
nodes.remove(s);
connections.remove(s);
}
}

View file

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

View file

@ -9,6 +9,9 @@ import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* CSV file parser to generate the network graph
*/
public class Parse {
private static final Logger LOGGER = Logger
.getLogger(IDFMNetworkExtractor.class.getName());
@ -42,7 +45,7 @@ public class Parse {
private static final int STOP_TIME = 30;
//Walking speed in m/s
private static final double WALK_SPEED = 1.;
public static final double WALK_SPEED = 1.;
private HashSet<Stop> nodes = new HashSet<>();
private HashMap<Stop, Set<Connection>> connections = new HashMap<>();
@ -182,6 +185,13 @@ public class Parse {
}
}
/**
* Adds schedules to graph stops, parsed from a CSV line
* @param input the current line we want to parse
* @param stopsHashSet the map of stop names to their objects
* @param connections the map of stops to their connections
*/
private static void addSchedule(String[] input, HashMap<String, ArrayList<Stop>> stopsHashSet, HashMap<Stop, Set<Connection>> connections) {
String line = input[0];
@ -211,12 +221,13 @@ public class Parse {
}
}
/**
* Parse CSV files to build the network graph
*/
public void parseFiles(){
IDFMNetworkExtractor.buildFiles();
try {
CSVTools.readCSVFromFile(TRACE_FILE_NAME,
(String[] line) -> addLine(line, nodes, tmp, connections));
@ -228,17 +239,27 @@ public class Parse {
c.sortSchedule();
}
}
} catch (IOException e) {
}
catch (IOException e) {
LOGGER.log(Level.SEVERE, "Error while reading the line paths", e);
}
}
/**
* Returns network graph from parsed CSV files
* @return the graphe of the network
*/
public Graph createGraph() {
return new Graph(nodes, connections);
}
public Finder createFinder(Graph graph) {
return new Finder(graph);
}
public List<Path> getItinerary(Stop src, Stop dst, double startTime ){
Graph graph = new Graph(nodes, connections);
Finder finder = new Finder(graph);
return finder.findPath(src, dst, startTime);
}
}

View file

@ -1,5 +1,8 @@
package fr.u_paris.gla.project.itinerary;
/**
* A representation of a path
*/
public class Path {
private Stop current;
@ -15,6 +18,11 @@ public class Path {
private Connection connection;
/**
* @param current the start stop
* @param connection the connection to the next stop
* @param startTime departure time from node current
*/
public Path(Stop current, Connection connection, double startTime) {
this.current = current;
this.connection = connection;
@ -24,26 +32,50 @@ public class Path {
this.line = connection.getLineName();
}
/**
* Returns the connection used by the path
* @return the connection used
*/
public Connection getConnection(){
return this.connection;
}
/**
* Returns the start stop
* @return the start stop
*/
public Stop getCurrentStop() {
return this.current;
}
/**
* Returns the next stop
* @return the next stop
*/
public Stop getNextStop() {
return next;
}
/**
* Returns stop start time
* @return the time in s
*/
public double getStartTime() {
return this.startTime;
}
/**
* Returns the travel time between the two stops.
* @return the travel time in s
*/
public double travelTime() {
return this.travelTime;
}
/**
* Returns the name of the line taken.
* @return the name of the line
*/
public String getLine() {
return this.line;
}

View file

@ -1,9 +1,15 @@
package fr.u_paris.gla.project.itinerary;
import fr.u_paris.gla.project.utils.GPS;
import java.util.HashSet;
import java.util.Set;
public class Stop implements GraphNode {
/**
* A representation of a stop used as a node
* for the path-finding algorithm.
*/
public class Stop {
// The total number of stops
private static int counter = 0;
@ -20,6 +26,15 @@ public class Stop implements GraphNode {
private double f;
//Maximal speed in m/s
private final double MAX_SPEED = 14.;
/**
* @param line the line passing through the stop
* @param name the name of the stop
* @param latitude the latitude of the stop in decimal degrees (DD)
* @param longitude the longitude of the stop in DD
*/
public Stop(String line, String name, double latitude, double longitude) {
lines = new HashSet<>();
lines.add(line);
@ -32,36 +47,31 @@ public class Stop implements GraphNode {
@Override
public String toString() {
return "Stop{" +
"id=" + id +
", lines=" + lines +
", name='" + name + '\'' +
", latitude=" + latitude +
", longitude=" + longitude +
'}';
return name;
}
@Override
public int getId(){
return id;
}
@Override
/**
* Computes the heuristic cost of the node relative to the goal node
* @param goalNode the node we're trying to reach
* @return the heuristic cost
*/
public double getHeuristicCost(Stop goalNode) {
return 0;
double distance = GPS.distance(this.latitude, this.longitude, goalNode.latitude, goalNode.longitude);
return distance/MAX_SPEED;
}
@Override
public Set<Stop> getNeighbors() {
return null;
}
@Override
public double getCost(Stop neighbor) {
return 0;
}
@Override
public double getF() {
return f;
}
@ -70,21 +80,41 @@ public class Stop implements GraphNode {
this.f = value;
}
/**
* Returns the name of the stop
* @return the name of the stop
*/
public String getName(){
return name;
}
/**
* Returns latitude of the stop
* @return stop latitude in DD
*/
public double getLatitude(){
return latitude;
}
/**
* Returns longitude of the stop
* @return stop longitude in DD
*/
public double getLongitude(){
return longitude;
}
/**
* Add a transport line to the stop
* @param s the line to add
*/
public void addLine(String s){
lines.add(s);
}
/**
* Returns the lines
* @return all transport lines passing through this stop.
*/
public Set<String> getLines() { return this.lines; }
}

View file

@ -17,9 +17,17 @@ public class ApiUtils {
private static final Logger LOGGER = Logger
.getLogger(IDFMNetworkExtractor.class.getName());
// OpenStreetMap API URL
/**
* OpenStreetMap API URL
*/
private static final String OSM_URL = "https://nominatim.openstreetmap.org/search";
/**
* This function returns the GPS location of a string, using OSM API.
* The string can be anything, and adress, a street, a place.
* @param term the term to search
* @return the GPS location, (0,0) if not result
*/
public static double[] getGPSLocation(String term) {
try {
String urlString = String.format("%s?q=%s&format=json", OSM_URL, URLEncoder.encode(term, StandardCharsets.UTF_8));

View file

@ -6,7 +6,6 @@ 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;
@ -33,7 +32,7 @@ public final class CSVTools {
* @param contentLineConsumer the variable used to store the data
* @throws IOException if it's impossible to download the file
*/
private static void readCSVFromInputStream(InputStream is, Consumer<String[]> contentLineConsumer)
public static void readCSVFromInputStream(InputStream is, Consumer<String[]> contentLineConsumer)
throws IOException {
ICSVParser parser = new CSVParserBuilder().withSeparator(';').build();
try (Reader reader = new BufferedReader(
@ -75,8 +74,8 @@ public final class CSVTools {
}
/** Save our current CSV variable's data into an actual file
* @param filename the saved file's name and path
* @param contentLineConsumer our data variable
* @param filename saved file's name and path
* @param contentLinesConsumer our data variable
* @throws IOException if we can't write the data into the file
*/
public static void writeCSVToFile(String filename,
@ -88,20 +87,4 @@ public final class CSVTools {
}
}
}
// /** Save our current CSV variable's data into an actual file
// * @param filename the saved file's name and path
// * @param contentLineConsumer our data variable
// * @throws IOException if we can't write the data into the file
// */
// public static void writeCSVToFile(String filename,
// Stream<String[][]> contentLinesConsumer) throws IOException {
// try (FileWriter writer = new FileWriter(filename, StandardCharsets.UTF_8)) {
// CSVWriterBuilder wBuilder = new CSVWriterBuilder(writer).withSeparator(';');
// try (ICSVWriter csv = wBuilder.build()) {
// contentLinesConsumer.forEachOrdered(line -> Arrays.stream(line).forEach(csv::writeNext));
// }
// }
// }
}

View file

@ -99,22 +99,22 @@ public class CSVStreamProviderTest {
@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
final double TWO_ACCELERATION_DISTANCE = 0.1;
final double MAX_SPEED = 10.0;
// Exemple de distance à tester
double distanceExample = 1.0; // 1 km
// Calcul attendu basé sur la formule fournie
double expected = Math.max(0, distanceExample - TWO_ACCELERATION_DISTANCE) / MAX_SPEED
+ Math.pow(Math.min(distanceExample, TWO_ACCELERATION_DISTANCE) / MAX_SPEED, 2);
+ (2 * Math.sqrt(Math.min(distanceExample, TWO_ACCELERATION_DISTANCE) * TWO_ACCELERATION_DISTANCE) / MAX_SPEED);
// Accès à la méthode distanceToTime via la réflexion
Method method = CSVStreamProvider.class.getDeclaredMethod("distanceToTime", double.class);
Method method = CSVStreamProvider.class.getDeclaredMethod("distanceToTime", double.class, String.class);
method.setAccessible(true);
// Invocation de la méthode distanceToTime et stockage du résultat
double result = (Double) method.invoke(null, distanceExample);
double result = (Double) method.invoke(null, distanceExample, "Bus");
// Assertion pour vérifier si le résultat est conforme à l'attendu
assertEquals(expected, result, "Le calcul du temps à partir de la distance devrait être conforme à l'attendu.");

View file

@ -15,6 +15,7 @@ public class StopEntryTest {
}
*/
/*
//Si le le test testToString du haut ne marche pas essayer celui du bas
@Test
public void testToString() {
@ -23,6 +24,7 @@ public class StopEntryTest {
String expected = "Chatelet [2.346, 48.853]";
assertEquals(expected, stop.toString());
}
*/
//Test de compareTo