@transportme/load-ptv-gtfs 1.0.0 → 1.0.2

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/index.mjs ADDED
@@ -0,0 +1,26 @@
1
+ import RouteLoader from './lib/loader/RouteLoader.mjs'
2
+ import ShapeLoader from './lib/loader/ShapeLoader.mjs'
3
+ import StopsLoader from './lib/loader/StopsLoader.mjs'
4
+ import TripLoader from './lib/loader/TripLoader.mjs'
5
+
6
+ import GTFSAgency from './lib/gtfs-parser/GTFSAgency.mjs'
7
+ import GTFSCalendar from './lib/gtfs-parser/GTFSCalendar.mjs'
8
+ import GTFSCalendarDate from './lib/gtfs-parser/GTFSCalendarDate.mjs'
9
+ import GTFSRoute from './lib/gtfs-parser/GTFSRoute.mjs'
10
+ import { GTFSShape, GTFSShapePoint } from './lib/gtfs-parser/GTFSShape.mjs'
11
+ import { GTFSStop, GTFSPlatformStop } from './lib/gtfs-parser/GTFSStop.mjs'
12
+ import { GTFSStopTime } from './lib/gtfs-parser/GTFSStopTime.mjs'
13
+ import GTFSTrip from './lib/gtfs-parser/GTFSTrip.mjs'
14
+
15
+ const GTFSTypes = {
16
+ GTFSAgency, GTFSCalendar, GTFSCalendarDate,
17
+ GTFSRoute, GTFSShape, GTFSShapePoint,
18
+ GTFSStop, GTFSPlatformStop,
19
+ GTFSStopTime, GTFSTrip
20
+ }
21
+
22
+ export {
23
+ RouteLoader, ShapeLoader,
24
+ StopsLoader, TripLoader,
25
+ GTFSTypes
26
+ }
@@ -1,6 +1,7 @@
1
1
  import GTFSRouteReader from '../gtfs-parser/readers/GTFSRouteReader.mjs'
2
2
  import GTFSAgencyReader from '../gtfs-parser/readers/GTFSAgencyReader.mjs'
3
3
  import { STOP_UTILS } from '@transportme/transportvic-utils'
4
+ import GTFSRoute from '../gtfs-parser/GTFSRoute.mjs'
4
5
 
5
6
  const { sanitiseName } = STOP_UTILS
6
7
 
@@ -14,6 +15,13 @@ export default class RouteLoader {
14
15
 
15
16
  #routeIDMap = {}
16
17
 
18
+ /**
19
+ * Creates a new Shape Loader.
20
+ *
21
+ * @param {string} routesFile The path for the routes.txt file
22
+ * @param {string} agencyFile The path for the agency.txt file
23
+ * @param {DatabaseConnection} database A database connection
24
+ */
17
25
  constructor(routesFile, agencyFile, mode, database) {
18
26
  this.#routes = database.getCollection('routes')
19
27
  this.#mode = mode
@@ -61,33 +69,42 @@ export default class RouteLoader {
61
69
  }, matchingRoute)
62
70
  }
63
71
 
72
+ /**
73
+ * Loads a route into the database
74
+ *
75
+ * @param {GTFSRoute} route The route being added
76
+ * @param {function} [processRoute] Used to modify the route data. Should return null to drop the route
77
+ */
78
+ async loadRoute(route, processRoute) {
79
+ let originalRouteID = route.originalRouteGTFSID
80
+ let routeData = this.generateDBRouteData(route)
81
+ let processedData = processRoute ? await processRoute(routeData) : routeData
82
+ if (!processedData) return
83
+
84
+ this.#routeIDMap[originalRouteID] = processedData.routeGTFSID
85
+
86
+ let matchingRoute = await this.findMatchingRoute(processedData)
87
+
88
+ if (matchingRoute) {
89
+ await this.mergeRoutes(matchingRoute, processedData)
90
+ } else {
91
+ await this.#routes.createDocument(processedData)
92
+ }
93
+ }
94
+
64
95
  /**
65
96
  * Loads the route data into the database.
66
97
  *
67
98
  * @param {Object} options An optional parameter to allow for custom route processing
68
- * @param {function} options.processRoute A function to modify the route data. If a route should be dropped, it should return null.
99
+ * @param {function} [options.processRoute] A function to modify the route data. If a route should be dropped, it should return null.
69
100
  */
