@@ -20,7 +20,9 @@ import net.youapps.transport.data.transport.model.TripLeg
2020import net.youapps.transport.toJavaDate
2121import net.youapps.transport.toZonedDateTime
2222import java.time.ZonedDateTime
23+ import java.time.temporal.ChronoUnit
2324import java.util.Date
25+ import kotlin.collections.orEmpty
2426
2527class 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(),
0 commit comments