gtfs-to-html 2.4.3 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/utils.js CHANGED
@@ -27,7 +27,6 @@ import {
27
27
  getTimetableNotesReferences,
28
28
  getTimetableNotes,
29
29
  getRoutes,
30
- getDb,
31
30
  getCalendars,
32
31
  getTimetableStopOrders,
33
32
  getStops,
@@ -37,6 +36,7 @@ import {
37
36
  getTimetables,
38
37
  getTimetablePages,
39
38
  getAgencies,
39
+ openDb,
40
40
  } from 'gtfs';
41
41
  import { stringify } from 'csv-stringify';
42
42
  import moment from 'moment';
@@ -275,8 +275,8 @@ const sortTripsByStoptimeAtStop = (trips, stopId) =>
275
275
  /*
276
276
  * Get all calendar dates for a specific timetable.
277
277
  */
278
- const getCalendarDatesForTimetable = async (timetable, config) => {
279
- const calendarDates = await getCalendarDates(
278
+ const getCalendarDatesForTimetable = (timetable, config) => {
279
+ const calendarDates = getCalendarDates(
280
280
  {
281
281
  service_id: timetable.service_ids,
282
282
  },
@@ -334,8 +334,8 @@ const getDaysFromCalendars = (calendars) => {
334
334
  /*
335
335
  * Get the `trip_headsign` for a specific timetable.
336
336
  */
337
- const getDirectionHeadsignFromTimetable = async (timetable) => {
338
- const trips = await getTrips(
337
+ const getDirectionHeadsignFromTimetable = (timetable) => {
338
+ const trips = getTrips(
339
339
  {
340
340
  direction_id: timetable.direction_id,
341
341
  route_id: timetable.route_ids,
@@ -353,31 +353,31 @@ const getDirectionHeadsignFromTimetable = async (timetable) => {
353
353
  /*
354
354
  * Get the notes for a specific timetable.
355
355
  */
356
- const getTimetableNotesForTimetable = async (timetable, config) => {
356
+ const getTimetableNotesForTimetable = (timetable, config) => {
357
357
  const noteReferences = [
358
358
  // Get all notes for this timetable.
359
- ...(await getTimetableNotesReferences({
359
+ ...getTimetableNotesReferences({
360
360
  timetable_id: timetable.timetable_id,
361
- })),
361
+ }),
362
362
 
363
363
  // Get all notes for this route.
364
- ...(await getTimetableNotesReferences({
364
+ ...getTimetableNotesReferences({
365
365
  route_id: timetable.routes.map((route) => route.route_id),
366
366
  timetable_id: null,
367
- })),
367
+ }),
368
368
 
369
369
  // Get all notes for all trips in this timetable.
370
- ...(await getTimetableNotesReferences({
370
+ ...getTimetableNotesReferences({
371
371
  trip_id: timetable.orderedTrips.map((trip) => trip.trip_id),
372
- })),
372
+ }),
373
373
 
374
374
  // Get all notes for all stops in this timetable.
375
- ...(await getTimetableNotesReferences({
375
+ ...getTimetableNotesReferences({
376
376
  stop_id: timetable.stops.map((stop) => stop.stop_id),
377
377
  trip_id: null,
378
378
  route_id: null,
379
379
  timetable_id: null,
380
- })),
380
+ }),
381
381
  ];
382
382
 
383
383
  const usedNoteReferences = [];
@@ -416,7 +416,7 @@ const getTimetableNotesForTimetable = async (timetable, config) => {
416
416
  }
417
417
  }
418
418
 
419
- const notes = await getTimetableNotes({
419
+ const notes = getTimetableNotes({
420
420
  note_id: usedNoteReferences.map((noteReference) => noteReference.note_id),
421
421
  });
422
422
 
@@ -445,14 +445,14 @@ const getTimetableNotesForTimetable = async (timetable, config) => {
445
445
  * Create a timetable page from a single timetable. Used if no
446
446
  * `timetable_pages.txt` is present.
447
447
  */
448
- const convertTimetableToTimetablePage = async (timetable, config) => {
448
+ const convertTimetableToTimetablePage = (timetable, config) => {
449
449
  if (!timetable.routes) {
450
- timetable.routes = await getRoutes({
450
+ timetable.routes = getRoutes({
451
451
  route_id: timetable.route_ids,
452
452
  });
453
453
  }
454
454
 
455
- const filename = await generateFileName(timetable, config);
455
+ const filename = generateFileName(timetable, config);
456
456
 
457
457
  return {
458
458
  timetable_page_id: timetable.timetable_id,
@@ -517,61 +517,47 @@ const convertRouteToTimetablePage = (
517
517
  * Create timetable pages for all routes in an agency. Used if no
518
518
  * `timetables.txt` is present.
519
519
  */
520
- const convertRoutesToTimetablePages = async (config) => {
521
- const db = getDb();
522
- const routes = await getRoutes();
523
- const calendars = await getCalendars();
520
+ const convertRoutesToTimetablePages = (config) => {
521
+ const db = openDb(config);
522
+ const routes = getRoutes();
523
+ const calendars = getCalendars();
524
524
 
525
525
  // Find all calendar dates with service_ids not present in `calendar.txt`.
526
526
  const serviceIds = calendars.map((calendar) => calendar.service_id);
527
- const calendarDates = await db.all(
528
- `SELECT * FROM calendar_dates WHERE exception_type = 1 AND service_id NOT IN (${serviceIds
529
- .map((serviceId) => `'${serviceId}'`)
530
- .join(', ')})`
531
- );
527
+ const calendarDates = db
528
+ .prepare(
529
+ `SELECT * FROM calendar_dates WHERE exception_type = 1 AND service_id NOT IN (${serviceIds
530
+ .map((serviceId) => `'${serviceId}'`)
531
+ .join(', ')})`
532
+ )
533
+ .all();
534
+
535
+ const timetablePages = routes.map((route) => {
536
+ const trips = getTrips(
537
+ {
538
+ route_id: route.route_id,
539
+ },
540
+ ['trip_headsign', 'direction_id']
541
+ );
542
+ const directions = uniqBy(trips, (trip) => trip.direction_id);
543
+ const dayGroups = groupBy(calendars, calendarToCalendarCode);
544
+ const calendarDateGroups = groupBy(calendarDates, 'service_id');
532
545
 
533
- const timetablePages = await Promise.all(
534
- routes.map(async (route) => {
535
- const trips = await getTrips(
536
- {
537
- route_id: route.route_id,
538
- },
539
- ['trip_headsign', 'direction_id']
540
- );
541
- const directions = uniqBy(trips, (trip) => trip.direction_id);
542
- const dayGroups = groupBy(calendars, calendarToCalendarCode);
543
- const calendarDateGroups = groupBy(calendarDates, 'service_id');
544
-
545
- return Promise.all(
546
- directions.map((direction) =>
547
- Promise.all([
548
- Promise.all(
549
- Object.values(dayGroups).map((calendars) =>
550
- convertRouteToTimetablePage(
551
- route,
552
- direction,
553
- calendars,
554
- null,
555
- config
556
- )
557
- )
558
- ),
559
- Promise.all(
560
- Object.values(calendarDateGroups).map((calendarDates) =>
561
- convertRouteToTimetablePage(
562
- route,
563
- direction,
564
- null,
565
- calendarDates,
566
- config
567
- )
568
- )
569
- ),
570
- ])
546
+ return directions.map((direction) => [
547
+ Object.values(dayGroups).map((calendars) =>
548
+ convertRouteToTimetablePage(route, direction, calendars, null, config)
549
+ ),
550
+ Object.values(calendarDateGroups).map((calendarDates) =>
551
+ convertRouteToTimetablePage(
552
+ route,
553
+ direction,
554
+ null,
555
+ calendarDates,
556
+ config
571
557
  )
572
- );
573
- })
574
- );
558
+ ),
559
+ ]);
560
+ });
575
561
 
576
562
  return compact(flattenDeep(timetablePages));
577
563
  };
@@ -652,9 +638,9 @@ const duplicateStopsForDifferentArrivalDeparture = (
652
638
  /*
653
639
  * Get a sorted array of stop_ids for a specific timetable.
654
640
  */
655
- const getStopOrder = async (timetable, config) => {
641
+ const getStopOrder = (timetable, config) => {
656
642
  // First, check if `timetable_stop_order.txt` for route exists
657
- const timetableStopOrders = await getTimetableStopOrders(
643
+ const timetableStopOrders = getTimetableStopOrders(
658
644
  {
659
645
  timetable_id: timetable.timetable_id,
660
646
  },
@@ -714,45 +700,43 @@ const getStopOrder = async (timetable, config) => {
714
700
  /*
715
701
  * Get an array of stops for a specific timetable.
716
702
  */
717
- const getStopsForTimetable = async (timetable, config) => {
703
+ const getStopsForTimetable = (timetable, config) => {
718
704
  if (timetable.orderedTrips.length === 0) {
719
705
  return [];
720
706
  }
721
707
 
722
- const orderedStopIds = await getStopOrder(timetable, config);
723
- const orderedStops = await Promise.all(
724
- orderedStopIds.map(async (stopId, index) => {
725
- const stops = await getStops({
726
- stop_id: stopId,
727
- });
708
+ const orderedStopIds = getStopOrder(timetable, config);
709
+ const orderedStops = orderedStopIds.map((stopId, index) => {
710
+ const stops = getStops({
711
+ stop_id: stopId,
712
+ });
728
713
 
729
- if (stops.length === 0) {
730
- throw new Error(
731
- `No stop found found for stop_id=${stopId} in timetable_id=${timetable.timetable_id}`
732
- );
733
- }
714
+ if (stops.length === 0) {
715
+ throw new Error(
716
+ `No stop found found for stop_id=${stopId} in timetable_id=${timetable.timetable_id}`
717
+ );
718
+ }
734
719
 
735
- const stop = {
736
- ...stops[0],
737
- trips: [],
738
- };
720
+ const stop = {
721
+ ...stops[0],
722
+ trips: [],
723
+ };
739
724
 
740
- if (
741
- index < orderedStopIds.length - 1 &&
742
- stopId === orderedStopIds[index + 1]
743
- ) {
744
- stop.type = 'arrival';
745
- } else if (index > 0 && stopId === orderedStopIds[index - 1]) {
746
- stop.type = 'departure';
747
- }
725
+ if (
726
+ index < orderedStopIds.length - 1 &&
727
+ stopId === orderedStopIds[index + 1]
728
+ ) {
729
+ stop.type = 'arrival';
730
+ } else if (index > 0 && stopId === orderedStopIds[index - 1]) {
731
+ stop.type = 'departure';
732
+ }
748
733
 
749
- return stop;
750
- })
751
- );
734
+ return stop;
735
+ });
752
736
 
753
737
  // If `showStopCity` is true, look up stop attributes.
754
738
  if (timetable.showStopCity) {
755
- const stopAttributes = await getStopAttributes({
739
+ const stopAttributes = getStopAttributes({
756
740
  stop_id: orderedStopIds,
757
741
  });
758
742
 
@@ -773,8 +757,8 @@ const getStopsForTimetable = async (timetable, config) => {
773
757
  /*
774
758
  * Get all calendars from a specific timetable.
775
759
  */
776
- const getCalendarsFromTimetable = async (timetable) => {
777
- const db = getDb();
760
+ const getCalendarsFromTimetable = (timetable) => {
761
+ const db = openDb();
778
762
  let whereClause = '';
779
763
  const whereClauses = [];
780
764
 
@@ -808,14 +792,14 @@ const getCalendarsFromTimetable = async (timetable) => {
808
792
  whereClause = `WHERE ${whereClauses.join(' AND ')}`;
809
793
  }
810
794
 
811
- return db.all(`SELECT * FROM calendar ${whereClause}`);
795
+ return db.prepare(`SELECT * FROM calendar ${whereClause}`).all();
812
796
  };
813
797
 
814
798
  /*
815
799
  * Get all calendar date service ids for an agency between two dates.
816
800
  */
817
- const getCalendarDatesServiceIds = async (startDate, endDate) => {
818
- const db = getDb();
801
+ const getCalendarDatesServiceIds = (startDate, endDate) => {
802
+ const db = openDb();
819
803
  const whereClauses = ['exception_type = 1'];
820
804
 
821
805
  if (endDate) {
@@ -826,11 +810,13 @@ const getCalendarDatesServiceIds = async (startDate, endDate) => {
826
810
  whereClauses.push(`date >= ${sqlString.escape(startDate)}`);
827
811
  }
828
812
 
829
- const calendarDates = await db.all(
830
- `SELECT DISTINCT service_id FROM calendar_dates WHERE ${whereClauses.join(
831
- ' AND '
832
- )}`
833
- );
813
+ const calendarDates = db
814
+ .prepare(
815
+ `SELECT DISTINCT service_id FROM calendar_dates WHERE ${whereClauses.join(
816
+ ' AND '
817
+ )}`
818
+ )
819
+ .all();
834
820
  return calendarDates.map((calendarDate) => calendarDate.service_id);
835
821
  };
836
822
 
@@ -839,8 +825,8 @@ const getCalendarDatesServiceIds = async (startDate, endDate) => {
839
825
  * and the stop_id of parent station itself. If no parent station, it returns the
840
826
  * stop_id.
841
827
  */
842
- const getAllStationStopIds = async (stopId) => {
843
- const stops = await getStops({
828
+ const getAllStationStopIds = (stopId) => {
829
+ const stops = getStops({
844
830
  stop_id: stopId,
845
831
  });
846
832
 
@@ -850,7 +836,7 @@ const getAllStationStopIds = async (stopId) => {
850
836
  return [stopId];
851
837
  }
852
838
 
853
- const stopsInParentStation = await getStops(
839
+ const stopsInParentStation = getStops(
854
840
  {
855
841
  parent_station: stop.parent_station,
856
842
  },
@@ -866,8 +852,8 @@ const getAllStationStopIds = async (stopId) => {
866
852
  /*
867
853
  * Get trips with the same `block_id`.
868
854
  */
869
- const getTripsWithSameBlock = async (trip, timetable) => {
870
- const trips = await getTrips(
855
+ const getTripsWithSameBlock = (trip, timetable) => {
856
+ const trips = getTrips(
871
857
  {
872
858
  block_id: trip.block_id,
873
859
  service_id: timetable.service_ids,
@@ -875,26 +861,24 @@ const getTripsWithSameBlock = async (trip, timetable) => {
875
861
  ['trip_id', 'route_id']
876
862
  );
877
863
 
878
- await Promise.all(
879
- trips.map(async (blockTrip) => {
880
- const stopTimes = await getStoptimes(
881
- {
882
- trip_id: blockTrip.trip_id,
883
- },
884
- [],
885
- [['stop_sequence', 'ASC']]
886
- );
864
+ for (const blockTrip of trips) {
865
+ const stopTimes = getStoptimes(
866
+ {
867
+ trip_id: blockTrip.trip_id,
868
+ },
869
+ [],
870
+ [['stop_sequence', 'ASC']]
871
+ );
887
872
 
888
- if (stopTimes.length === 0) {
889
- throw new Error(
890
- `No stoptimes found found for trip_id=${blockTrip.trip_id}`
891
- );
892
- }
873
+ if (stopTimes.length === 0) {
874
+ throw new Error(
875
+ `No stoptimes found found for trip_id=${blockTrip.trip_id}`
876
+ );
877
+ }
893
878
 
894
- blockTrip.firstStoptime = first(stopTimes);
895
- blockTrip.lastStoptime = last(stopTimes);
896
- })
897
- );
879
+ blockTrip.firstStoptime = first(stopTimes);
880
+ blockTrip.lastStoptime = last(stopTimes);
881
+ }
898
882
 
899
883
  return sortBy(trips, (trip) => trip.firstStoptime.departure_timestamp);
900
884
  };
@@ -903,7 +887,7 @@ const getTripsWithSameBlock = async (trip, timetable) => {
903
887
  * Get next trip and previous trip with the same `block_id` if it arrives or
904
888
  * departs from the same stop and is a different route.
905
889
  */
906
- const addTripContinuation = async (trip, timetable) => {
890
+ const addTripContinuation = (trip, timetable) => {
907
891
  if (!trip.block_id) {
908
892
  return;
909
893
  }
@@ -911,10 +895,10 @@ const addTripContinuation = async (trip, timetable) => {
911
895
  const maxContinuesAsWaitingTimeSeconds = 60 * 60;
912
896
 
913
897
  const firstStoptime = first(trip.stoptimes);
914
- const firstStopIds = await getAllStationStopIds(firstStoptime.stop_id);
898
+ const firstStopIds = getAllStationStopIds(firstStoptime.stop_id);
915
899
  const lastStoptime = last(trip.stoptimes);
916
- const lastStopIds = await getAllStationStopIds(lastStoptime.stop_id);
917
- const blockTrips = await getTripsWithSameBlock(trip, timetable);
900
+ const lastStopIds = getAllStationStopIds(lastStoptime.stop_id);
901
+ const blockTrips = getTripsWithSameBlock(trip, timetable);
918
902
 
919
903
  // "Continues From" trips must be the previous trip chronologically.
920
904
  const previousTrip = findLast(
@@ -937,7 +921,7 @@ const addTripContinuation = async (trip, timetable) => {
937
921
  firstStoptime.departure_timestamp - maxContinuesAsWaitingTimeSeconds &&
938
922
  firstStopIds.includes(previousTrip.lastStoptime.stop_id)
939
923
  ) {
940
- const routes = await getRoutes({
924
+ const routes = getRoutes({
941
925
  route_id: previousTrip.route_id,
942
926
  });
943
927
 
@@ -968,7 +952,7 @@ const addTripContinuation = async (trip, timetable) => {
968
952
  lastStoptime.arrival_timestamp + maxContinuesAsWaitingTimeSeconds &&
969
953
  lastStopIds.includes(nextTrip.firstStoptime.stop_id)
970
954
  ) {
971
- const routes = await getRoutes({
955
+ const routes = getRoutes({
972
956
  route_id: nextTrip.route_id,
973
957
  });
974
958
 
@@ -984,15 +968,24 @@ const addTripContinuation = async (trip, timetable) => {
984
968
  const filterTrips = (timetable) => {
985
969
  let filteredTrips = timetable.orderedTrips;
986
970
 
987
- // Remove adjacent stoptimes with the same stop_id
971
+ // Combine adjacent stoptimes with the same `stop_id`
988
972
  for (const trip of filteredTrips) {
989
- trip.stoptimes = trip.stoptimes.filter((stoptime, index) => {
990
- if (index === 0) {
991
- return true;
973
+ const combinedStoptimes = [];
974
+
975
+ for (const [index, stoptime] of trip.stoptimes.entries()) {
976
+ if (
977
+ index === 0 ||
978
+ stoptime.stop_id !== trip.stoptimes[index - 1].stop_id
979
+ ) {
980
+ combinedStoptimes.push(stoptime);
981
+ } else {
982
+ // The `stoptime` is the same as previous, use `arrival_time` from previous and `departure_time` from this stoptime
983
+ combinedStoptimes[combinedStoptimes.length - 1].departure_time =
984
+ stoptime.departure_time;
992
985
  }
986
+ }
993
987
 
994
- return stoptime.stop_id !== trip.stoptimes[index - 1].stop_id;
995
- });
988
+ trip.stoptimes = combinedStoptimes;
996
989
  }
997
990
 
998
991
  // Remove stoptimes for stops not used in timetable
@@ -1012,7 +1005,9 @@ const filterTrips = (timetable) => {
1012
1005
  /*
1013
1006
  * Get all trips from a timetable.
1014
1007
  */
1015
- const getTripsForTimetable = async (timetable, calendars, config) => {
1008
+
1009
+ /* eslint-disable complexity */
1010
+ const getTripsForTimetable = (timetable, calendars, config) => {
1016
1011
  const tripQuery = {
1017
1012
  route_id: timetable.route_ids,
1018
1013
  service_id: timetable.service_ids,
@@ -1022,7 +1017,7 @@ const getTripsForTimetable = async (timetable, calendars, config) => {
1022
1017
  tripQuery.direction_id = timetable.direction_id;
1023
1018
  }
1024
1019
 
1025
- const trips = await getTrips(tripQuery);
1020
+ const trips = getTrips(tripQuery);
1026
1021
 
1027
1022
  if (trips.length === 0) {
1028
1023
  timetable.warnings.push(
@@ -1034,7 +1029,7 @@ const getTripsForTimetable = async (timetable, calendars, config) => {
1034
1029
  );
1035
1030
  }
1036
1031
 
1037
- const frequencies = await getFrequencies({
1032
+ const frequencies = getFrequencies({
1038
1033
  trip_id: trips.map((trip) => trip.trip_id),
1039
1034
  });
1040
1035
 
@@ -1042,81 +1037,78 @@ const getTripsForTimetable = async (timetable, calendars, config) => {
1042
1037
  timetable.service_ids = uniq(trips.map((trip) => trip.service_id));
1043
1038
 
1044
1039
  const formattedTrips = [];
1045
- await Promise.all(
1046
- trips.map(async (trip) => {
1047
- const formattedTrip = formatTrip(trip, timetable, calendars, config);
1048
- formattedTrip.stoptimes = await getStoptimes(
1049
- {
1050
- trip_id: formattedTrip.trip_id,
1051
- },
1052
- [],
1053
- [['stop_sequence', 'ASC']]
1054
- );
1055
1040
 
1056
- if (formattedTrip.stoptimes.length === 0) {
1057
- timetable.warnings.push(
1058
- `No stoptimes found for trip_id=${
1059
- formattedTrip.trip_id
1060
- }, route_id=${timetable.route_ids.join('_')}, timetable_id=${
1061
- timetable.timetable_id
1062
- }`
1063
- );
1064
- }
1041
+ for (const trip of trips) {
1042
+ const formattedTrip = formatTrip(trip, timetable, calendars, config);
1043
+ formattedTrip.stoptimes = getStoptimes(
1044
+ {
1045
+ trip_id: formattedTrip.trip_id,
1046
+ },
1047
+ [],
1048
+ [['stop_sequence', 'ASC']]
1049
+ );
1065
1050
 
1066
- // Exclude trips before timetable `start_timestamp`
1067
- if (
1068
- timetable.start_timestamp !== '' &&
1069
- timetable.start_timestamp !== null &&
1070
- timetable.start_timestamp !== undefined
1071
- ) {
1072
- if (trip.stoptimes[0].arrival_timestamp < timetable.start_timestamp) {
1073
- return;
1074
- }
1075
- }
1051
+ if (formattedTrip.stoptimes.length === 0) {
1052
+ timetable.warnings.push(
1053
+ `No stoptimes found for trip_id=${
1054
+ formattedTrip.trip_id
1055
+ }, route_id=${timetable.route_ids.join('_')}, timetable_id=${
1056
+ timetable.timetable_id
1057
+ }`
1058
+ );
1059
+ }
1076
1060
 
1077
- // Exclude trips after timetable `end_timestamp`
1078
- if (
1079
- timetable.end_timestamp !== '' &&
1080
- timetable.end_timestamp !== null &&
1081
- timetable.end_timestamp !== undefined
1082
- ) {
1083
- if (trip.stoptimes[0].arrival_timestamp >= timetable.end_timestamp) {
1084
- return;
1085
- }
1086
- }
1061
+ // Exclude trips before timetable `start_timestamp`
1062
+ if (
1063
+ timetable.start_timestamp !== '' &&
1064
+ timetable.start_timestamp !== null &&
1065
+ timetable.start_timestamp !== undefined &&
1066
+ trip.stoptimes[0].arrival_timestamp < timetable.start_timestamp
1067
+ ) {
1068
+ return;
1069
+ }
1087
1070
 
1088
- if (timetable.show_trip_continuation) {
1089
- await addTripContinuation(formattedTrip, timetable);
1071
+ // Exclude trips after timetable `end_timestamp`
1072
+ if (
1073
+ timetable.end_timestamp !== '' &&
1074
+ timetable.end_timestamp !== null &&
1075
+ timetable.end_timestamp !== undefined &&
1076
+ trip.stoptimes[0].arrival_timestamp >= timetable.end_timestamp
1077
+ ) {
1078
+ return;
1079
+ }
1090
1080
 
1091
- if (formattedTrip.continues_as_route) {
1092
- timetable.has_continues_as_route = true;
1093
- }
1081
+ if (timetable.show_trip_continuation) {
1082
+ addTripContinuation(formattedTrip, timetable);
1094
1083
 
1095
- if (formattedTrip.continues_from_route) {
1096
- timetable.has_continues_from_route = true;
1097
- }
1084
+ if (formattedTrip.continues_as_route) {
1085
+ timetable.has_continues_as_route = true;
1098
1086
  }
1099
1087
 
1100
- const tripFrequencies = frequencies.filter(
1101
- (frequency) => frequency.trip_id === trip.trip_id
1102
- );
1103
-
1104
- if (tripFrequencies.length === 0) {
1105
- formattedTrips.push(formattedTrip);
1106
- } else {
1107
- const frequencyTrips = generateTripsByFrequencies(
1108
- formattedTrip,
1109
- frequencies,
1110
- config
1111
- );
1112
- formattedTrips.push(...frequencyTrips);
1113
- timetable.frequencies = frequencies;
1114
- timetable.frequencyExactTimes = some(frequencies, {
1115
- exact_times: 1,
1116
- });
1088
+ if (formattedTrip.continues_from_route) {
1089
+ timetable.has_continues_from_route = true;
1117
1090
  }
1118
- })
1119
- );
1091
+ }
1092
+
1093
+ const tripFrequencies = frequencies.filter(
1094
+ (frequency) => frequency.trip_id === trip.trip_id
1095
+ );
1096
+
1097
+ if (tripFrequencies.length === 0) {
1098
+ formattedTrips.push(formattedTrip);
1099
+ } else {
1100
+ const frequencyTrips = generateTripsByFrequencies(
1101
+ formattedTrip,
1102
+ frequencies,
1103
+ config
1104
+ );
1105
+ formattedTrips.push(...frequencyTrips);
1106
+ timetable.frequencies = frequencies;
1107
+ timetable.frequencyExactTimes = some(frequencies, {
1108
+ exact_times: 1,
1109
+ });
1110
+ }
1111
+ }
1120
1112
 
1121
1113
  if (config.useParentStation) {
1122
1114
  const stopIds = [];
@@ -1127,7 +1119,7 @@ const getTripsForTimetable = async (timetable, calendars, config) => {
1127
1119
  }
1128
1120
  }
1129
1121
 
1130
- const stops = await getStops(
1122
+ const stops = getStops(
1131
1123
  {
1132
1124
  stop_id: uniq(stopIds),
1133
1125
  },
@@ -1147,73 +1139,65 @@ const getTripsForTimetable = async (timetable, calendars, config) => {
1147
1139
 
1148
1140
  return sortTrips(formattedTrips, config);
1149
1141
  };
1142
+ /* eslint-enable complexity */
1150
1143
 
1151
1144
  /*
1152
1145
  * Format timetables for display.
1153
1146
  */
1154
- const formatTimetables = async (timetables, config) => {
1155
- const formattedTimetables = await Promise.all(
1156
- timetables.map(async (timetable) => {
1157
- timetable.warnings = [];
1158
- const dayList = formatDays(timetable, config);
1159
- const calendars = await getCalendarsFromTimetable(timetable);
1160
- let serviceIds = calendars.map((calendar) => calendar.service_id);
1161
-
1162
- if (timetable.include_exceptions === 1) {
1163
- const calendarDatesServiceIds = await getCalendarDatesServiceIds(
1164
- timetable.start_date,
1165
- timetable.end_date
1166
- );
1167
- serviceIds = uniq([...serviceIds, ...calendarDatesServiceIds]);
1168
- }
1147
+ const formatTimetables = (timetables, config) => {
1148
+ const formattedTimetables = timetables.map((timetable) => {
1149
+ timetable.warnings = [];
1150
+ const dayList = formatDays(timetable, config);
1151
+ const calendars = getCalendarsFromTimetable(timetable);
1152
+ let serviceIds = calendars.map((calendar) => calendar.service_id);
1153
+
1154
+ if (timetable.include_exceptions === 1) {
1155
+ const calendarDatesServiceIds = getCalendarDatesServiceIds(
1156
+ timetable.start_date,
1157
+ timetable.end_date
1158
+ );
1159
+ serviceIds = uniq([...serviceIds, ...calendarDatesServiceIds]);
1160
+ }
1169
1161
 
1170
- Object.assign(timetable, {
1171
- noServiceSymbolUsed: false,
1172
- requestDropoffSymbolUsed: false,
1173
- noDropoffSymbolUsed: false,
1174
- requestPickupSymbolUsed: false,
1175
- noPickupSymbolUsed: false,
1176
- interpolatedStopSymbolUsed: false,
1177
- showStopCity: config.showStopCity,
1178
- showStopDescription: config.showStopDescription,
1179
- noServiceSymbol: config.noServiceSymbol,
1180
- requestDropoffSymbol: config.requestDropoffSymbol,
1181
- noDropoffSymbol: config.noDropoffSymbol,
1182
- requestPickupSymbol: config.requestPickupSymbol,
1183
- noPickupSymbol: config.noPickupSymbol,
1184
- interpolatedStopSymbol: config.interpolatedStopSymbol,
1185
- orientation: timetable.orientation || config.defaultOrientation,
1186
- service_ids: serviceIds,
1187
- dayList,
1188
- dayListLong: formatDaysLong(dayList, config),
1189
- });
1162
+ Object.assign(timetable, {
1163
+ noServiceSymbolUsed: false,
1164
+ requestDropoffSymbolUsed: false,
1165
+ noDropoffSymbolUsed: false,
1166
+ requestPickupSymbolUsed: false,
1167
+ noPickupSymbolUsed: false,
1168
+ interpolatedStopSymbolUsed: false,
1169
+ showStopCity: config.showStopCity,
1170
+ showStopDescription: config.showStopDescription,
1171
+ noServiceSymbol: config.noServiceSymbol,
1172
+ requestDropoffSymbol: config.requestDropoffSymbol,
1173
+ noDropoffSymbol: config.noDropoffSymbol,
1174
+ requestPickupSymbol: config.requestPickupSymbol,
1175
+ noPickupSymbol: config.noPickupSymbol,
1176
+ interpolatedStopSymbol: config.interpolatedStopSymbol,
1177
+ orientation: timetable.orientation || config.defaultOrientation,
1178
+ service_ids: serviceIds,
1179
+ dayList,
1180
+ dayListLong: formatDaysLong(dayList, config),
1181
+ });
1190
1182
 
1191
- timetable.orderedTrips = await getTripsForTimetable(
1192
- timetable,
1193
- calendars,
1194
- config
1195
- );
1196
- timetable.stops = await getStopsForTimetable(timetable, config);
1197
- timetable.calendarDates = await getCalendarDatesForTimetable(
1198
- timetable,
1199
- config
1200
- );
1201
- timetable.timetable_label = formatTimetableLabel(timetable);
1202
- timetable.notes = await getTimetableNotesForTimetable(timetable, config);
1183
+ timetable.orderedTrips = getTripsForTimetable(timetable, calendars, config);
1184
+ timetable.stops = getStopsForTimetable(timetable, config);
1185
+ timetable.calendarDates = getCalendarDatesForTimetable(timetable, config);
1186
+ timetable.timetable_label = formatTimetableLabel(timetable);
1187
+ timetable.notes = getTimetableNotesForTimetable(timetable, config);
1203
1188
 
1204
- if (config.showMap) {
1205
- timetable.geojson = await getTimetableGeoJSON(timetable, config);
1206
- }
1189
+ if (config.showMap) {
1190
+ timetable.geojson = getTimetableGeoJSON(timetable, config);
1191
+ }
1207
1192
 
1208
- // Filter trips after all timetable properties are assigned
1209
- timetable.orderedTrips = filterTrips(timetable);
1193
+ // Filter trips after all timetable properties are assigned
1194
+ timetable.orderedTrips = filterTrips(timetable);
1210
1195
 
1211
- // Format stops after all timetable properties are assigned
1212
- timetable.stops = formatStops(timetable, config);
1196
+ // Format stops after all timetable properties are assigned
1197
+ timetable.stops = formatStops(timetable, config);
1213
1198
 
1214
- return timetable;
1215
- })
1216
- );
1199
+ return timetable;
1200
+ });
1217
1201
 
1218
1202
  if (config.allowEmptyTimetables) {
1219
1203
  return formattedTimetables;
@@ -1227,15 +1211,15 @@ const formatTimetables = async (timetables, config) => {
1227
1211
  /*
1228
1212
  * Get all timetable pages for an agency.
1229
1213
  */
1230
- export async function getTimetablePagesForAgency(config) {
1231
- const timetables = mergeTimetablesWithSameId(await getTimetables());
1214
+ export function getTimetablePagesForAgency(config) {
1215
+ const timetables = mergeTimetablesWithSameId(getTimetables());
1232
1216
 
1233
1217
  // If no timetables, build each route and direction into a timetable.
1234
1218
  if (timetables.length === 0) {
1235
1219
  return convertRoutesToTimetablePages(config);
1236
1220
  }
1237
1221
 
1238
- const timetablePages = await getTimetablePages(
1222
+ const timetablePages = getTimetablePages(
1239
1223
  {},
1240
1224
  [],
1241
1225
  [['timetable_page_id', 'ASC']]
@@ -1244,48 +1228,44 @@ export async function getTimetablePagesForAgency(config) {
1244
1228
  // Check if there are any timetable pages defined in `timetable_pages.txt`.
1245
1229
  if (timetablePages.length === 0) {
1246
1230
  // If no timetablepages, use timetables
1247
- return Promise.all(
1248
- timetables.map((timetable) =>
1249
- convertTimetableToTimetablePage(timetable, config)
1250
- )
1231
+ return timetables.map((timetable) =>
1232
+ convertTimetableToTimetablePage(timetable, config)
1251
1233
  );
1252
1234
  }
1253
1235
 
1254
- const routes = await getRoutes();
1236
+ const routes = getRoutes();
1255
1237
 
1256
1238
  // Otherwise, use timetable pages defined in `timetable_pages.txt`.
1257
- return Promise.all(
1258
- timetablePages.map(async (timetablePage) => {
1259
- timetablePage.timetables = sortBy(
1260
- timetables.filter(
1261
- (timetable) =>
1262
- timetable.timetable_page_id === timetablePage.timetable_page_id
1263
- ),
1264
- 'timetable_sequence'
1265
- );
1239
+ return timetablePages.map((timetablePage) => {
1240
+ timetablePage.timetables = sortBy(
1241
+ timetables.filter(
1242
+ (timetable) =>
1243
+ timetable.timetable_page_id === timetablePage.timetable_page_id
1244
+ ),
1245
+ 'timetable_sequence'
1246
+ );
1266
1247
 
1267
- // Add routes for each timetable.
1268
- for (const timetable of timetablePage.timetables) {
1269
- timetable.routes = routes.filter((route) =>
1270
- timetable.route_ids.includes(route.route_id)
1271
- );
1272
- }
1248
+ // Add routes for each timetable.
1249
+ for (const timetable of timetablePage.timetables) {
1250
+ timetable.routes = routes.filter((route) =>
1251
+ timetable.route_ids.includes(route.route_id)
1252
+ );
1253
+ }
1273
1254
 
1274
- return timetablePage;
1275
- })
1276
- );
1255
+ return timetablePage;
1256
+ });
1277
1257
  }
1278
1258
 
1279
1259
  /*
1280
1260
  * Get a timetable_page by id.
1281
1261
  */
1282
- const getTimetablePageById = async (timetablePageId, config) => {
1262
+ const getTimetablePageById = (timetablePageId, config) => {
1283
1263
  // Check if there are any timetable pages defined in `timetable_pages.txt`.
1284
- const timetablePages = await getTimetablePages({
1264
+ const timetablePages = getTimetablePages({
1285
1265
  timetable_page_id: timetablePageId,
1286
1266
  });
1287
1267
 
1288
- const timetables = mergeTimetablesWithSameId(await getTimetables());
1268
+ const timetables = mergeTimetablesWithSameId(getTimetables());
1289
1269
 
1290
1270
  if (timetablePages.length > 1) {
1291
1271
  throw new Error(
@@ -1304,13 +1284,11 @@ const getTimetablePageById = async (timetablePageId, config) => {
1304
1284
  );
1305
1285
 
1306
1286
  // Add routes for each timetable
1307
- await Promise.all(
1308
- timetablePage.timetables.map(async (timetable) => {
1309
- timetable.routes = await getRoutes({
1310
- route_id: timetable.route_ids,
1311
- });
1312
- })
1313
- );
1287
+ for (const timetable of timetablePage.timetables) {
1288
+ timetable.routes = getRoutes({
1289
+ route_id: timetable.route_ids,
1290
+ });
1291
+ }
1314
1292
 
1315
1293
  return timetablePage;
1316
1294
  }
@@ -1347,11 +1325,11 @@ const getTimetablePageById = async (timetablePageId, config) => {
1347
1325
 
1348
1326
  const routeId = parts.join('|');
1349
1327
 
1350
- const routes = await getRoutes({
1328
+ const routes = getRoutes({
1351
1329
  route_id: routeId,
1352
1330
  });
1353
1331
 
1354
- const trips = await getTrips(
1332
+ const trips = getTrips(
1355
1333
  {
1356
1334
  route_id: routeId,
1357
1335
  direction_id: directionId,
@@ -1367,12 +1345,12 @@ const getTimetablePageById = async (timetablePageId, config) => {
1367
1345
  }
1368
1346
 
1369
1347
  if (/^[01]*$/.test(calendarCode)) {
1370
- calendars = await getCalendars({
1348
+ calendars = getCalendars({
1371
1349
  ...calendarCodeToCalendar(calendarCode),
1372
1350
  });
1373
1351
  } else {
1374
1352
  serviceId = calendarCode;
1375
- calendarDates = await getCalendarDates({
1353
+ calendarDates = getCalendarDates({
1376
1354
  exception_type: 1,
1377
1355
  service_id: serviceId,
1378
1356
  });
@@ -1453,10 +1431,10 @@ export function setDefaultConfig(initialConfig) {
1453
1431
  /*
1454
1432
  * Get a timetable page by id.
1455
1433
  */
1456
- export async function getFormattedTimetablePage(timetablePageId, config) {
1457
- const timetablePage = await getTimetablePageById(timetablePageId, config);
1434
+ export function getFormattedTimetablePage(timetablePageId, config) {
1435
+ const timetablePage = getTimetablePageById(timetablePageId, config);
1458
1436
 
1459
- timetablePage.consolidatedTimetables = await formatTimetables(
1437
+ timetablePage.consolidatedTimetables = formatTimetables(
1460
1438
  timetablePage.timetables,
1461
1439
  config
1462
1440
  );
@@ -1472,7 +1450,7 @@ export async function getFormattedTimetablePage(timetablePageId, config) {
1472
1450
  flatMap(timetablePage.consolidatedTimetables, 'route_ids')
1473
1451
  );
1474
1452
 
1475
- const timetableRoutes = await getRoutes(
1453
+ const timetableRoutes = getRoutes(
1476
1454
  {
1477
1455
  route_id: timetablePage.route_ids,
1478
1456
  },
@@ -1493,21 +1471,17 @@ export async function getFormattedTimetablePage(timetablePageId, config) {
1493
1471
  }
1494
1472
 
1495
1473
  // Get `direction_name` for each timetable.
1496
- await Promise.all(
1497
- timetablePage.consolidatedTimetables.map(async (timetable) => {
1498
- if (isNullOrEmpty(timetable.direction_name)) {
1499
- timetable.direction_name = await getDirectionHeadsignFromTimetable(
1500
- timetable
1501
- );
1502
- }
1474
+ for (const timetable of timetablePage.consolidatedTimetables) {
1475
+ if (isNullOrEmpty(timetable.direction_name)) {
1476
+ timetable.direction_name = getDirectionHeadsignFromTimetable(timetable);
1477
+ }
1503
1478
 
1504
- if (!timetable.routes) {
1505
- timetable.routes = await getRoutes({
1506
- route_id: timetable.route_ids,
1507
- });
1508
- }
1509
- })
1510
- );
1479
+ if (!timetable.routes) {
1480
+ timetable.routes = getRoutes({
1481
+ route_id: timetable.route_ids,
1482
+ });
1483
+ }
1484
+ }
1511
1485
 
1512
1486
  return timetablePage;
1513
1487
  }
@@ -1555,7 +1529,7 @@ export function generateTimetableHTML(timetablePage, config) {
1555
1529
  /*
1556
1530
  * Generate the CSV timetable for a timetable page.
1557
1531
  */
1558
- export async function generateTimetableCSV(timetable) {
1532
+ export function generateTimetableCSV(timetable) {
1559
1533
  // Generate horizontal orientation, then transpose if vertical is needed.
1560
1534
  const lines = [];
1561
1535
 
@@ -1597,15 +1571,15 @@ export async function generateTimetableCSV(timetable) {
1597
1571
  /*
1598
1572
  * Generate the HTML for the agency overview page.
1599
1573
  */
1600
- export async function generateOverviewHTML(timetablePages, config) {
1601
- const agencies = await getAgencies();
1574
+ export function generateOverviewHTML(timetablePages, config) {
1575
+ const agencies = getAgencies();
1602
1576
  if (agencies.length === 0) {
1603
1577
  throw new Error('No agencies found');
1604
1578
  }
1605
1579
 
1606
1580
  let geojson;
1607
1581
  if (config.showMap) {
1608
- geojson = await getAgencyGeoJSON(config);
1582
+ geojson = getAgencyGeoJSON(config);
1609
1583
  }
1610
1584
 
1611
1585
  // Sort timetables for display, first numerically then alphabetically.