Merge branch 'horraires' into 'idf-mobilite-net'

Schedule data implementation

See merge request gla-groupe-3/projet!7
This commit is contained in:
Mylloon 2024-04-06 10:46:08 +02:00
commit 62fd2e8bcd
11 changed files with 660 additions and 175 deletions

View file

@ -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

View file

@ -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;
}
}

View file

@ -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<String, int[]> timings = new HashMap<String, int[]>(){{
// 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<String, int[]> timings = new HashMap<String, int[]>(){{
put("Bus", new int[]{11, 8, 7});
put("Funicular", new int[]{15, 25, 20});
put("Tram", new int[]{6, 7, 8, 9});
put("Rail", new int[]{10, 11,15,12,20});
put("Subway", new int[]{4, 2, 6,3,3,4});
}};
private static 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<Transport> currentTransport;
private Iterator<TraceDescription> currentDescription = Collections.emptyIterator();
private String current_tansport_type = "";
private LocalDateTime currentHour = null;
private LocalDateTime lastHour = null;
/**
* Create the stream provider
*/
public CSVSchedulesProvider(Iterator<Transport> transports) {
this.currentTransport = transports;
}
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);
}
}

View file

@ -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<TraceEntry> currentTrace;
private final Iterator<TraceEntry> currentTrace;
private Iterator<List<StopEntry>> currentPath = Collections.emptyIterator();
private Iterator<StopEntry> currentSegmentStart = Collections.emptyIterator();
private Iterator<StopEntry> currentSegmentEnd = Collections.emptyIterator();
Map<StopEntry, Set<StopEntry>> lineSegments = new HashMap<>();
// The transport id with its value
private final Map<String, Transport> transports;
List <TraceDescription> 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<TraceEntry> traces) {
public CSVStreamProvider(Iterator<TraceEntry> traces, Map<String, Transport> 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);
}
}
}

View file

@ -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<TraceEntry> currentTrace;
private Iterator<List<StopEntry>> currentPath = Collections.emptyIterator();
private Iterator<StopEntry> currentSegmentStart = Collections.emptyIterator();
private Iterator<StopEntry> currentSegmentEnd = Collections.emptyIterator();
Map<StopEntry, Set<StopEntry>> 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<TraceEntry> 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<String> terminus = trace.getTerminus();
if (!terminus.isEmpty()) {
this.line[ScheduleFormat.TERMINUS_INDEX] = terminus.get(0);
}
this.lineSegments.clear();
}
List<StopEntry> path = this.currentPath.next();
this.currentSegmentEnd = path.iterator();
if (this.currentSegmentEnd.hasNext()) {
this.currentSegmentEnd.next();
this.currentSegmentStart = path.iterator();
}
} while (currentSegmentStart == null);
}
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);
}
}

View file

@ -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<String, Transport> 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<List<StopEntry>> stops) {
for (List<StopEntry> path : stops) {
for (int i = 0; i < path.size(); i++) {
StopEntry stop = path.get(i);
if (!(stop instanceof UnidentifiedStopEntry)) {
if (!(stop instanceof UnidentifiedStopEntry unidentified)) {
continue;
}
UnidentifiedStopEntry unidentified = (UnidentifiedStopEntry) stop;
StopEntry stopResolution = unidentified.resolve();
if (stopResolution == null) {
return false;
@ -157,8 +223,18 @@ public class IDFMNetworkExtractor {
Double.parseDouble(line[IDFM_STOPS_LAT_INDEX]));
String rid = line[IDFM_STOPS_RID_INDEX];
//Add traces description if it's empty
if (traces.containsKey(rid)) {
TraceEntry tmp = traces.get(rid);
if (tmp.isDescriptionEmpty()) {
List<TraceDescription> descriptions = extractDescription(line[IDFM_STOPS_SCHEDULES_INDEX]);
tmp.addDescriptions(descriptions);
}
}
// 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<String, TraceEntry> 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<List<StopEntry>> buildPaths = buildPaths(line[IDFM_TRACE_SHAPE_INDEX]);
entry.getPaths().addAll(buildPaths);
if (buildPaths.isEmpty()) {
@ -239,4 +315,27 @@ public class IDFMNetworkExtractor {
return all;
}
private static List<TraceDescription> extractDescription(String JSON) {
List<TraceDescription> all = new ArrayList<>();
try {
JSONArray schedules = new JSONArray(JSON);
for (int i = 0; i < schedules.length(); i++) {
JSONObject stop = schedules.getJSONObject(i);
String from = stop.getString("from");
String to = stop.getString("to");
String first = stop.getString("first");
String last = stop.getString("last");
//We skip the lines where from equals to
// if(from.compareTo(to) != 0){
all.add(new TraceDescription(from, to, first, last));
// }
}
} catch (JSONException e) {
// Ignoring invalid element!
// e.printStackTrace();
}
return all;
}
}

View file

@ -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<String, BifStop> 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);
}
}

View file

@ -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<Integer> 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;
}
}

