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/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..cc81298 --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/idfm/BifStop.java @@ -0,0 +1,11 @@ +package fr.u_paris.gla.project.idfm; + +public class BifStop { + public int bifurc; + public Stop stop; + + public BifStop(int bif, Stop s){ + bifurc = bif; + stop = s; + } +} 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..b06035b --- /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.*; + +import org.apache.commons.lang3.ObjectUtils.Null; +public class CSVSchedulesProvider { + private static final DateTimeFormatter HOUR_MINUTE_FORMATTER = ScheduleFormat.getTimeFormatter(); + // private static final HashMap timings = new HashMap(){{ + // put("Bus", new int[]{45, 50}); + // put("Funicular", new int[]{120, 70}); + // put("Tram", new int[]{72, 60}); + // put("Rail", new int[]{120, 60,50}); + // put("Subway", new int[]{50, 45}); + // }}; + 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}); + }}; + + private static int DEFAULT_TIMING = 6; + // private static int MINUTES_BEFORE_LAST_DEPARTURE = 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(); + } + + } + + private void skipToNextDescription() { + if (this.currentDescription.hasNext()) { + TraceDescription description = this.currentDescription.next(); + // hours_count = 0; + // current_time = description.first; + // last_time = description.last; + currentHour = convertIntoLocalDateTime(description.first); + lastHour = convertIntoLocalDateTime(description.last); + // System.out.println("** SkipTOnextD: last hour est "+lastHour+" first est "+currentHour+" desc.last est "+description.last+ " et desc.first est "+description.first); + + + 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(); + } + } + + private void skipToNextTransport() { + if (this.currentTransport.hasNext()) { + Transport transport = this.currentTransport.next(); + this.line[ScheduleFormat.LINE_INDEX] = transport.name; + // System.out.println("Changement de transport"+transport.name); + + // transport.buildBifurcation(); + current_tansport_type = transport.type; + this.currentDescription = transport.descriptions.iterator(); + skipToNextDescription(); + } else { + + } + } + + public String[][] next() { + if (!hasNext()) { + return null; + } + skipToNext(); + return new String[][]{Arrays.copyOf(this.line, this.line.length)}; + + } + + 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(); + } + + private static long calculateDuration(String debut, String dernier) { + LocalTime debutTime = LocalTime.parse(debut, HOUR_MINUTE_FORMATTER); + LocalTime dernierTime = LocalTime.parse(dernier, HOUR_MINUTE_FORMATTER); + + Duration difference = Duration.between(debutTime, dernierTime); + return difference.toMinutes(); + } + + 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]; + } + + public static LocalDateTime convertIntoLocalDateTime(String heureMinute) { + LocalDateTime aujourdHui = LocalDateTime.now(); + LocalTime time = LocalTime.parse(heureMinute, 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..3a48c1a 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(); @@ -115,7 +130,7 @@ public final class CSVStreamProvider { } while (currentSegmentStart == null); } - public String[] next() { + public String[][] next() { if (!this.onNext) { skipToNext(); } @@ -129,10 +144,11 @@ 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); - - return Arrays.copyOf(this.line, this.line.length); + .toString(bifurcation); + fillTransports(bifurcation); + return new String[][]{Arrays.copyOf(this.line, this.line.length)}; } /** @param stop1 @@ -165,4 +181,23 @@ public final class CSVStreamProvider { + Math.pow(Math.min(distance, TWO_ACCELERATION_DISTANCE) / MAX_SPEED, 2); } + private void fillTransports(int bif) { + 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..eabed68 --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/idfm/Stop.java @@ -0,0 +1,52 @@ +package fr.u_paris.gla.project.idfm; + +import java.util.List; +import java.util.Map; +import java.util.ArrayList; +import java.util.HashMap; + +public class Stop { + + Map connected = new HashMap<>(); + public String name; + + public Stop(String n){ + name = n; + } + + // public boolean isStopConnected(String stopName) { + // // for (BifStop b : connected) { + // // if (b.stop.name.equals(stopName)) { + // // return true; + // // } + // // } + // // return false; + // return getStop(stopName) != null; + // } + + // public Stop getStop(String stopName) { + // // if (this.name.equals(stopName)) { + // // return this; + // // } + // // for (BifStop b : connected) { + // // if (b.stop.name.equals(stopName)) { + // // return b.stop; + // // } + // // } + // // return null; + // return transport.getStopFromIndex(stopName); + // } + public boolean isStopConnected(String stopName) { + return connected.containsKey(stopName); + } + + public void addConnectedStop(BifStop stop) { + connected.put(stop.stop.name, stop); + } + + 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..5f86d26 --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/idfm/TraceDescription.java @@ -0,0 +1,24 @@ +package fr.u_paris.gla.project.idfm; + +import java.util.List; +import java.util.ArrayList; + +public class TraceDescription { + public String from; + public String to; + public String first; + public String last; + List bifurcation = new ArrayList<>(); + + public TraceDescription(String fr,String t, String f, String l){ + from = fr; + to = t; + first = f; + last = l; + } + + @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..5dd2404 --- /dev/null +++ b/src/main/java/fr/u_paris/gla/project/idfm/Transport.java @@ -0,0 +1,214 @@ +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; + + +public class Transport { + Map stopsMap = new HashMap<>(); + public String name; + public String type; + List descriptions = new ArrayList<>(); + + + public Transport(String n,String t_type){ + name = n; + type = t_type; + } + + 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, debut.name, fin.name, new ArrayList(), new ArrayList()); + if (sol.getKey()) { + found++; + d.bifurcation = sol.getValue(); + } + } + } + // System.out.println("J'en ai trouvé "+found); + } + + 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<>(); // Utiliser un HashSet pour les arrêts déjà visités + SimpleEntry> sol = roadToLastOptimized(debut.name, debut.name, fin.name, alreadyVisited, new ArrayList()); + if (sol.getKey()) { + found++; + d.bifurcation = sol.getValue(); + } + } + } + // System.out.println("J'en ai trouvé " + found); +} + + public boolean isTerminus(String stop){ + for(TraceDescription t: descriptions){ + if(stop.equals(t.first) || stop.equals(t.last)) + return true; + } + return false; + } + + public SimpleEntry > roadToLast(String currentStop,String first, String last, List alreadyVisited, List bif){ + + if(currentStop.equals(last)){ + return new SimpleEntry<>(true,bif); + } + + //Checker if the current stop is the bad terminus + if(isTerminus(currentStop)){ + return new SimpleEntry<>(false,bif); + } + 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<>(bif); + if(b.bifurc!= 0) + bifCopy.add(b.bifurc); + solutions.add(roadToLast(b.stop.name, first, 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) ; + } + + public SimpleEntry> roadToLastOptimized(String currentStop, String first, String last, Set alreadyVisited, List bif) { + if (currentStop.equals(last)) { + return new SimpleEntry<>(true, bif); + } + + // Checker if the current stop is the bad terminus + if (isTerminus(currentStop)) { + return new SimpleEntry<>(false, bif); + } + + 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<>(bif); + if (b.bifurc != 0) { + bifCopy.add(b.bifurc); + } + solutions.add(roadToLastOptimized(b.stop.name, first, 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); +} + + + 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); + } + + // public void addStop(String start,String end,int bifurcation){ + // Stop start_stop; + // Stop end_stop; + // if (!stopsMap.containsKey(start)){ + // start_stop = new Stop(start); + // stopsMap.put(start, start_stop); + // }else{ + // start_stop = stopsMap.get(start); + // } + + // if (!stopsMap.containsKey(end)){ + // end_stop = new Stop(end); + // stopsMap.put(end, end_stop); + // }else{ + // end_stop = stopsMap.get(end); + // } + // start_stop.connected.add( new BifStop(bifurcation,end_stop) ); + + // } + + + /** + * + * @param stopsMap + * @param start + * @param end + * @return true if the start stop has been added before the end stop + */ + public boolean startBeforeEnd( String start, String end) { + for (String key : stopsMap.keySet()) { + if (key.equals(start)) { + return true; + } + if (key.equals(end)) { + return false; + } + } + return false; + } + + // 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) { + // 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/utils/CSVTools.java b/src/main/java/fr/u_paris/gla/project/utils/CSVTools.java index d87442d..9886b4d 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; @@ -68,11 +69,11 @@ public final class CSVTools { * @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(line -> Arrays.stream(line).forEach(csv::writeNext)); } } }