Add departures

Co-authored-by: Ange Herman KOUE-HEMAZRO <kankoe-ange-herman.koue-hemazro@etu.u-paris.fr>
This commit is contained in:
Mylloon 2024-03-08 23:35:51 +01:00
parent 5727710944
commit 2f0114dac8
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
4 changed files with 237 additions and 33 deletions

View file

@ -0,0 +1,140 @@
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.MessageFormat;
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;
import fr.u_paris.gla.project.utils.GPS;
public class CSVStreamSchedulesProvider {
/*
* private static final NumberFormat GPS_FORMATTER = ScheduleFormat
* .getGPSFormatter();
*/
private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat
.getInstance(Locale.ENGLISH);
static {
MINUTES_SECOND_FORMATTER.setMinimumIntegerDigits(2);
}
/** Number of seconds in a minute. */
private static final int SECONDS_IN_MINUTES = 60;
private static final long SECONDS_IN_HOURS = 3_600;
// Magically chosen values
/** Maximal speed in km/h */
private static final double MAX_SPEED = 5;
/** Distance to reach maximal speed in km */
private static final double TWO_ACCELERATION_DISTANCE = 0.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;
this.line[ScheduleFormat.TERMINUS_INDEX] = trace.getTerminus().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

@ -1,5 +1,5 @@
/** /**
* *
*/ */
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
@ -23,9 +23,11 @@ import org.json.JSONObject;
import fr.u_paris.gla.project.utils.CSVTools; import fr.u_paris.gla.project.utils.CSVTools;
import fr.u_paris.gla.project.utils.GPS; import fr.u_paris.gla.project.utils.GPS;
/** Code of an extractor for the data from IDF mobilite. /**
* * Code of an extractor for the data from IDF mobilite.
* @author Emmanuel Bigeon */ *
* @author Emmanuel Bigeon
*/
public class IDFMNetworkExtractor { public class IDFMNetworkExtractor {
/** The logger for information on the process */ /** The logger for information on the process */
@ -37,14 +39,15 @@ public class IDFMNetworkExtractor {
private static final String STOPS_FILE_URL = "https://data.iledefrance-mobilites.fr/api/explore/v2.1/catalog/datasets/arrets-lignes/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B"; private static final String STOPS_FILE_URL = "https://data.iledefrance-mobilites.fr/api/explore/v2.1/catalog/datasets/arrets-lignes/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B";
// IDF mobilite csv formats // IDF mobilite csv formats
private static final int IDFM_TRACE_ID_INDEX = 0; private static final int IDFM_TRACE_ID_INDEX = 0;
private static final int IDFM_TRACE_SNAME_INDEX = 1; private static final int IDFM_TRACE_SNAME_INDEX = 1;
private static final int IDFM_TRACE_SHAPE_INDEX = 6; private static final int IDFM_TRACE_SHAPE_INDEX = 6;
private static final int IDFM_STOPS_RID_INDEX = 0; private static final int IDFM_STOPS_RID_INDEX = 0;
private static final int IDFM_STOPS_SCHEDULES_INDEX = 3;
private static final int IDFM_STOPS_NAME_INDEX = 5; private static final int IDFM_STOPS_NAME_INDEX = 5;
private static final int IDFM_STOPS_LON_INDEX = 6; private static final int IDFM_STOPS_LON_INDEX = 6;
private static final int IDFM_STOPS_LAT_INDEX = 7; private static final int IDFM_STOPS_LAT_INDEX = 7;
// Magically chosen values // Magically chosen values
/** A number of stops on each line */ /** A number of stops on each line */
@ -53,14 +56,16 @@ public class IDFMNetworkExtractor {
// Well named constants // Well named constants
private static final double QUARTER_KILOMETER = .25; private static final double QUARTER_KILOMETER = .25;
/** Main entry point for the extractor of IDF mobilite data into a network as /**
* Main entry point for the extractor of IDF mobilite data into a network as
* defined by this application. * 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) { public static void main(String[] args) {
if (args.length != 1) { if (args.length != 2) {
LOGGER.severe("Invalid command line. Missing target file."); LOGGER.severe("Invalid command line. Missing target files.");
return; return;
} }
@ -91,6 +96,20 @@ public class IDFMNetworkExtractor {
LOGGER.log(Level.SEVERE, e, LOGGER.log(Level.SEVERE, e,
() -> MessageFormat.format("Could not write in file {0}", args[0])); () -> MessageFormat.format("Could not write in file {0}", args[0]));
} }
CSVStreamSchedulesProvider providerschedules = new CSVStreamSchedulesProvider(traces.values().iterator());
TraceEntry tmp = traces.values().iterator().next();
tmp.getTerminus()
.forEach(m -> LOGGER.log(Level.INFO, m));
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]));
}
} }
private static void cleanTraces(Map<String, TraceEntry> traces) { private static void cleanTraces(Map<String, TraceEntry> traces) {
@ -134,6 +153,10 @@ public class IDFMNetworkExtractor {
Double.parseDouble(line[IDFM_STOPS_LON_INDEX]), Double.parseDouble(line[IDFM_STOPS_LON_INDEX]),
Double.parseDouble(line[IDFM_STOPS_LAT_INDEX])); Double.parseDouble(line[IDFM_STOPS_LAT_INDEX]));
String rid = line[IDFM_STOPS_RID_INDEX]; String rid = line[IDFM_STOPS_RID_INDEX];
if (traces.keySet().contains(rid)) {
extractTerminus(line[IDFM_STOPS_SCHEDULES_INDEX]).forEach(t -> traces.get(rid).addTerminus(t));
}
traces.computeIfPresent(rid, traces.computeIfPresent(rid,
(String k, TraceEntry trace) -> addCandidate(trace, entry)); (String k, TraceEntry trace) -> addCandidate(trace, entry));
stops.add(entry); stops.add(entry);
@ -191,4 +214,25 @@ public class IDFMNetworkExtractor {
} }
return all; return all;
} }
private static List<String> extractTerminus(String pathsJSON) {
List<String> all = new ArrayList<>();
try {
JSONArray schedules = new JSONArray(pathsJSON);
for (int i = 0; i < schedules.length(); i++) {
JSONObject stop = schedules.getJSONObject(i);
String terminus = stop.getString("from");
all.add(terminus);
}
} catch (
JSONException e) {
// Ignoring invalid element!
LOGGER.log(Level.FINE, e,
() -> MessageFormat.format("Invalid json element {0}", pathsJSON)); //$NON-NLS-1$
}
return all;
}
} }

View file

@ -1,22 +1,27 @@
/** /**
* *
*/ */
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** Representation of a transport line /**
* * Representation of a transport line
* @author Emmanuel Bigeon */ *
* @author Emmanuel Bigeon
*/
public final class TraceEntry { public final class TraceEntry {
public final String lname; public final String lname;
private List<String> terminus = new ArrayList<>();
private List<List<StopEntry>> paths = new ArrayList<>(); private List<List<StopEntry>> paths = new ArrayList<>();
/** Create a transport line. /**
* * Create a transport line.
* @param lname the name of the line */ *
* @param lname the name of the line
*/
public TraceEntry(String lname) { public TraceEntry(String lname) {
super(); super();
this.lname = lname; this.lname = lname;
@ -29,7 +34,16 @@ public final class TraceEntry {
return paths; return paths;
} }
/** @return the list of terminus */
public List<String> getTerminus() {
return terminus;
}
public void addPath(List<StopEntry> path) { public void addPath(List<StopEntry> path) {
paths.add(new ArrayList<>(path)); paths.add(new ArrayList<>(path));
} }
public void addTerminus(String term) {
terminus.add(term);
}
} }

View file

@ -1,5 +1,5 @@
/** /**
* *
*/ */
package fr.u_paris.gla.project.io; package fr.u_paris.gla.project.io;
@ -7,30 +7,36 @@ import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle; import java.time.format.ResolverStyle;
import java.util.List; import java.util.List;
/** A tool class for the schedule format. /**
* * A tool class for the schedule format.
* @author Emmanuel Bigeon */ *
* @author Emmanuel Bigeon
*/
public final class ScheduleFormat { public final class ScheduleFormat {
public static final int LINE_INDEX = 0; public static final int NUMBER_COLUMNS = 4;
public static final int LINE_INDEX = 0;
public static final int TRIP_SEQUENCE_INDEX = 1; public static final int TRIP_SEQUENCE_INDEX = 1;
public static final int TERMINUS_INDEX = 2; public static final int TERMINUS_INDEX = 2;
public static final int TIME_INDEX = 3; public static final int TIME_INDEX = 3;
/** Hidden constructor for tool class */ /** Hidden constructor for tool class */
private ScheduleFormat() { private ScheduleFormat() {
// Tool class // Tool class
} }
/** Read a trip sequence from its string representation /**
* * Read a trip sequence from its string representation
*
* @param representation the representation * @param representation the representation
* @return the sequence of branching */ * @return the sequence of branching
*/
public static List<Integer> getTripSequence(String representation) { public static List<Integer> getTripSequence(String representation) {
// TODO Read a trip sequence from a string // TODO Read a trip sequence from a string
throw new RuntimeException("Not implemented yet"); throw new RuntimeException("Not implemented yet");
} }
public static DateTimeFormatter getTimeFormatter() { public static DateTimeFormatter getTimeFormatter() {
return DateTimeFormatter.ofPattern("HH:mm").withResolverStyle(ResolverStyle.LENIENT); return DateTimeFormatter.ofPattern("HH:mm").withResolverStyle(ResolverStyle.LENIENT);
} }