View file

@ -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<String> terminus = new ArrayList<>();
private List<List<StopEntry>> paths = new ArrayList<>();
List <TraceDescription> 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<TraceDescription> desctipt){
descriptions.addAll(desctipt);
}
}

View file

@ -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<String, Stop> stopsMap = new HashMap<>();
public String name;
public String type;
List <TraceDescription> 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<Boolean, List<Integer>> sol = roadToLast(debut.name, debut.name, fin.name, new ArrayList<String>(), new ArrayList<Integer>());
if (sol.getKey()) {
found++;
d.bifurcation = sol.getValue();
}
}
}
// System.out.println("J'en ai trouvé "+found);
}
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<String> alreadyVisited = new HashSet<>(); // Utiliser un HashSet pour les arrêts déjà visités
SimpleEntry<Boolean, List<Integer>> sol = roadToLastOptimized(debut.name, debut.name, fin.name, alreadyVisited, new ArrayList<Integer>());
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<Boolean,List<Integer> > roadToLast(String currentStop,String first, String last, List<String> alreadyVisited, List<Integer> 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<String> visitedCopy = new ArrayList<>(alreadyVisited);
visitedCopy.add(currentStop);
Stop current = stopsMap.get(currentStop);
List <SimpleEntry<Boolean,List<Integer>> > solutions = new ArrayList<>();
for(BifStop b: current.connected.values()){
if(!visitedCopy.contains(b.stop.name)){
List<Integer> bifCopy = new ArrayList<>(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<Integer> bifSol = new ArrayList<>();
boolean trouve = false;
for(SimpleEntry<Boolean,List<Integer>> se: solutions){
if(se.getKey()){
trouve = true;
bifSol = se.getValue();
}
}
return new SimpleEntry<>(trouve,bifSol) ;
}
public SimpleEntry<Boolean, List<Integer>> roadToLastOptimized(String currentStop, String first, String last, Set<String> alreadyVisited, List<Integer> 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<SimpleEntry<Boolean, List<Integer>>> solutions = new ArrayList<>();
for (BifStop b : current.connected.values()) {
if (!alreadyVisited.contains(b.stop.name)) {
List<Integer> 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<Integer> bifSol = new ArrayList<>();
boolean trouve = false;
for (SimpleEntry<Boolean, List<Integer>> se : solutions) {
if (se.getKey()) {
trouve = true;
bifSol = se.getValue();
break; // Exit loop if a solution is found
}
}
alreadyVisited.remove(currentStop); // Remove current stop from visited after processing
return new SimpleEntry<>(trouve, bifSol);
}
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<String, Stop> 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<TraceDescription> desctipt){
descriptions.addAll(desctipt);
}
}

View file

@ -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<String[]> contentLineConsumer) throws IOException {
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()) {
contentLineConsumer.forEachOrdered(csv::writeNext);
contentLinesConsumer.forEachOrdered(line -> Arrays.stream(line).forEach(csv::writeNext));
}
}
}