Merge branch 'dev' into 'gui-displayres-javadoc'

# Conflicts:
#   src/main/java/fr/u_paris/gla/project/gui/View.java
This commit is contained in:
RODRIGUEZ lucas 2024-05-05 14:36:27 +02:00
commit 7e6c9d8ec7
16 changed files with 90 additions and 127 deletions

6
.gitignore vendored
View file

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

View file

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

View file

@ -64,7 +64,6 @@ public class App {
} }
} }
else { else {
// testRelease();
run(); run();
} }
} }
@ -83,26 +82,6 @@ public class App {
SwingUtilities.invokeLater(() -> new View(graph, finder, s)); SwingUtilities.invokeLater(() -> new View(graph, finder, s));
} }
public static void testRelease(){
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());
}
}
/** @param out the output stream */ /** @param out the output stream */
public static void printAppInfos(PrintStream out) { public static void printAppInfos(PrintStream out) {
Properties props = readApplicationProperties(); Properties props = readApplicationProperties();

View file

@ -290,6 +290,7 @@ public class View extends JFrame {
}); });
} }
}); });
SeeStopButton.addActionListener(f -> { SeeStopButton.addActionListener(f -> {
Connection c; Connection c;
if ((c = (Connection) StopsLinesComboBox.getSelectedItem()) != null) { if ((c = (Connection) StopsLinesComboBox.getSelectedItem()) != null) {
@ -316,35 +317,28 @@ public class View extends JFrame {
} }
}); });
ButtonLocation.addActionListener(new ActionListener() { ButtonLocation.addActionListener(e -> {
@Override
public void actionPerformed(ActionEvent e) {
CardPanel.removeAll();
String cur = TextLocation.getText(); String cur = TextLocation.getText();
if (!cur.isEmpty()) {
CardPanel.removeAll();
LoadStringStops(cur); LoadStringStops(cur);
LoadSearchResultItinerary(searchResPath, modelItinerary); LoadSearchResultItinerary(searchResPath, modelItinerary);
System.out.println("search location clicked with text " + cur);
CardPanel.add(ItineraryPanel); CardPanel.add(ItineraryPanel);
}
CardPanel.repaint(); CardPanel.repaint();
CardPanel.revalidate(); CardPanel.revalidate();
}
}); });
ButtonCoord.addActionListener(new ActionListener() { ButtonCoord.addActionListener(e -> {
@Override
public void actionPerformed(ActionEvent e) {
CardPanel.removeAll();
String cur = TextCoord.getText(); String cur = TextCoord.getText();
System.out.println(cur); if (!cur.isEmpty()) {
CardPanel.removeAll();
LoadStringCoords(cur); LoadStringCoords(cur);
LoadSearchResultItinerary(searchResPath, modelItinerary); LoadSearchResultItinerary(searchResPath, modelItinerary);
System.out.println("search coord clicked with text " + cur);
CardPanel.add(ItineraryPanel); CardPanel.add(ItineraryPanel);
}
CardPanel.repaint(); CardPanel.repaint();
CardPanel.revalidate(); CardPanel.revalidate();
}
}); });
tableStops.addMouseListener(new MouseAdapter() { tableStops.addMouseListener(new MouseAdapter() {
@ -433,16 +427,13 @@ public class View extends JFrame {
* @param stops a String in format (x1,y1);(x2,y2) * @param stops a String in format (x1,y1);(x2,y2)
*/ */
public void LoadStringCoords(String stops){ public void LoadStringCoords(String stops){
System.out.println(stops);
stops = stops.replaceAll("[()]", "").replaceAll(";", ","); stops = stops.replaceAll("[()]", "").replaceAll(";", ",");
String[] stops_array = stops.split(","); String[] stops_array = stops.split(",");
double[] coords = new double[4]; double[] coords = new double[4];
System.out.println(Arrays.toString(stops_array));
for (int i = 0; i < 4; i++){ for (int i = 0; i < 4; i++){
coords[i] = Double.parseDouble(stops_array[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()); searchResPath = (ArrayList<Path>) finder.findPath(coords[0], coords[1], coords[2], coords[3], LocalDateTime.now().toLocalTime().toSecondOfDay());
} }
/** Load all stops related to locations /** Load all stops related to locations
@ -477,21 +468,10 @@ public class View extends JFrame {
count = 0; count = 0;
for (Stop stop : stops) { for (Stop stop : stops) {
// Add a row to the table with Stop's line in the first column and Stop's name in the second column // Add a row to the table with Stop's line in the first column and Stop's name in the second column
model.addRow(new Object[]{String.join(",", stop.getLines()), stop.getName()}); model.addRow(new Object[]{String.join(",", stop.getLines()), stop.getName()});
++count; ++count;
} }
System.out.println(stops.toString());
for (int i = 0; i < model.getRowCount(); i++) {
for (int j = 0; j < model.getColumnCount(); j++) {
System.out.print("valeur at coord " + i +";" + j +": " + model.getValueAt(i, j) + "\t");
}
System.out.println();
}
System.out.println(count);
tableStops.revalidate(); tableStops.revalidate();
tableStops.repaint(); tableStops.repaint();
paneStops.setViewportView(tableStops); paneStops.setViewportView(tableStops);
@ -512,7 +492,6 @@ public class View extends JFrame {
model.setRowCount(0); model.setRowCount(0);
model.setColumnCount(cols); model.setColumnCount(cols);
// Add new rows based on the search results // Add new rows based on the search results
count = 0; count = 0;
Path last = null; Path last = null;
@ -523,24 +502,14 @@ public class View extends JFrame {
int hours = (int) (time / 3600); int hours = (int) (time / 3600);
int minutes = (int) ((time % 3600) / 60); int minutes = (int) ((time % 3600) / 60);
model.addRow(new Object[]{path.getLine(), path.getCurrentStop(), String.format("%02d:%02d", hours, minutes)}); model.addRow(new Object[]{path.getLine(), path.getCurrentStop(), String.format("%02d:%02d", hours, minutes)});
++count; ++count;
last = path; last = path;
} }
} }
if (last != null) model.addRow(new Object[]{last.getLine(), last.getNextStop()}); if (last != null)
model.addRow(new Object[]{last.getLine(), last.getNextStop()});
System.out.println(paths);
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);
tableItinerary.revalidate(); tableItinerary.revalidate();
tableItinerary.repaint(); tableItinerary.repaint();
@ -549,7 +518,6 @@ public class View extends JFrame {
paneItinerary.repaint(); paneItinerary.repaint();
ItineraryPanel.revalidate(); ItineraryPanel.revalidate();
ItineraryPanel.repaint(); ItineraryPanel.repaint();
this.displayTableValues(model);
} }
/** Takes a table's data as argument and displays it /** Takes a table's data as argument and displays it
@ -589,13 +557,4 @@ public class View extends JFrame {
LOGGER.severe("Default desktop browser not set"); LOGGER.severe("Default desktop browser not set");
} }
} }
/*
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));
SwingUtilities.invokeLater(() -> new View(graph, finder, s));
}
*/
} }

View file

@ -60,6 +60,12 @@ public final class CSVImageProvider {
return Arrays.copyOf(this.line, this.line.length); return Arrays.copyOf(this.line, this.line.length);
} }
/**
* This function returns a list of ImagePair, which represents the name of the line and the link to the
* image of the line details.
* The list is created once and then store in a static variable.
* @return an ArrayList of ImagePair
*/
public static ArrayList<ImagePair> getLineImageMap() { public static ArrayList<ImagePair> getLineImageMap() {
if (lineImageMap != null) if (lineImageMap != null)
return lineImageMap; return lineImageMap;
@ -72,10 +78,6 @@ public final class CSVImageProvider {
String detail = line[ImageFormat.LINE_DETAIL_INDEX]; String detail = line[ImageFormat.LINE_DETAIL_INDEX];
String imageUrl = line[ImageFormat.IMAGE_URL_INDEX]; String imageUrl = line[ImageFormat.IMAGE_URL_INDEX];
int index = (int) lineImageMap.stream()
.filter(pair -> pair.getLine().equals(label))
.count();
lineImageMap.add(new ImagePair(label, detail, imageUrl)); lineImageMap.add(new ImagePair(label, detail, imageUrl));
}); });
} }

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() { private void skipToNextDescription() {
if (this.currentDescription.hasNext()) { if (this.currentDescription.hasNext()) {

View file

@ -202,7 +202,7 @@ public final class CSVStreamProvider {
} while (currentSegmentStart == null); } while (currentSegmentStart == null);
} }
/** Store current trace' data as a String array /** Store current trace data as a String array
* @return The newly generated line of text * @return The newly generated line of text
*/ */
public String[] next() { public String[] next() {
@ -271,7 +271,7 @@ public final class CSVStreamProvider {
Double max_speed = max_speed_by_type.get(type); Double max_speed = max_speed_by_type.get(type);
Double two_acc_distance = two_acceleration_distance_by_type.get(type); Double two_acc_distance = two_acceleration_distance_by_type.get(type);
return Math.max(0, distance - two_acc_distance) / max_speed return Math.max(0, distance - two_acc_distance) / max_speed
+ Math.pow(Math.min(distance, two_acc_distance) / max_speed, 2); + 2 * Math.sqrt(Math.min(distance, two_acc_distance) * two_acc_distance)/max_speed;
} }
private void fillTransports(int bif) { private void fillTransports(int bif) {

View file

@ -5,8 +5,19 @@ package fr.u_paris.gla.project.idfm;
* These getters ables a ComboBox to show the label returned by toString, and get a specific value when the object is returned * 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 { public class ImagePair {
/**
* The name of the line
*/
private final String line; private final String line;
/**
* The label that will be shown in the ComboBox
*/
private final String label; private final String label;
/**
* The link of the line details
*/
private final String value; private final String value;
public ImagePair(String label, String label_detail, String value){ public ImagePair(String label, String label_detail, String value){

View file

@ -3,11 +3,6 @@
*/ */
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.
*/ */

View file

@ -87,7 +87,7 @@ public class Connection{
public double getCost(double currentTime) { public double getCost(double currentTime) {
if(this.schedules.size() == 0) { if(this.schedules.size() == 0) {
if(this.lineName.equals("WALK")) { if(this.lineName.equals("WALK") || this.lineName.equals("")) {
return this.time; return this.time;
} }
return this.time + 900; return this.time + 900;

View file

@ -27,7 +27,12 @@ public class Finder {
graph.addNode(fromNode); graph.addNode(fromNode);
graph.addNode(toNode); graph.addNode(toNode);
return findPath(fromNode, toNode, startTime); List<Path> result = findPath(fromNode, toNode, startTime);
graph.removeNode(fromNode);
graph.removeNode(toNode);
return result;
} }
/** /**

View file

@ -1,5 +1,6 @@
package fr.u_paris.gla.project.itinerary; package fr.u_paris.gla.project.itinerary;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -43,6 +44,20 @@ public class Graph {
} }
public void removeNode(Stop s) { 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); nodes.remove(s);
connections.remove(s); connections.remove(s);
} }

View file

@ -1,5 +1,7 @@
package fr.u_paris.gla.project.itinerary; package fr.u_paris.gla.project.itinerary;
import fr.u_paris.gla.project.utils.GPS;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -20,6 +22,9 @@ public class Stop {
private double f; private double f;
//Maximal speed in m/s
private final double MAX_SPEED = 14.;
public Stop(String line, String name, double latitude, double longitude) { public Stop(String line, String name, double latitude, double longitude) {
lines = new HashSet<>(); lines = new HashSet<>();
lines.add(line); lines.add(line);
@ -40,7 +45,8 @@ public class Stop {
} }
public double getHeuristicCost(Stop goalNode) { public double getHeuristicCost(Stop goalNode) {
return 0; double distance = GPS.distance(this.latitude, this.longitude, goalNode.latitude, goalNode.longitude);
return distance/MAX_SPEED;
} }
public Set<Stop> getNeighbors() { public Set<Stop> getNeighbors() {

View file

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

View file

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