Merge branch 'javadoc-idfm' into idf-mobilite-net

This commit is contained in:
Mylloon 2024-04-23 01:40:16 +02:00
commit 919df017fa
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
6 changed files with 153 additions and 19 deletions

View file

@ -63,7 +63,7 @@ public class App {
} }
} }
/** @param out */ /** @param out the output stream */
public static void printAppInfos(PrintStream out) { public static void printAppInfos(PrintStream out) {
Properties props = new Properties(); Properties props = new Properties();
try (InputStream is = App.class.getResourceAsStream("application.properties")) { //$NON-NLS-1$ try (InputStream is = App.class.getResourceAsStream("application.properties")) { //$NON-NLS-1$

View file

@ -1,5 +1,5 @@
/** /**
* *
*/ */
package fr.u_paris.gla.project.idfm; package fr.u_paris.gla.project.idfm;
@ -19,9 +19,18 @@ import java.util.Set;
import fr.u_paris.gla.project.io.NetworkFormat; import fr.u_paris.gla.project.io.NetworkFormat;
import fr.u_paris.gla.project.utils.GPS; import fr.u_paris.gla.project.utils.GPS;
/**
* CSV Stream Provider class
*/
public final class CSVStreamProvider { public final class CSVStreamProvider {
/**
* Formatter from numbers into GPS Coordinates
*/
private static final NumberFormat GPS_FORMATTER = NetworkFormat private static final NumberFormat GPS_FORMATTER = NetworkFormat
.getGPSFormatter(); .getGPSFormatter();
/**
* Formatter from numbers into MM:SS
*/
private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat private static final NumberFormat MINUTES_SECOND_FORMATTER = NumberFormat
.getInstance(Locale.ENGLISH); .getInstance(Locale.ENGLISH);
static { static {
@ -29,6 +38,9 @@ public final class CSVStreamProvider {
} }
/** Number of seconds in a minute. */ /** Number of seconds in a minute. */
private static final int SECONDS_IN_MINUTES = 60; private static final int SECONDS_IN_MINUTES = 60;
/**
* Number of seconds in an hour
*/
private static final long SECONDS_IN_HOURS = 3_600; private static final long SECONDS_IN_HOURS = 3_600;
// Magically chosen values // Magically chosen values
/** Maximal speed in km/h */ /** Maximal speed in km/h */
@ -36,34 +48,69 @@ public final class CSVStreamProvider {
/** Distance to reach maximal speed in km */ /** Distance to reach maximal speed in km */
private static final double TWO_ACCELERATION_DISTANCE = 0.2; private static final double TWO_ACCELERATION_DISTANCE = 0.2;
/**
* Current CSV Line
*/
private final String[] line = new String[NetworkFormat.NUMBER_COLUMNS]; private final String[] line = new String[NetworkFormat.NUMBER_COLUMNS];
/**
* Current CSV transport line iterator
*/
private final Iterator<TraceEntry> currentTrace; private final Iterator<TraceEntry> currentTrace;
/**
* Current Stop path iterator
*/
private Iterator<List<StopEntry>> currentPath = Collections.emptyIterator(); private Iterator<List<StopEntry>> currentPath = Collections.emptyIterator();
/**
* current iterator for the begin of the line
*/
private Iterator<StopEntry> currentSegmentStart = Collections.emptyIterator(); private Iterator<StopEntry> currentSegmentStart = Collections.emptyIterator();
/**
* current iterator for the end of the line
*/
private Iterator<StopEntry> currentSegmentEnd = Collections.emptyIterator(); private Iterator<StopEntry> currentSegmentEnd = Collections.emptyIterator();
/**
* HashMap of the current line's segments
*/
Map<StopEntry, Set<StopEntry>> lineSegments = new HashMap<>(); Map<StopEntry, Set<StopEntry>> lineSegments = new HashMap<>();
// The transport id with its value // The transport id with its value
private final Map<String, Transport> transports; private final Map<String, Transport> transports;
List <TraceDescription> descriptions = new ArrayList<>(); List <TraceDescription> descriptions = new ArrayList<>();
/**
* current begin of line
*/
private StopEntry start = null; private StopEntry start = null;
/**
* current end of line
*/
private StopEntry end = null; private StopEntry end = null;
/**
* csv stream iterator checker
*/
private boolean hasNext = false; private boolean hasNext = false;
/**
* tells if we're already on the next
*/
private boolean onNext = false; private boolean onNext = false;
private String traceId = ""; private String traceId = "";
private String traceType = ""; private String traceType = "";
private String url_image = ""; private String url_image = "";
/** Create the stream provider */ /** Create the stream provider
* @param traces an iterator of the possible traces
* @param t map of transports */
public CSVStreamProvider(Iterator<TraceEntry> traces, Map<String, Transport> t) { public CSVStreamProvider(Iterator<TraceEntry> traces, Map<String, Transport> t) {
this.currentTrace = traces; this.currentTrace = traces;
transports = t; transports = t;
} }
/** Method that tells if we have segments or paths to go through
* @return if there are next elements or not
*/
public boolean hasNext() { public boolean hasNext() {
if (!this.onNext) { if (!this.onNext) {
skipToNext(); skipToNext();
@ -71,6 +118,9 @@ public final class CSVStreamProvider {
return this.hasNext; return this.hasNext;
} }
/**
* Skip to either the next segment or the next path
*/
private void skipToNext() { private void skipToNext() {
if (this.onNext) { if (this.onNext) {
return; return;
@ -86,6 +136,9 @@ public final class CSVStreamProvider {
} }
} }
/**
* Skips to the next segment
*/
private void skipToNextNewSegment() { private void skipToNextNewSegment() {
do { do {
this.start = this.currentSegmentStart.next(); this.start = this.currentSegmentStart.next();
@ -132,6 +185,9 @@ public final class CSVStreamProvider {
} while (currentSegmentStart == null); } while (currentSegmentStart == null);
} }
/** Store current trace' data as a String array
* @return The newly generated line of text
*/
public String[] next() { public String[] next() {
if (!this.onNext) { if (!this.onNext) {
skipToNext(); skipToNext();
@ -155,9 +211,10 @@ public final class CSVStreamProvider {
} }
/** @param stop1 /** creates adds a station into the next line String
* @param nextLine * @param stop the stop
* @param i */ * @param nextLine the next line
* @param index the stop index in the next line */
private static void fillStation(StopEntry stop, String[] nextLine, int index) { private static void fillStation(StopEntry stop, String[] nextLine, int index) {
nextLine[index] = stop.lname; nextLine[index] = stop.lname;
nextLine[index + 1] = MessageFormat.format("{0}, {1}", //$NON-NLS-1$ nextLine[index + 1] = MessageFormat.format("{0}, {1}", //$NON-NLS-1$
@ -166,8 +223,9 @@ public final class CSVStreamProvider {
} }
/** @param distanceToTime /** turns a number into a formatted time string
* @return */ * @param time the time value
* @return the time as a String */
private static String formatTime(long time) { private static String formatTime(long time) {
return MessageFormat.format("{0}:{1}", //$NON-NLS-1$ return MessageFormat.format("{0}:{1}", //$NON-NLS-1$
MINUTES_SECOND_FORMATTER.format(time / SECONDS_IN_MINUTES), MINUTES_SECOND_FORMATTER.format(time % SECONDS_IN_MINUTES)); MINUTES_SECOND_FORMATTER.format(time / SECONDS_IN_MINUTES), MINUTES_SECOND_FORMATTER.format(time % SECONDS_IN_MINUTES));
@ -177,7 +235,7 @@ public final class CSVStreamProvider {
* <p> * <p>
* This is a model with an linear acceleration and deceleration periods and a * This is a model with an linear acceleration and deceleration periods and a
* constant speed in between. * constant speed in between.
* *
* @param distance the distance (in km) * @param distance the distance (in km)
* @return the duration of the trip (in hours) */ * @return the duration of the trip (in hours) */
private static double distanceToTime(double distance) { private static double distanceToTime(double distance) {
@ -204,7 +262,7 @@ public final class CSVStreamProvider {
transp.addDescriptions(descriptions); transp.addDescriptions(descriptions);
} }
} }
} }

View file

@ -30,20 +30,50 @@ public class IDFMNetworkExtractor {
private static final Logger LOGGER = Logger private static final Logger LOGGER = Logger
.getLogger(IDFMNetworkExtractor.class.getName()); .getLogger(IDFMNetworkExtractor.class.getName());
/**
* the URL of the Trace CSV
*/
// IDF mobilite API URLs // IDF mobilite API URLs
private static final String TRACE_FILE_URL = "https://data.iledefrance-mobilites.fr/api/explore/v2.1/catalog/datasets/traces-des-lignes-de-transport-en-commun-idfm/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B"; private static final String TRACE_FILE_URL = "https://data.iledefrance-mobilites.fr/api/explore/v2.1/catalog/datasets/traces-des-lignes-de-transport-en-commun-idfm/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B";
/**
* The URL of the Stops CSV
*/
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";
/**
* the index in the CSV of a Trace's ID
*/
// 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;
/**
* the index in the CSV of a Trace's Name
*/
private static final int IDFM_TRACE_SNAME_INDEX = 1; private static final int IDFM_TRACE_SNAME_INDEX = 1;
/**
* the index in the CSV of a Trace's shape
*/
private static final int IDFM_TRACE_SHAPE_INDEX = 6; private static final int IDFM_TRACE_SHAPE_INDEX = 6;
private static final int IDFM_TRACE_TYPE_INDEX = 3; private static final int IDFM_TRACE_TYPE_INDEX = 3;
/**
* The index in the CSV of the Stops' id
*/
private static final int IDFM_STOPS_RID_INDEX = 0; private static final int IDFM_STOPS_RID_INDEX = 0;
/**
* The index in the CSV of the Stops' schedules
*/
private static final int IDFM_STOPS_SCHEDULES_INDEX = 3; private static final int IDFM_STOPS_SCHEDULES_INDEX = 3;
/**
* The index in the CSV of the Stops' names
*/
private static final int IDFM_STOPS_NAME_INDEX = 5; private static final int IDFM_STOPS_NAME_INDEX = 5;
/**
* The index in the CSV of the Stops' longitude
*/
private static final int IDFM_STOPS_LON_INDEX = 6; private static final int IDFM_STOPS_LON_INDEX = 6;
/**
* The index in the CSV of the Stops' latitude
*/
private static final int IDFM_STOPS_LAT_INDEX = 7; private static final int IDFM_STOPS_LAT_INDEX = 7;
private static final int IDFM_URL_INDEX = 10; private static final int IDFM_URL_INDEX = 10;
@ -53,11 +83,14 @@ public class IDFMNetworkExtractor {
*/ */
private static final int GUESS_STOPS_BY_LINE = 5; private static final int GUESS_STOPS_BY_LINE = 5;
/**
* The quarter of a kilometer as a static value
*/
// 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 mobilité 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)
@ -192,6 +225,9 @@ public class IDFMNetworkExtractor {
} }
} }
/** Clean the traces/remove the unresolved lines
* @param traces the traces to clean
*/
private static void cleanTraces(Map<String, TraceEntry> traces) { private static void cleanTraces(Map<String, TraceEntry> traces) {
Set<String> toRemove = new HashSet<>(); Set<String> toRemove = new HashSet<>();
for (Entry<String, TraceEntry> traceEntry : traces.entrySet()) { for (Entry<String, TraceEntry> traceEntry : traces.entrySet()) {
@ -207,9 +243,9 @@ public class IDFMNetworkExtractor {
} }
} }
/** /** Tells if the current trasport line has all its stops entries resolved
* @param path * @param stops the stops list
*/ * @return if the line is "clean"*/
private static boolean cleanLine(List<List<StopEntry>> stops) { private static boolean cleanLine(List<List<StopEntry>> stops) {
for (List<StopEntry> path : stops) { for (List<StopEntry> path : stops) {
for (int i = 0; i < path.size(); i++) { for (int i = 0; i < path.size(); i++) {
@ -227,6 +263,11 @@ public class IDFMNetworkExtractor {
return true; return true;
} }
/** adds a stop to all related variables
* @param line the transport line involved with the new stop
* @param traces the traces related to it
* @param stops the general stops list
*/
private static void addStop(String[] line, Map<String, TraceEntry> traces, private static void addStop(String[] line, Map<String, TraceEntry> traces,
List<StopEntry> stops) { List<StopEntry> stops) {
StopEntry entry = new StopEntry(line[IDFM_STOPS_NAME_INDEX], StopEntry entry = new StopEntry(line[IDFM_STOPS_NAME_INDEX],
@ -254,6 +295,10 @@ public class IDFMNetworkExtractor {
stops.add(entry); stops.add(entry);
} }
/** add a line to the related list of traces
* @param line the line as a string
* @param traces the traces
*/
private static void addLine(String[] line, Map<String, TraceEntry> traces) { private static void addLine(String[] line, Map<String, TraceEntry> traces) {
TraceEntry entry = new TraceEntry(line[IDFM_TRACE_SNAME_INDEX], line[IDFM_TRACE_ID_INDEX],line[IDFM_TRACE_TYPE_INDEX], line[IDFM_URL_INDEX]); TraceEntry entry = new TraceEntry(line[IDFM_TRACE_SNAME_INDEX], line[IDFM_TRACE_ID_INDEX],line[IDFM_TRACE_TYPE_INDEX], line[IDFM_URL_INDEX]);
List<List<StopEntry>> buildPaths = buildPaths(line[IDFM_TRACE_SHAPE_INDEX]); List<List<StopEntry>> buildPaths = buildPaths(line[IDFM_TRACE_SHAPE_INDEX]);
@ -266,6 +311,11 @@ public class IDFMNetworkExtractor {
} }
} }
/** add a new entry as a candidate to a trace
* @param trace the trace
* @param entry the entry
* @return the trace in question
*/
private static TraceEntry addCandidate(TraceEntry trace, StopEntry entry) { private static TraceEntry addCandidate(TraceEntry trace, StopEntry entry) {
for (List<StopEntry> path : trace.getPaths()) { for (List<StopEntry> path : trace.getPaths()) {
for (StopEntry stopEntry : path) { for (StopEntry stopEntry : path) {
@ -280,6 +330,10 @@ public class IDFMNetworkExtractor {
return trace; return trace;
} }
/** turn a JSON list of stops into a list of paths
* @param pathsJSON the JSON String of all paths
* @return the paths as a List of StopEntries
*/
private static List<List<StopEntry>> buildPaths(String pathsJSON) { private static List<List<StopEntry>> buildPaths(String pathsJSON) {
List<List<StopEntry>> all = new ArrayList<>(); List<List<StopEntry>> all = new ArrayList<>();
try { try {
@ -307,6 +361,10 @@ public class IDFMNetworkExtractor {
return all; return all;
} }
/** extract the terminus out of a JSON file
* @param JSON the JSON
* @return a list of strings related to the terminus
*/
private static List<String> extractTerminus(String JSON) { private static List<String> extractTerminus(String JSON) {
List<String> all = new ArrayList<>(); List<String> all = new ArrayList<>();
try { try {

View file

@ -14,8 +14,10 @@ import java.util.Locale;
* *
* @author Emmanuel Bigeon */ * @author Emmanuel Bigeon */
public final class NetworkFormat { public final class NetworkFormat {
/** The amount of columns in the CSV file */
public static final int NUMBER_COLUMNS = 8; public static final int NUMBER_COLUMNS = 8;
/** The amount of decimal places in the GPS' coordinates */
public static final int GPS_PRECISION = 18; public static final int GPS_PRECISION = 18;
/** The index of the line name in the network format */ /** The index of the line name in the network format */
@ -65,7 +67,7 @@ public final class NetworkFormat {
/** Get a formatter for the numbers in a GPS coordinate pair /** Get a formatter for the numbers in a GPS coordinate pair
* *
* @return the formatter for numbers in a GPS coordinate pair */ * @return the {@link java.text.NumberFormat} formatter for numbers in a GPS coordinate pair */
public static NumberFormat getGPSFormatter() { public static NumberFormat getGPSFormatter() {
NumberFormat instance = NumberFormat.getNumberInstance(Locale.ENGLISH); NumberFormat instance = NumberFormat.getNumberInstance(Locale.ENGLISH);
instance.setMaximumFractionDigits(GPS_PRECISION); instance.setMaximumFractionDigits(GPS_PRECISION);

View file

@ -14,11 +14,16 @@ import java.util.List;
* @author Emmanuel Bigeon * @author Emmanuel Bigeon
*/ */
public final class ScheduleFormat { public final class ScheduleFormat {
/** The amount of columns in the CSV file */
public static final int NUMBER_COLUMNS = 4; public static final int NUMBER_COLUMNS = 4;
/** The index of the line name in the schedule format */
public static final int LINE_INDEX = 0; public static final int LINE_INDEX = 0;
/** The index of the trip sequence in the schedule format */
public static final int TRIP_SEQUENCE_INDEX = 1; public static final int TRIP_SEQUENCE_INDEX = 1;
/** The index of the terminus name in the schedule format */
public static final int TERMINUS_INDEX = 2; public static final int TERMINUS_INDEX = 2;
/** The index of the time in the schedule format */
public static final int TIME_INDEX = 3; public static final int TIME_INDEX = 3;
/** Hidden constructor for tool class */ /** Hidden constructor for tool class */

View file

@ -1,5 +1,5 @@
/** /**
* *
*/ */
package fr.u_paris.gla.project.utils; package fr.u_paris.gla.project.utils;
@ -19,7 +19,7 @@ import com.opencsv.ICSVWriter;
import com.opencsv.exceptions.CsvValidationException; import com.opencsv.exceptions.CsvValidationException;
/** A CSV tool class. /** A CSV tool class.
* *
* @author Emmanuel Bigeon */ * @author Emmanuel Bigeon */
public final class CSVTools { public final class CSVTools {
@ -28,6 +28,11 @@ public final class CSVTools {
// Tool class // Tool class
} }
/** get a CSV file from a URL, download and parse it, and keep values in memory
* @param is 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
*/
private static void readCSVFromInputStream(InputStream is, Consumer<String[]> contentLineConsumer) private static void readCSVFromInputStream(InputStream is, Consumer<String[]> contentLineConsumer)
throws IOException { throws IOException {
ICSVParser parser = new CSVParserBuilder().withSeparator(';').build(); ICSVParser parser = new CSVParserBuilder().withSeparator(';').build();
@ -46,7 +51,13 @@ public final class CSVTools {
throw new IOException("Invalid csv file", e); //$NON-NLS-1$ throw new IOException("Invalid csv file", e); //$NON-NLS-1$
} }
} }
/** get a CSV file from a file and parse it, keeping values in memory
* @param filename the saved file's name and path
* @param contentLineConsumer the variable used to store the data
* @throws IOException if it's impossible to read the file
*/
public static void readCSVFromFile(String filename, Consumer<String[]> contentLineConsumer) public static void readCSVFromFile(String filename, Consumer<String[]> contentLineConsumer)
throws IOException { throws IOException {
File file = new File(filename); File file = new File(filename);