Skip to content
Draft
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/main/java/org/mtransit/android/MtLogExt.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
@file:Suppress("unused")

package org.mtransit.android

import org.mtransit.android.commons.MTLog
import org.mtransit.android.commons.toMillis
import java.util.Calendar
import java.util.Date
import kotlin.time.Duration
import kotlin.time.Instant

fun Long?.toDateTimeLog() = MTLog.formatDateTime(this)
fun Long?.toDurationLog() = MTLog.formatDuration(this)
fun Date?.toDurationLog() = this?.time.toDurationLog()
fun Calendar?.toDurationLog() = this?.timeInMillis.toDurationLog()
fun Duration?.toDurationLog() = this?.inWholeMilliseconds.toDateTimeLog()
Comment thread
mmathieum marked this conversation as resolved.
Outdated

fun Long?.toDateTimeLog() = MTLog.formatDateTime(this)
fun Date?.toDateTimeLog() = this?.time.toDateTimeLog()

fun Calendar?.toDateTimeLog() = this?.time.toDateTimeLog()
fun Instant?.toDateTimeLog() = this?.toMillis().toDateTimeLog()

@Deprecated("Use toDateTimeLog() instead", ReplaceWith("this.toDateTimeLog()"))
fun Long?.formatDateTime() = this.toDateTimeLog()
18 changes: 16 additions & 2 deletions src/main/java/org/mtransit/android/commons/MTLog.java
Original file line number Diff line number Diff line change
Expand Up @@ -378,11 +378,25 @@ private static String getLogMsg(@NonNull String tag, @NonNull String logMsg) {
if (Constants.DEBUG) {
logMsg = StringUtils.oneLineOneSpace(logMsg);
}
final String time = BuildConfig.DEBUG ? LOG_TIME_FORMAT.formatThreadSafe(TimeUtils.currentTimeMillis())
: String.valueOf(TimeUtils.currentTimeMillis());
final String time = makeTime(TimeUtils.currentTimeMillis());
return String.format("%s:%s>%s", time, tag, logMsg);
}

@Nullable
public static String makeTime(@Nullable Calendar calendar) {
return calendar == null ? null : makeTime(calendar.getTimeInMillis());
}

@Nullable
public static String makeTime(@Nullable Long timeInMs) {
return timeInMs == null ? null : makeTime(timeInMs.longValue());
}

@NonNull
public static String makeTime(long timeMs) {
return BuildConfig.DEBUG ? LOG_TIME_FORMAT.formatThreadSafe(timeMs) : String.valueOf(timeMs);
}

