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;
@ -23,9 +23,11 @@ import org.json.JSONObject;
import fr.u_paris.gla.project.utils.CSVTools;
import fr.u_paris.gla.project.utils.GPS;
/** Code of an extractor for the data from IDF mobilite.
*
* @author Emmanuel Bigeon */
/**
* Code of an extractor for the data from IDF mobilite.
*
* @author Emmanuel Bigeon
*/
public class IDFMNetworkExtractor {
/** 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";
// 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_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_LON_INDEX = 6;
private static final int IDFM_STOPS_LAT_INDEX = 7;
private static final int IDFM_STOPS_LON_INDEX = 6;
private static final int IDFM_STOPS_LAT_INDEX = 7;
// Magically chosen values
/** A number of stops on each line */
@ -53,14 +56,16 @@ public class IDFMNetworkExtractor {
// Well named constants
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.
*
* @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) {
if (args.length != 1) {
LOGGER.severe("Invalid command line. Missing target file.");
if (args.length != 2) {
LOGGER.severe("Invalid command line. Missing target files.");
return;
}
@ -91,6 +96,20 @@ public class IDFMNetworkExtractor {
LOGGER.log(Level.SEVERE, e,
() -> 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) {
@ -134,6 +153,10 @@ public class IDFMNetworkExtractor {
Double.parseDouble(line[IDFM_STOPS_LON_INDEX]),
Double.parseDouble(line[IDFM_STOPS_LAT_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,
(String k, TraceEntry trace) -> addCandidate(trace, entry));
stops.add(entry);
@ -191,4 +214,25 @@ public class IDFMNetworkExtractor {
}
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;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/** Representation of a transport line
*
* @author Emmanuel Bigeon */
/**
* Representation of a transport line
*
* @author Emmanuel Bigeon
*/
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<>();
/** Create a transport line.
*
* @param lname the name of the line */
/**
* Create a transport line.
*
* @param lname the name of the line
*/
public TraceEntry(String lname) {
super();
this.lname = lname;
@ -29,7 +34,16 @@ public final class TraceEntry {
return paths;
}
/** @return the list of terminus */
public List<String> getTerminus() {
return terminus;
}
public void addPath(List<StopEntry> 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;
@ -7,30 +7,36 @@ import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle;
import java.util.List;
/** A tool class for the schedule format.
*
* @author Emmanuel Bigeon */
/**
* A tool class for the schedule format.
*
* @author Emmanuel Bigeon
*/
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 TERMINUS_INDEX = 2;
public static final int TIME_INDEX = 3;
public static final int TERMINUS_INDEX = 2;
public static final int TIME_INDEX = 3;
/** Hidden constructor for tool class */
private ScheduleFormat() {
// Tool class
}
/** Read a trip sequence from its string representation
*
/**
* Read a trip sequence from its string representation
*
* @param representation the representation
* @return the sequence of branching */
* @return the sequence of branching
*/
public static List<Integer> getTripSequence(String representation) {
// TODO Read a trip sequence from a string
throw new RuntimeException("Not implemented yet");
}
public static DateTimeFormatter getTimeFormatter() {
return DateTimeFormatter.ofPattern("HH:mm").withResolverStyle(ResolverStyle.LENIENT);
}