@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,105 @@
1
+ import { expect } from 'chai'
2
+ import path from 'path'
3
+ import url from 'url'
4
+ import { LokiDatabaseConnection } from '@transportme/database'
5
+ import StopsLoader from '../lib/loader/StopsLoader.mjs'
6
+ import RouteLoader from '../lib/loader/RouteLoader.mjs'
7
+ import TripLoader from '../lib/loader/TripLoader.mjs'
8
+ import ShapeLoader from '../lib/loader/ShapeLoader.mjs'
9
+ import { TRANSIT_MODES } from '../lib/constants.mjs'
10
+ import suburbs from './sample-data/suburbs.json' with { type: 'json' }
11
+
12
+ const __filename = url.fileURLToPath(import.meta.url)
13
+ const __dirname = path.dirname(__filename)
14
+
15
+ const routesFile = path.join(__dirname, 'sample-data', 'routes', 'metro_bus_routes.txt')
16
+ const agencyFile = path.join(__dirname, 'sample-data', 'routes', 'agency.txt')
17
+
18
+ const calendarFile = path.join(__dirname, 'sample-data', 'calendar', 'calendar.txt')
19
+ const calendarDatesFile = path.join(__dirname, 'sample-data', 'calendar', 'calendar_dates.txt')
20
+
21
+ const stopsFile = path.join(__dirname, 'sample-data', 'shapes', 'stops.txt')
22
+ const stopTimesFile = path.join(__dirname, 'sample-data', 'shapes', 'stop_times.txt')
23
+ const tripsFile = path.join(__dirname, 'sample-data', 'shapes', 'trips.txt')
24
+ const shapeFile = path.join(__dirname, 'sample-data', 'shapes', 'shapes.txt')
25
+
26
+ describe('The ShapeLoader class', () => {
27
+ it('Should process the shapes and append it to the route data', async () => {
28
+ let database = new LokiDatabaseConnection('test-db')
29
+ let stops = await database.createCollection('stops')
30
+ let routes = await database.createCollection('routes')
31
+ let trips = await database.createCollection('gtfs timetables')
32
+
33
+ let stopLoader = new StopsLoader(stopsFile, suburbs, TRANSIT_MODES.metroBus, database)
34
+ await stopLoader.loadStops()
35
+
36
+ let routeLoader = new RouteLoader(routesFile, agencyFile, TRANSIT_MODES.metroBus, database)
37
+ await routeLoader.loadRoutes()
38
+
39
+ let routeIDMap = routeLoader.getRouteIDMap()
40
+
41
+ let tripLoader = new TripLoader({
42
+ tripsFile, stopTimesFile,
43
+ calendarFile, calendarDatesFile
44
+ }, TRANSIT_MODES.metroBus, database)
45
+
46
+ await tripLoader.loadTrips({ routeIDMap })
47
+ let shapeIDMap = tripLoader.getShapeIDMap()
48
+
49
+ let shapeLoader = new ShapeLoader(shapeFile, database)
50
+
51
+ await shapeLoader.loadShapes({ shapeIDMap })
52
+
53
+ let route = await routes.findDocument({ routeGTFSID: '4-601' })
54
+
55
+ expect(route).to.exist
56
+ expect(route.routePath.length).to.equal(2)
57
+
58
+ let monashHuntingdale = route.routePath.find(path => path.fullGTFSIDs.includes('49-601-aus-1.3.H'))
59
+ expect(monashHuntingdale).to.exist
60
+ expect(monashHuntingdale.length).to.equal(2848.26)
61
+ expect(monashHuntingdale.path.coordinates.length).to.equal(38)
62
+
63
+ expect(monashHuntingdale.path.coordinates[0]).to.deep.equal([ 145.132081, -37.913926 ])
64
+ })
65
+
66
+ it('Should merge duplicate shapes with the same length and start/end coordinates', async () => {
67
+ let database = new LokiDatabaseConnection('test-db')
68
+ let stops = await database.createCollection('stops')
69
+ let routes = await database.createCollection('routes')
70
+ let trips = await database.createCollection('gtfs timetables')
71
+
72
+ let stopLoader = new StopsLoader(stopsFile, suburbs, TRANSIT_MODES.metroBus, database)
73
+ await stopLoader.loadStops()
74
+
75
+ let routeLoader = new RouteLoader(routesFile, agencyFile, TRANSIT_MODES.metroBus, database)
76
+ await routeLoader.loadRoutes()
77
+
78
+ let routeIDMap = routeLoader.getRouteIDMap()
79
+
80
+ let tripLoader = new TripLoader({
81
+ tripsFile, stopTimesFile,
82
+ calendarFile, calendarDatesFile
83
+ }, TRANSIT_MODES.metroBus, database)
84
+
85
+ await tripLoader.loadTrips({ routeIDMap })
86
+ let shapeIDMap = tripLoader.getShapeIDMap()
87
+
88
+ let shapeLoader = new ShapeLoader(shapeFile, database)
89
+
90
+ await shapeLoader.loadShapes({ shapeIDMap })
91
+
92
+ let testTrip = await trips.findDocument({ tripID: '49-601--1-MF10-999' })
93
+ expect(testTrip.shapeID).to.equal('49-601-aus-1.4.H')
94
+
95
+ let route = await routes.findDocument({ routeGTFSID: testTrip.routeGTFSID })
96
+ expect(route.routeNumber).to.equal('601')
97
+
98
+ let tripShape = route.routePath.find(path => path.fullGTFSIDs.includes(testTrip.shapeID))
99
+ expect(tripShape).to.exist
100
+ expect(tripShape.fullGTFSIDs).to.have.members([
101
+ '49-601-aus-1.3.H',
102
+ '49-601-aus-1.4.H'
103
+ ])
104
+ })
105
+ })
@@ -0,0 +1,23 @@
1
+ import { expect } from 'chai'
2
+ import path from 'path'
3
+ import url from 'url'
4
+ import GTFSShapeReader from '../lib/gtfs-parser/readers/GTFSShapeReader.mjs'
5
+
6
+ const __filename = url.fileURLToPath(import.meta.url)
7
+ const __dirname = path.dirname(__filename)
8
+
9
+ const shapeFile = path.join(__dirname, 'sample-data', 'shapes', 'shapes.txt')
10
+
11
+ describe('The GTFSShapeReader class', () => {
12
+ it('Should read the trips.txt file and return a GTFSTrip object', async () => {
13
+ let reader = new GTFSShapeReader(shapeFile)
14
+ await reader.open()
15
+
16
+ let shape = await reader.getNextEntity()
17
+
18
+ expect(shape.shapeID).to.equal('49-601-aus-1.2.R')
19
+ expect(shape.points.length).to.equal(46)
20
+ expect(shape.shapeLength).to.equal(3069.43)
21
+ expect(shape.hash).to.equal(`3069.43-145.102663,-37.910905-145.131911,-37.913896`)
22
+ })
23
+ })
@@ -0,0 +1,49 @@
1
+ import { LokiDatabaseConnection } from '@transportme/database'
2
+ import StopsLoader from '../lib/loader/StopsLoader.mjs'
3
+ import { TRANSIT_MODES } from '../lib/constants.mjs'
4
+ import path from 'path'
5
+ import url from 'url'
6
+ import { expect } from 'chai'
7
+ import suburbs from './sample-data/suburbs.json' with { type: 'json' }
8
+
9
+ const __filename = url.fileURLToPath(import.meta.url)
10
+ const __dirname = path.dirname(__filename)
11
+
12
+ const stopsFile = path.join(__dirname, 'sample-data', 'gtfs-splitting', 'nov_2024_train_data.txt')
13
+
14
+ describe('The GTFS Stops Loader (Testing on the projected Nov 2024 data)', () => {
15
+ it('Should process the stops and add them to the database', async () => {
16
+ let database = new LokiDatabaseConnection('test-db')
17
+ let stops = await database.createCollection('stops')
18
+
19
+ let loader = new StopsLoader(stopsFile, suburbs, TRANSIT_MODES.metroTrain, database)
20
+ await loader.loadStops()
21
+
22
+ let stop = await stops.findDocument({
23
+ 'stopName': 'Camberwell Railway Station'
24
+ })
25
+
26
+ expect(stop).to.not.be.null
27
+ })
28
+
29
+ it('Should label the individual platforms with their platform numbers', async () => {
30
+ let database = new LokiDatabaseConnection('test-db')
31
+ let stops = await database.createCollection('stops')
32
+
33
+ let loader = new StopsLoader(stopsFile, suburbs, TRANSIT_MODES.metroTrain, database)
34
+ await loader.loadStops()
35
+
36
+ let stop = await stops.findDocument({
37
+ 'stopName': 'Camberwell Railway Station'
38
+ })
39
+
40
+ let platformIDs = ["11207", "11208", "11209"]
41
+ let platforms = platformIDs.map(id => stop.bays.find(bay => bay.stopGTFSID === id))
42
+
43
+ for (let i = 0; i < platformIDs.length; i++) {
44
+ let platform = platforms[i]
45
+ expect(platform).to.not.be.undefined
46
+ expect(platforms[i].platform).to.equal((i + 1).toString())
47
+ }
48
+ })
49
+ })
@@ -0,0 +1,223 @@
1
+ import { LokiDatabaseConnection } from '@transportme/database'
2
+ import StopsLoader from '../lib/loader/StopsLoader.mjs'
3
+ import { TRANSIT_MODES } from '../lib/constants.mjs'
4
+ import path from 'path'
5
+ import url from 'url'
6
+ import { expect } from 'chai'
7
+ import suburbs from './sample-data/suburbs.json' with { type: 'json' }
8
+
9
+ import uniqueStops from './sample-data/stop-data/unique-stops.json' with { type: 'json' }
10
+ import nameOverrides from './sample-data/stop-data/name-overrides.json' with { type: 'json' }
11
+ import GTFSStopsReader from '../lib/gtfs-parser/readers/GTFSStopsReader.mjs'
12
+
13
+ const __filename = url.fileURLToPath(import.meta.url)
14
+ const __dirname = path.dirname(__filename)
15
+
16
+ const stopsFile = path.join(__dirname, 'sample-data', 'gtfs-splitting', 'sample_stops.txt')
17
+
18
+ const uniqueStopsBus = path.join(__dirname, 'sample-data', 'gtfs-splitting', 'force_unique_stops_bus.txt')
19
+ const uniqueStopsTram = path.join(__dirname, 'sample-data', 'gtfs-splitting', 'force_unique_stops_tram.txt')
20
+
21
+ const stopNameOverrides = path.join(__dirname, 'sample-data', 'gtfs-splitting', 'name_overrides.txt')
22
+
23
+ const specialHeader = path.join(__dirname, 'sample-data', 'gtfs-splitting', 'special_chars_stops_csv.txt')
24
+
25
+ describe('The GTFS Stops Loader', () => {
26
+ it('Should process the stops and add them to the database', async () => {
27
+ let database = new LokiDatabaseConnection('test-db')
28
+ let stops = await database.createCollection('stops')
29
+
30
+ let loader = new StopsLoader(stopsFile, suburbs, TRANSIT_MODES.bus, database)
31
+ await loader.loadStops()
32
+
33
+ let stop = await stops.findDocument({
34
+ 'bays.stopGTFSID': '10011'
35
+ })
36
+ expect(stop).to.not.be.null
37
+ expect(stop.stopName).to.equal('Moffat Street/Main Road West')
38
+ })
39
+
40
+ it('Should merge street-level stops matching with the exact same name', async () => {
41
+ let database = new LokiDatabaseConnection('test-db')
42
+ let stops = await database.createCollection('stops')
43
+
44
+ let loader = new StopsLoader(stopsFile, suburbs, TRANSIT_MODES.bus, database)
45
+ await loader.loadStops()
46
+
47
+ let wavWatson = await stops.findDocument({
48
+ 'bays.stopGTFSID': '16074'
49
+ })
50
+
51
+ expect(wavWatson).to.not.be.null
52
+ expect(wavWatson.stopName).to.equal('Waverley Road/Watsons Road')
53
+ expect(wavWatson.bays.length).to.equal(2)
54
+ expect(wavWatson.suburb).to.deep.equal(['Glen Waverley'])
55
+ expect(wavWatson.cleanSuburbs).to.deep.equal(['glen-waverley'])
56
+
57
+ let wavWarrigal = await stops.findDocument({
58
+ 'bays.stopGTFSID': '9379'
59
+ })
60
+
61
+ expect(wavWarrigal).to.not.be.null
62
+ expect(wavWarrigal.stopName).to.equal('Waverley Road/Warrigal Road')
63
+ expect(wavWarrigal.bays.length).to.equal(2)
64
+ })
65
+
66
+ it('Should merge non street stops, and keep the secondary stop name if they are the same', async () => {
67
+ let database = new LokiDatabaseConnection('test-db')
68
+ let stops = await database.createCollection('stops')
69
+
70
+ let loader = new StopsLoader(stopsFile, suburbs, TRANSIT_MODES.bus, database)
71
+ await loader.loadStops()
72
+
73
+ let stop = await stops.findDocument({
74
+ 'bays.stopGTFSID': '19580'
75
+ })
76
+
77
+ expect(stop).to.not.be.null
78
+ expect(stop.bays.length).to.equal(3)
79
+ expect(stop.stopName).to.equal('Belgrave Railway Station/Belgrave-Gembrook Road')
80
+ })
81
+
82
+ it('Should merge non street stops, and discard the secondary stop name if they are different', async () => {
83
+ let database = new LokiDatabaseConnection('test-db')
84
+ let stops = await database.createCollection('stops')
85
+
86
+ let loader = new StopsLoader(stopsFile, suburbs, TRANSIT_MODES.bus, database)
87
+ await loader.loadStops()
88
+
89
+ let stop = await stops.findDocument({
90
+ 'bays.stopGTFSID': '28191'
91
+ })
92
+
93
+ expect(stop).to.not.be.null
94
+ expect(stop.bays.length).to.equal(3)
95
+ expect(stop.stopName).to.equal('Lilydale Railway Station')
96
+ })
97
+
98
+ it('Should update the suburb list as well', async () => {
99
+ let database = new LokiDatabaseConnection('test-db')
100
+ let stops = await database.createCollection('stops')
101
+
102
+ let loader = new StopsLoader(stopsFile, suburbs, TRANSIT_MODES.bus, database)
103
+ await loader.loadStops()
104
+
105
+ let stop = await stops.findDocument({
106
+ 'bays.stopGTFSID': '51586'
107
+ })
108
+
109
+ expect(stop).to.not.be.null
110
+ expect(stop.bays.length).to.equal(2)
111
+ expect(stop.stopName).to.equal('Huntingdale Railway Station')
112
+ expect(stop.suburb).to.deep.equal(['Huntingdale', 'Oakleigh'])
113
+ })
114
+
115
+ it('Should not merge stops that are forced to be unique and would otherwise be merged', async () => {
116
+ let database = new LokiDatabaseConnection('test-db')
117
+ let stops = await database.createCollection('stops')
118
+
119
+ function getMergeName(stop) {
120
+ if (uniqueStops.includes(stop.fullStopName)) return stop.fullStopName
121
+ }
122
+
123
+ await (new StopsLoader(uniqueStopsBus, suburbs, TRANSIT_MODES.bus, database)).loadStops({ getMergeName })
124
+ await (new StopsLoader(uniqueStopsTram, suburbs, 'tram', database)).loadStops({ getMergeName })
125
+
126
+ let melbRoyal = await stops.findDocument({
127
+ 'bays.stopGTFSID': '16830'
128
+ })
129
+
130
+ expect(melbRoyal).to.not.be.null
131
+ expect(melbRoyal.bays.length).to.equal(1)
132
+ expect(melbRoyal.stopName).to.equal('Melbourne University/Royal Parade')
133
+
134
+ let melbGrattan = await stops.findDocument({
135
+ 'bays.stopGTFSID': '28670'
136
+ })
137
+
138
+ expect(melbGrattan).to.not.be.null
139
+ expect(melbGrattan.bays.length).to.equal(4)
140
+ expect(melbGrattan.stopName).to.equal('Melbourne University/Grattan Street')
141
+
142
+ let melbSwanston = await stops.findDocument({
143
+ 'bays.stopGTFSID': '87'
144
+ })
145
+
146
+ expect(melbSwanston).to.not.be.null
147
+ expect(melbSwanston.bays.length).to.equal(3)
148
+ expect(melbSwanston.stopName).to.equal('Melbourne University/Swanston Street')
149
+ })
150
+
151
+ it('Should override stop names if required', async () => {
152
+ let database = new LokiDatabaseConnection('test-db')
153
+ let stops = await database.createCollection('stops')
154
+
155
+ await (new StopsLoader(stopNameOverrides, suburbs, TRANSIT_MODES.bus, database)).loadStops({
156
+ processStop: stop => {
157
+ let updatedName = nameOverrides[stop.fullStopName]
158
+ if (updatedName) stop.fullStopName = updatedName
159
+
160
+ return stop
161
+ }
162
+ })
163
+
164
+ let ballarat = await stops.findDocument({
165
+ 'bays.stopGTFSID': '49020'
166
+ })
167
+
168
+ expect(ballarat).to.not.be.null
169
+ expect(ballarat.bays.length).to.equal(3)
170
+ expect(ballarat.stopName).to.equal('Ballarat Railway Station')
171
+ expect(ballarat.bays[0].originalName).to.equal('Ballarat Bus Interchange (Soldiers Hill)')
172
+ })
173
+
174
+ it('Should handle CSV blank spaces and other unicode junk', async () => {
175
+ let database = new LokiDatabaseConnection('test-db')
176
+ let stops = await database.createCollection('stops')
177
+
178
+ await (new StopsLoader(specialHeader, suburbs, TRANSIT_MODES.bus, database)).loadStops()
179
+
180
+ let gumRd = await stops.findDocument({
181
+ 'bays.stopGTFSID': '10009'
182
+ })
183
+
184
+ expect(gumRd).to.not.be.null
185
+ expect(gumRd.stopName).to.equal('Gum Road/Main Road West')
186
+ })
187
+
188
+ it('Should allow for individual stops to be loaded in', async () => {
189
+ let database = new LokiDatabaseConnection('test-db')
190
+ let stops = await database.createCollection('stops')
191
+
192
+ let loader = new StopsLoader(specialHeader, suburbs, TRANSIT_MODES.bus, database)
193
+ let reader = new GTFSStopsReader('')
194
+
195
+ await loader.loadStop(reader.processEntity({
196
+ stop_id: '51586',
197
+ stop_name: 'Huntingdale Station/Haughton Road (Oakleigh)',
198
+ stop_lat: '-37.9111998619901',
199
+ stop_lon: '145.103064853799'
200
+ }))
201
+
202
+ let huntingdale = await stops.findDocument({
203
+ 'bays.stopGTFSID': '51586'
204
+ })
205
+
206
+ expect(huntingdale).to.not.be.null
207
+ expect(huntingdale.stopName).to.equal('Huntingdale Railway Station/Haughton Road')
208
+
209
+ await loader.loadStop(reader.processEntity({
210
+ stop_id: '22440',
211
+ stop_name: 'Huntingdale Station/Huntingdale Road (Oakleigh)',
212
+ stop_lat: '-37.911010298723',
213
+ stop_lon: '145.103604328761'
214
+ }))
215
+
216
+ huntingdale = await stops.findDocument({
217
+ 'bays.stopGTFSID': '22440'
218
+ })
219
+
220
+ expect(huntingdale).to.not.be.null
221
+ expect(huntingdale.stopName).to.equal('Huntingdale Railway Station')
222
+ })
223
+ })
@@ -0,0 +1,37 @@
1
+ import { expect } from 'chai'
2
+ import path from 'path'
3
+ import url from 'url'
4
+ import GTFSStopTimesReader from '../lib/gtfs-parser/readers/GTFSStopTimesReader.mjs'
5
+
6
+ const __filename = url.fileURLToPath(import.meta.url)
7
+ const __dirname = path.dirname(__filename)
8
+
9
+ const stopTimesFile = path.join(__dirname, 'sample-data', 'trips', 'stop_times.txt')
10
+
11
+ describe('The GTFSStopTimesReader class', () => {
12
+ it('Should read the stop times one trips worth at a time', async () => {
13
+ let reader = new GTFSStopTimesReader(stopTimesFile)
14
+
15
+ await reader.open()
16
+
17
+ let stopTimes = await reader.getNextEntity()
18
+ expect(stopTimes.tripID).to.equal('1.T2.2-ALM-vpt-1.1.R')
19
+ expect(stopTimes.stops.length).to.equal(7)
20
+ expect(stopTimes.stops[0].stopID).to.equal('19847')
21
+ expect(stopTimes.stops[0].departureTime).to.equal('04:57')
22
+
23
+ expect(stopTimes.stops[6].stopID).to.equal('19853')
24
+ expect(stopTimes.stops[6].departureTime).to.equal('05:08')
25
+
26
+ await reader.getNextEntity()
27
+ await reader.getNextEntity()
28
+
29
+ let lastTrip = await reader.getNextEntity()
30
+ expect(lastTrip.tripID).to.equal('101.T2.2-ALM-vpt-1.2.H')
31
+ expect(lastTrip.stops.length).to.equal(7)
32
+ expect(lastTrip.stops[0].stopID).to.equal('19853')
33
+ expect(lastTrip.stops[0].departureTime).to.equal('23:31')
34
+
35
+ expect(reader.available()).to.be.false
36
+ })
37
+ })