@tmlmobilidade/generate-offer-files 20250626.2245.27 → 20250627.1200.48
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/dist/main.js +40 -97
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
import LOGGER from '@helperkits/logger';
|
|
3
3
|
import TIMETRACKER from '@helperkits/timer';
|
|
4
4
|
import { JsonWriter } from '@helperkits/writer';
|
|
5
|
-
import {
|
|
5
|
+
import { validateGtfsCalendar, validateGtfsCalendarDate, validateGtfsRouteExtended, validateGtfsStopExtended, validateGtfsTripExtended } from '@tmlmobilidade/types';
|
|
6
6
|
import { convertMetersOrKilometersToMeters, Dates, getOperationalDatesFromRange } from '@tmlmobilidade/utils';
|
|
7
7
|
import { parse as csvParser } from 'csv-parse';
|
|
8
8
|
import extract from 'extract-zip';
|
|
9
9
|
import fs from 'fs';
|
|
10
|
-
import { ExceptionType } from 'gtfs-types';
|
|
11
10
|
/* * */
|
|
12
11
|
export async function generateOfferOutput(filePath, startDate, endDate, outputDir, feedId) {
|
|
13
12
|
try {
|
|
@@ -76,21 +75,13 @@ export async function generateOfferOutput(filePath, startDate, endDate, outputDi
|
|
|
76
75
|
const parseEachRow = async (data) => {
|
|
77
76
|
//
|
|
78
77
|
//
|
|
79
|
-
// Validate the
|
|
80
|
-
|
|
81
|
-
let serviceIdStartDate;
|
|
82
|
-
let serviceIdEndDate;
|
|
83
|
-
try {
|
|
84
|
-
serviceIdStartDate = validateOperationalDate(data.start_date);
|
|
85
|
-
serviceIdEndDate = validateOperationalDate(data.end_date);
|
|
86
|
-
}
|
|
87
|
-
catch (error) {
|
|
88
|
-
LOGGER.error(`Error creating operational date "${data.start_date}" or "${data.end_date}" for service_id "${data.service_id}"`, error);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
78
|
+
// Validate the current row against the proper type
|
|
79
|
+
const validatedData = validateGtfsCalendar(data);
|
|
91
80
|
//
|
|
92
81
|
// Check if this service_id is between the given start_date and end_date.
|
|
93
82
|
// Clip the service_id's start and end dates to the given start and end dates.
|
|
83
|
+
let serviceIdStartDate = validatedData.start_date;
|
|
84
|
+
let serviceIdEndDate = validatedData.end_date;
|
|
94
85
|
if (serviceIdEndDate < startDate || serviceIdStartDate > endDate)
|
|
95
86
|
return;
|
|
96
87
|
if (serviceIdStartDate < startDate)
|
|
@@ -105,24 +96,24 @@ export async function generateOfferOutput(filePath, startDate, endDate, outputDi
|
|
|
105
96
|
const validOperationalDates = [];
|
|
106
97
|
for (const currentDate of allOperationalDatesInRange) {
|
|
107
98
|
const dayOfWeek = Dates.fromOperationalDate(currentDate, 'Europe/Lisbon').toFormat('c');
|
|
108
|
-
if (dayOfWeek === '1' &&
|
|
99
|
+
if (dayOfWeek === '1' && validatedData.monday === 1)
|
|
109
100
|
validOperationalDates.push(currentDate);
|
|
110
|
-
if (dayOfWeek === '2' &&
|
|
101
|
+
if (dayOfWeek === '2' && validatedData.tuesday === 1)
|
|
111
102
|
validOperationalDates.push(currentDate);
|
|
112
|
-
if (dayOfWeek === '3' &&
|
|
103
|
+
if (dayOfWeek === '3' && validatedData.wednesday === 1)
|
|
113
104
|
validOperationalDates.push(currentDate);
|
|
114
|
-
if (dayOfWeek === '4' &&
|
|
105
|
+
if (dayOfWeek === '4' && validatedData.thursday === 1)
|
|
115
106
|
validOperationalDates.push(currentDate);
|
|
116
|
-
if (dayOfWeek === '5' &&
|
|
107
|
+
if (dayOfWeek === '5' && validatedData.friday === 1)
|
|
117
108
|
validOperationalDates.push(currentDate);
|
|
118
|
-
if (dayOfWeek === '6' &&
|
|
109
|
+
if (dayOfWeek === '6' && validatedData.saturday === 1)
|
|
119
110
|
validOperationalDates.push(currentDate);
|
|
120
|
-
if (dayOfWeek === '7' &&
|
|
111
|
+
if (dayOfWeek === '7' && validatedData.sunday === 1)
|
|
121
112
|
validOperationalDates.push(currentDate);
|
|
122
113
|
}
|
|
123
114
|
//
|
|
124
115
|
// Save the valid operational dates for this service_id
|
|
125
|
-
savedCalendarDates.set(
|
|
116
|
+
savedCalendarDates.set(validatedData.service_id, validOperationalDates);
|
|
126
117
|
//
|
|
127
118
|
};
|
|
128
119
|
//
|
|
@@ -154,40 +145,33 @@ export async function generateOfferOutput(filePath, startDate, endDate, outputDi
|
|
|
154
145
|
const parseEachRow = async (data) => {
|
|
155
146
|
//
|
|
156
147
|
//
|
|
157
|
-
// Validate the
|
|
158
|
-
|
|
159
|
-
try {
|
|
160
|
-
currentOperationalDate = validateOperationalDate(data.date);
|
|
161
|
-
}
|
|
162
|
-
catch (error) {
|
|
163
|
-
LOGGER.error(`Error creating operational date "${data.date}" for service_id "${data.service_id}"`, error);
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
148
|
+
// Validate the current row against the proper type
|
|
149
|
+
const validatedData = validateGtfsCalendarDate(data);
|
|
166
150
|
//
|
|
167
151
|
// Skip if this row's date is not between the given start and end dates
|
|
168
|
-
if (
|
|
152
|
+
if (validatedData.date < startDate || validatedData.date > endDate)
|
|
169
153
|
return;
|
|
170
154
|
//
|
|
171
155
|
// If we're here, it means the service_id is valid between the given dates.
|
|
172
156
|
// Get the previously saved calendars and check if it exists for this service_id.
|
|
173
|
-
const savedCalendar = savedCalendarDates.get(
|
|
157
|
+
const savedCalendar = savedCalendarDates.get(validatedData.service_id);
|
|
174
158
|
if (savedCalendar) {
|
|
175
159
|
// Create a new Set to avoid duplicated dates
|
|
176
160
|
const updatedCalendar = new Set(savedCalendar);
|
|
177
161
|
// If this service_id was previously saved, either add or remove the current date
|
|
178
162
|
// to it based on the exception_type value for this row.
|
|
179
|
-
if (
|
|
180
|
-
updatedCalendar.add(
|
|
181
|
-
else if (
|
|
182
|
-
updatedCalendar.delete(
|
|
163
|
+
if (validatedData.exception_type === 1)
|
|
164
|
+
updatedCalendar.add(validatedData.date);
|
|
165
|
+
else if (validatedData.exception_type === 2)
|
|
166
|
+
updatedCalendar.delete(validatedData.date);
|
|
183
167
|
// Update the service_id with the new dates
|
|
184
|
-
savedCalendarDates.set(
|
|
168
|
+
savedCalendarDates.set(validatedData.service_id, Array.from(updatedCalendar));
|
|
185
169
|
}
|
|
186
170
|
else {
|
|
187
171
|
// If this is the first time we're seeing this service_id, then it is only necessary
|
|
188
172
|
// to initiate a new dates array if it is a service addition
|
|
189
|
-
if (
|
|
190
|
-
savedCalendarDates.set(
|
|
173
|
+
if (validatedData.exception_type === 1) {
|
|
174
|
+
savedCalendarDates.set(validatedData.service_id, [validatedData.date]);
|
|
191
175
|
}
|
|
192
176
|
}
|
|
193
177
|
//
|
|
@@ -219,31 +203,16 @@ export async function generateOfferOutput(filePath, startDate, endDate, outputDi
|
|
|
219
203
|
//
|
|
220
204
|
LOGGER.info(`Reading zip entry "trips.txt"...`);
|
|
221
205
|
const parseEachRow = async (data) => {
|
|
222
|
-
//
|
|
223
|
-
|
|
206
|
+
// Validate the current row against the proper type
|
|
207
|
+
const validatedData = validateGtfsTripExtended(data);
|
|
224
208
|
// For each trip, check if the associated service_id was saved
|
|
225
209
|
// in the previous step or not. Include it if yes, skip otherwise.
|
|
226
|
-
if (!savedCalendarDates.has(
|
|
210
|
+
if (!savedCalendarDates.has(validatedData.service_id))
|
|
227
211
|
return;
|
|
228
|
-
//
|
|
229
|
-
|
|
230
|
-
// to
|
|
231
|
-
|
|
232
|
-
direction_id: data.direction_id,
|
|
233
|
-
pattern_id: data.pattern_id,
|
|
234
|
-
route_id: data.route_id,
|
|
235
|
-
service_id: data.service_id,
|
|
236
|
-
shape_id: data.shape_id,
|
|
237
|
-
trip_headsign: data.trip_headsign,
|
|
238
|
-
trip_id: data.trip_id,
|
|
239
|
-
wheelchair_accessible: data.wheelchair_accessible,
|
|
240
|
-
};
|
|
241
|
-
//
|
|
242
|
-
// Save this trip for later and reference
|
|
243
|
-
// the associated route_id to filter them later.
|
|
244
|
-
savedTrips.set(data.trip_id, parsedRowData);
|
|
245
|
-
referencedRouteIds.add(data.route_id);
|
|
246
|
-
//
|
|
212
|
+
// Save the exported row
|
|
213
|
+
savedTrips.set(validatedData.trip_id, validatedData);
|
|
214
|
+
// Reference the associated entities to filter them later.
|
|
215
|
+
referencedRouteIds.add(validatedData.route_id);
|
|
247
216
|
};
|
|
248
217
|
//
|
|
249
218
|
// Setup the CSV parsing operation
|
|
@@ -265,28 +234,14 @@ export async function generateOfferOutput(filePath, startDate, endDate, outputDi
|
|
|
265
234
|
//
|
|
266
235
|
LOGGER.info(`Reading zip entry "routes.txt"...`);
|
|
267
236
|
const parseEachRow = async (data) => {
|
|
268
|
-
//
|
|
269
|
-
|
|
237
|
+
// Validate the current row against the proper type
|
|
238
|
+
const validatedData = validateGtfsRouteExtended(data);
|
|
270
239
|
// For each route, only save the ones referenced
|
|
271
240
|
// by the previously saved trips.
|
|
272
|
-
if (!referencedRouteIds.has(
|
|
241
|
+
if (!referencedRouteIds.has(validatedData.route_id))
|
|
273
242
|
return;
|
|
274
|
-
//
|
|
275
|
-
|
|
276
|
-
const parsedRowData = {
|
|
277
|
-
agency_id: data.agency_id,
|
|
278
|
-
line_id: data.line_id,
|
|
279
|
-
line_long_name: data.line_long_name,
|
|
280
|
-
line_short_name: data.line_short_name,
|
|
281
|
-
path_type: data.path_type,
|
|
282
|
-
route_color: data.route_color,
|
|
283
|
-
route_id: data.route_id,
|
|
284
|
-
route_long_name: data.route_long_name,
|
|
285
|
-
route_short_name: data.route_short_name,
|
|
286
|
-
route_text_color: data.route_text_color,
|
|
287
|
-
};
|
|
288
|
-
savedRoutes.set(data.route_id, parsedRowData);
|
|
289
|
-
//
|
|
243
|
+
// Save the exported row
|
|
244
|
+
savedRoutes.set(validatedData.route_id, validatedData);
|
|
290
245
|
};
|
|
291
246
|
//
|
|
292
247
|
// Setup the CSV parsing operation
|
|
@@ -309,22 +264,10 @@ export async function generateOfferOutput(filePath, startDate, endDate, outputDi
|
|
|
309
264
|
//
|
|
310
265
|
LOGGER.info(`Reading zip entry "stops.txt"...`);
|
|
311
266
|
const parseEachRow = async (data) => {
|
|
312
|
-
//
|
|
313
|
-
|
|
314
|
-
// Save
|
|
315
|
-
|
|
316
|
-
location_type: data.location_type,
|
|
317
|
-
municipality_id: data.municipality_id,
|
|
318
|
-
parent_station: data.parent_station,
|
|
319
|
-
parish_id: data.parish_id,
|
|
320
|
-
region_id: data.region_id,
|
|
321
|
-
stop_id: data.stop_id,
|
|
322
|
-
stop_lat: Number(data.stop_lat),
|
|
323
|
-
stop_lon: Number(data.stop_lon),
|
|
324
|
-
stop_name: data.stop_name,
|
|
325
|
-
};
|
|
326
|
-
savedStops.set(data.stop_id, parsedRowData);
|
|
327
|
-
//
|
|
267
|
+
// Validate the current row against the proper type
|
|
268
|
+
const validatedData = validateGtfsStopExtended(data);
|
|
269
|
+
// Save the exported row
|
|
270
|
+
savedStops.set(validatedData.stop_id, validatedData);
|
|
328
271
|
};
|
|
329
272
|
//
|
|
330
273
|
// Setup the CSV parsing operation
|