listShapesForRoute method
Implementation
Future<Set<RouteDirection>> listShapesForRoute(
GtfsDataset dataset,
Route route,
) async {
final trips = (await dataset.trips.listResource(
LoadCriterion([
'route_id',
], (requestedFields) => requestedFields[0] == route.id),
));
Map<RawDirectionId, Set<String>> rawRouteDirections = {};
void addRawRouteDirection(RawDirectionId value) {
final existingRawRouteDirection = rawRouteDirections.keys
.cast<RawDirectionId?>()
.firstWhere(
(element) =>
listEquals(element!.stopIds, value.stopIds) &&
listEquals(
element.headsigns.toList(growable: false),
value.headsigns.toList(growable: false),
),
orElse: () => null,
);
rawRouteDirections[existingRawRouteDirection ?? value] =
(rawRouteDirections[existingRawRouteDirection] ?? <String>{})
..add(value.tripId);
}
String? currentTripId;
Map<int, String> currentMarkedStopIds = {};
Set<String> headsigns = {};
final tripIds = trips.map((trip) => trip.id);
await for (StopTime stopTime in dataset.stopTimes.streamResource(
LoadCriterion([
'trip_id',
], (requestedFields) => tripIds.contains(requestedFields[0])),
)) {
if (currentTripId == null) {
currentTripId = stopTime.tripId;
final firstHeadsign =
trips
.firstWhere((element) => element.id == currentTripId)
.tripHeadsign;
if (firstHeadsign != null) {
headsigns.add(firstHeadsign);
}
} else if (currentTripId != stopTime.tripId) {
final sortedStopIds = (currentMarkedStopIds.entries.toList(
growable: false,
)..sort(
(a, b) => a.key.compareTo(b.key),
)).map((e) => e.value).toList(growable: false);
addRawRouteDirection((
stopIds: sortedStopIds,
headsigns: headsigns,
tripId: currentTripId,
));
currentTripId = stopTime.tripId;
currentMarkedStopIds = {};
headsigns = {};
final headsign =
trips
.firstWhere((element) => element.id == currentTripId)
.tripHeadsign;
if (headsign != null) {
headsigns.add(headsign);
}
}
currentMarkedStopIds[stopTime.stopSequence] =
stopTime.stopId!; // TODO: Make work with edge cases
if (stopTime.stopHeadsign != null) {
headsigns.add(stopTime.stopHeadsign!);
}
}
final sortedStopIds = (currentMarkedStopIds.entries.toList(growable: false)
..sort(
(a, b) => a.key.compareTo(b.key),
)).map((e) => e.value).toList(growable: false);
addRawRouteDirection((
stopIds: sortedStopIds,
headsigns: headsigns,
tripId: currentTripId!,
));
Set<String> presentStopIds = rawRouteDirections.keys.fold(
<String>{},
(previousValue, element) => previousValue..addAll(element.stopIds),
);
Map<String, Stop> stops = {};
await for (AStop stop in dataset.stops.streamResource(
LoadCriterion([
'stop_id',
], (requestedFields) => presentStopIds.contains(requestedFields.single)),
)) {
stops[stop.id] =
stop
as Stop; // From the spec we know these are type 0 (stop/platform)
}
return rawRouteDirections.entries
.map(
(kp) => RouteDirection(
stops: kp.key.stopIds.map((e) => stops[e]!).toList(growable: false),
name: kp.key.headsigns.join(' / '),
tripIds: kp.value.toList(growable: false),
),
)
.toSet();
}