Skip to content
114 changes: 68 additions & 46 deletions src/main/java/org/mtransit/parser/DefaultAgencyTools.java

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion src/main/java/org/mtransit/parser/TimeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.mtransit.commons.FeatureFlags;

import java.util.Locale;

@SuppressWarnings("WeakerAccess")
public final class TimeUtils {

private static final int PRECISION_IN_SECONDS = 10;
private static final int PRECISION_IN_SECONDS = FeatureFlags.F_SCHEDULE_IN_MINUTES ? 1 : 10;

@Nullable
public static Integer cleanExtraSeconds(@Nullable Integer time) {
if (PRECISION_IN_SECONDS <= 1) return time;
int extraSeconds = time == null ? 0 : time % PRECISION_IN_SECONDS;
if (extraSeconds > 0) { // IF too precise DO
return cleanTime(time, extraSeconds);
Expand Down
18 changes: 11 additions & 7 deletions src/main/java/org/mtransit/parser/TimeUtilsExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@ import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.Date
import java.util.Locale
import kotlin.math.abs
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.nanoseconds

fun formatSimpleDuration(durationInMs: Long) = buildString {
durationInMs.milliseconds.toComponents { days, hours, minutes, seconds, nanoseconds ->
days.takeIf { it > 0 }?.let { append(days).append("d ") }
hours.takeIf { it > 0 }?.let { append(hours).append("h ") }
minutes.takeIf { it > 0 }?.let { append(minutes).append("m ") }
seconds.takeIf { it > 0 }?.let { append(seconds).append("s ") }
nanoseconds.takeIf { it > 0 }?.let { append(nanoseconds).append("ns ") }
val negative = durationInMs < 0
abs(durationInMs).milliseconds.toComponents { days, hours, minutes, seconds, nanoseconds ->
days.takeIf { it > 0 }?.let { append(it).append("d ") }
hours.takeIf { it > 0 }?.let { append(it).append("h ") }
minutes.takeIf { it > 0 }?.let { append(it).append("m ") }
seconds.takeIf { it > 0 }?.let { append(it).append("s ") }
nanoseconds.takeIf { it > 0 }?.nanoseconds?.inWholeMilliseconds?.let { append(it).append("ms ") }
}
}
if (negative) insert(0, "-")
}.trim()

private val shortDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss z", Locale.ENGLISH)
.withZone(ZoneId.systemDefault())
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/org/mtransit/parser/db/DumpDbUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ object DumpDbUtils {
if (FeatureFlags.F_EXPORT_SERVICE_ID_INTS) {
SQLUtils.executeUpdate(statement, GTFSCommons.T_SERVICE_IDS_SQL_DROP)
}
if (FeatureFlags.F_EXPORT_TRIP_ID_INTS) {
SQLUtils.executeUpdate(statement, GTFSCommons.T_TRIP_IDS_SQL_DROP)
}
SQLUtils.executeUpdate(statement, GTFSCommons.T_SERVICE_DATES_SQL_DROP)
// CREATE
SQLUtils.executeUpdate(statement, GTFSCommons.T_ROUTE_SQL_CREATE)
Expand All @@ -44,6 +47,9 @@ object DumpDbUtils {
if (FeatureFlags.F_EXPORT_SERVICE_ID_INTS) {
SQLUtils.executeUpdate(statement, GTFSCommons.T_SERVICE_IDS_SQL_CREATE)
}
if (FeatureFlags.F_EXPORT_TRIP_ID_INTS) {
SQLUtils.executeUpdate(statement, GTFSCommons.T_TRIP_IDS_SQL_CREATE)
}
SQLUtils.executeUpdate(statement, GTFSCommons.T_SERVICE_DATES_SQL_CREATE)
SQLUtils.executeUpdate(statement, GTFSCommons.T_STRINGS_SQL_CREATE)
}
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/mtransit/parser/gtfs/data/GFieldTypes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import java.util.Locale
@Suppress("unused", "MemberVisibilityCanBePrivate")
object GFieldTypes {

@Suppress("SpellCheckingInspection")
const val TIME_FORMAT_PATTERN = "HHmmss"

const val DATE_FORMAT_PATTERN = "yyyyMMdd"
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/mtransit/parser/gtfs/data/GRoute.kt
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ data class GRoute(
append(routeShortName)
append(")")
}
append("}")
}

fun to() = Route(
Expand Down
24 changes: 15 additions & 9 deletions src/main/java/org/mtransit/parser/gtfs/data/GSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,14 @@ public void addTrip(@NotNull GTrip gTrip, @Nullable PreparedStatement insertStop
this.tripIdIntsUIDs.put(gTrip.getTripIdInt(), gTrip.getUID());
}

@NotNull
private Collection<Integer> getAllTripRouteIdInts() {
if (USE_DB_ONLY) {
return GIDs.getInts(GTFSDataBase.selectTripRouteIds());
}
return this.routeIdIntTripsCache.keySet();
}

public int readTripsCount() {
if (USE_DB_ONLY) {
return GTFSDataBase.countTrips();
Expand Down Expand Up @@ -805,9 +813,7 @@ public void cleanupExcludedData() {
int r = 0;
try {
final Collection<Integer> allRouteIdsInt = getAllRouteIdInts(); // this agency & type & not excluded only
final Collection<Integer> allTripRouteIdInts =
USE_DB_ONLY ? GIDs.getInts(GTFSDataBase.selectTripRouteIds())
: this.routeIdIntTripsCache.keySet();
final Collection<Integer> allTripRouteIdInts = getAllTripRouteIdInts();
for (Integer tripRouteIdInt : allTripRouteIdInts) {
if (!allRouteIdsInt.contains(tripRouteIdInt)) {
final List<GTrip> routeTrips = getRouteTrips(tripRouteIdInt);
Expand Down Expand Up @@ -886,19 +892,19 @@ public void cleanupExcludedServiceIds() {
int r = 0;
try {
final Collection<Integer> allRouteIdsInt = getAllRouteIdInts();
final Collection<Integer> allTripIdsInt = getAllRouteIdInts();
HashSet<Integer> routeTripServiceIdInts = new HashSet<>();
final Collection<Integer> allTripRouteIdInts = getAllTripRouteIdInts();
final HashSet<Integer> notExcludedRouteTripServiceIdInts = new HashSet<>();
for (Integer gRouteIdInt : allRouteIdsInt) {
if (allTripIdsInt.contains(gRouteIdInt)) {
if (allTripRouteIdInts.contains(gRouteIdInt)) {
for (GTrip gTrip : getRouteTrips(gRouteIdInt)) {
routeTripServiceIdInts.add(gTrip.getServiceIdInt());
notExcludedRouteTripServiceIdInts.add(gTrip.getServiceIdInt());
}
}
}
final Iterator<GCalendar> itGCalendar = getAllCalendars().iterator();
while (itGCalendar.hasNext()) {
final GCalendar gCalendar = itGCalendar.next();
if (!routeTripServiceIdInts.contains(gCalendar.getServiceIdInt())) {
if (!notExcludedRouteTripServiceIdInts.contains(gCalendar.getServiceIdInt())) {
itGCalendar.remove();
if (ALL_CALENDARS_STORED_IN_CALENDAR_DATES) {
for (GCalendarDate gCalendarDate : gCalendar.flattenToCalendarDates()) {
Expand All @@ -917,7 +923,7 @@ public void cleanupExcludedServiceIds() {
Iterator<GCalendarDate> itGCalendarDate = getAllCalendarDates().iterator();
while (itGCalendarDate.hasNext()) {
GCalendarDate gCalendarDate = itGCalendarDate.next();
if (!routeTripServiceIdInts.contains(gCalendarDate.getServiceIdInt())) {
if (!notExcludedRouteTripServiceIdInts.contains(gCalendarDate.getServiceIdInt())) {
itGCalendarDate.remove();
GTFSDataBase.deleteCalendarDate(gCalendarDate.to());
logRemoved("Removed calendar date (or calendar): %s.", gCalendarDate.toStringPlus());
Expand Down
1 change: 0 additions & 1 deletion src/main/java/org/mtransit/parser/gtfs/data/GTime.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package org.mtransit.parser.gtfs.data

import org.mtransit.parser.Constants.EMPTY
import org.mtransit.parser.MTLog
import java.lang.Exception
import java.util.Calendar
import java.util.Date

Expand Down
74 changes: 63 additions & 11 deletions src/main/java/org/mtransit/parser/mt/MGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
import org.mtransit.parser.mt.data.MDirectionStop;
import org.mtransit.parser.mt.data.MString;
import org.mtransit.parser.mt.data.MStrings;
import org.mtransit.parser.mt.data.MTripId;
import org.mtransit.parser.mt.data.MTripIds;

import java.io.BufferedWriter;
import java.io.File;
Expand Down Expand Up @@ -166,19 +168,20 @@ public static MSpec generateMSpec(@NotNull GSpec gtfs, @NotNull GAgencyTools age
Collections.sort(mStopsList);
final ArrayList<MRoute> mRoutesList = new ArrayList<>(mRoutes);
Collections.sort(mRoutesList);
final ArrayList<MDirection> mTripsList = new ArrayList<>(mDirections);
Collections.sort(mTripsList);
final ArrayList<MDirection> mDirectionsList = new ArrayList<>(mDirections);
Collections.sort(mDirectionsList);
final ArrayList<MDirectionStop> mDirectionStopsList = new ArrayList<>(mDirectionStops);
Collections.sort(mDirectionStopsList);
final ArrayList<MServiceDate> mServiceDatesList = new ArrayList<>(mServiceDates);
Collections.sort(mServiceDatesList);
MTLog.log("Generating routes, trips, trip stops & stops objects... DONE");
MTLog.log("- Agencies: %d", mAgenciesList.size());
MTLog.log("- Routes: %d", mRoutesList.size());
MTLog.log("- Trips: %d", mTripsList.size());
MTLog.log("- Trip stops: %d", mDirectionStopsList.size());
MTLog.log("- Directions: %d", mDirectionsList.size());
MTLog.log("- Direction stops: %d", mDirectionStopsList.size());
MTLog.log("- Stops: %d", mStopsList.size());
MTLog.log("- Service Ids: %d", MServiceIds.count());
MTLog.log("- Trip Ids: %d", MTripIds.count());
MTLog.log("- Strings: %d", MStrings.count());
MTLog.log("- Service Dates: %d", mServiceDatesList.size());
MTLog.log("- Route with Frequencies: %d", mRouteFrequencies.size());
Expand All @@ -188,7 +191,7 @@ public static MSpec generateMSpec(@NotNull GSpec gtfs, @NotNull GAgencyTools age
mAgenciesList,
mStopsList,
mRoutesList,
mTripsList,
mDirectionsList,
mDirectionStopsList,
mServiceDatesList,
mRouteFrequencies,
Expand All @@ -208,6 +211,7 @@ private static void logMerging(@NotNull String msg, long routeId) {
private static final String GTFS_SCHEDULE = "gtfs_schedule";
private static final String GTFS_SCHEDULE_SERVICE_DATES = GTFS_SCHEDULE + "_service_dates"; // DB
private static final String GTFS_SCHEDULE_SERVICE_IDS = GTFS_SCHEDULE + "_service_ids"; // DB
private static final String GTFS_SCHEDULE_TRIP_IDS = GTFS_SCHEDULE + "_trip_ids"; // DB
private static final String GTFS_SCHEDULE_STOP = GTFS_SCHEDULE + "_stop_"; // file
private static final String GTFS_FREQUENCY = "gtfs_frequency";
private static final String GTFS_FREQUENCY_ROUTE = GTFS_FREQUENCY + "_route_"; // file
Expand Down Expand Up @@ -284,6 +288,8 @@ public static void dumpFiles(@NotNull GAgencyTools gAgencyTools,
dumpScheduleStops(gAgencyTools, mSpec, fileBase, deleteAll, rawDirF);
// FREQUENCY ROUTES
dumpFrequencyRoutes(gAgencyTools, mSpec, fileBase, deleteAll, rawDirF);
// TRIP IDS
dumpTripIds(mSpec, fileBase, deleteAll, dataDirF, rawDirF, dbConnection);
// SERVICE IDS
dumpServiceIds(mSpec, fileBase, deleteAll, dataDirF, rawDirF, dbConnection); // AFTER SCHEDULE STOPS & FREQUENCY ROUTES
// STRINGS
Expand Down Expand Up @@ -523,6 +529,52 @@ private static Pair<Pair<Double, Double>, Pair<Double, Double>> dumpRDSStops(@Nu
return minMaxLatLng;
}

private static void dumpTripIds(
@Nullable MSpec mSpec,
@NotNull String fileBase,
boolean deleteAll,
@NotNull File dataDirF,
@NotNull File rawDirF,
@Nullable Connection dbConnection) {
if (!FeatureFlags.F_EXPORT_TRIP_ID_INTS) return;
if (!deleteAll
&& (mSpec == null || !mSpec.isValid() || (F_PRE_FILLED_DB && dbConnection == null))) {
throw new MTLog.Fatal("Generated data invalid (agencies: %s)!", mSpec);
}
if (F_PRE_FILLED_DB) {
FileUtils.deleteIfExist(new File(rawDirF, fileBase + GTFS_SCHEDULE_TRIP_IDS)); // migration from src/main/res/raw to data
}
final File file = new File(F_PRE_FILLED_DB ? dataDirF : rawDirF, fileBase + GTFS_SCHEDULE_TRIP_IDS);
FileUtils.deleteIfExist(file); // delete previous
if (deleteAll) return;
try (BufferedWriter ow = new BufferedWriter(new FileWriter(file))) {
MTLog.logPOINT(); // LOG
Statement dbStatement = null;
String sqlInsert = null;
if (F_PRE_FILLED_DB) {
SQLUtils.setAutoCommit(dbConnection, false); // START TRANSACTION
dbStatement = dbConnection.createStatement();
sqlInsert = GTFSCommons.getT_TRIP_IDS_SQL_INSERT();
}
for (MTripId mTripId : MTripIds.getAll()) {
final String tripIdsInsert = mTripId.toFile();
if (F_PRE_FILLED_DB) {
SQLUtils.executeUpdate(
dbStatement,
String.format(sqlInsert, tripIdsInsert)
);
}
ow.write(tripIdsInsert);
ow.write(Constants.NEW_LINE);
}
if (F_PRE_FILLED_DB) {
SQLUtils.setAutoCommit(dbConnection, true); // END TRANSACTION == commit()
}
} catch (Exception ioe) {
throw new MTLog.Fatal(ioe, "I/O Error while writing trip IDs file!");
}
}

private static void dumpServiceIds(
@Nullable MSpec mSpec,
@NotNull String fileBase,
Expand Down Expand Up @@ -576,7 +628,7 @@ private static void dumpStrings(
@NotNull File dataDirF,
@NotNull File rawDirF,
@Nullable Connection dbConnection) {
if (!FeatureFlags.F_EXPORT_STRINGS) return;
if (!FeatureFlags.F_EXPORT_STRINGS && !FeatureFlags.F_EXPORT_SCHEDULE_STRINGS) return;
if (!deleteAll
&& (mSpec == null || !mSpec.isValid() || (F_PRE_FILLED_DB && dbConnection == null))) {
throw new MTLog.Fatal("Generated data invalid (agencies: %s)!", mSpec);
Expand Down Expand Up @@ -743,15 +795,15 @@ private static void dumpScheduleStops(@NotNull GAgencyTools gAgencyTools,
} // LOG
MSchedule lastSchedule = null;
for (MSchedule mSchedule : mStopSchedules) {
if (mSchedule.isSameServiceAndDirection(lastSchedule)) {
ow.write(SQLUtils.COLUMN_SEPARATOR);
ow.write(mSchedule.toFileSameServiceIdAndDirectionId(lastSchedule));
} else {
if (!mSchedule.isSameServiceAndDirection(lastSchedule)) {
lastSchedule = null;
if (!empty) {
ow.write(Constants.NEW_LINE);
}
ow.write(mSchedule.toFileNewServiceIdAndDirectionId(gAgencyTools));
} else {
ow.write(SQLUtils.COLUMN_SEPARATOR);
}
ow.write(mSchedule.toFile(gAgencyTools, lastSchedule));
empty = false;
lastSchedule = mSchedule;
}
Expand Down
Loading