70
- async loadRoutes({ processRoute } = { processRoute: r => r }) {
101
+ async loadRoutes({ processRoute } = {}) {
71
102
  await this.loadAgencies()
72
103
 
73
104
  await this.#routesReader.open()
74
105
  while (this.#routesReader.available()) {
75
106
  let route = await this.#routesReader.getNextEntity()
76
-
77
- let originalRouteID = route.originalRouteGTFSID
78
- let routeData = this.generateDBRouteData(route)
79
- let processedData = await processRoute(routeData)
80
- if (!processedData) continue
81
-
82
- this.#routeIDMap[originalRouteID] = processedData.routeGTFSID
83
-
84
- let matchingRoute = await this.findMatchingRoute(processedData)
85
-
86
- if (matchingRoute) {
87
- await this.mergeRoutes(matchingRoute, processedData)
88
- } else {
89
- await this.#routes.createDocument(processedData)
90
- }
107
+ await this.loadRoute(route, processRoute)
91
108
  }
92
109
  }
93
110
 
@@ -8,6 +8,12 @@ export default class ShapeLoader {
8
8
 
9
9
  #routeCache = {}
10
10
 
11
+ /**
12
+ * Creates a new Shape Loader.
13
+ *
14
+ * @param {string} shapeFile The path for the shapes.txt file
15
+ * @param {DatabaseConnection} database A database connection
16
+ */
11
17
  constructor(shapeFile, database) {
12
18
  this.#routes = database.getCollection('routes')
13
19
  this.#shapeReader = new GTFSShapeReader(shapeFile)
@@ -10,6 +10,14 @@ export default class StopsLoader {
10
10
  #mode
11
11
  #stopsReader
12
12
 
13
+ /**
14
+ * Creates a new Stop Loader.
15
+ *
16
+ * @param {string} stopsFile The path for the stops.txt file
17
+ * @param {FeatureCollection} suburbs A GeoJSON FeatureCollection containing a list of all suburbs located within Victoria
18
+ * @param {string} mode The transit mode being loaded
19
+ * @param {DatabaseConnection} database A database connection
20
+ */
13
21
  constructor(stopsFile, suburbs, mode, database) {
14
22
  this.#stops = database.getCollection('stops')
15
23
  this.#mode = mode
@@ -106,7 +114,7 @@ export default class StopsLoader {
106
114
  * @param {function} options.processStop Used to process as stop's data.
107
115
  * @param {function} options.getMergeName Used to get a stop's merge name. Return null to use the default merge name.
108
116
  */
109
- async loadStop(stop, {processStop, getMergeName} = {}) {
117
+ async loadStop(stop, { processStop, getMergeName } = {}) {
110
118
  let processedData = processStop ? processStop(stop) : stop
111
119
 
112
120
  let defaultMergeName = this.getMergeName(processedData)
@@ -1,7 +1,9 @@
1
+ import DatabaseConnection from '@transportme/database/lib/DatabaseConnection.mjs'
1
2
  import GTFSCalendarReader from '../gtfs-parser/readers/GTFSCalendarReader.mjs'
2
3
  import GTFSStopTimesReader from '../gtfs-parser/readers/GTFSStopTimesReader.mjs'
3
4
  import GTFSTripReader from '../gtfs-parser/readers/GTFSTripReader.mjs'
4
5
  import async from 'async'
6
+ import { GTFSStopTime } from '../gtfs-parser/GTFSStopTime.mjs'
5
7
 
6
8
  export default class TripLoader {
7
9
 
@@ -25,6 +27,19 @@ export default class TripLoader {
25
27
 
26
28
  #shapeIDMap = {}
27
29
 
30
+ #tripsToLoad = []
31
+
32
+ /**
33
+ * Creates a new Trip Loader.
34
+ *
35
+ * @param {Object} paths Required file paths for the TripLoader
36
+ * @param {string} paths.tripsFile The path for the trips.txt file
37
+ * @param {string} paths.stopTimesFile The path for the stop_times.txt file
38
+ * @param {string} paths.calendarFile The path for the calendar.txt file
39
+ * @param {string} paths.calendarDatesFile The path for the calendar_dates.txt file
40
+ * @param {string} mode The transit mode being loaded
41
+ * @param {DatabaseConnection} database A database connection
42
+ */
28
43
  constructor({ tripsFile, stopTimesFile, calendarFile, calendarDatesFile }, mode, database) {
29
44
  this.#routes = database.getCollection('routes')
30
45
  this.#stops = database.getCollection('stops')
@@ -132,12 +147,33 @@ export default class TripLoader {
132
147
  return dbTrip
133
148
  }
134
149
 
150
+ /**
151
+ * Loads a trip into the database.
152
+ *
153
+ * @param {Object} tripData The trip data
154
+ * @param {string} tripData.tripID The trip ID
155
+ * @param {GTFSStopTime[]} tripData.stops The trip's stops
156
+ * @param {function} [processTrip] Used to process a trip.
157
+ */
158
+ async loadTrip({ tripID, stops }, processTrip) {
159
+ let rawTripData = this.#tripDetails[tripID]
160
+ let tripData = await this.generateDBTripData(rawTripData, stops)
161
+ if (!tripData) return
162
+
163
+ let processedData = processTrip ? await processTrip(tripData) : tripData
164
+ if (!processedData) return
165
+
166
+ this.#shapeIDMap[tripData.shapeID] = tripData.routeGTFSID
167
+
168
+ this.#tripsToLoad.push(processedData)
169
+ }
170
+
135
171
  /**
136
172
  * Loads the trip data into the database.
137
173
  *
138
174
  * @param {object} options A list of options for the trip loader
139
175
  * @param {object} options.routeIDMap A mapping of full route IDs to their simplified IDs.
140
- * @param {function} options.processTrip A function to modify trip data on a per-trip basis. It should return null to discard the trip.
176
+ * @param {function} [options.processTrip] A function to modify trip data on a per-trip basis. It should return null to discard the trip.
141
177
  */
142
178
  async loadTrips({ routeIDMap, processTrip }) {
143
179
  this.#routeIDMap = routeIDMap
@@ -146,38 +182,29 @@ export default class TripLoader {
146
182
  await this.loadTripsData()
147
183
 
148
184
  let tripsLoaded = 0
149
- let trips = []
150
185
 
151
186
  await this.#stopTimesReader.open()
152
187
  while (this.#stopTimesReader.available()) {
153
- let { tripID, stops } = await this.#stopTimesReader.getNextEntity()
154
-
155
- let rawTripData = this.#tripDetails[tripID]
156
- let tripData = await this.generateDBTripData(rawTripData, stops)
157
- if (!tripData) continue
158
-
159
- let processedData = processTrip ? await processTrip(tripData) : tripData
160
- if (!processedData) continue
161
-
162
- this.#shapeIDMap[tripData.shapeID] = tripData.routeGTFSID
163
-
164
- trips.push(processedData)
165
-
166
- tripsLoaded += 1
188
+ let gtfsTrip = await this.#stopTimesReader.getNextEntity()
189
+ await this.loadTrip(gtfsTrip, processTrip)
167
190
 
168
- if (tripsLoaded === 5000) { // Flush the cache every 5000 trips
169
- this.#routeCache = {}
170
- this.#stopCache = {}
171
-
172
- await this.#trips.createDocuments(trips)
173
- trips = []
174
-
175
- tripsLoaded = 0
191
+ if (this.#tripsToLoad.length === 5000) { // Flush the cache every 5000 trips
192
+ tripsLoaded += this.#tripsToLoad.length
193
+ await this.writeTrips()
176
194
  }
177
195
  }
178
196
 
179
- if (trips.length) {
180
- await this.#trips.createDocuments(trips)
197
+ tripsLoaded += this.#tripsToLoad.length
198
+ await this.writeTrips()
199
+ }
200
+
201
+ async writeTrips() {
202
+ if (this.#tripsToLoad.length) {
203
+ this.#routeCache = {}
204
+ this.#stopCache = {}
205
+
206
+ await this.#trips.createDocuments(this.#tripsToLoad)
207
+ this.#tripsToLoad = []
181
208
  }
182
209
  }
183
210
 
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@transportme/load-ptv-gtfs",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "",
5
- "main": "index.js",
5
+ "main": "index.mjs",
6
6
  "scripts": {
7
7
  "test": "mocha"
8
8
  },