private static void logEntireMessage(@NonNull LogMethod logMethod, String logMsg) {
if (logMsg.length() < MAX_LOG_CAT_LENGTH) {
logMethod.callLog(
Expand Down
15 changes: 5 additions & 10 deletions src/main/java/org/mtransit/android/commons/data/Schedule.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,7 @@ public void setProviderPrecisionInMs(long providerPrecisionInMs) {
@NonNull
@Override
public String toString() {
return Schedule.class.getSimpleName() + "{" +
"timestamps=" + timestamps +
", providerPrecisionInMs=" + providerPrecisionInMs +
", usefulUntilInMs=" + usefulUntilInMs +
", noPickup=" + noPickup +
", frequencies=" + frequencies +
'}';
return ScheduleExtKt.toStringK(this);
}

@Nullable
Expand Down Expand Up @@ -230,9 +224,7 @@ public int getFrequenciesCount() {
}

public void addTimestampWithoutSort(@Nullable Timestamp newTimestamp) {
if (newTimestamp == null) {
return;
}
if (newTimestamp == null) return;
this.timestamps.add(newTimestamp);
}

Expand Down Expand Up @@ -508,6 +500,9 @@ public void setArrivalT(long arrivalT) {
}

public void setArrivalDiffMs(@Nullable Long arrivalDiffMs) {
if (arrivalDiffMs != null && arrivalDiffMs == 0L) {
arrivalDiffMs = null;
}
this.arrivalDiffMs = arrivalDiffMs;
}

Expand Down
88 changes: 81 additions & 7 deletions src/main/java/org/mtransit/android/commons/data/ScheduleExt.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
package org.mtransit.android.commons.data

import org.mtransit.android.commons.Constants
import org.mtransit.android.commons.MTLog
import org.mtransit.android.commons.floorBy
import org.mtransit.android.commons.millisToInstant
import org.mtransit.android.commons.roundToNearest
import org.mtransit.android.commons.toMillis
import org.mtransit.android.toDateTimeLog
import org.mtransit.android.toDurationLog
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlin.time.Instant

fun Schedule.toNoData() = Schedule(
fun makeSchedule(
id: Int? = null,
targetUUID: String,
lastUpdateInMs: Long,
validityInMs: Long,
readFromSourceAtInMs: Long,
providerPrecisionInMs: Long,
isNoPickup: Boolean = false,
sourceLabel: String? = null,
noData: Boolean = false
) = Schedule(
id,
targetUUID,
lastUpdateInMs,
Expand All @@ -20,7 +31,38 @@ fun Schedule.toNoData() = Schedule(
providerPrecisionInMs,
isNoPickup,
sourceLabel,
true // NO DATA
noData,
)

fun RouteDirectionStop.makeSchedule(
lastUpdateInMs: Long,
validityInMs: Long,
readFromSourceAtInMs: Long,
providerPrecisionInMs: Long,
sourceLabel: String,
noData: Boolean,
) = makeSchedule(
targetUUID = uuid,
lastUpdateInMs = lastUpdateInMs,
validityInMs = validityInMs,
readFromSourceAtInMs = readFromSourceAtInMs,
providerPrecisionInMs = providerPrecisionInMs,
sourceLabel = sourceLabel,
noData = noData
).apply {
isNoPickup = this@makeSchedule.isNoPickup
}

fun Schedule.toNoData() = makeSchedule(
id = id,
targetUUID = targetUUID,
lastUpdateInMs = lastUpdateInMs,
validityInMs = validityInMs,
readFromSourceAtInMs = readFromSourceAtInMs,
providerPrecisionInMs = providerPrecisionInMs,
isNoPickup = isNoPickup,
sourceLabel = sourceLabel,
noData = true // NO DATA
)

val Schedule.providerPrecision get() = providerPrecisionInMs.milliseconds
Expand Down Expand Up @@ -128,19 +170,51 @@ fun Schedule.Timestamp.updateArrivalForRealTime(newArrival: Instant) {
@Suppress("unused")
val Schedule.hasRealTime get() = this.timestamps.any { it.isRealTime }

fun Schedule.toStringK() = buildString {
append("S{")
append("uuid:").append(targetUUID)
append(",")
append("proPre:").append(providerPrecisionInMs.toDurationLog())
append(",")
append("useUtl:").append(usefulUntilInMs.toDateTimeLog())
append(",")
if (isNoPickup) {
append("noPickup")
append(",")
}
timestamps.takeIf { it.isNotEmpty() }?.let { timestamps ->
append("t[").append(timestamps.size).append("]")
if (Constants.DEBUG) {
append(timestamps.joinToString(separator = ",", prefix = ":{", postfix = "}") { it.toStringShort() })
}
append(",")
}
frequencies.takeIf { it.isNotEmpty() }?.let { frequencies ->
append("f[").append(frequencies.size).append("]")
if (Constants.DEBUG) {
append(frequencies.joinToString(separator = ",", prefix = ":{", postfix = "}") { it.toString() })
}
append(",")
}
append("}")
}

@Suppress("unused")
fun Schedule.Timestamp.toStringShort() = buildString {
append("T{")
arrivalTIfDifferent?.let {
append("a=").append(if (Constants.DEBUG) MTLog.formatDateTime(arrivalT) else arrivalT)
append("a=").append(if (Constants.DEBUG) arrivalT.toDateTimeLog() else arrivalT)
if (originalArrivalDelayMs != 0L) {
append("[+/-:").append(if (Constants.DEBUG) MTLog.formatDuration(originalArrivalDelayMs) else originalArrivalDelayMs).append("]")
append("[+/-:").append(if (Constants.DEBUG) originalArrivalDelayMs.toDateTimeLog() else originalArrivalDelayMs).append("]")
}
append(",")
}
append("d=").append(if (Constants.DEBUG) MTLog.formatDateTime(departureT) else departureT)
append("d=").append(if (Constants.DEBUG) departureT.toDateTimeLog() else departureT)
if (originalDepartureDelayMs != 0L) {
append("[+/-:").append(if (Constants.DEBUG) MTLog.formatDuration(originalDepartureDelayMs) else originalDepartureDelayMs).append("]")
append("[+/-:").append(if (Constants.DEBUG) originalDepartureDelayMs.toDateTimeLog() else originalDepartureDelayMs).append("]")
}
Comment thread
mmathieum marked this conversation as resolved.
if (tripId != null) {
append("[tId:").append(tripId).append("]")
}
if (isRealTime) {
append("[RT]")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,8 @@ private static String getAGENCY_TIME_AM_PM_FORMAT(@NonNull Context context) {
/**
* Override if multiple {@link GTFSRealTimeProvider} implementations in same app.
*/
private static String getAGENCY_TIME_ZONE(@NonNull Context context) {
@NonNull
public static String getAGENCY_TIME_ZONE(@NonNull Context context) {
if (agencyTimeZone == null) {
agencyTimeZone = context.getResources().getString(R.string.gtfs_real_time_agency_time_zone);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.mtransit.android.commons.data.RouteDirectionStop
import org.mtransit.android.commons.data.Stop
import org.mtransit.android.commons.provider.GTFSRealTimeProvider
import org.mtransit.android.commons.provider.GTFSRealTimeProvider.MT_HASH_SECRET_AND_DATE
import org.mtransit.android.commons.provider.GTFSRealTimeProvider.getAGENCY_TIME_ZONE
import org.mtransit.android.commons.provider.GTFSRealTimeProvider.getAGENCY_URL_HEADER_NAMES
import org.mtransit.android.commons.provider.GTFSRealTimeProvider.getAGENCY_URL_HEADER_VALUES
import org.mtransit.android.commons.provider.GTFSRealTimeProvider.getAGENCY_URL_TOKEN
Expand All @@ -20,6 +21,7 @@ import org.mtransit.android.commons.provider.GTFSRealTimeProvider.getAgencyRoute
import org.mtransit.android.commons.provider.GTFSRealTimeProvider.getAgencyRouteTypeTagTargetUUID
import org.mtransit.android.commons.provider.GTFSRealTimeProvider.getAgencyStopTagTargetUUID
import org.mtransit.android.commons.provider.GTFSRealTimeProvider.getAgencyTagTargetUUID
import org.mtransit.android.commons.provider.GTFSRealTimeProvider.isIGNORE_DIRECTION
import org.mtransit.android.commons.provider.GTFSRealTimeProvider.isUSE_URL_HASH_SECRET_AND_DATE
import org.mtransit.android.commons.provider.gtfs.GtfsRealtimeExt.optRouteId
import org.mtransit.android.commons.provider.gtfs.GtfsRealtimeExt.optStopId
Expand All @@ -31,6 +33,9 @@ import com.google.transit.realtime.GtfsRealtime.EntitySelector as GEntitySelecto
import com.google.transit.realtime.GtfsRealtime.TripDescriptor as GTripDescriptor
import com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate as GTUStopTimeUpdate

val GTFSRealTimeProvider.ignoreDirection get() = isIGNORE_DIRECTION(requireContextCompat())
val GTFSRealTimeProvider.timeZone get() = getAGENCY_TIME_ZONE(requireContextCompat())

private val GTFSRealTimeProvider.routeIdCleanupPattern get() = getRouteIdCleanupPattern(requireContextCompat())
fun GTFSRealTimeProvider.parseRouteId(es: GEntitySelector) = es.optRouteId?.let { parseRouteId(it) }
fun GTFSRealTimeProvider.parseRouteId(td: GTripDescriptor) = td.optRouteId?.let { parseRouteId(it) }
Expand All @@ -40,10 +45,11 @@ private val GTFSRealTimeProvider.tripIdCleanupPattern get() = getTripIdCleanupPa
fun GTFSRealTimeProvider.parseTripId(td: GTripDescriptor) = td.optTripId?.let { parseTripId(it) }
fun GTFSRealTimeProvider.parseTripId(gTripId: String) = gTripId.originalIdToId(tripIdCleanupPattern)

private val GTFSRealTimeProvider.stopIdCleanupPattern get() = getStopIdCleanupPattern(requireContextCompat())
fun GTFSRealTimeProvider.parseStopId(es: GEntitySelector) = es.optStopId?.let { parseStopId(it) }
@Suppress("unused")
fun GTFSRealTimeProvider.parseStopId(stu: GTUStopTimeUpdate) = stu.optStopId?.let { parseStopId(it) }
fun GTFSRealTimeProvider.parseStopId(es: GEntitySelector) = es.optStopId?.let { parseStopId(it) }
fun GTFSRealTimeProvider.parseStopId(gStopId: String) = gStopId.originalIdToHash(stopIdCleanupPattern)
private val GTFSRealTimeProvider.stopIdCleanupPattern get() = getStopIdCleanupPattern(requireContextCompat())

val GTFSRealTimeProvider.agencyTag get() = getAgencyTag(requireContextCompat())

Expand All @@ -62,6 +68,50 @@ fun RouteDirectionStop.getRouteTag(provider: GTFSRealTimeProvider) = this.route.
fun RouteDirectionStop.getDirectionTag(provider: GTFSRealTimeProvider) = this.direction.getDirectionTag(provider)
fun RouteDirectionStop.getStopTag(provider: GTFSRealTimeProvider) = this.stop.getStopTag(provider)

fun GTFSRealTimeProviderFilter.getPrimaryTargetUUIDs(
provider: GTFSRealTimeProvider,
ignoreDirection: Boolean = false,
includeStopTags: Boolean = false
): Pair<String, String>? =
(poi as? RouteDirectionStop)?.getPrimaryTargetUUIDs(provider, ignoreDirection, includeStopTags)
?: routeDirection?.getPrimaryTargetUUIDs(provider, ignoreDirection)
?: route?.getPrimaryTargetUUIDs(provider)

fun RouteDirectionStop.getPrimaryTargetUUIDs(
provider: GTFSRealTimeProvider,
ignoreDirection: Boolean = false,
includeStopTags: Boolean = false
) = when {
includeStopTags && ignoreDirection -> getAgencyRouteStopTagTargetUUID(provider.agencyTag, getRouteTag(provider), getStopTag(provider))?.let { it to uuid }
includeStopTags ->
getAgencyRouteDirectionStopTagTargetUUID(provider.agencyTag, getRouteTag(provider), getDirectionTag(provider), getStopTag(provider))?.let { it to uuid }

else -> getAgencyRouteDirectionTagTargetUUID(provider.agencyTag, getRouteTag(provider), getDirectionTag(provider))?.let { it to routeDirectionUUID }
}

fun RouteDirection.getPrimaryTargetUUIDs(
provider: GTFSRealTimeProvider,
ignoreDirection: Boolean = false,
) = when {
ignoreDirection -> getAgencyRouteTagTargetUUID(provider.agencyTag, getRouteTag(provider)) to route.uuid
else -> getAgencyRouteDirectionTagTargetUUID(provider.agencyTag, getRouteTag(provider), getDirectionTag(provider))?.let { it to uuid }
}

fun Route.getPrimaryTargetUUIDs(
provider: GTFSRealTimeProvider,
) =
getAgencyRouteTagTargetUUID(provider.agencyTag, getRouteTag(provider)) to uuid

fun GTFSRealTimeProviderFilter.getTargetUUIDs(
provider: GTFSRealTimeProvider,
includeAgencyTag: Boolean = false,
includeRouteType: Boolean = false,
includeStopTags: Boolean = false,
) =
(poi as? RouteDirectionStop)?.getTargetUUIDs(provider, includeAgencyTag, includeRouteType, includeStopTags)
?: routeDirection?.getTargetUUIDs(provider, includeAgencyTag, includeRouteType)
?: route?.getTargetUUIDs(provider, includeAgencyTag, includeRouteType)

fun RouteDirectionStop.getTargetUUIDs(
provider: GTFSRealTimeProvider,
includeAgencyTag: Boolean = false,
Expand All @@ -81,14 +131,22 @@ fun RouteDirectionStop.getTargetUUIDs(
}
}

fun RouteDirection.getTargetUUIDs(provider: GTFSRealTimeProvider, includeAgencyTag: Boolean = false, includeRouteType: Boolean = false) = buildMap {
fun RouteDirection.getTargetUUIDs(
provider: GTFSRealTimeProvider,
includeAgencyTag: Boolean = false,
includeRouteType: Boolean = false,
) = buildMap {
if (includeAgencyTag) put(getAgencyTagTargetUUID(provider.agencyTag), authority)
if (includeRouteType) getAgencyRouteTypeTagTargetUUID(provider.agencyTag, getRouteTypeTag(provider))?.let { put(it, authority) }
put(getAgencyRouteTagTargetUUID(provider.agencyTag, getRouteTag(provider)), route.uuid)
getAgencyRouteDirectionTagTargetUUID(provider.agencyTag, getRouteTag(provider), getDirectionTag(provider))?.let { put(it, uuid) }
}

fun Route.getTargetUUIDs(provider: GTFSRealTimeProvider, includeAgencyTag: Boolean = false, includeRouteType: Boolean = false) = buildMap {
fun Route.getTargetUUIDs(
provider: GTFSRealTimeProvider,
includeAgencyTag: Boolean = false,
includeRouteType: Boolean = false,
) = buildMap {
if (includeAgencyTag) put(getAgencyTagTargetUUID(provider.agencyTag), authority)
if (includeRouteType) getAgencyRouteTypeTagTargetUUID(provider.agencyTag, getRouteTypeTag(provider))?.let { put(it, authority) }
put(getAgencyRouteTagTargetUUID(provider.agencyTag, getRouteTag(provider)), uuid)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.mtransit.android.commons.provider.gtfs

import org.mtransit.android.commons.data.POI
import org.mtransit.android.commons.data.Route
import org.mtransit.android.commons.data.RouteDirection

interface GTFSRealTimeProviderFilter {
val poi: POI?
val routeDirection: RouteDirection?
val route: Route?
}
Loading