Skip to content

Commit 1cc6dca

Browse files
committed
fix: wrong transfer time calculation and transfer time inconsistencies
1 parent 841f3d4 commit 1cc6dca

File tree

4 files changed

+87
-66
lines changed

4 files changed

+87
-66
lines changed

app/src/main/java/net/youapps/transport/components/directions/IndividualTripCard.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ val individualIcons = mapOf(
2020

2121
@Composable
2222
fun IndividualTripCard(leg: TripLeg.Individual) {
23-
CardWithIcon(individualIcons[leg.type], TextUtils.formatDistance(leg.distance))
23+
CardWithIcon(individualIcons[leg.type], leg.distance?.let { TextUtils.formatDistance(it) })
2424
}

app/src/main/java/net/youapps/transport/data/transport/PTETransportProvider.kt

Lines changed: 79 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import net.youapps.transport.data.transport.model.TripLeg
2020
import net.youapps.transport.toJavaDate
2121
import net.youapps.transport.toZonedDateTime
2222
import java.time.ZonedDateTime
23+
import java.time.temporal.ChronoUnit
2324
import java.util.Date
25+
import kotlin.collections.orEmpty
2426

2527
class PTETransportProvider(private val network: NetworkProvider) : TransportProvider {
2628
override suspend fun queryStations(query: String): List<Location> {
@@ -97,38 +99,15 @@ class PTETransportProvider(private val network: NetworkProvider) : TransportProv
9799
)
98100
}
99101
val trips = response.trips.orEmpty().map { trip ->
102+
val legs = trip.legs.map { it.toTripLeg() }.toMutableList()
103+
fillWithAndFixTransferLegs(legs)
104+
100105
Trip(
101106
id = trip.id,
102107
from = trip.from.toLocation(),
103108
to = trip.to.toLocation(),
104109
duration = trip.duration,
105-
legs = trip.legs.map { leg ->
106-
return@map when (leg) {
107-
is de.schildbach.pte.dto.Trip.Public -> {
108-
TripLeg.Public(
109-
line = leg.line.toTransportLine(leg.destination),
110-
arrival = leg.arrivalStop.toStop(),
111-
departure = leg.departureStop.toStop(),
112-
intermediateStops = leg.intermediateStops?.map { it.toStop() }
113-
.orEmpty(),
114-
path = leg.toCoordinateList(),
115-
message = leg.message
116-
)
117-
}
118-
119-
is de.schildbach.pte.dto.Trip.Individual -> {
120-
TripLeg.Individual(
121-
path = leg.toCoordinateList(),
122-
distance = leg.distance,
123-
arrival = leg.arrival.toStop(leg.arrivalTime),
124-
departure = leg.departure.toStop(leg.departureTime),
125-
type = IndividualType.valueOf(leg.type.name)
126-
)
127-
}
128-
129-
else -> throw IllegalArgumentException("unsupported trip leg")
130-
}
131-
}
110+
legs = legs
132111
)
133112
}
134113

@@ -139,6 +118,79 @@ class PTETransportProvider(private val network: NetworkProvider) : TransportProv
139118
)
140119
}
141120

