@transportme/load-ptv-gtfs 1.0.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.
Files changed (77) hide show
  1. package/.github/workflows/unit-test.yml +46 -0
  2. package/lib/constants.mjs +18 -0
  3. package/lib/gtfs-package/PTVGTFS.mjs +96 -0
  4. package/lib/gtfs-parser/GTFSAgency.mjs +15 -0
  5. package/lib/gtfs-parser/GTFSCalendar.mjs +63 -0
  6. package/lib/gtfs-parser/GTFSCalendarDate.mjs +15 -0
  7. package/lib/gtfs-parser/GTFSRoute.mjs +106 -0
  8. package/lib/gtfs-parser/GTFSShape.mjs +39 -0
  9. package/lib/gtfs-parser/GTFSStop.mjs +212 -0
  10. package/lib/gtfs-parser/GTFSStopTime.mjs +30 -0
  11. package/lib/gtfs-parser/GTFSTrip.mjs +169 -0
  12. package/lib/gtfs-parser/readers/GTFSAgencyReader.mjs +27 -0
  13. package/lib/gtfs-parser/readers/GTFSCalendarDatesReader.mjs +25 -0
  14. package/lib/gtfs-parser/readers/GTFSCalendarReader.mjs +63 -0
  15. package/lib/gtfs-parser/readers/GTFSReader.mjs +48 -0
  16. package/lib/gtfs-parser/readers/GTFSRouteReader.mjs +35 -0
  17. package/lib/gtfs-parser/readers/GTFSShapeReader.mjs +75 -0
  18. package/lib/gtfs-parser/readers/GTFSStopTimesReader.mjs +85 -0
  19. package/lib/gtfs-parser/readers/GTFSStopsReader.mjs +36 -0
  20. package/lib/gtfs-parser/readers/GTFSTripReader.mjs +61 -0
  21. package/lib/gtfs-parser/readers/line-reader.mjs +112 -0
  22. package/lib/loader/RouteLoader.mjs +101 -0
  23. package/lib/loader/ShapeLoader.mjs +86 -0
  24. package/lib/loader/StopsLoader.mjs +139 -0
  25. package/lib/loader/TripLoader.mjs +187 -0
  26. package/lib/post-processing/merge-stops.mjs +85 -0
  27. package/lib/post-processing/set-route-stops.mjs +73 -0
  28. package/lib/post-processing/set-stop-services.mjs +64 -0
  29. package/lib/utils.mjs +16 -0
  30. package/package.json +27 -0
  31. package/test/gtfs-calendar.test.mjs +182 -0
  32. package/test/gtfs-route-loader.test.mjs +190 -0
  33. package/test/gtfs-routes.test.mjs +77 -0
  34. package/test/gtfs-shapes-loader.test.mjs +105 -0
  35. package/test/gtfs-shapes.test.mjs +23 -0
  36. package/test/gtfs-stop-loader-metro.test.mjs +49 -0
  37. package/test/gtfs-stop-loader.test.mjs +223 -0
  38. package/test/gtfs-stop-times.test.mjs +37 -0
  39. package/test/gtfs-stops.test.mjs +290 -0
  40. package/test/gtfs-trip-loader.test.mjs +142 -0
  41. package/test/gtfs-trips.test.mjs +109 -0
  42. package/test/line-reader.test.mjs +94 -0
  43. package/test/merge-stops.test.mjs +376 -0
  44. package/test/ptv-gtfs.test.mjs +106 -0
  45. package/test/sample-data/calendar/calendar.txt +34 -0
  46. package/test/sample-data/calendar/calendar_dates.txt +26 -0
  47. package/test/sample-data/gtfs-splitting/force_unique_stops_bus.txt +7 -0
  48. package/test/sample-data/gtfs-splitting/force_unique_stops_tram.txt +3 -0
  49. package/test/sample-data/gtfs-splitting/line_reader_test.txt +8 -0
  50. package/test/sample-data/gtfs-splitting/name_overrides.txt +4 -0
  51. package/test/sample-data/gtfs-splitting/nov_2024_train_data.txt +6 -0
  52. package/test/sample-data/gtfs-splitting/sample_stops.txt +20 -0
  53. package/test/sample-data/gtfs-splitting/special_chars_stops_csv.txt +6 -0
  54. package/test/sample-data/gtfs-splitting/stops_without_secondary.txt +6 -0
  55. package/test/sample-data/gtfs-unzipping/gtfs.zip +0 -0
  56. package/test/sample-data/one_line.csv +2 -0
  57. package/test/sample-data/routes/agency.txt +11 -0
  58. package/test/sample-data/routes/metro_bus_routes.txt +4 -0
  59. package/test/sample-data/routes/metro_lines.txt +5 -0
  60. package/test/sample-data/routes/regional_bus_routes.txt +7 -0
  61. package/test/sample-data/routes/vline.txt +7 -0
  62. package/test/sample-data/routes/west_gipp_transit.txt +20 -0
  63. package/test/sample-data/shapes/shapes.txt +89 -0
  64. package/test/sample-data/shapes/stop_times.txt +9 -0
  65. package/test/sample-data/shapes/stops.txt +4 -0
  66. package/test/sample-data/shapes/trips.txt +4 -0
  67. package/test/sample-data/stop-data/name-overrides.json +25 -0
  68. package/test/sample-data/stop-data/unique-stops.json +1 -0
  69. package/test/sample-data/suburbs.json +77 -0
  70. package/test/sample-data/trips/bus_trips.txt +5 -0
  71. package/test/sample-data/trips/stop_times.txt +29 -0
  72. package/test/sample-data/trips/stop_times_new.txt +8 -0
  73. package/test/sample-data/trips/stops.txt +8 -0
  74. package/test/sample-data/trips/trips.txt +5 -0
  75. package/test/sample-data/trips/trips_new.txt +2 -0
  76. package/test/set-stop-services.test.mjs +69 -0
  77. package/test/utils-test.mjs +26 -0
