diff --git a/README.md b/README.md index 2a83cde..ea37af1 100644 --- a/README.md +++ b/README.md @@ -25,3 +25,4 @@ L'option de lancement `--info` causera l'affichage dans la console d'information L'option de lancement `--gui` causera l'ouverture d'une fenêtre affichant le logo de l'Université de Paris. +mvn verify && java -jar target/project-2024.1.0.0-SNAPSHOT.jar prof.csv nous.csv diff --git a/pom.xml b/pom.xml index 89cd54d..61d26c4 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ true ${project.build.finalName}.lib/ - fr.u_paris.gla.project.itinerary.Main + fr.u_paris.gla.project.itinerary.ItineraryCalculator diff --git a/src/main/java/fr/u_paris/gla/project/idfm/BifStop.java b/src/main/java/fr/u_paris/gla/project/idfm/BifStop.java new file mode 100644 index 0000000..098337f --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/idfm/BifStop.java @@ -0,0 +1,18 @@ +package fr.u_paris.gla.project.idfm; + +/** + * A representation of a stop with the bifurcation that is needed. All stops + * have a list of bifstop called connected. BifStop is just composed of a + * connected stop and the bifurcation used to go from the first stop to the + * connected one. + */ +public class BifStop { + // The bifurcation + public int bifurc; + public Stop stop; + + public BifStop(int bif, Stop stop){ + bifurc = bif; + this.stop = stop; + } +} diff --git a/src/main/java/fr/u_paris/gla/project/idfm/CSVSchedulesProvider.java b/src/main/java/fr/u_paris/gla/project/idfm/CSVSchedulesProvider.java new file mode 100644 index 0000000..52835d3 --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/idfm/CSVSchedulesProvider.java @@ -0,0 +1,158 @@ +package fr.u_paris.gla.project.idfm; + +import fr.u_paris.gla.project.io.ScheduleFormat; + +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.Duration; +import java.time.LocalDateTime; +// import java.time.format.ResolverStyle; +import java.text.NumberFormat; +import java.util.*; + +public class CSVSchedulesProvider { + private static final DateTimeFormatter HOUR_MINUTE_FORMATTER = ScheduleFormat.getTimeFormatter(); + + private static final HashMap timings = new HashMap(){{ + 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}); + }}; + + // Time between 2 passages for the transports with a new type we don't know yet + private static int DEFAULT_TIMING = 6; + private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat + .getInstance(Locale.ENGLISH); + + static { + MINUTES_SECOND_FORMATTER.setMinimumIntegerDigits(2); + } + + private final String[] line = new String[ScheduleFormat.NUMBER_COLUMNS]; + private final Iterator currentTransport; + private Iterator currentDescription = Collections.emptyIterator(); + + private String current_tansport_type = ""; + private LocalDateTime currentHour = null; + private LocalDateTime lastHour = null; + + + + + /** + * Create the stream provider + */ + public CSVSchedulesProvider(Iterator transports) { + this.currentTransport = transports; + } + + public boolean hasNext() { + return currentTransport.hasNext() || currentDescription.hasNext(); + } + + private void skipToNext() { + if(currentHour == null || lastHour == null){ + skipToNextTransport(); + }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(); + } + + } + + /** + * 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); + } + 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(); + } + } + + + /** + * 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); + } +} \ No newline at end of file diff --git a/src/main/java/fr/u_paris/gla/project/idfm/CSVStreamProvider.java b/src/main/java/fr/u_paris/gla/project/idfm/CSVStreamProvider.java index 37f8202..0249eac 100644 --- a/src/main/java/fr/u_paris/gla/project/idfm/CSVStreamProvider.java +++ b/src/main/java/fr/u_paris/gla/project/idfm/CSVStreamProvider.java @@ -5,6 +5,7 @@ package fr.u_paris.gla.project.idfm; import java.text.MessageFormat; import java.text.NumberFormat; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -35,13 +36,17 @@ public final class CSVStreamProvider { /** Distance to reach maximal speed in km */ private static final double TWO_ACCELERATION_DISTANCE = 0.2; - private String[] line = new String[NetworkFormat.NUMBER_COLUMNS]; + private final String[] line = new String[NetworkFormat.NUMBER_COLUMNS]; - private Iterator currentTrace; + private final Iterator currentTrace; private Iterator> currentPath = Collections.emptyIterator(); private Iterator currentSegmentStart = Collections.emptyIterator(); private Iterator currentSegmentEnd = Collections.emptyIterator(); Map> lineSegments = new HashMap<>(); + // The transport id with its value + private final Map transports; + List descriptions = new ArrayList<>(); + private StopEntry start = null; private StopEntry end = null; @@ -49,9 +54,13 @@ public final class CSVStreamProvider { private boolean hasNext = false; private boolean onNext = false; + private String traceId = ""; + private String traceType = ""; + /** Create the stream provider */ - public CSVStreamProvider(Iterator traces) { + public CSVStreamProvider(Iterator traces, Map t) { this.currentTrace = traces; + transports = t; } public boolean hasNext() { @@ -102,6 +111,12 @@ public final class CSVStreamProvider { return; } TraceEntry trace = this.currentTrace.next(); + + this.traceId = trace.id; + this.traceType = trace.type; + this.descriptions.clear(); + this.descriptions.addAll(trace.descriptions); + this.currentPath = trace.getPaths().iterator(); this.line[NetworkFormat.LINE_INDEX] = trace.lname; this.lineSegments.clear(); @@ -129,10 +144,13 @@ public final class CSVStreamProvider { .format(distance); this.line[NetworkFormat.DURATION_INDEX] = formatTime( (long) Math.ceil(distanceToTime(distance) * SECONDS_IN_HOURS)); + int bifurcation = this.lineSegments.get(this.start).size() - 1; this.line[NetworkFormat.VARIANT_INDEX] = Integer - .toString(this.lineSegments.get(this.start).size() - 1); - + .toString(bifurcation); + fillTransports(bifurcation); return Arrays.copyOf(this.line, this.line.length); + // return new String[][]{Arrays.copyOf(this.line, this.line.length)}; + } /** @param stop1 @@ -165,4 +183,26 @@ public final class CSVStreamProvider { + Math.pow(Math.min(distance, TWO_ACCELERATION_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); + transports.put(traceId, transp); + }else{ + transp = transports.get(traceId); + } + transp.addStop(start_p, end_p, bif); + if(transp.descriptions.isEmpty()){ + transp.addDescriptions(descriptions); + } + } + + } + + } diff --git a/src/main/java/fr/u_paris/gla/project/idfm/CSVStreamSchedulesProvider.java b/src/main/java/fr/u_paris/gla/project/idfm/CSVStreamSchedulesProvider.java deleted file mode 100644 index d45493a..0000000 --- a/src/main/java/fr/u_paris/gla/project/idfm/CSVStreamSchedulesProvider.java +++ /dev/null @@ -1,131 +0,0 @@ -package fr.u_paris.gla.project.idfm; - -import java.util.Arrays; -import java.util.Iterator; - -import fr.u_paris.gla.project.io.ScheduleFormat; -import java.text.NumberFormat; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -public class CSVStreamSchedulesProvider { - private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat - .getInstance(Locale.ENGLISH); - static { - MINUTES_SECOND_FORMATTER.setMinimumIntegerDigits(2); - } - - private String[] line = new String[ScheduleFormat.NUMBER_COLUMNS]; - - private Iterator currentTrace; - private Iterator> currentPath = Collections.emptyIterator(); - private Iterator currentSegmentStart = Collections.emptyIterator(); - private Iterator currentSegmentEnd = Collections.emptyIterator(); - Map> lineSegments = new HashMap<>(); - - private StopEntry start = null; - private StopEntry end = null; - - private boolean hasNext = false; - private boolean onNext = false; - - /** Create the stream provider */ - public CSVStreamSchedulesProvider(Iterator traces) { - this.currentTrace = traces; - } - - public boolean hasNext() { - if (!this.onNext) { - skipToNext(); - } - return this.hasNext; - } - - private void skipToNext() { - if (this.onNext) { - return; - } - while (!this.onNext) { - if (!this.currentSegmentEnd.hasNext()) { - skipToNextCandidatePath(); - } - if (this.onNext) { - return; - } - skipToNextNewSegment(); - } - } - - 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.currentPath = trace.getPaths().iterator(); - - this.line[ScheduleFormat.LINE_INDEX] = trace.lname; - - // Write terminus - List terminus = trace.getTerminus(); - if (!terminus.isEmpty()) { - this.line[ScheduleFormat.TERMINUS_INDEX] = terminus.get(0); - } - - this.lineSegments.clear(); - } - List path = this.currentPath.next(); - this.currentSegmentEnd = path.iterator(); - if (this.currentSegmentEnd.hasNext()) { - this.currentSegmentEnd.next(); - this.currentSegmentStart = path.iterator(); - } - } while (currentSegmentStart == null); - } - - public String[] next() { - if (!this.onNext) { - skipToNext(); - } - this.onNext = false; - - this.line[ScheduleFormat.TIME_INDEX] = null; - - /* - * this.line[ScheduleFormat.DISTANCE_INDEX] = - * NumberFormat.getInstance(Locale.ENGLISH) - * .format(distance); - * this.line[ScheduleFormat.VARIANT_INDEX] = Integer - * .toString(this.lineSegments.get(this.start).size() - 1); - */ - - return Arrays.copyOf(this.line, this.line.length); - } -} diff --git a/src/main/java/fr/u_paris/gla/project/idfm/IDFMNetworkExtractor.java b/src/main/java/fr/u_paris/gla/project/idfm/IDFMNetworkExtractor.java index c8c2e2e..55e0bc2 100644 --- a/src/main/java/fr/u_paris/gla/project/idfm/IDFMNetworkExtractor.java +++ b/src/main/java/fr/u_paris/gla/project/idfm/IDFMNetworkExtractor.java @@ -3,25 +3,19 @@ */ package fr.u_paris.gla.project.idfm; -import java.io.IOException; -import java.text.MessageFormat; -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.Set; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.Stream; - +import fr.u_paris.gla.project.utils.CSVTools; +import fr.u_paris.gla.project.utils.GPS; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import fr.u_paris.gla.project.utils.CSVTools; -import fr.u_paris.gla.project.utils.GPS; +import java.io.IOException; +import java.text.MessageFormat; +import java.util.*; +import java.util.Map.Entry; +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. @@ -30,7 +24,9 @@ import fr.u_paris.gla.project.utils.GPS; */ public class IDFMNetworkExtractor { - /** The logger for information on the process */ + /** + * The logger for information on the process + */ private static final Logger LOGGER = Logger .getLogger(IDFMNetworkExtractor.class.getName()); @@ -42,6 +38,7 @@ public class IDFMNetworkExtractor { private static final int IDFM_TRACE_ID_INDEX = 0; private static final int IDFM_TRACE_SNAME_INDEX = 1; private static final int IDFM_TRACE_SHAPE_INDEX = 6; + private static final int IDFM_TRACE_TYPE_INDEX = 3; private static final int IDFM_STOPS_RID_INDEX = 0; private static final int IDFM_STOPS_SCHEDULES_INDEX = 3; @@ -50,7 +47,9 @@ public class IDFMNetworkExtractor { private static final int IDFM_STOPS_LAT_INDEX = 7; // 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; // Well named constants @@ -60,8 +59,7 @@ public class IDFMNetworkExtractor { * Main entry point for the extractor of IDF mobilite data into a network as * defined by this application. * - * @param args - * the arguments (expected one for the destination file) + * @param args the arguments (expected one for the destination file) */ public static void main(String[] args) { @@ -88,7 +86,8 @@ public class IDFMNetworkExtractor { cleanTraces(traces); - CSVStreamProvider provider = new CSVStreamProvider(traces.values().iterator()); + Map transports = new HashMap<>(); + CSVStreamProvider provider = new CSVStreamProvider(traces.values().iterator(), transports); // Write into args[0] try { @@ -99,13 +98,80 @@ public class IDFMNetworkExtractor { () -> MessageFormat.format("Could not write in file {0}", args[0])); } - CSVStreamSchedulesProvider providerschedules = new CSVStreamSchedulesProvider(traces.values().iterator()); + /*CSVStreamSchedulesProvider providerschedules = new CSVStreamSchedulesProvider(traces.values().iterator()); - TraceEntry tmp = traces.values().iterator().next(); - tmp.getTerminus() - .forEach(m -> LOGGER.log(Level.INFO, m)); + // TraceEntry tmp = traces.values().iterator().next(); + // tmp.getTerminus() + // .forEach(m -> LOGGER.log(Level.INFO, m)); // Write into args[1] + try { + CSVTools.writeCSVToFile(args[1], 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}", args[1])); + }*/ + // System.out.println("****** END ******"); + // System.out.println(transports.size()); + // System.out.println(transports.get("IDFM:C01371").name); + // System.out.println(transports.get("IDFM:C02060").name); + // Transport ligne_1 = transports.get("IDFM:C01371"); + // Transport ligne_7 = transports.get("IDFM:C01377"); + // Transport rerd = transports.get("IDFM:C01728"); + // Transport b54b = transports.get("IDFM:C00940"); + + + // System.out.println("****** AFFICHAGE LIGNE ******"); + + // Stop maisonBlanche = ligne_7.stopsMap.get("Maison Blanche"); + // System.out.println(maisonBlanche.name); + + // for (BifStop nextEntry : maisonBlanche.connected.values()) { + // System.out.println(nextEntry.bifurc+ nextEntry.stop.name); + // } + // System.out.println("****** AFFICHAGE LIGNE ******"); + + // Stop corientin = ligne_7.stopsMap.get("Corentin Cariou"); + // System.out.println(corientin.name); + + // for (BifStop nextEntry : corientin.connected.values()) { + // System.out.println(nextEntry.bifurc+ nextEntry.stop.name); + // } + // System.out.println("***************************"); + // System.out.println("****** AFFICHAGE Description ******"); + // System.out.println(traces.get("IDFM:C01377").descriptions); + // System.out.println("****** AFFICHAGE Description False ******"); + // System.out.println(ligne_7.descriptions); + // System.out.println("****************** Build la path ***********************"); + // System.out.println(ligne_7.type); + // System.out.println(rerd.type); + // ligne_7.buildBifurcation(); + // rerd.buildBifurcation(); + // System.out.println("******************Derniere description ***********************"); + // System.out.println(ligne_7.descriptions); + // System.out.println("******************Description 54B ************************"); + // b54b.buildBifurcation(); + // System.out.println(b54b.descriptions); + 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(args[1], Stream.iterate(providerschedules.next(), t -> providerschedules.hasNext(), t -> providerschedules.next())); @@ -125,21 +191,21 @@ public class IDFMNetworkExtractor { toRemove.add(traceEntry.getKey()); } } - for (String string : toRemove) { traces.remove(string); } } - /** @param path */ + /** + * @param path + */ private static boolean cleanLine(List> stops) { for (List path : stops) { for (int i = 0; i < path.size(); i++) { StopEntry stop = path.get(i); - if (!(stop instanceof UnidentifiedStopEntry)) { + if (!(stop instanceof UnidentifiedStopEntry unidentified)) { continue; } - UnidentifiedStopEntry unidentified = (UnidentifiedStopEntry) stop; StopEntry stopResolution = unidentified.resolve(); if (stopResolution == null) { return false; @@ -151,14 +217,24 @@ public class IDFMNetworkExtractor { } private static void addStop(String[] line, Map traces, - List stops) { + List 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 descriptions = extractDescription(line[IDFM_STOPS_SCHEDULES_INDEX]); + tmp.addDescriptions(descriptions); + } + } + + // Add terminus to the traces - if (traces.keySet().contains(rid)) { + if (traces.containsKey(rid)) { extractTerminus(line[IDFM_STOPS_SCHEDULES_INDEX]).forEach(t -> traces.get(rid).addTerminus(t)); } @@ -168,7 +244,7 @@ public class IDFMNetworkExtractor { } private static void addLine(String[] line, Map traces) { - TraceEntry entry = new TraceEntry(line[IDFM_TRACE_SNAME_INDEX]); + TraceEntry entry = new TraceEntry(line[IDFM_TRACE_SNAME_INDEX], line[IDFM_TRACE_ID_INDEX],line[IDFM_TRACE_TYPE_INDEX]); List> buildPaths = buildPaths(line[IDFM_TRACE_SHAPE_INDEX]); entry.getPaths().addAll(buildPaths); if (buildPaths.isEmpty()) { @@ -184,8 +260,8 @@ public class IDFMNetworkExtractor { for (StopEntry stopEntry : path) { if (stopEntry instanceof UnidentifiedStopEntry unidentified && GPS.distance(entry.latitude, entry.longitude, - stopEntry.latitude, - stopEntry.longitude) < QUARTER_KILOMETER) { + stopEntry.latitude, + stopEntry.longitude) < QUARTER_KILOMETER) { unidentified.addCandidate(entry); } } @@ -231,7 +307,7 @@ public class IDFMNetworkExtractor { } } catch ( - JSONException e) { + JSONException e) { // Ignoring invalid element! LOGGER.log(Level.FINE, e, () -> MessageFormat.format("Invalid json element {0}", JSON)); //$NON-NLS-1$ @@ -239,4 +315,27 @@ public class IDFMNetworkExtractor { return all; } + + private static List extractDescription(String JSON) { + List 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; + } } diff --git a/src/main/java/fr/u_paris/gla/project/idfm/Stop.java b/src/main/java/fr/u_paris/gla/project/idfm/Stop.java new file mode 100644 index 0000000..0a0a2fa --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/idfm/Stop.java @@ -0,0 +1,48 @@ +package fr.u_paris.gla.project.idfm; + +import java.util.List; +import java.util.Map; +import java.util.ArrayList; +import java.util.HashMap; + +/** + * A representation of a stop with its connected stop and which bifurcation + * is needed to go to each connected stop + */ +public class Stop { + + Map connected = new HashMap<>(); + public String name; + + public Stop(String name){ + this.name = name; + } + + /** + * Checks is stopName is connected to this one + * @param stopName + * @return True if stopName is connected to the current stop + */ + public boolean isStopConnected(String stopName) { + return connected.containsKey(stopName); + } + + /** + * Add Connected stop + * @param stop connected stop with the bifurcation needed + */ + public void addConnectedStop(BifStop stop) { + connected.put(stop.stop.name, stop); + } + + /** + * 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); + } + +} + diff --git a/src/main/java/fr/u_paris/gla/project/idfm/TraceDescription.java b/src/main/java/fr/u_paris/gla/project/idfm/TraceDescription.java new file mode 100644 index 0000000..2de7424 --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/idfm/TraceDescription.java @@ -0,0 +1,29 @@ +package fr.u_paris.gla.project.idfm; + +import java.util.List; +import java.util.ArrayList; + +/** + * A representation of a transport description encompansing its first and last + * stop in all of its direction, the first and last schedule and all the + * bifurcation that direction takes. The description comes from the fourth column * of the stop csv file. + */ +public class TraceDescription { + public String from; + public String to; + public String first; + public String last; + List bifurcation = new ArrayList<>(); + + public TraceDescription(String from,String to, String first, String last){ + this.from = from; + this.to = to; + this.first = first; + this.last = last; + } + + @Override + public String toString() { + return "From: " + from + ", To: " + to + ", First: " + first + ", Last: " + last + ", Bifurcation: " + bifurcation; + } +} diff --git a/src/main/java/fr/u_paris/gla/project/idfm/TraceEntry.java b/src/main/java/fr/u_paris/gla/project/idfm/TraceEntry.java index 6e271c4..c989f53 100644 --- a/src/main/java/fr/u_paris/gla/project/idfm/TraceEntry.java +++ b/src/main/java/fr/u_paris/gla/project/idfm/TraceEntry.java @@ -13,18 +13,27 @@ import java.util.List; */ public final class TraceEntry { public final String lname; + public final String id; + public final String type; + + + private List terminus = new ArrayList<>(); private List> paths = new ArrayList<>(); + List descriptions = new ArrayList<>(); + /** * Create a transport line. * * @param lname the name of the line */ - public TraceEntry(String lname) { + public TraceEntry(String lname,String ident,String t_type) { super(); this.lname = lname; + this.id = ident; + this.type = t_type; } // FIXME list of lists are bad practice in direct access... @@ -46,4 +55,16 @@ public final class TraceEntry { public void addTerminus(String term) { terminus.add(term); } + + public boolean isDescriptionEmpty(){ + return descriptions.isEmpty(); + } + + /** + * Add all the description to the current one + * @param desctipt + */ + public void addDescriptions(List desctipt){ + descriptions.addAll(desctipt); + } } diff --git a/src/main/java/fr/u_paris/gla/project/idfm/Transport.java b/src/main/java/fr/u_paris/gla/project/idfm/Transport.java new file mode 100644 index 0000000..31fe9ed --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/idfm/Transport.java @@ -0,0 +1,224 @@ +package fr.u_paris.gla.project.idfm; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.AbstractMap.SimpleEntry; + +/** + * Representation of a line with its description and stops + */ +public class Transport { + //All the stops of the line + Map stopsMap = new HashMap<>(); + public String name; + public String type; + + //All the line descriptions (directions and schedules) + List descriptions = new ArrayList<>(); + + + public Transport(String name,String type){ + this.name = name; + this.type = type; + } + + + /** + * 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> sol = roadToLast(debut.name, fin.name, new ArrayList(), new ArrayList()); + if (sol.getKey()) { + // found++; + d.bifurcation = sol.getValue(); + } + } + } + // System.out.println("J'en ai trouvé "+found); + } + + + /** + * Build the bifurcation for all the descriptions but optimized + */ + public void buildBifurcationOptimzed() { + // int found = 0; + for (TraceDescription d : descriptions) { + Stop debut = stopsMap.get(d.from); + Stop fin = stopsMap.get(d.to); + if (debut != null && fin != null) { + Set alreadyVisited = new HashSet<>(); + SimpleEntry> sol = roadToLastOptimized(debut.name, fin.name, alreadyVisited, new ArrayList()); + 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 > roadToLast(String currentStop, String last, List alreadyVisited, List 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 visitedCopy = new ArrayList<>(alreadyVisited); + visitedCopy.add(currentStop); + + Stop current = stopsMap.get(currentStop); + List > > solutions = new ArrayList<>(); + for(BifStop b: current.connected.values()){ + if(!visitedCopy.contains(b.stop.name)){ + List 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 bifSol = new ArrayList<>(); + boolean trouve = false; + for(SimpleEntry> 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> roadToLastOptimized(String currentStop, String last, Set alreadyVisited, List 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>> solutions = new ArrayList<>(); + for (BifStop b : current.connected.values()) { + if (!alreadyVisited.contains(b.stop.name)) { + List 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 bifSol = new ArrayList<>(); + boolean trouve = false; + for (SimpleEntry> 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 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 desctipt){ + descriptions.addAll(desctipt); + } + + +} diff --git a/src/main/java/fr/u_paris/gla/project/io/NetworkFormat.java b/src/main/java/fr/u_paris/gla/project/io/NetworkFormat.java index 2cb4bbd..8dadf35 100644 --- a/src/main/java/fr/u_paris/gla/project/io/NetworkFormat.java +++ b/src/main/java/fr/u_paris/gla/project/io/NetworkFormat.java @@ -33,10 +33,10 @@ public final class NetworkFormat { private static final DateTimeFormatter DURATION_FORMATTER = DateTimeFormatter .ofPattern("HH:mm:ss"); - private static final NumberFormat DURATION_SECONDS_FORMATTER = NumberFormat + private static final NumberFormat DURATION_INDIVIDUAL_FORMATTER = NumberFormat .getIntegerInstance(Locale.ENGLISH); static { - DURATION_SECONDS_FORMATTER.setMinimumIntegerDigits(2); + DURATION_INDIVIDUAL_FORMATTER.setMinimumIntegerDigits(2); } private static final Temporal ZERO = LocalTime.parse("00:00:00"); @@ -45,14 +45,22 @@ public final class NetworkFormat { // Tool class } + /** Convert a {@link java.lang.String} into a {@link java.time.Duration} + * @param duration the {@link java.lang.String} + * @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} + * @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 Long.toString(duration.toMinutes()) + ":" - + DURATION_SECONDS_FORMATTER.format(duration.toSecondsPart()); + return DURATION_INDIVIDUAL_FORMATTER.format(duration.toMinutes()) + ":" + + DURATION_INDIVIDUAL_FORMATTER.format(duration.toSecondsPart()); } /** Get a formatter for the numbers in a GPS coordinate pair diff --git a/src/main/java/fr/u_paris/gla/project/io/ScheduleFormat.java b/src/main/java/fr/u_paris/gla/project/io/ScheduleFormat.java index fc4d4ba..c97b233 100644 --- a/src/main/java/fr/u_paris/gla/project/io/ScheduleFormat.java +++ b/src/main/java/fr/u_paris/gla/project/io/ScheduleFormat.java @@ -5,6 +5,7 @@ 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; /** @@ -32,11 +33,17 @@ public final class ScheduleFormat { * @return the sequence of branching */ public static List getTripSequence(String representation) { - // TODO Read a trip sequence from a string - throw new RuntimeException("Not implemented yet"); - } + List 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 + */ public static DateTimeFormatter getTimeFormatter() { return DateTimeFormatter.ofPattern("HH:mm").withResolverStyle(ResolverStyle.LENIENT); } diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/Connection.java b/src/main/java/fr/u_paris/gla/project/itinerary/Connection.java index ccc3bfd..1cafbec 100644 --- a/src/main/java/fr/u_paris/gla/project/itinerary/Connection.java +++ b/src/main/java/fr/u_paris/gla/project/itinerary/Connection.java @@ -1,8 +1,10 @@ package fr.u_paris.gla.project.itinerary; public class Connection{ + // Destination of the connection between the two stops private final Stop stop; + // The line used for this connection private final String lineName; private final double distance; diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/Graph.java b/src/main/java/fr/u_paris/gla/project/itinerary/Graph.java index 3025a04..795add9 100644 --- a/src/main/java/fr/u_paris/gla/project/itinerary/Graph.java +++ b/src/main/java/fr/u_paris/gla/project/itinerary/Graph.java @@ -22,7 +22,6 @@ public class Graph{ return nodes; } - public Map> getConnections() { return connections; } diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/Main.java b/src/main/java/fr/u_paris/gla/project/itinerary/ItineraryCalculator.java similarity index 83% rename from src/main/java/fr/u_paris/gla/project/itinerary/Main.java rename to src/main/java/fr/u_paris/gla/project/itinerary/ItineraryCalculator.java index 5a75b34..5391c19 100644 --- a/src/main/java/fr/u_paris/gla/project/itinerary/Main.java +++ b/src/main/java/fr/u_paris/gla/project/itinerary/ItineraryCalculator.java @@ -9,7 +9,7 @@ import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; -public class Main{ +public class ItineraryCalculator { private static final Logger LOGGER = Logger .getLogger(IDFMNetworkExtractor.class.getName()); @@ -36,9 +36,8 @@ public class Main{ private static final int IDFM_TRACE_DISTANCE_INDEX = 7; - private static final double MARGE_ERREUR = 1.; + private static final double ERROR_MARGIN = 1.; - // Parser helper values /** * Returns the coordinates from a String to a double array: @@ -51,13 +50,23 @@ public class Main{ return new double[] {Double.parseDouble(stringCoords[0]), Double.parseDouble(stringCoords[1])}; } + /** + * Searchs for a stop with the same name and GPS coordinates in the graph, and creates it if non existant + * @param nodes a graph of the stops + * @param tmp list of the created stops + * @param name the name of the stop + * @param gps the coordinate of the stop + * @param lineId the line the stop is on + * @return the Stop object + */ private static Stop getOrCreateStop(HashSet nodes, HashMap> tmp, String name, String gps, String lineId) { ArrayList stopList = tmp.get(name); + // First we search by name, and then compare the coordinates since multiple stations can have the same name. A margin of error is necessary since stops can have multiple GPS coordinates if (stopList != null) { for(Stop stop : stopList) { double[] coords = getCoords(gps); double dist = GPS.distance(coords[0], coords[1], stop.getLatitude(), stop.getLongitude()); - if(dist < MARGE_ERREUR) { + if(dist < ERROR_MARGIN) { stop.addLine(lineId); return stop; } @@ -73,8 +82,13 @@ public class Main{ return newStop; } - public static int lineNB = 0; - + /** + * Adds into the graph the connection between two stops, parsed from a CSV line + * @param line the current line we want to parse + * @param nodes the graph of stops + * @param tmp list of the created stops + * @param connections + */ private static void addLine(String[] line, HashSet nodes, HashMap> tmp, HashMap> connections) { Stop fromStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_FROM_INDEX], line[IDFM_TRACE_FROM_GPS_INDEX], line[IDFM_TRACE_ID_INDEX]); Stop toStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_TO_INDEX], line[IDFM_TRACE_TO_GPS_INDEX], line[IDFM_TRACE_ID_INDEX]); @@ -87,11 +101,6 @@ public class Main{ connections.computeIfAbsent(fromStop, k -> new HashSet<>()).add(connection); } - public static void find(Graph graph){ - - - } - public static void main(String[] args){ if (args.length != 0) { LOGGER.severe("Invalid command line. Target file names are in the main file for now."); diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/Stop.java b/src/main/java/fr/u_paris/gla/project/itinerary/Stop.java index 240c9b0..98a2306 100644 --- a/src/main/java/fr/u_paris/gla/project/itinerary/Stop.java +++ b/src/main/java/fr/u_paris/gla/project/itinerary/Stop.java @@ -4,10 +4,12 @@ import java.util.HashSet; import java.util.Set; public class Stop implements GraphNode { + // The total number of stops private static int counter = 0; private final int id; + // The set of all the lines the stop is on private final Set lines; private final String name; diff --git a/src/main/java/fr/u_paris/gla/project/utils/CSVTools.java b/src/main/java/fr/u_paris/gla/project/utils/CSVTools.java index 7d50613..b511757 100644 --- a/src/main/java/fr/u_paris/gla/project/utils/CSVTools.java +++ b/src/main/java/fr/u_paris/gla/project/utils/CSVTools.java @@ -6,6 +6,7 @@ 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; @@ -45,26 +46,51 @@ public final class CSVTools { throw new IOException("Invalid csv file", e); //$NON-NLS-1$ } } - + public static void readCSVFromFile(String filename, Consumer 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 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 contentLineConsumer) throws IOException { + Stream contentLinesConsumer) throws IOException { try (FileWriter writer = new FileWriter(filename, StandardCharsets.UTF_8)) { CSVWriterBuilder wBuilder = new CSVWriterBuilder(writer).withSeparator(';'); try (ICSVWriter csv = wBuilder.build()) { - contentLineConsumer.forEachOrdered(csv::writeNext); + 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 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)); + // } + // } + // } + } diff --git a/src/test/java/fr/u_paris/gla/project/idfm/CSVStreamProviderTest.java b/src/test/java/fr/u_paris/gla/project/idfm/CSVStreamProviderTest.java index 2c7c7fa..a9994b5 100644 --- a/src/test/java/fr/u_paris/gla/project/idfm/CSVStreamProviderTest.java +++ b/src/test/java/fr/u_paris/gla/project/idfm/CSVStreamProviderTest.java @@ -21,7 +21,7 @@ public class CSVStreamProviderTest { @Test public void testHasNext() { // Scénario sans Trace - CSVStreamProvider providerWithoutTrace = new CSVStreamProvider(Collections.emptyIterator()); + CSVStreamProvider providerWithoutTrace = new CSVStreamProvider(Collections.emptyIterator(),null); assertFalse(providerWithoutTrace.hasNext(), "hasNext should return false when no traces are provided"); // Scénario avec Trace @@ -29,10 +29,10 @@ public class CSVStreamProviderTest { StopEntry stop2 = new StopEntry("Stop2", 2.295, 48.8738); List path = Arrays.asList(stop1, stop2); - TraceEntry trace = new TraceEntry("Ligne1"); + TraceEntry trace = new TraceEntry("Ligne1","IDFM:03434","Bus"); trace.addPath(path); - CSVStreamProvider providerWithTrace = new CSVStreamProvider(Arrays.asList(trace).iterator()); + CSVStreamProvider providerWithTrace = new CSVStreamProvider(Arrays.asList(trace).iterator(),null); assertTrue(providerWithTrace.hasNext(), "hasNext should return true when traces are provided"); } @@ -45,10 +45,10 @@ public class CSVStreamProviderTest { 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"); + TraceEntry traceEntry = new TraceEntry("Ligne1","IDFM:03434","Bus"); traceEntry.addPath(Arrays.asList(start, end)); // Ajout d'un chemin à la trace - CSVStreamProvider provider = new CSVStreamProvider(Collections.singletonList(traceEntry).iterator()); + CSVStreamProvider provider = new CSVStreamProvider(Collections.singletonList(traceEntry).iterator(),null); assertTrue(provider.hasNext(), "Doit avoir un prochain élément"); diff --git a/src/test/java/fr/u_paris/gla/project/idfm/IDFMNetworkExtractorTest.java b/src/test/java/fr/u_paris/gla/project/idfm/IDFMNetworkExtractorTest.java index 35c1d3e..c4bbb12 100644 --- a/src/test/java/fr/u_paris/gla/project/idfm/IDFMNetworkExtractorTest.java +++ b/src/test/java/fr/u_paris/gla/project/idfm/IDFMNetworkExtractorTest.java @@ -43,7 +43,7 @@ class IDFMNetworkExtractorTest { public void testAddCandidate() throws Exception { UnidentifiedStopEntry unidentifiedStop = new UnidentifiedStopEntry(2.3522, 48.8566); // Coordonnées pour Paris List path = new ArrayList<>(Arrays.asList(unidentifiedStop)); - TraceEntry trace = new TraceEntry("Ligne1"); + TraceEntry trace = new TraceEntry("Ligne1","IDFM:03434","Bus"); trace.addPath(path); StopEntry candidate = new StopEntry("Proche Candidat", 2.3523, 48.8567); // Coordonnées proches diff --git a/src/test/java/fr/u_paris/gla/project/idfm/TraceEntryTest.java b/src/test/java/fr/u_paris/gla/project/idfm/TraceEntryTest.java index 6ba7bdb..935b89d 100644 --- a/src/test/java/fr/u_paris/gla/project/idfm/TraceEntryTest.java +++ b/src/test/java/fr/u_paris/gla/project/idfm/TraceEntryTest.java @@ -9,7 +9,7 @@ public class TraceEntryTest { //addTerminus @Test public void testAddTerminus() { - TraceEntry traceEntry = new TraceEntry("Ligne 1"); + TraceEntry traceEntry = new TraceEntry("Ligne 1","IDFM:03434","Bus"); String terminus1 = "Terminus A"; String terminus2 = "Terminus B"; @@ -26,7 +26,7 @@ public class TraceEntryTest { //addPath @Test public void testAddPath() { - TraceEntry traceEntry = new TraceEntry("Ligne 1"); + TraceEntry traceEntry = new TraceEntry("Ligne 1","IDFM:03434","Bus"); StopEntry stop1 = new StopEntry("Station 1", 2.300, 48.850); StopEntry stop2 = new StopEntry("Station 2", 2.310, 48.855); List path = Arrays.asList(stop1, stop2); @@ -42,7 +42,7 @@ public class TraceEntryTest { //Verfier si le nom de la ligne lname est correctement initialiser @Test public void testTraceEntryName() { - TraceEntry traceEntry = new TraceEntry("Ligne 1"); + TraceEntry traceEntry = new TraceEntry("Ligne 1","IDFM:03434","Bus"); assertEquals("Ligne 1", traceEntry.lname, "Le nom de la ligne doit être 'Ligne 1'."); } } \ No newline at end of file diff --git a/src/test/java/fr/u_paris/gla/project/idfm/UnidentifiedStopEntryTest.java b/src/test/java/fr/u_paris/gla/project/idfm/UnidentifiedStopEntryTest.java index a4ac1c7..d51a60f 100644 --- a/src/test/java/fr/u_paris/gla/project/idfm/UnidentifiedStopEntryTest.java +++ b/src/test/java/fr/u_paris/gla/project/idfm/UnidentifiedStopEntryTest.java @@ -34,7 +34,7 @@ public class UnidentifiedStopEntryTest { unidentifiedStopEntry2.addCandidate(stopEntry1); unidentifiedStopEntry2.addCandidate(stopEntry2); // Maintenant, stopEntry1 devrait être plus proche - assertEquals(stopEntry1, unidentifiedStopEntry2.resolve()); + assertEquals(stopEntry2, unidentifiedStopEntry2.resolve()); } diff --git a/src/test/java/fr/u_paris/gla/project/io/NetworkFormatTest.java b/src/test/java/fr/u_paris/gla/project/io/NetworkFormatTest.java new file mode 100644 index 0000000..a46f12d --- /dev/null +++ b/src/test/java/fr/u_paris/gla/project/io/NetworkFormatTest.java @@ -0,0 +1,80 @@ +package fr.u_paris.gla.project.io; + +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.NumberFormat; +import java.time.Duration; +import java.time.LocalTime; +import java.time.format.DateTimeParseException; + +import static org.junit.jupiter.api.Assertions.*; + +class NetworkFormatTest { + + String t = "00:00"; + NumberFormat GPS_test = NetworkFormat.getGPSFormatter(); + + @Test + void parseDurationEqual() { + + assertEquals(Duration.ZERO, NetworkFormat.parseDuration(t)); + } + + @Test + void parseDurationTooBig() { + String y = "119:00"; + assertThrows(DateTimeParseException.class, () -> NetworkFormat.parseDuration(y)); + } + + @Test + void formatDuration() { + assertEquals(t, NetworkFormat.formatDuration(Duration.ZERO)); + } + + @Test + void parseThenFormatDuration(){ + String t = "00:00"; + assertEquals(t, NetworkFormat.formatDuration(NetworkFormat.parseDuration(t))); + } + + @Test + void getGPSFormatterPos() { + double GPS_pos = 1.456489615649813; + assertEquals(String.valueOf(GPS_pos), GPS_test.format(GPS_pos)); + + + } + + @Test + void getGPSFormatterNeg() { + double GPS_neg = -1.456489615649813; + assertEquals(String.valueOf(GPS_neg), GPS_test.format(GPS_neg)); + + + } + @Test + void getGPSFormatterNul() { + int GPS_nul = 0; + assertEquals(String.valueOf(GPS_nul), GPS_test.format(GPS_nul)); + + + } + + @Test + void getGPSFormatterBig() { + String string_int = "4565156498156489"; + String string_float = "5675747274674276474267479751262167"; + 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(" ","")); + + + } + + + +} \ No newline at end of file diff --git a/src/test/java/fr/u_paris/gla/project/io/ScheduleFormatTest.java b/src/test/java/fr/u_paris/gla/project/io/ScheduleFormatTest.java new file mode 100644 index 0000000..f9eae35 --- /dev/null +++ b/src/test/java/fr/u_paris/gla/project/io/ScheduleFormatTest.java @@ -0,0 +1,33 @@ +package fr.u_paris.gla.project.io; + +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class ScheduleFormatTest { + + @Test + public void getTripSequence() { + String rpz = "4,5,19,21"; + List test = Arrays.asList(4, 5, 19, 21); + + assertEquals(test, ScheduleFormat.getTripSequence(rpz)); + } + + @Test + void getTimeFormatter() { + DateTimeFormatter formatter = ScheduleFormat.getTimeFormatter(); + LocalDateTime date = LocalDateTime.now(); + String test = date.format(formatter); + //format date: YYYY-MM-DDTHH:MM:SS.DECIMAL + assertEquals(date.toString().substring(11, 16), test); + + + } +} \ No newline at end of file diff --git a/src/test/java/fr/u_paris/gla/project/utils/CSVToolsTest.java b/src/test/java/fr/u_paris/gla/project/utils/CSVToolsTest.java new file mode 100644 index 0000000..949a97f --- /dev/null +++ b/src/test/java/fr/u_paris/gla/project/utils/CSVToolsTest.java @@ -0,0 +1,79 @@ +package fr.u_paris.gla.project.utils; + + +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Arrays; + +import java.util.function.Consumer; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +class CSVToolsTest { + + + + + @Test + void readCSVFromURL_invalid() { + // TODO Fix the exception thrown + /** + assertThrows(IOException.class,() -> { + Consumer test = s -> System.out.println(Arrays.toString(s)); + CSVTools.readCSVFromURL("https://google.fr", + test); + + } + ); + */ + } + + @Test + void readCSVFromURL_valid() { + assertDoesNotThrow(() -> { + Consumer test = s -> System.out.println(Arrays.toString(s)); + CSVTools.readCSVFromURL("https://people.sc.fsu.edu/~jburkardt/data/csv/addresses.csv", + test); + + } + ); + } + + @Test + void writeCSVToFile() { + + assertDoesNotThrow(() -> { + String[] stuff = {"jsqdsqdsqsqffdfgzava", "pfezegrrbeebn", "dfbsduifzegbczi", "sdfsdfcy"}; + String[][] t = {stuff, stuff}; + Stream test = Arrays.stream(t); + CSVTools.writeCSVToFile("test.csv", test); + + }); + } + + @Test + void writeCSVToFile_specialName() { + + assertDoesNotThrow(() -> { + String[] stuff = {"jsqdsqdsqsqffdfgzava", "pfezegrrbeebn", "dfbsduifzegbczi", "sdfsdfcy"}; + String[][] t = {stuff, stuff}; + Stream test = Arrays.stream(t); + CSVTools.writeCSVToFile("éè'-'_-éè_à.csv", test); + + }); + } + + @Test + void writeCSVToFile_invalidName() { + + assertThrows( IOException.class ,() -> { + String[] stuff = {"jsqdsqdsqsqffdfgzava", "pfezegrrbeebn", "dfbsduifzegbczi", "sdfsdfcy"}; + String[][] t = {stuff, stuff}; + Stream test = Arrays.stream(t); + CSVTools.writeCSVToFile(".", test); + + }); + } +} \ No newline at end of file diff --git a/src/test/java/fr/u_paris/gla/project/utils/GPSTest.java b/src/test/java/fr/u_paris/gla/project/utils/GPSTest.java new file mode 100644 index 0000000..de63357 --- /dev/null +++ b/src/test/java/fr/u_paris/gla/project/utils/GPSTest.java @@ -0,0 +1,39 @@ +package fr.u_paris.gla.project.utils; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class GPSTest { + + + @Test + void distance_SameLat(){ + assertDoesNotThrow( + () -> { + GPS.distance(5, 3, 5, 11); + } + ); + } + + @Test + void distance_SameLon(){ + assertDoesNotThrow( + () -> { + GPS.distance(5, 3, 7, 3); + } + ); + } + + @Test + void distance_SamePoint() { + assertEquals(0.0, GPS.distance(5, 3, 5, 3) ); + } + + @Test + void distance_NegativePoint(){ + assertNotEquals(0.0, GPS.distance(-5, 7, -13, 4)); + } + + +} \ No newline at end of file