121+
private fun de.schildbach.pte.dto.Trip.Leg.toTripLeg() = when (this) {
122+
is de.schildbach.pte.dto.Trip.Public -> {
123+
TripLeg.Public(
124+
line = line.toTransportLine(destination),
125+
arrival = arrivalStop.toStop(),
126+
departure = departureStop.toStop(),
127+
intermediateStops = intermediateStops?.map { it.toStop() }
128+
.orEmpty(),
129+
path = toCoordinateList(),
130+
message = message
131+
)
132+
}
133+
134+
is de.schildbach.pte.dto.Trip.Individual -> {
135+
TripLeg.Individual(
136+
path = toCoordinateList(),
137+
distance = distance,
138+
arrival = arrival.toStop(arrivalTime),
139+
departure = departure.toStop(departureTime),
140+
type = IndividualType.valueOf(type.name)
141+
)
142+
}
143+
144+
else -> throw IllegalArgumentException("unsupported trip leg")
145+
}
146+
147+
/**
148+
* Add individual trip legs for each platform change.
149+
*
150+
* E.g., if there's a trip leg that arrives at platform 8 at 18:30, and the next trip leg starts
151+
* at platform 3 at 18:52, this inserts a individual trip leg with a duration of 22min.
152+
*/
153+
private fun fillWithAndFixTransferLegs(legs: MutableList<TripLeg>) {
154+
var i = 0
155+
// we have to move by index here because we modify `legs` inside the loop
156+
// i.e., otherwise we would modify the iterator while reading it, which would cause undefined
157+
// behavior
158+
while (i < legs.size - 1) {
159+
val leg = legs[i]
160+
val nextLeg = legs[i + 1]
161+
162+
if (leg is TripLeg.Public && nextLeg is TripLeg.Public) {
163+
legs.add(
164+
i + 1, TripLeg.Individual(
165+
departure = leg.arrival,
166+
arrival = nextLeg.departure,
167+
type = IndividualType.TRANSFER
168+
)
169+
)
170+
i++
171+
} else if (leg is TripLeg.Individual) {
172+
// calculate approximated duration of this transfer (= end - start)
173+
// and set start and end time to the ones of the previous/next trip leg
174+
// needed because otherwise durationMillis would always equal approxDurationMillis
175+
val approxDuration = ChronoUnit.MILLIS.between(
176+
leg.departure.departureTime.predictedOrPlanned,
177+
leg.arrival.arrivalTime.predictedOrPlanned,
178+
)
179+
val startTime =
180+
legs.getOrNull(i - 1)?.arrival?.arrivalTime ?: leg.departure.departureTime
181+
val endTime = nextLeg.departure.departureTime
182+
183+
legs[i] = leg.copy(
184+
approxDurationMillis = approxDuration,
185+
departure = leg.departure.copy(departureTime = startTime),
186+
arrival = leg.arrival.copy(arrivalTime = endTime)
187+
)
188+
}
189+
190+
i++
191+
}
192+
}
193+
142194
private fun de.schildbach.pte.dto.Location.toLocation() = Location(
143195
id = id,
144196
name = uniqueShortName(),

app/src/main/java/net/youapps/transport/data/transport/model/Trip.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@ sealed class TripLeg {
3939
): TripLeg()
4040

4141
data class Individual(
42+
val type: IndividualType,
4243
override val departure: Stop,
4344
override val arrival: Stop,
44-
val distance: Int,
45-
override val path: List<GeoCoordinate>?,
46-
val type: IndividualType
45+
val distance: Int? = null,
46+
override val path: List<GeoCoordinate>? = null,
47+
val approxDurationMillis: Long? = null
4748
): TripLeg()
4849

4950
abstract val departure: Stop

app/src/main/java/net/youapps/transport/screens/TripDetailsScreen.kt

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -100,49 +100,17 @@ fun TripDetailsScreen(
100100
TripLegPublic(leg) { location ->
101101
navController.navigate(NavRoutes.DeparturesFromLocation(location))
102102
}
103-
104-
// display change time between current and next trip leg
105-
tripLegs.getOrNull(index + 1)?.let { nextLeg ->
106-
if (nextLeg is TripLeg.Public) {
107-
HorizontalDivider()
108-
109-
val changeTimeMillis = remember {
110-
TextUtils.dateDifferenceMillis(
111-
leg.arrival.arrivalTime.predictedOrPlanned
112-
?: return@remember null,
113-
nextLeg.departure.departureTime.predictedOrPlanned
114-
?: return@remember null
115-
)
116-
}
117-
118-
TripTransfer(changeTimeMillis)
119-
}
120-
}
121103
}
122104

123105
is TripLeg.Individual -> {
124106
val isTransferLeg =
125107
leg.type !in arrayOf(IndividualType.BIKE, IndividualType.CAR)
126-
if (!isTransferLeg) {
108+
if (isTransferLeg) {
109+
TripTransfer(leg.durationMillis, leg.distance, leg.approxDurationMillis)
110+
} else {
127111
TripLegIndividual(leg) { location ->
128112
navController.navigate(NavRoutes.DeparturesFromLocation(location))
129113
}
130-
} else {
131-
// display change time between current and next trip leg
132-
tripLegs.getOrNull(index + 1)?.let { nextLeg ->
133-
HorizontalDivider()
134-
135-
val changeTimeMillis = remember {
136-
TextUtils.dateDifferenceMillis(
137-
leg.arrival.arrivalTime.predictedOrPlanned
138-
?: return@remember null,
139-
nextLeg.departure.departureTime.predictedOrPlanned
140-
?: return@remember null
141-
)
142-
}
143-
144-
TripTransfer(changeTimeMillis, leg.distance, leg.durationMillis)
145-
}
146114
}
147115
}
148116
}

0 commit comments

Comments
 (0)