@@ -0,0 +1,169 @@
1
+ import { TRANSIT_MODES } from '../constants.mjs'
2
+ import GTFSCalendar from './GTFSCalendar.mjs'
3
+
4
+ export default class GTFSTrip {
5
+
6
+ #routeGTFSID
7
+ #operationDays
8
+ #tripID
9
+ #shapeID
10
+ #headsign
11
+ #direction
12
+ #block
13
+
14
+ /**
15
+ *
16
+ * @param {Object} param0 The trip data
17
+ * @param {string} param0.routeGTFSID The route ID associated with the trip. This should be the raw ID, eg "6-123-mjp-1"
18
+ * @param {GTFSCalendar} param0.calendar The calendar type
19
+ * @param {string} param0.id The unique trip ID
20
+ * @param {string} param0.shapeID The shape ID associate with the trip
21
+ * @param {string} param0.headsign The headsign on the vehicle serving the trip
22
+ * @param {string} param0.direction The direction of the trip. "0" for outbound and "1" for inbound trips.
23
+ * @param {string} param0.block The block ID of the trip.
24
+ */
25
+ constructor({ routeGTFSID, calendar, id, shapeID, headsign, direction, block }) {
26
+ this.#routeGTFSID = routeGTFSID
27
+ this.#operationDays = calendar.getOperationDays()
28
+ this.#tripID = id
29
+ this.#shapeID = shapeID
30
+ this.#headsign = headsign
31
+ this.#direction = direction
32
+ this.#block = block
33
+ }
34
+
35
+ /**
36
+ * Checks if the GTFSTrip (or subclass) is able to process the given trip data
37
+ * @param {Object} data The trip being checked
38
+ * @returns true if the class is able to process the trip
39
+ */
40
+ static canProcess(data) {
41
+ return true
42
+ }
43
+
44
+ /**
45
+ * Creates a new GTFSTrip with the trip data that was passed in
46
+ * @param {Object} data The trip data being created
47
+ * @param {string} mode The transit mode
48
+ * @returns {GTFSTrip} A trip instance representing the data being passed in
49
+ */
50
+ static create(data, mode) {
51
+ let types = [ SmartrakTrip, MetroTrip, GTFSTrip ]
52
+ for (let type of types) {
53
+ if (type.canProcess(data, mode)) return new type(data)
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Gets the trip data in a database friendly format
59
+ * @returns {Object} The trip data that will be saved into the database
60
+ */
61
+ getTripData() {
62
+ return {
63
+ routeGTFSID: this.getRouteGTFSID(),
64
+ operationDays: this.getOperationDays(),
65
+ tripID: this.getTripID(),
66
+ shapeID: this.getShapeID(),
67
+ block: this.getBlock(),
68
+ gtfsDirection: this.getGTFSDirection()
69
+ }
70
+ }
71
+
72
+ getBlock() {
73
+ return this.#block || null
74
+ }
75
+
76
+ getOperationDays() {
77
+ return this.#operationDays
78
+ }
79
+
80
+ getRouteGTFSID() {
81
+ return this.#routeGTFSID
82
+ }
83
+
84
+ getShapeID() {
85
+ return this.#shapeID
86
+ }
87
+
88
+ getTripID() {
89
+ return this.#tripID
90
+ }
91
+
92
+ getHeadsign() {
93
+ return this.#headsign
94
+ }
95
+
96
+ getGTFSDirection() {
97
+ return parseInt(this.#direction)
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Used to represent a Smartrak bus trip.
103
+ *
104
+ * Trip IDs are of the form DEPOT-ROUTE--ROUTE_VARIANT-ROSTER-TRIP_ID
105
+ *
106
+ * Example: 13-476--1-Sat5-34737060
107
+ */
108
+ export class SmartrakTrip extends GTFSTrip {
109
+
110
+ #depotID
111
+
112
+ constructor(data) {
113
+ super(data)
114
+
115
+ let depotID = data.id.match(/^(\d{2})-\w+/)
116
+ this.#depotID = depotID[1]
117
+ }
118
+
119
+ static canProcess(data, mode) {
120
+ return mode === TRANSIT_MODES.bus && data.id.match(/^(\d{2})-\w+/)
121
+ }
122
+
123
+ getTripData() {
124
+ return {
125
+ ...super.getTripData(),
126
+ depotID: this.getDepotID()
127
+ }
128
+ }
129
+
130
+ getDepotID() {
131
+ return parseInt(this.#depotID)
132
+ }
133
+
134
+ }
135
+
136
+ /**
137
+ * Used to represent a Metro train trip.
138
+ *
139
+ * Trip IDs are of the form 02-ROUTE--ROUTE_VARIANT-ROSTER-TDN. Note that TDNs are alphanumeric
140
+ *
141
+ * Example: 02-BEG--58-T5_n4-3651
142
+ */
143
+ export class MetroTrip extends GTFSTrip {
144
+
145
+ #runID
146
+
147
+ constructor(data) {
148
+ super(data)
149
+
150
+ let runID = data.id.match(/^02-\w{3}-.*-(\w\d{3})$/)
151
+ this.#runID = runID[1]
152
+ }
153
+
154
+ static canProcess(data, mode) {
155
+ return mode === TRANSIT_MODES.metroTrain && data.id.match(/^02-\w{3}-.*-(\w\d{3})$/)
156
+ }
157
+
158
+ getTripData() {
159
+ return {
160
+ ...super.getTripData(),
161
+ runID: this.getRunID()
162
+ }
163
+ }
164
+
165
+ getRunID() {
166
+ return this.#runID
167
+ }
168
+
169
+ }
@@ -0,0 +1,27 @@
1
+ import GTFSAgency from '../GTFSAgency.mjs'
2
+ import GTFSReader from './GTFSReader.mjs'
3
+
4
+ export default class GTFSAgencyReader extends GTFSReader {
5
+
6
+ /**
7
+ * Converts a CSV row into an operator object
8
+ *
9
+ * @param {object} data A JSON object containing the following fields:
10
+ * - id: The operator ID
11
+ * - name: The operator name
12
+ * - website: The operator's website
13
+ * - phone: The operator's phone number
14
+ *
15
+ * @returns {GTFSAgency} An object representing the operator data
16
+ */
17
+ processEntity(data) {
18
+ let agencyData = {
19
+ id: data.agency_id,
20
+ name: data.agency_name,
21
+ website: data.agency_url,
22
+ phone: data.agency_phone
23
+ }
24
+
25
+ return new GTFSAgency(agencyData)
26
+ }
27
+ }
@@ -0,0 +1,25 @@
1
+ import GTFSCalendarDate from '../GTFSCalendarDate.mjs'
2
+ import GTFSReader from './GTFSReader.mjs'
3
+
4
+ export default class GTFSCalendarDateReader extends GTFSReader {
5
+
6
+ /**
7
+ * Converts a CSV row into an operator object
8
+ *
9
+ * @param {object} data A JSON object containing the following fields:
10
+ * @param {string} data.id The calendar ID
11
+ * @param {string} data.date The calendar date
12
+ * @param {string} data.type The exception type
13
+ *
14
+ * @returns {GTFSCalendarDate} An object representing the calendar date entry
15
+ */
16
+ processEntity(data) {
17
+ let calendarDateData = {
18
+ id: data.service_id,
19
+ date: data.date,
20
+ type: data.exception_type
21
+ }
22
+
23
+ return new GTFSCalendarDate(calendarDateData)
24
+ }
25
+ }
@@ -0,0 +1,63 @@
1
+ import GTFSCalendar from '../GTFSCalendar.mjs'
2
+ import GTFSCalendarDateReader from './GTFSCalendarDatesReader.mjs'
3
+ import GTFSReader from './GTFSReader.mjs'
4
+
5
+ export default class GTFSCalendarReader extends GTFSReader {
6
+
7
+ #calendarDateFile
8
+ #calendarDates = {}
9
+
10
+ /**
11
+ * Constructs a new GTFS Calendar reader.
12
+ *
13
+ * @param {string} calendarFile The path to the GTFS Calendar file
14
+ * @param {string} calendarDateFile The path to the GTFS Calendar Dates file
15
+ */
16
+ constructor(calendarFile, calendarDateFile) {
17
+ super(calendarFile)
18
+ this.#calendarDateFile = calendarDateFile
19
+ }
20
+
21
+ async open() {
22
+ await super.open()
23
+
24
+ let calendarDateReader = new GTFSCalendarDateReader(this.#calendarDateFile)
25
+ await calendarDateReader.open()
26
+ while (calendarDateReader.available()) {
27
+ let calendarDate = await calendarDateReader.getNextEntity()
28
+ if (!this.#calendarDates[calendarDate.id]) this.#calendarDates[calendarDate.id] = []
29
+ this.#calendarDates[calendarDate.id].push(calendarDate)
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Converts a CSV row into a calendar object
35
+ *
36
+ * @param {object} data A JSON object containing the following fields:
37
+ * @param {string} data.id The calendar ID
38
+ * @param {string} data.monday Indicates if a service will operate on a Monday within the given date range. "1" for operating and "0" for not operating.
39
+ * @param {string} data.tuesday Same as data.monday but for Tuesday
40
+ * @param {string} data.wednesday Same as data.monday but for Wednesday
41
+ * @param {string} data.thursday Same as data.monday but for Thursday
42
+ * @param {string} data.friday Same as data.monday but for Friday
43
+ * @param {string} data.saturday Same as data.monday but for Saturday
44
+ * @param {string} data.sunday Same as data.monday but for Sunday
45
+ * @param {string} data.startDay The start day of the calendar interval (inclusive).
46
+ * @param {string} data.endDay The end day of the calendar interval (inclusive).
47
+ *
48
+ * @returns {GTFSCalendar} An object representing the operator data
49
+ */
50
+ processEntity(data) {
51
+ let calendarData = {
52
+ id: data.service_id,
53
+ daysOfWeek: [
54
+ data.monday, data.tuesday, data.wednesday, data.thursday,
55
+ data.friday, data.saturday, data.sunday
56
+ ],
57
+ startDay: data.start_date,
58
+ endDay: data.end_date
59
+ }
60
+
61
+ return new GTFSCalendar(calendarData, this.#calendarDates[data.service_id])
62
+ }
63
+ }
@@ -0,0 +1,48 @@
1
+ import CSVLineReader from './line-reader.mjs'
2
+
3
+ export default class GTFSReader {
4
+
5
+ /** @type {string} */
6
+ #file
7
+ #reader
8
+
9
+ constructor(file) {
10
+ this.#file = file
11
+ this.#reader = new CSVLineReader(file)
12
+ }
13
+
14
+ /**
15
+ * Opens the underlying `CSVLineReader`
16
+ */
17
+ async open() {
18
+ await this.#reader.open()
19
+ }
20
+
21
+ /**
22
+ * Checks if there is more data available for reading
23
+ *
24
+ * @returns {boolean} Returns true if there is more data available
25
+ */
26
+ available() {
27
+ return this.#reader.available()
28
+ }
29
+
30
+ /**
31
+ * Gets the data of the next entity in the file.
32
+ *
33
+ * @returns {Promise<GTFSEntity>} The data of the next entity
34
+ */
35
+ async getNextEntity() {
36
+ return this.processEntity(await this.#reader.nextLine())
37
+ }
38
+
39
+ /**
40
+ * Converts a CSV row into its entity data
41
+ * @param {object} data The CSV row data
42
+ *
43
+ * @returns {GTFSEntity} An object representing the entity data
44
+ */
45
+ processEntity(data) {
46
+ return null
47
+ }
48
+ }
@@ -0,0 +1,35 @@
1
+ import GTFSRoute from '../GTFSRoute.mjs'
2
+ import GTFSReader from './GTFSReader.mjs'
3
+
4
+ export default class GTFSRouteReader extends GTFSReader {
5
+
6
+ /** @type {string} */
7
+ #mode
8
+
9
+ constructor(file, mode) {
10
+ super(file, mode)
11
+ this.#mode = mode
12
+ }
13
+
14
+ /**
15
+ * Converts a CSV row into a route object
16
+ *
17
+ * @param {object} data A JSON object containing the following fields:
18
+ * - routeGTFSID: The route ID
19
+ * - agencyID: The route agency ID
20
+ * - routeNumber: The route number, or empty if it does not exist
21
+ * - routeName: The route name
22
+ * @param {string} mode The route mode (eg: bus, metro train)
23
+ * @returns {GTFSRoute} An object representing the route data
24
+ */
25
+ processEntity(data) {
26
+ let routeData = {
27
+ routeGTFSID: data.route_id,
28
+ agencyID: data.agency_id,
29
+ routeNumber: data.route_short_name,
30
+ routeName: data.route_long_name
31
+ }
32
+
33
+ return GTFSRoute.create(routeData, this.#mode)
34
+ }
35
+ }
@@ -0,0 +1,75 @@
1
+ import { GTFSShape, GTFSShapePoint } from '../GTFSShape.mjs'
2
+ import CSVLineReader from './line-reader.mjs'
3
+
4
+ export default class GTFSShapeReader {
5
+
6
+ /** @type {string} */
7
+ #file
8
+ #reader
9
+
10
+ constructor(file) {
11
+ this.#file = file
12
+ this.#reader = new CSVLineReader(file)
13
+ }
14
+
15
+ /**
16
+ * Opens the underlying `CSVLineReader`
17
+ */
18
+ async open() {
19
+ await this.#reader.open()
20
+ }
21
+
22
+ /**
23
+ * Checks if there is more data available for reading
24
+ *
25
+ * @returns {boolean} Returns true if there is more data available
26
+ */
27
+ available() {
28
+ return this.#reader.available()
29
+ }
30
+
31
+ /**
32
+ * Gets the data of the next entity in the file.
33
+ *
34
+ * @returns {Promise<GTFSEntity>} The data of the next entity
35
+ */
36
+ async getNextEntity() {
37
+ let firstLine = await this.#reader.nextLine()
38
+ let shapeID = firstLine.shape_id
39
+
40
+ let lines = [ firstLine ]
41
+
42
+ while (this.#reader.available()) {
43
+ let nextLine = await this.#reader.nextLine()
44
+ if (nextLine.shape_id !== shapeID) {
45
+ this.#reader.unreadLine()
46
+ break
47
+ } else {
48
+ lines.push(nextLine)
49
+ }
50
+ }
51
+
52
+ return new GTFSShape(shapeID, lines.map(line => this.processEntity(line)))
53
+ }
54
+
55
+ /**
56
+ * Converts a CSV row into a shape point object
57
+ *
58
+ * @param {object} data A JSON object containing the following fields:
59
+ * @param {string} data.shape_pt_lat The shape point's latitude
60
+ * @param {string} data.shape_pt_lon The shape point's longitude
61
+ * @param {string} data.shape_pt_sequence The shape point's sequence in the overall shape
62
+ * @param {string} data.shape_dist_traveled The distance travelled up to that point in the shape
63
+ *
64
+ * @returns {GTFSShapePoint} An object representing the shape data
65
+ */
66
+ processEntity(data) {
67
+ let shapeData = {
68
+ latitude: parseFloat(data.shape_pt_lat),
69
+ longitude: parseFloat(data.shape_pt_lon),
70
+ distance: parseFloat(data.shape_dist_traveled)
71
+ }
72
+
73
+ return new GTFSShapePoint(shapeData)
74
+ }
75
+ }
@@ -0,0 +1,85 @@
1
+ import { GTFSStopTime } from '../GTFSStopTime.mjs'
2
+ import CSVLineReader from './line-reader.mjs'
3
+
4
+ export default class GTFSStopTimesReader {
5
+
6
+ /** @type {string} */
7
+ #file
8
+ #reader
9
+
10
+ constructor(file) {
11
+ this.#file = file
12
+ this.#reader = new CSVLineReader(file)
13
+ }
14
+
15
+ /**
16
+ * Opens the underlying `CSVLineReader`
17
+ */
18
+ async open() {
19
+ await this.#reader.open()
20
+ }
21
+
22
+ /**
23
+ * Checks if there is more data available for reading
24
+ *
25
+ * @returns {boolean} Returns true if there is more data available
26
+ */
27
+ available() {
28
+ return this.#reader.available()
29
+ }
30
+
31
+ /**
32
+ * Gets the data of the next entity in the file.
33
+ *
34
+ * @returns {Promise<GTFSEntity>} The data of the next entity
35
+ */
36
+ async getNextEntity() {
37
+ let firstLine = await this.#reader.nextLine()
38
+ let tripID = firstLine.trip_id
39
+
40
+ let lines = [ firstLine ]
41
+
42
+ while (this.#reader.available()) {
43
+ let nextLine = await this.#reader.nextLine()
44
+ if (nextLine.trip_id !== tripID) {
45
+ this.#reader.unreadLine()
46
+ break
47
+ } else {
48
+ lines.push(nextLine)
49
+ }
50
+ }
51
+
52
+ return {
53
+ tripID,
54
+ stops: lines.map(line => this.processEntity(line))
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Converts a CSV row into a stop time object
60
+ *
61
+ * @param {object} data A JSON object containing the following fields:
62
+ * @param {string} data.arrival_time The stop's arrival time
63
+ * @param {string} data.departure_time The stop's departure time
64
+ * @param {string} data.stop_id The stop ID
65
+ * @param {string} data.stop_sequence The stop sequence
66
+ * @param {string} data.pickup_type The pickup conditions. "0" for no restrictions and "1" for no pickup allowed
67
+ * @param {string} data.drop_off_type The dropoff conditions. "0" for no restrictions and "1" for no dropoff allowed
68
+ * @param {string} data.shape_dist_traveled The distance travelled along the shape
69
+ *
70
+ * @returns {GTFSStopTime} An object representing the stop data
71
+ */
72
+ processEntity(data) {
73
+ let stopData = {
74
+ arrivalTime: data.arrival_time,
75
+ departureTime: data.departure_time,
76
+ stopID: data.stop_id,
77
+ stopSequence: data.stop_sequence,
78
+ pickup: data.pickup_type,
79
+ dropoff: data.drop_off_type,
80
+ distance: data.shape_dist_traveled
81
+ }
82
+
83
+ return new GTFSStopTime(stopData)
84
+ }
85
+ }
@@ -0,0 +1,36 @@
1
+ import { GTFSStop, GTFSPlatformStop } from '../GTFSStop.mjs'
2
+ import GTFSReader from './GTFSReader.mjs'
3
+
4
+ export default class GTFSStopsReader extends GTFSReader {
5
+
6
+ #suburbData
7
+
8
+ constructor(file, suburbData) {
9
+ super(file)
10
+ this.#suburbData = suburbData
11
+ }
12
+
13
+ /**
14
+ * Converts a CSV row into a stop object
15
+ *
16
+ * @param {object} data A JSON object containing the following fields:
17
+ * @param {string} data.stop_id The stop ID
18
+ * @param {string} data.stop_name The stop's name
19
+ * @param {string} data.stop_lat The stop's latitude
20
+ * @param {string} data.stop_lon The stop's longitude
21
+ * @param {string} [data.platform] The stop's platform number. Optional, stops without a platform (eg bus stops) do not need to provide this
22
+ *
23
+ * @returns {GTFSStop} An object representing the stop data
24
+ */
25
+ processEntity(data) {
26
+ let stopData = {
27
+ stopGTFSID: data.stop_id,
28
+ stopName: data.stop_name,
29
+ stopLat: data.stop_lat,
30
+ stopLon: data.stop_lon,
31
+ platform: data.platform_code
32
+ }
33
+
34
+ return GTFSStop.create(stopData, this.#suburbData)
35
+ }
36
+ }
@@ -0,0 +1,61 @@
1
+ import GTFSTrip from '../GTFSTrip.mjs'
2
+ import GTFSReader from './GTFSReader.mjs'
3
+
4
+ export default class GTFSTripReader extends GTFSReader {
5
+
6
+ #calendars
7
+ #routeMappings
8
+ #mode
9
+
10
+ constructor(tripsFile, calendars, routeMappings, mode) {
11
+ super(tripsFile)
12
+ this.#calendars = calendars
13
+ this.#routeMappings = routeMappings
14
+ this.#mode = mode
15
+ }
16
+
17
+ /**
18
+ * Sets the route ID mappings of the trip reader.
19
+ *
20
+ * @param {object} routeMappings The route ID mappings
21
+ */
22
+ setRouteMappings(routeMappings) {
23
+ this.#routeMappings = routeMappings
24
+ }
25
+
26
+ /**
27
+ *
28
+ * @param {object} calendars The calendar ID to GTFSCalendar mappings
29
+ */
30
+ setCalendar(calendars) {
31
+ this.#calendars = calendars
32
+ }
33
+
34
+ /**
35
+ * Converts a CSV row into a trip object
36
+ *
37
+ * @param {object} data A JSON object containing the following fields:
38
+ * @param {string} data.route_id The trip's route ID
39
+ * @param {string} data.service_id The trip's calendar ID
40
+ * @param {string} data.trip_id The trip's unique trip ID
41
+ * @param {string} data.shape_id The trip's shape ID
42
+ * @param {string} data.trip_headsign The trip's headsign
43
+ * @param {string} data.direction_id The trip's direction ID
44
+ * @param {string} data.block_id The trip's block ID
45
+ *
46
+ * @returns {GTFSTrip} An object representing the trip data
47
+ */
48
+ processEntity(data) {
49
+ let tripData = {
50
+ routeGTFSID: this.#routeMappings[data.route_id],
51
+ calendar: this.#calendars[data.service_id],
52
+ id: data.trip_id,
53
+ shapeID: data.shape_id,
54
+ headsign: data.trip_headsign,
55
+ direction: data.direction_id,
56
+ block: data.block_id
57
+ }
58
+
59
+ return GTFSTrip.create(tripData, this.#mode)
60
+ }
61
+ }