@golemio/pid 2.1.13-dev.509351734 → 2.1.13
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/db/example/{00_truncate_tables.sql → __truncate_tables.sql} +0 -0
- package/db/example/{01_departure_directions.sql → departure_directions.sql} +0 -0
- package/db/example/{02_pid_line_example_115.sql → pid_line_example_115.sql} +0 -0
- package/db/example/{03_ropidgtfs_dump.sql → ropid_gtfs_dump.sql} +27 -27
- package/db/example/{04_ropidvymi_example.sql → ropidvymi_example.sql} +0 -0
- package/db/example/{07_tmp_example.sql → tmp_example.sql} +0 -0
- package/db/example/{pb/trip_updates.pb → trip_updates.pb} +0 -0
- package/db/example/{pb/vehicle_positions.pb → vehicle_positions.pb} +0 -0
- package/db/example/{05_vehicle_positions_dump.sql → vehicle_positions_dump.sql} +0 -0
- package/db/example/{99_precomputed_tables.sql → zzz_precomputed_tables.sql} +0 -0
- package/dist/const.d.ts +0 -4
- package/dist/const.js +1 -6
- package/dist/const.js.map +1 -1
- package/dist/integration-engine/ropid-gtfs/RopidGTFSScheduledTripsModel.d.ts +1 -1
- package/dist/integration-engine/ropid-gtfs/RopidGTFSStopTimesModel.d.ts +0 -11
- package/dist/integration-engine/ropid-gtfs/RopidGTFSStopTimesModel.js +0 -34
- package/dist/integration-engine/ropid-gtfs/RopidGTFSStopTimesModel.js.map +1 -1
- package/dist/integration-engine/ropid-gtfs/RopidGTFSTripsModel.js +1 -2
- package/dist/integration-engine/ropid-gtfs/RopidGTFSTripsModel.js.map +1 -1
- package/dist/integration-engine/ropid-gtfs/RopidGTFSWorker.js +2 -2
- package/dist/integration-engine/ropid-gtfs/RopidGTFSWorker.js.map +1 -1
- package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsPositionsModel.d.ts → VehiclePositionsPositionsModel.d.ts} +3 -3
- package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsPositionsModel.js → VehiclePositionsPositionsModel.js} +3 -3
- package/dist/integration-engine/vehicle-positions/VehiclePositionsPositionsModel.js.map +1 -0
- package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsRunsMessagesModel.d.ts → VehiclePositionsRunsMessagesModel.d.ts} +0 -0
- package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsRunsMessagesModel.js → VehiclePositionsRunsMessagesModel.js} +5 -5
- package/dist/integration-engine/vehicle-positions/VehiclePositionsRunsMessagesModel.js.map +1 -0
- package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsRunsModel.d.ts → VehiclePositionsRunsModel.d.ts} +2 -2
- package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsRunsModel.js → VehiclePositionsRunsModel.js} +2 -2
- package/dist/integration-engine/vehicle-positions/VehiclePositionsRunsModel.js.map +1 -0
- package/dist/integration-engine/vehicle-positions/{transformations/VehiclePositionsRunsTransformation.d.ts → VehiclePositionsRunsTransformation.d.ts} +1 -1
- package/dist/integration-engine/vehicle-positions/{transformations/VehiclePositionsRunsTransformation.js → VehiclePositionsRunsTransformation.js} +1 -1
- package/dist/integration-engine/vehicle-positions/VehiclePositionsRunsTransformation.js.map +1 -0
- package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsStopsModel.d.ts → VehiclePositionsStopsModel.d.ts} +0 -0
- package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsStopsModel.js → VehiclePositionsStopsModel.js} +1 -1
- package/dist/integration-engine/vehicle-positions/VehiclePositionsStopsModel.js.map +1 -0
- package/dist/integration-engine/vehicle-positions/VehiclePositionsTransformation.d.ts +49 -0
- package/dist/integration-engine/vehicle-positions/{transformations/VehiclePositionsTransformation.js → VehiclePositionsTransformation.js} +45 -42
- package/dist/integration-engine/vehicle-positions/VehiclePositionsTransformation.js.map +1 -0
- package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsTripsModel.d.ts → VehiclePositionsTripsModel.d.ts} +7 -5
- package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsTripsModel.js → VehiclePositionsTripsModel.js} +30 -48
- package/dist/integration-engine/vehicle-positions/VehiclePositionsTripsModel.js.map +1 -0
- package/dist/integration-engine/vehicle-positions/VehiclePositionsWorker.d.ts +90 -43
- package/dist/integration-engine/vehicle-positions/VehiclePositionsWorker.js +213 -327
- package/dist/integration-engine/vehicle-positions/VehiclePositionsWorker.js.map +1 -1
- package/dist/integration-engine/vehicle-positions/index.d.ts +5 -2
- package/dist/integration-engine/vehicle-positions/index.js +5 -2
- package/dist/integration-engine/vehicle-positions/index.js.map +1 -1
- package/dist/output-gateway/vehicle-positions/models/VehiclePositionsTripsModel.js +1 -1
- package/dist/output-gateway/vehicle-positions/models/VehiclePositionsTripsModel.js.map +1 -1
- package/dist/schema-definitions/vehicle-positions/index.d.ts +2 -9
- package/dist/schema-definitions/vehicle-positions/index.js +2 -18
- package/dist/schema-definitions/vehicle-positions/index.js.map +1 -1
- package/package.json +82 -83
- package/db/example/06_ropidgtfs_train_trips_stop_times.sql +0 -83
- package/dist/integration-engine/vehicle-positions/VehiclePositionsInterfaces.d.ts +0 -152
- package/dist/integration-engine/vehicle-positions/VehiclePositionsInterfaces.js +0 -3
- package/dist/integration-engine/vehicle-positions/VehiclePositionsInterfaces.js.map +0 -1
- package/dist/integration-engine/vehicle-positions/VehiclePositionsUtils.d.ts +0 -22
- package/dist/integration-engine/vehicle-positions/VehiclePositionsUtils.js +0 -53
- package/dist/integration-engine/vehicle-positions/VehiclePositionsUtils.js.map +0 -1
- package/dist/integration-engine/vehicle-positions/models/VehiclePositionsPositionsModel.js.map +0 -1
- package/dist/integration-engine/vehicle-positions/models/VehiclePositionsRunsMessagesModel.js.map +0 -1
- package/dist/integration-engine/vehicle-positions/models/VehiclePositionsRunsModel.js.map +0 -1
- package/dist/integration-engine/vehicle-positions/models/VehiclePositionsStopsModel.js.map +0 -1
- package/dist/integration-engine/vehicle-positions/models/VehiclePositionsTripsModel.js.map +0 -1
- package/dist/integration-engine/vehicle-positions/models/index.d.ts +0 -5
- package/dist/integration-engine/vehicle-positions/models/index.js +0 -18
- package/dist/integration-engine/vehicle-positions/models/index.js.map +0 -1
- package/dist/integration-engine/vehicle-positions/transformations/VehiclePositionsRunsTransformation.js.map +0 -1
- package/dist/integration-engine/vehicle-positions/transformations/VehiclePositionsTransformation.d.ts +0 -108
- package/dist/integration-engine/vehicle-positions/transformations/VehiclePositionsTransformation.js.map +0 -1
- package/dist/integration-engine/vehicle-positions/transformations/index.d.ts +0 -2
- package/dist/integration-engine/vehicle-positions/transformations/index.js +0 -15
- package/dist/integration-engine/vehicle-positions/transformations/index.js.map +0 -1
|
@@ -27,6 +27,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
27
27
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
28
|
});
|
|
29
29
|
};
|
|
30
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
31
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
32
|
+
var m = o[Symbol.asyncIterator], i;
|
|
33
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
34
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
35
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
36
|
+
};
|
|
30
37
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
38
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
39
|
};
|
|
@@ -45,13 +52,12 @@ const helpers_1 = require("@golemio/core/dist/integration-engine/helpers");
|
|
|
45
52
|
const models_1 = require("@golemio/core/dist/integration-engine/models");
|
|
46
53
|
const workers_1 = require("@golemio/core/dist/integration-engine/workers");
|
|
47
54
|
const ropid_gtfs_1 = require("../../schema-definitions/ropid-gtfs");
|
|
55
|
+
const RopidGTFSTripsModel_1 = require("../ropid-gtfs/RopidGTFSTripsModel");
|
|
48
56
|
const vehicle_positions_1 = require("../../schema-definitions/vehicle-positions");
|
|
57
|
+
const _1 = require("./");
|
|
49
58
|
const const_1 = require("../../const");
|
|
50
|
-
const
|
|
59
|
+
const VehiclePositionsRunsTransformation_1 = require("./VehiclePositionsRunsTransformation");
|
|
51
60
|
const RopidGTFSStopTimesModel_1 = require("../ropid-gtfs/RopidGTFSStopTimesModel");
|
|
52
|
-
const models_2 = require("./models");
|
|
53
|
-
const transformations_1 = require("./transformations");
|
|
54
|
-
const VehiclePositionsUtils_1 = require("./VehiclePositionsUtils");
|
|
55
61
|
var PositionHandlerEnum;
|
|
56
62
|
(function (PositionHandlerEnum) {
|
|
57
63
|
PositionHandlerEnum["TRACKING"] = "TRACKING";
|
|
@@ -103,11 +109,10 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
103
109
|
}
|
|
104
110
|
}
|
|
105
111
|
for (const key in chunks) {
|
|
106
|
-
const
|
|
107
|
-
const updatedTrips = yield this.modelTrips.findAllAssocTripIds(chunks[key]);
|
|
112
|
+
const allIds = yield this.modelTrips.findAllAssocTripIds(chunks[key]);
|
|
108
113
|
yield this.sendMessageToExchange("workers." + this.queuePrefix + ".updateDelay", JSON.stringify({
|
|
109
|
-
positions,
|
|
110
|
-
updatedTrips,
|
|
114
|
+
positions: transformedData.positions.filter((position) => chunks[key].includes(position.trips_id)),
|
|
115
|
+
updatedTrips: allIds,
|
|
111
116
|
}));
|
|
112
117
|
}
|
|
113
118
|
});
|
|
@@ -126,7 +131,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
126
131
|
this.updateGTFSTripId = (msg) => __awaiter(this, void 0, void 0, function* () {
|
|
127
132
|
const inputData = JSON.parse(msg.content.toString());
|
|
128
133
|
// unique ids in input data in key-value (id-positions) structure
|
|
129
|
-
|
|
134
|
+
const positionsByIds = {};
|
|
130
135
|
for (const position of inputData.positions) {
|
|
131
136
|
positionsByIds[position.trips_id] = position;
|
|
132
137
|
}
|
|
@@ -135,13 +140,13 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
135
140
|
if (!trip.origin_route_name || !trip.sequence_id || !positionsByIds[trip.id].origin_timestamp)
|
|
136
141
|
return;
|
|
137
142
|
const timestampLast = (0, moment_timezone_1.default)(positionsByIds[trip.id].origin_timestamp).tz("Europe/Prague").format();
|
|
138
|
-
return this.
|
|
143
|
+
return this.getScheduledTrips({
|
|
139
144
|
route_id: trip.origin_route_name,
|
|
140
145
|
run_number: trip.sequence_id,
|
|
141
146
|
msg_last_timestamp: timestampLast,
|
|
142
147
|
});
|
|
143
148
|
}));
|
|
144
|
-
// find
|
|
149
|
+
// find for each trip gtfs data
|
|
145
150
|
const promiseValues = yield Promise.all(inputData.trips.map((trip) => __awaiter(this, void 0, void 0, function* () {
|
|
146
151
|
try {
|
|
147
152
|
return yield this.modelTrips.findGTFSTripId(trip);
|
|
@@ -151,71 +156,35 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
151
156
|
return err;
|
|
152
157
|
}
|
|
153
158
|
})));
|
|
154
|
-
let existingTripsPromiseValues = [], existingTripsPromiseErrors = [];
|
|
155
159
|
// filter only trips with found gtfs data
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
existingTripsPromiseErrors.push(trip);
|
|
159
|
-
}
|
|
160
|
-
else if (trip instanceof Array) {
|
|
161
|
-
existingTripsPromiseValues.push(...trip);
|
|
162
|
-
}
|
|
163
|
-
else if ((trip === null || trip === void 0 ? void 0 : trip.constructor) === Object) {
|
|
164
|
-
existingTripsPromiseValues.push(trip);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
let tripsByBlockId = {};
|
|
168
|
-
for (const trip of existingTripsPromiseValues) {
|
|
169
|
-
if (!trip.gtfs_block_id || !trip.gtfs_trip_id)
|
|
170
|
-
continue;
|
|
171
|
-
if (!tripsByBlockId[trip.gtfs_block_id]) {
|
|
172
|
-
tripsByBlockId[trip.gtfs_block_id] = new Set();
|
|
173
|
-
}
|
|
174
|
-
tripsByBlockId[trip.gtfs_block_id].add(trip.gtfs_trip_id);
|
|
175
|
-
}
|
|
176
|
-
// create cache for trip stops (grouped by block id)
|
|
177
|
-
const tripStopsSchedulesByBlockIds = yield Object.entries(tripsByBlockId).reduce((acc, [blockId, tripIds]) => __awaiter(this, void 0, void 0, function* () {
|
|
178
|
-
const tripStops = yield acc;
|
|
179
|
-
try {
|
|
180
|
-
tripStops[blockId] = yield this.setAndReturnTripStopsSchedule(blockId, [...tripIds]);
|
|
181
|
-
}
|
|
182
|
-
catch (err) {
|
|
183
|
-
helpers_1.IntegrationErrorHandler.handle(err);
|
|
184
|
-
}
|
|
185
|
-
return acc;
|
|
186
|
-
}), Promise.resolve({}));
|
|
160
|
+
const foundedTripsPromiseValues = [].concat(...promiseValues.filter((result) => !(result instanceof golemio_errors_1.CustomError)));
|
|
161
|
+
const foundedTripsPromiseErrors = promiseValues.filter((result) => result instanceof golemio_errors_1.CustomError);
|
|
187
162
|
let currentPosition;
|
|
188
|
-
for (const trip of
|
|
163
|
+
for (const trip of foundedTripsPromiseValues) {
|
|
189
164
|
if (positionsByIds[trip.id]) {
|
|
190
165
|
currentPosition = positionsByIds[trip.id];
|
|
191
|
-
continue;
|
|
192
|
-
}
|
|
193
|
-
if (!currentPosition) {
|
|
194
|
-
continue;
|
|
195
166
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
// duplicate position with new created trip for second trip
|
|
167
|
+
else {
|
|
168
|
+
// duplicate position with new created trip for second train trip
|
|
199
169
|
const newPosition = Object.assign({}, currentPosition);
|
|
200
170
|
newPosition.trips_id = trip.id;
|
|
201
|
-
newPosition.tracking = trackingStatus !== null && trackingStatus !== void 0 ? trackingStatus : newPosition.tracking;
|
|
202
171
|
inputData.positions.push(newPosition);
|
|
203
172
|
}
|
|
204
173
|
}
|
|
205
174
|
yield this.modelPositions.save(inputData.positions);
|
|
206
175
|
// successfully updated gtfs ids
|
|
207
|
-
for (let i = 0, chunkSize = 100, imax =
|
|
176
|
+
for (let i = 0, chunkSize = 100, imax = foundedTripsPromiseValues.length; i < imax; i += chunkSize) {
|
|
208
177
|
yield this.sendMessageToExchange("workers." + this.queuePrefix + ".updateDelay", JSON.stringify({
|
|
209
178
|
positions: [],
|
|
210
|
-
updatedTrips:
|
|
179
|
+
updatedTrips: foundedTripsPromiseValues.slice(i, i + chunkSize),
|
|
211
180
|
}));
|
|
212
181
|
}
|
|
213
182
|
// gtfsId updating errors
|
|
214
|
-
for (let i = 0, imax =
|
|
215
|
-
helpers_1.IntegrationErrorHandler.handle(
|
|
183
|
+
for (let i = 0, imax = foundedTripsPromiseErrors.length; i < imax; i++) {
|
|
184
|
+
helpers_1.IntegrationErrorHandler.handle(foundedTripsPromiseErrors[i]);
|
|
216
185
|
}
|
|
217
186
|
});
|
|
218
|
-
this.generateGtfsRt = () => __awaiter(this, void 0, void 0, function* () {
|
|
187
|
+
this.generateGtfsRt = (msg) => __awaiter(this, void 0, void 0, function* () {
|
|
219
188
|
const results = yield this.modelTrips.findAllForGTFSRt();
|
|
220
189
|
const updatesMessage = gtfsRealtime.FeedMessage.create();
|
|
221
190
|
const positionsMessage = gtfsRealtime.FeedMessage.create();
|
|
@@ -236,7 +205,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
236
205
|
tripId: r.gtfs_trip_id,
|
|
237
206
|
routeId: r.gtfs_route_id,
|
|
238
207
|
};
|
|
239
|
-
const vehicleDescriptor = Object.assign({ id: r.gtfs_route_type ===
|
|
208
|
+
const vehicleDescriptor = Object.assign({ id: r.gtfs_route_type === _1.GTFSRouteTypeEnum.TRAIN
|
|
240
209
|
? "train-" + r.cis_trip_number
|
|
241
210
|
: "service-" + r.gtfs_route_type + "-" + r.vehicle_registration_number }, (r.vehicle_registration_number && {
|
|
242
211
|
label: r.vehicle_registration_number,
|
|
@@ -365,10 +334,10 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
365
334
|
const tripIds = inputData.updatedTrips.map((trip) => trip.id);
|
|
366
335
|
if (((_b = inputData.positions) === null || _b === void 0 ? void 0 : _b.length) > 0) {
|
|
367
336
|
// unique ids in input data in key-value (id-positions) structure
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}
|
|
337
|
+
const positionsByIds = inputData.positions.reduce((acc, position) => {
|
|
338
|
+
acc[position.trips_id] = position;
|
|
339
|
+
return acc;
|
|
340
|
+
}, {});
|
|
372
341
|
// unique block_id's and its parent input trips_id in key-value (block_id-trips_id) structure
|
|
373
342
|
const blockIdsToParentTripsId = inputData.updatedTrips.reduce((acc, currentTrip) => {
|
|
374
343
|
if (!acc[currentTrip.gtfs_block_id]) {
|
|
@@ -384,34 +353,13 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
384
353
|
}
|
|
385
354
|
return acc;
|
|
386
355
|
}, {});
|
|
387
|
-
// Get cached schedule for each unique block_id
|
|
388
|
-
const tripStopsSchedulesByBlockIds = yield Object.keys(blockIdsToParentTripsId).reduce((acc, blockId) => __awaiter(this, void 0, void 0, function* () {
|
|
389
|
-
const tripStops = yield acc;
|
|
390
|
-
try {
|
|
391
|
-
const schedule = yield this.tripStopsModel.get(blockId);
|
|
392
|
-
if (schedule) {
|
|
393
|
-
tripStops[blockId] = schedule;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
catch (err) {
|
|
397
|
-
helpers_1.IntegrationErrorHandler.handle(err);
|
|
398
|
-
}
|
|
399
|
-
return acc;
|
|
400
|
-
}), Promise.resolve({}));
|
|
401
356
|
// duplicate positions for trips with block_ids
|
|
402
357
|
for (const trip of inputData.updatedTrips) {
|
|
403
|
-
if (positionsByIds[trip.id]) {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
return position.trips_id === blockIdsToParentTripsId[trip.gtfs_block_id];
|
|
408
|
-
});
|
|
409
|
-
const { shouldCreateNewPosition, trackingStatus } = VehiclePositionsUtils_1.VehiclePositionsUtils.determineNewPositionTracking(tripStopsSchedulesByBlockIds[trip.gtfs_block_id], trip, currentPosition);
|
|
410
|
-
if (shouldCreateNewPosition) {
|
|
411
|
-
// duplicate position with new created trip for second trip
|
|
412
|
-
const newPosition = Object.assign({}, currentPosition);
|
|
358
|
+
if (!positionsByIds[trip.id]) {
|
|
359
|
+
const newPosition = Object.assign({}, inputData.positions.find((position) => {
|
|
360
|
+
return position.trips_id === blockIdsToParentTripsId[trip.gtfs_block_id];
|
|
361
|
+
}));
|
|
413
362
|
newPosition.trips_id = trip.id;
|
|
414
|
-
newPosition.tracking = trackingStatus !== null && trackingStatus !== void 0 ? trackingStatus : newPosition.tracking;
|
|
415
363
|
inputData.positions.push(newPosition);
|
|
416
364
|
}
|
|
417
365
|
}
|
|
@@ -434,7 +382,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
434
382
|
helpers_1.log.debug("Delay Computation data (Redis) was not found. (gtfsTripId = " + trip.gtfs_trip_id + ")");
|
|
435
383
|
try {
|
|
436
384
|
const gtfs = yield this.getResultObjectForDelayCalculation(trip.gtfs_trip_id);
|
|
437
|
-
yield this.delayComputationTripsModel.set("trip_id", gtfs,
|
|
385
|
+
yield this.delayComputationTripsModel.set("trip_id", gtfs, 7200);
|
|
438
386
|
trip.gtfsData = gtfs;
|
|
439
387
|
}
|
|
440
388
|
catch (err) {
|
|
@@ -451,7 +399,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
451
399
|
}));
|
|
452
400
|
}
|
|
453
401
|
catch (err) {
|
|
454
|
-
throw new golemio_errors_1.CustomError(`Error while updating delay
|
|
402
|
+
throw new golemio_errors_1.CustomError(`Error while updating delay.`, true, this.constructor.name, 5001, err);
|
|
455
403
|
}
|
|
456
404
|
}
|
|
457
405
|
});
|
|
@@ -508,8 +456,9 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
508
456
|
* @returns {void}
|
|
509
457
|
*/
|
|
510
458
|
this.updateRunsGTFSTripId = (msg) => __awaiter(this, void 0, void 0, function* () {
|
|
459
|
+
var e_1, _e;
|
|
511
460
|
const input = JSON.parse(msg.content.toString());
|
|
512
|
-
const schedule = yield this.
|
|
461
|
+
const schedule = yield this.getScheduledTrips(input.run);
|
|
513
462
|
const { actual_stop_timestamp_scheduled: actualStopTimestampScheduled, msg_timestamp: msgTimestamp, events: event, } = input.run_message;
|
|
514
463
|
const delayMsg = {
|
|
515
464
|
updatedTrips: [],
|
|
@@ -524,51 +473,62 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
524
473
|
}
|
|
525
474
|
return;
|
|
526
475
|
}
|
|
527
|
-
if (
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
476
|
+
if (actualStopTimestampScheduled) {
|
|
477
|
+
const asts = (0, moment_timezone_1.default)(+actualStopTimestampScheduled);
|
|
478
|
+
// current gtfs trip for run
|
|
479
|
+
const gtfsCurrentTrip = schedule.find((el, i) => {
|
|
480
|
+
return asts.isBetween((0, moment_timezone_1.default)(el.start_timestamp), (0, moment_timezone_1.default)(el.end_timestamp), "second", "[]");
|
|
481
|
+
});
|
|
482
|
+
let isCurrentTripTracking = false;
|
|
483
|
+
if (gtfsCurrentTrip &&
|
|
484
|
+
// tram is always on track while pushes messages only on stops
|
|
485
|
+
(gtfsCurrentTrip.route_type === _1.GTFSRouteTypeEnum.TRAM ||
|
|
486
|
+
// when bus announces DEPARTURE TCP event, it means that trip is on track
|
|
487
|
+
(gtfsCurrentTrip.route_type === _1.GTFSRouteTypeEnum.BUS && event === const_1.TCPEventEnum.DEPARTURED) ||
|
|
488
|
+
// when trip has set first stop time, and message timestamp is after scheduled start, set as tracking
|
|
489
|
+
(asts.isSame((0, moment_timezone_1.default)(gtfsCurrentTrip.start_timestamp)) &&
|
|
490
|
+
(0, moment_timezone_1.default)(msgTimestamp).isSameOrAfter((0, moment_timezone_1.default)(gtfsCurrentTrip.start_timestamp))) ||
|
|
491
|
+
// of course when trip announcing some next stop time in schedule, then set as tracking
|
|
492
|
+
asts.isAfter((0, moment_timezone_1.default)(gtfsCurrentTrip.start_timestamp)))) {
|
|
493
|
+
isCurrentTripTracking = true;
|
|
494
|
+
}
|
|
495
|
+
const gtfsCurrentTripId = gtfsCurrentTrip && gtfsCurrentTrip.trip_id;
|
|
496
|
+
if (!gtfsCurrentTripId) {
|
|
497
|
+
helpers_1.log.warn(`updateRunsGTFSTripId: could not find current gtfsTrip for run: ${JSON.stringify(input)}`);
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
const currentTrip = yield this.modelTrips.upsertRunTrip(input, gtfsCurrentTrip);
|
|
501
|
+
yield this.modelPositions.upsertRunPosition(input, gtfsCurrentTrip, isCurrentTripTracking);
|
|
502
|
+
delayMsg.updatedTrips.push(currentTrip);
|
|
503
|
+
}
|
|
504
|
+
// last/next gtfs trip for run
|
|
505
|
+
const gtfsLastNextTrips = schedule.filter((el) => {
|
|
506
|
+
return (((asts.clone().subtract(15, "minutes") <= (0, moment_timezone_1.default)(el.end_timestamp) && (0, moment_timezone_1.default)(el.end_timestamp) <= asts) ||
|
|
507
|
+
(asts <= (0, moment_timezone_1.default)(el.start_timestamp) && (0, moment_timezone_1.default)(el.start_timestamp) <= asts.clone().add(60, "minutes"))) &&
|
|
508
|
+
el.trip_id !== (gtfsCurrentTrip === null || gtfsCurrentTrip === void 0 ? void 0 : gtfsCurrentTrip.trip_id));
|
|
509
|
+
});
|
|
510
|
+
try {
|
|
511
|
+
for (var gtfsLastNextTrips_1 = __asyncValues(gtfsLastNextTrips), gtfsLastNextTrips_1_1; gtfsLastNextTrips_1_1 = yield gtfsLastNextTrips_1.next(), !gtfsLastNextTrips_1_1.done;) {
|
|
512
|
+
const gtfsTrip = gtfsLastNextTrips_1_1.value;
|
|
513
|
+
const trip = yield this.modelTrips.upsertRunTrip(input, gtfsTrip);
|
|
514
|
+
yield this.modelPositions.upsertRunPosition(input, gtfsTrip, false);
|
|
515
|
+
delayMsg.updatedTrips.push(trip);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
519
|
+
finally {
|
|
520
|
+
try {
|
|
521
|
+
if (gtfsLastNextTrips_1_1 && !gtfsLastNextTrips_1_1.done && (_e = gtfsLastNextTrips_1.return)) yield _e.call(gtfsLastNextTrips_1);
|
|
522
|
+
}
|
|
523
|
+
finally { if (e_1) throw e_1.error; }
|
|
524
|
+
}
|
|
525
|
+
// send to updateDelay only if there are some trips updated
|
|
526
|
+
if (delayMsg.updatedTrips.length > 0) {
|
|
527
|
+
yield this.sendMessageToExchange("workers." + this.queuePrefix + ".updateDelay", JSON.stringify(delayMsg));
|
|
528
|
+
}
|
|
552
529
|
}
|
|
553
530
|
else {
|
|
554
|
-
|
|
555
|
-
yield this.modelPositions.upsertRunPosition(input, gtfsCurrentTrip, isCurrentTripTracking);
|
|
556
|
-
delayMsg.updatedTrips.push(currentTrip);
|
|
557
|
-
}
|
|
558
|
-
// last/next gtfs trip for run
|
|
559
|
-
const gtfsLastNextTrips = schedule.filter((el) => {
|
|
560
|
-
return (((asts.clone().subtract(15, "minutes") <= (0, moment_timezone_1.default)(el.end_timestamp) && (0, moment_timezone_1.default)(el.end_timestamp) <= asts) ||
|
|
561
|
-
(asts <= (0, moment_timezone_1.default)(el.start_timestamp) && (0, moment_timezone_1.default)(el.start_timestamp) <= asts.clone().add(60, "minutes"))) &&
|
|
562
|
-
el.trip_id !== (gtfsCurrentTrip === null || gtfsCurrentTrip === void 0 ? void 0 : gtfsCurrentTrip.trip_id));
|
|
563
|
-
});
|
|
564
|
-
for (const gtfsTrip of gtfsLastNextTrips) {
|
|
565
|
-
const trip = yield this.modelTrips.upsertRunTrip(input, gtfsTrip);
|
|
566
|
-
yield this.modelPositions.upsertRunPosition(input, gtfsTrip, false);
|
|
567
|
-
delayMsg.updatedTrips.push(trip);
|
|
568
|
-
}
|
|
569
|
-
// send to updateDelay only if there are some trips updated
|
|
570
|
-
if (delayMsg.updatedTrips.length > 0) {
|
|
571
|
-
yield this.sendMessageToExchange("workers." + this.queuePrefix + ".updateDelay", JSON.stringify(delayMsg));
|
|
531
|
+
helpers_1.log.warn(`updateRunsGTFSTripId: actualStopTimestampScheduled is not provided for current run: ${JSON.stringify(input.run)}`);
|
|
572
532
|
}
|
|
573
533
|
});
|
|
574
534
|
/**
|
|
@@ -598,7 +558,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
598
558
|
*
|
|
599
559
|
* @returns {string[]} array of tripIds
|
|
600
560
|
*/
|
|
601
|
-
this.
|
|
561
|
+
this.getScheduledTrips = (scheduleData) => __awaiter(this, void 0, void 0, function* () {
|
|
602
562
|
const { route_id, run_number, msg_last_timestamp } = scheduleData;
|
|
603
563
|
const scheduledTripIds = yield this.runTripsModel.get(`${route_id}_${run_number}`);
|
|
604
564
|
if (!(scheduledTripIds === null || scheduledTripIds === void 0 ? void 0 : scheduledTripIds.schedule)) {
|
|
@@ -608,34 +568,11 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
608
568
|
el.start_timestamp = (0, moment_timezone_1.default)(el.start_timestamp).tz("Europe/Prague").format();
|
|
609
569
|
el.end_timestamp = (0, moment_timezone_1.default)(el.end_timestamp).tz("Europe/Prague").format();
|
|
610
570
|
});
|
|
611
|
-
yield this.runTripsModel.set(`${route_id}_${run_number}`, { schedule: result },
|
|
571
|
+
yield this.runTripsModel.set(`${route_id}_${run_number}`, { schedule: result }, 21600);
|
|
612
572
|
return result;
|
|
613
573
|
}
|
|
614
574
|
return scheduledTripIds.schedule;
|
|
615
575
|
});
|
|
616
|
-
/**
|
|
617
|
-
* Get trip stops schedule by block id
|
|
618
|
-
*
|
|
619
|
-
* @param {string} blockId - Target gtfs block id
|
|
620
|
-
* @param {string} tripIds - List of inserted gtfs trip ids
|
|
621
|
-
*/
|
|
622
|
-
this.setAndReturnTripStopsSchedule = (blockId, tripIds) => __awaiter(this, void 0, void 0, function* () {
|
|
623
|
-
var _e;
|
|
624
|
-
const schedule = (_e = (yield this.tripStopsModel.get(blockId))) !== null && _e !== void 0 ? _e : {};
|
|
625
|
-
try {
|
|
626
|
-
const tripStops = yield this.modelGTFSStopTimes.findTripStops(tripIds);
|
|
627
|
-
const tripStopsSchedule = tripStops.reduce((acc, curr) => {
|
|
628
|
-
acc[curr.trip_id] = { trip_stops: curr.trip_stops };
|
|
629
|
-
return acc;
|
|
630
|
-
}, schedule);
|
|
631
|
-
yield this.tripStopsModel.set(blockId, tripStopsSchedule, VehiclePositionsUtils_1.VehiclePositionsUtils.TRIP_STOPS_CACHE_TTL);
|
|
632
|
-
return tripStopsSchedule;
|
|
633
|
-
}
|
|
634
|
-
catch (err) {
|
|
635
|
-
helpers_1.log.warn("Unable to retrieve trip stops", err);
|
|
636
|
-
return schedule;
|
|
637
|
-
}
|
|
638
|
-
});
|
|
639
576
|
/**
|
|
640
577
|
* Takes all newly computed positions and saves it, then save the last ones to the trips
|
|
641
578
|
*
|
|
@@ -743,9 +680,9 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
743
680
|
return PositionHandlerEnum.DO_NOTHING;
|
|
744
681
|
if (position.is_canceled)
|
|
745
682
|
return PositionHandlerEnum.CANCELED;
|
|
746
|
-
if (position.lat && position.lng && position.tracking ===
|
|
683
|
+
if (position.lat && position.lng && position.tracking === 2)
|
|
747
684
|
return PositionHandlerEnum.TRACKING;
|
|
748
|
-
if (position.tracking !==
|
|
685
|
+
if (position.tracking !== 2)
|
|
749
686
|
return PositionHandlerEnum.NOT_TRACKING;
|
|
750
687
|
return PositionHandlerEnum.NOT_TRACKING;
|
|
751
688
|
};
|
|
@@ -795,7 +732,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
795
732
|
}
|
|
796
733
|
else {
|
|
797
734
|
// if there is tracking 2 position with same origin_timestamp then this position is duplicate
|
|
798
|
-
const statePosition = tripPositions.positions.find((e) => e.origin_timestamp === position.origin_timestamp && e.tracking ===
|
|
735
|
+
const statePosition = tripPositions.positions.find((e) => e.origin_timestamp === position.origin_timestamp && e.tracking === 2)
|
|
799
736
|
? const_1.StatePositionEnum.DUPLICATE
|
|
800
737
|
: const_1.StatePositionEnum.AFTER_TRACK;
|
|
801
738
|
const lastShapesAnchorPoint = tripPositions.gtfsData.shapes_anchor_points[tripPositions.gtfsData.shapes_anchor_points.length - 1];
|
|
@@ -888,6 +825,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
888
825
|
.valueOf();
|
|
889
826
|
};
|
|
890
827
|
// FIND ALL SHAPE POINTS IN POLYGON CIRCLE, GET SEGMENTS WITH CONSEQUENTING POINTS
|
|
828
|
+
// TODO this should a class method
|
|
891
829
|
this.getShapePointsAroundPosition = (tripShapePoints, radius) => __awaiter(this, void 0, void 0, function* () {
|
|
892
830
|
const ptsInRadius = [];
|
|
893
831
|
let segmentIndex = 0;
|
|
@@ -1045,9 +983,9 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1045
983
|
if (Math.abs(timeRealDiff) < Math.abs(minTimeRealDiff)) {
|
|
1046
984
|
minTimeRealDiff = timeRealDiff;
|
|
1047
985
|
// push trip into nearest at_stop shape anchor point if trip "P" event (tram) / "V" event (bus)
|
|
1048
|
-
if (((gtfsRouteType ===
|
|
986
|
+
if (((gtfsRouteType === _1.GTFSRouteTypeEnum.TRAM &&
|
|
1049
987
|
currentPosition.properties.tcp_event === const_1.TCPEventEnum.ARRIVAL_ANNOUNCED) ||
|
|
1050
|
-
(gtfsRouteType ===
|
|
988
|
+
(gtfsRouteType === _1.GTFSRouteTypeEnum.BUS && currentPosition.properties.tcp_event === const_1.TCPEventEnum.V)) &&
|
|
1051
989
|
thisClosestPoint.this_stop_sequence === null) {
|
|
1052
990
|
let movingShapePointIndex = thisClosestPoint.index;
|
|
1053
991
|
while (thisClosestPoint.this_stop_sequence === null && movingShapePointIndex < lastTripShapePoint.index) {
|
|
@@ -1062,7 +1000,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1062
1000
|
statePosition = const_1.StatePositionEnum.ON_TRACK;
|
|
1063
1001
|
}
|
|
1064
1002
|
// if tram position has "V" avent tram is after track
|
|
1065
|
-
if (gtfsRouteType ===
|
|
1003
|
+
if (gtfsRouteType === _1.GTFSRouteTypeEnum.TRAM && currentPosition.properties.tcp_event === const_1.TCPEventEnum.V) {
|
|
1066
1004
|
statePosition = const_1.StatePositionEnum.AFTER_TRACK;
|
|
1067
1005
|
thisClosestPoint = lastTripShapePoint;
|
|
1068
1006
|
timeDelay = null;
|
|
@@ -1165,13 +1103,59 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1165
1103
|
if (!stopTimes || !stopTimes.stop_times || stopTimes.stop_times.length === 0) {
|
|
1166
1104
|
throw new Error(`"trip.stop_times" was not found for id ${tripId}.`);
|
|
1167
1105
|
}
|
|
1168
|
-
|
|
1106
|
+
// { <tripData>, stop_times: [ <stopTimesDataWithStop> ], shapes: [ <shapesData> ] }
|
|
1107
|
+
const shapesGeometryAnchorPoints = yield this.getShapesGeometryAnchorPoints(stopTimes.shape_id, shapes.shapes);
|
|
1108
|
+
// ----------------------------------------------
|
|
1109
|
+
// TEMP constS
|
|
1110
|
+
const stopSequenceMaximum = stopTimes.stop_times.length;
|
|
1169
1111
|
// MAKING COPY
|
|
1170
1112
|
const shapePoints = [];
|
|
1171
1113
|
// const to determine shape points of stops (in meters)
|
|
1172
|
-
const distanceBefore =
|
|
1173
|
-
const distanceAfter =
|
|
1174
|
-
|
|
1114
|
+
const distanceBefore = 100;
|
|
1115
|
+
const distanceAfter = 50;
|
|
1116
|
+
// TODO this should a class method
|
|
1117
|
+
const shapesAnchorPointsIterator = (i, cb) => {
|
|
1118
|
+
// end of iteration
|
|
1119
|
+
if (shapesGeometryAnchorPoints.length === i) {
|
|
1120
|
+
return cb();
|
|
1121
|
+
}
|
|
1122
|
+
// find stop in near distance
|
|
1123
|
+
const stopNearby = stopTimes.stop_times.reduce((r, s, j) => {
|
|
1124
|
+
if (shapesGeometryAnchorPoints[i].shape_dist_traveled >=
|
|
1125
|
+
s.shape_dist_traveled - (distanceBefore * 1.0) / 1000 &&
|
|
1126
|
+
shapesGeometryAnchorPoints[i].shape_dist_traveled <=
|
|
1127
|
+
s.shape_dist_traveled + (distanceAfter * 1.0) / 1000) {
|
|
1128
|
+
const thisDistanceToStop = Math.abs(shapesGeometryAnchorPoints[i].shape_dist_traveled - s.shape_dist_traveled);
|
|
1129
|
+
if (r.distanceToStop > thisDistanceToStop) {
|
|
1130
|
+
r.distanceToStop = thisDistanceToStop;
|
|
1131
|
+
r.this_stop_sequence = s.stop_sequence;
|
|
1132
|
+
r.at_stop = true;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
return r;
|
|
1136
|
+
}, { at_stop: false, stop_sequence: null, distanceToStop: Infinity, this_stop_sequence: null });
|
|
1137
|
+
let lastStopSequence;
|
|
1138
|
+
let nextStopSequence;
|
|
1139
|
+
// SET THIS STOP
|
|
1140
|
+
if (stopNearby.at_stop) {
|
|
1141
|
+
lastStopSequence = Math.min(stopNearby.this_stop_sequence, stopSequenceMaximum);
|
|
1142
|
+
nextStopSequence = Math.min(stopNearby.this_stop_sequence + 1, stopSequenceMaximum);
|
|
1143
|
+
}
|
|
1144
|
+
else {
|
|
1145
|
+
const lastNextSequences = stopTimes.stop_times.reduce((r, s, j) => {
|
|
1146
|
+
if (j < stopTimes.stop_times.length - 1) {
|
|
1147
|
+
if (shapesGeometryAnchorPoints[i].shape_dist_traveled >= s.shape_dist_traveled &&
|
|
1148
|
+
shapesGeometryAnchorPoints[i].shape_dist_traveled <=
|
|
1149
|
+
stopTimes.stop_times[j + 1].shape_dist_traveled) {
|
|
1150
|
+
r.last_stop_sequence = j + 1;
|
|
1151
|
+
r.next_stop_sequence = j + 1 + 1;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
return r;
|
|
1155
|
+
}, { last_stop_sequence: 1, next_stop_sequence: 2 });
|
|
1156
|
+
lastStopSequence = lastNextSequences.last_stop_sequence;
|
|
1157
|
+
nextStopSequence = lastNextSequences.next_stop_sequence;
|
|
1158
|
+
}
|
|
1175
1159
|
let bearing = 0;
|
|
1176
1160
|
// add bearing from shape computed for previous shapePoint
|
|
1177
1161
|
if (i > 0) {
|
|
@@ -1189,37 +1173,13 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1189
1173
|
bearing = shapePoints[i - 1].bearing;
|
|
1190
1174
|
}
|
|
1191
1175
|
}
|
|
1192
|
-
// init values
|
|
1193
|
-
let thisStopSequence = null;
|
|
1194
|
-
let lastStopSequence = shapesGeometryAnchorPoints[i].last_stop_sequence;
|
|
1195
|
-
let nextStopSequence = shapesGeometryAnchorPoints[i].next_stop_sequence;
|
|
1196
|
-
// these are origin stop_times shape point fron shapes table, clearly at stops points
|
|
1197
|
-
if (shapesGeometryAnchorPoints[i].this_stop_sequence) {
|
|
1198
|
-
thisStopSequence = shapesGeometryAnchorPoints[i].this_stop_sequence;
|
|
1199
|
-
}
|
|
1200
|
-
// if is shape anchor point in close distance AFTER LAST stop, then set it also AT STOP
|
|
1201
|
-
else if (i > 0 &&
|
|
1202
|
-
shapesGeometryAnchorPoints[i].shape_dist_traveled -
|
|
1203
|
-
stopTimes.stop_times[shapesGeometryAnchorPoints[i].last_stop_sequence - 1].shape_dist_traveled <=
|
|
1204
|
-
distanceAfter) {
|
|
1205
|
-
thisStopSequence = shapesGeometryAnchorPoints[i].last_stop_sequence;
|
|
1206
|
-
}
|
|
1207
|
-
// if is shape anchor point in close distance BEFORE NEXT stop, then set it also AT STOP
|
|
1208
|
-
else if (i < shapesGeometryAnchorPoints.length - 1 &&
|
|
1209
|
-
stopTimes.stop_times[shapesGeometryAnchorPoints[i].next_stop_sequence - 1].shape_dist_traveled -
|
|
1210
|
-
shapesGeometryAnchorPoints[i].shape_dist_traveled <=
|
|
1211
|
-
distanceBefore) {
|
|
1212
|
-
thisStopSequence = shapesGeometryAnchorPoints[i].next_stop_sequence;
|
|
1213
|
-
lastStopSequence = shapesGeometryAnchorPoints[i].next_stop_sequence;
|
|
1214
|
-
nextStopSequence = Math.min(shapesGeometryAnchorPoints[i].next_stop_sequence + 1, stopTimes.stop_times.length);
|
|
1215
|
-
}
|
|
1216
1176
|
const distanceFromLastStop = Math.round((shapesGeometryAnchorPoints[i].shape_dist_traveled -
|
|
1217
1177
|
stopTimes.stop_times[lastStopSequence - 1].shape_dist_traveled) *
|
|
1218
1178
|
1000) / 1000;
|
|
1219
1179
|
// if is trip at stop than set departure by this stop
|
|
1220
1180
|
// between stops do linear interpolation from departure from last stop and arrival of next stop
|
|
1221
|
-
const timeScheduledSeconds =
|
|
1222
|
-
? stopTimes.stop_times[lastStopSequence - 1].
|
|
1181
|
+
const timeScheduledSeconds = stopNearby.at_stop
|
|
1182
|
+
? stopTimes.stop_times[lastStopSequence - 1].departure_time_seconds
|
|
1223
1183
|
: stopTimes.stop_times[lastStopSequence - 1].departure_time_seconds +
|
|
1224
1184
|
Math.round(((stopTimes.stop_times[nextStopSequence - 1].arrival_time_seconds -
|
|
1225
1185
|
stopTimes.stop_times[lastStopSequence - 1].departure_time_seconds) *
|
|
@@ -1228,22 +1188,29 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1228
1188
|
stopTimes.stop_times[lastStopSequence - 1].shape_dist_traveled));
|
|
1229
1189
|
shapePoints.push({
|
|
1230
1190
|
index: i,
|
|
1231
|
-
at_stop:
|
|
1191
|
+
at_stop: stopNearby.at_stop,
|
|
1232
1192
|
bearing,
|
|
1233
1193
|
coordinates: shapesGeometryAnchorPoints[i].coordinates,
|
|
1234
1194
|
distance_from_last_stop: distanceFromLastStop,
|
|
1235
1195
|
last_stop_sequence: lastStopSequence,
|
|
1236
1196
|
next_stop_sequence: nextStopSequence,
|
|
1237
|
-
shape_dist_traveled:
|
|
1238
|
-
this_stop_sequence:
|
|
1197
|
+
shape_dist_traveled: shapesGeometryAnchorPoints[i].shape_dist_traveled,
|
|
1198
|
+
this_stop_sequence: stopNearby.at_stop ? stopNearby.this_stop_sequence : null,
|
|
1239
1199
|
time_scheduled_seconds: timeScheduledSeconds,
|
|
1240
1200
|
});
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
trip_id: tripId,
|
|
1244
|
-
stop_times: stopTimes.stop_times,
|
|
1245
|
-
shapes_anchor_points: shapePoints,
|
|
1201
|
+
// next step
|
|
1202
|
+
shapesAnchorPointsIterator(i + 1, cb);
|
|
1246
1203
|
};
|
|
1204
|
+
return new Promise((resolve, reject) => {
|
|
1205
|
+
shapesAnchorPointsIterator(0, () => {
|
|
1206
|
+
// FINAL OBJECT
|
|
1207
|
+
resolve({
|
|
1208
|
+
trip_id: tripId,
|
|
1209
|
+
stop_times: stopTimes.stop_times,
|
|
1210
|
+
shapes_anchor_points: shapePoints,
|
|
1211
|
+
});
|
|
1212
|
+
});
|
|
1213
|
+
});
|
|
1247
1214
|
}
|
|
1248
1215
|
catch (err) {
|
|
1249
1216
|
helpers_1.log.error(err);
|
|
@@ -1255,156 +1222,75 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1255
1222
|
*
|
|
1256
1223
|
* @param {string} shapeId - GTFS shape id
|
|
1257
1224
|
* @param {ITransformedTripShape[]} shapes - GTFS shape points
|
|
1258
|
-
* @param {IStopTime[]} stops
|
|
1259
1225
|
* @returns {IShapeGeometryAnchorPoint[]} - Result array of geometry points along trip track shape
|
|
1260
1226
|
*/
|
|
1261
|
-
this.getShapesGeometryAnchorPoints = (shapeId, shapes,
|
|
1227
|
+
this.getShapesGeometryAnchorPoints = (shapeId, shapes) => __awaiter(this, void 0, void 0, function* () {
|
|
1228
|
+
var _m;
|
|
1229
|
+
const shapesAnchorPoints = [];
|
|
1262
1230
|
try {
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
if (currentSegment.length) {
|
|
1279
|
-
segmentShapes.push(currentSegment);
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
let segmentArr = [];
|
|
1283
|
-
// concat arrays of stop divided segments with distributed shape points
|
|
1284
|
-
for (const segment of segmentShapes) {
|
|
1285
|
-
segmentArr = [...segmentArr, ...this.divideSegmentLine(segment)];
|
|
1286
|
-
}
|
|
1287
|
-
// Make initial shapesGeometryAnchorPoints
|
|
1288
|
-
let stopCounter = 0;
|
|
1289
|
-
const resultArr = segmentArr.map((segment, index) => {
|
|
1290
|
-
let this_stop_sequence;
|
|
1291
|
-
let last_stop_sequence;
|
|
1292
|
-
let next_stop_sequence;
|
|
1293
|
-
if (segment.shape_at_stop) {
|
|
1294
|
-
stopCounter++;
|
|
1295
|
-
this_stop_sequence = stopCounter;
|
|
1296
|
-
}
|
|
1297
|
-
else {
|
|
1298
|
-
this_stop_sequence = null;
|
|
1231
|
+
// CREATE turf LineString OBJECT FOR GIVEN COORDINATES
|
|
1232
|
+
const line = turf.lineString(shapes.map((p) => {
|
|
1233
|
+
return [p.shape_pt_lon, p.shape_pt_lat];
|
|
1234
|
+
}));
|
|
1235
|
+
// DEFAULT step BETWEEN TWO POINTS ON PATH [km] - SHORT DISTANCE IMPACTS PROCESS DURATION
|
|
1236
|
+
const step = config_1.config.vehiclePositions.stepBetweenPoints;
|
|
1237
|
+
const distance = ruler.lineDistance((_m = line.geometry) === null || _m === void 0 ? void 0 : _m.coordinates);
|
|
1238
|
+
// TODO this should a class method
|
|
1239
|
+
const lineIterator = (i, cb) => {
|
|
1240
|
+
var _a;
|
|
1241
|
+
// end of iteration
|
|
1242
|
+
if (i >= distance) {
|
|
1243
|
+
return cb();
|
|
1299
1244
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
resultArr.push({
|
|
1317
|
-
index: resultArr.length,
|
|
1318
|
-
coordinates: [
|
|
1319
|
-
Math.round(shapes[shapes.length - 1].shape_pt_lon * 100000) / 100000,
|
|
1320
|
-
Math.round(shapes[shapes.length - 1].shape_pt_lat * 100000) / 100000,
|
|
1321
|
-
],
|
|
1322
|
-
last_stop_sequence: stopCounter,
|
|
1323
|
-
next_stop_sequence: stopCounter,
|
|
1324
|
-
shape_dist_traveled: Math.round(shapes[shapes.length - 1].shape_dist_traveled * 1000) / 1000,
|
|
1325
|
-
this_stop_sequence: stopCounter,
|
|
1245
|
+
// ADD ALL POINTS TO shapes_anchor_points
|
|
1246
|
+
shapesAnchorPoints.push({
|
|
1247
|
+
// RETURNS coordinates ALONG path WITH GIVER i (DISTANCE) IN 5 DECIMAL PLACES
|
|
1248
|
+
coordinates: ruler.along((_a = line.geometry) === null || _a === void 0 ? void 0 : _a.coordinates, i).map((c) => {
|
|
1249
|
+
return Math.round(c * 100000) / 100000;
|
|
1250
|
+
}),
|
|
1251
|
+
// shape_dist_traveled IS IMPORTANT FOR DECIDING LAST STOP
|
|
1252
|
+
shape_dist_traveled: Math.round(i * 1000) / 1000, // 1 METER PRECISSION
|
|
1253
|
+
});
|
|
1254
|
+
// next step
|
|
1255
|
+
lineIterator(i + step, cb);
|
|
1256
|
+
};
|
|
1257
|
+
return new Promise((resolve, reject) => {
|
|
1258
|
+
lineIterator(0, () => {
|
|
1259
|
+
resolve(shapesAnchorPoints);
|
|
1260
|
+
});
|
|
1326
1261
|
});
|
|
1327
|
-
return resultArr;
|
|
1328
1262
|
}
|
|
1329
1263
|
catch (err) {
|
|
1330
1264
|
helpers_1.log.error(err);
|
|
1331
1265
|
helpers_1.log.error(shapeId);
|
|
1332
|
-
return
|
|
1333
|
-
}
|
|
1334
|
-
};
|
|
1335
|
-
/**
|
|
1336
|
-
* Generates new shape points from segment of trip shape along original one
|
|
1337
|
-
* - preserving start and end shape points belonging to stops
|
|
1338
|
-
* - creates new set of shape points between stops to get same point distance along original shape
|
|
1339
|
-
*
|
|
1340
|
-
* @param {ISegmentShape[]} segmentsArr - Original shape points segment between two stops
|
|
1341
|
-
* @param {number} distance - Minimal distance for two consequent shape points
|
|
1342
|
-
* @returns {ISegmentShape[]} - Result array of new shape points
|
|
1343
|
-
*/
|
|
1344
|
-
this.divideSegmentLine = (segmentArr, distance = config_1.config.vehiclePositions.stepBetweenPoints) => {
|
|
1345
|
-
const shapeId = segmentArr[0].shape_id;
|
|
1346
|
-
const shapeCount = segmentArr.length;
|
|
1347
|
-
const startShapeDistTraveled = segmentArr[0].shape_dist_traveled;
|
|
1348
|
-
const endShapeDistTraveled = segmentArr[shapeCount - 1].shape_dist_traveled;
|
|
1349
|
-
const shapeDistLength = endShapeDistTraveled - startShapeDistTraveled;
|
|
1350
|
-
const segmentLine = turf.lineString(segmentArr.map((s) => {
|
|
1351
|
-
return [s.shape_pt_lon, s.shape_pt_lat];
|
|
1352
|
-
}));
|
|
1353
|
-
// because we dont believe source shape distances, rather compute length with turf.js
|
|
1354
|
-
const segmentLength = turf.length(segmentLine);
|
|
1355
|
-
const middlePointsCount = Math.floor(segmentLength / distance);
|
|
1356
|
-
const distanceOffset = (segmentLength - distance * middlePointsCount) / 2;
|
|
1357
|
-
// put first shape point
|
|
1358
|
-
const resultSegmentPoints = [
|
|
1359
|
-
Object.assign(Object.assign({}, segmentArr[0]), { shape_pt_sequence: 1 }),
|
|
1360
|
-
];
|
|
1361
|
-
// for each middle point create acording shape point with interpolated origin shape dist traveled
|
|
1362
|
-
for (let i = 0; i < middlePointsCount; i++) {
|
|
1363
|
-
const currentDistance = i * distance + distanceOffset;
|
|
1364
|
-
const currentDistDistance = (shapeDistLength / segmentLength) * currentDistance;
|
|
1365
|
-
const newPoint = turf.along(segmentLine, i * distance + distanceOffset);
|
|
1366
|
-
resultSegmentPoints.push({
|
|
1367
|
-
shape_id: shapeId,
|
|
1368
|
-
shape_at_stop: false,
|
|
1369
|
-
shape_pt_sequence: resultSegmentPoints.length + 1,
|
|
1370
|
-
shape_pt_lat: newPoint.geometry.coordinates[1],
|
|
1371
|
-
shape_pt_lon: newPoint.geometry.coordinates[0],
|
|
1372
|
-
shape_dist_traveled: startShapeDistTraveled + currentDistDistance,
|
|
1373
|
-
});
|
|
1266
|
+
return shapesAnchorPoints;
|
|
1374
1267
|
}
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
this.
|
|
1378
|
-
this.
|
|
1379
|
-
this.
|
|
1380
|
-
this.
|
|
1381
|
-
this.
|
|
1382
|
-
this.transformation = new transformations_1.VehiclePositionsTransformation();
|
|
1268
|
+
});
|
|
1269
|
+
this.modelPositions = new _1.VehiclePositionsPositionsModel();
|
|
1270
|
+
this.modelStops = new _1.VehiclePositionsStopsModel();
|
|
1271
|
+
this.modelRuns = new _1.VehiclePositionsRunsModel();
|
|
1272
|
+
this.transformationRuns = new VehiclePositionsRunsTransformation_1.VehiclePositionsRunsTransformation();
|
|
1273
|
+
this.modelTrips = new _1.VehiclePositionsTripsModel();
|
|
1274
|
+
this.transformation = new _1.VehiclePositionsTransformation();
|
|
1383
1275
|
this.delayComputationTripsModel = new models_1.RedisModel(ropid_gtfs_1.RopidGTFS.delayComputationTrips.name + "Model", {
|
|
1384
1276
|
decodeDataAfterGet: JSON.parse,
|
|
1385
1277
|
encodeDataBeforeSave: JSON.stringify,
|
|
1386
1278
|
isKeyConstructedFromData: true,
|
|
1387
1279
|
prefix: ropid_gtfs_1.RopidGTFS.delayComputationTrips.mongoCollectionName,
|
|
1388
1280
|
}, new golemio_validator_1.Validator(ropid_gtfs_1.RopidGTFS.delayComputationTrips.name + "ModelValidator", ropid_gtfs_1.RopidGTFS.delayComputationTrips.outputMongooseSchemaObject));
|
|
1389
|
-
this.runTripsModel = new models_1.RedisModel(vehicle_positions_1.VehiclePositions.
|
|
1281
|
+
this.runTripsModel = new models_1.RedisModel(vehicle_positions_1.VehiclePositions.runs_trips.name + "Model", {
|
|
1390
1282
|
decodeDataAfterGet: JSON.parse,
|
|
1391
1283
|
encodeDataBeforeSave: JSON.stringify,
|
|
1392
1284
|
isKeyConstructedFromData: false,
|
|
1393
|
-
prefix: vehicle_positions_1.VehiclePositions.
|
|
1394
|
-
}, new golemio_validator_1.Validator(vehicle_positions_1.VehiclePositions.
|
|
1285
|
+
prefix: vehicle_positions_1.VehiclePositions.runs_trips.namespacePrefix,
|
|
1286
|
+
}, new golemio_validator_1.Validator(vehicle_positions_1.VehiclePositions.runs_trips.name + "ModelValidator", vehicle_positions_1.VehiclePositions.runs_trips.outputMongooseSchemaObject));
|
|
1395
1287
|
this.queuePrefix = config_1.config.RABBIT_EXCHANGE_NAME + "." + vehicle_positions_1.VehiclePositions.name.toLowerCase();
|
|
1396
1288
|
this.gtfsRtModel = new models_1.RedisModel("GTFSRealTimeModel", {
|
|
1397
1289
|
isKeyConstructedFromData: false,
|
|
1398
1290
|
prefix: "files:gtfsRt",
|
|
1399
1291
|
});
|
|
1400
|
-
this.tripStopsModel = new models_1.RedisModel(vehicle_positions_1.VehiclePositions.tripStops.name + "Model", {
|
|
1401
|
-
decodeDataAfterGet: JSON.parse,
|
|
1402
|
-
encodeDataBeforeSave: JSON.stringify,
|
|
1403
|
-
isKeyConstructedFromData: false,
|
|
1404
|
-
prefix: vehicle_positions_1.VehiclePositions.tripStops.namespacePrefix,
|
|
1405
|
-
}, new golemio_validator_1.Validator(vehicle_positions_1.VehiclePositions.tripStops.name + "ModelValidator", vehicle_positions_1.VehiclePositions.tripStops.outputMongooseSchemaObject));
|
|
1406
|
-
this.modelGTFSTrips = new RopidGTFSTripsModel_1.RopidGTFSTripsModel();
|
|
1407
1292
|
this.modelGTFSStopTimes = new RopidGTFSStopTimesModel_1.RopidGTFSStopTimesModel();
|
|
1293
|
+
this.modelGTFSTrips = new RopidGTFSTripsModel_1.RopidGTFSTripsModel();
|
|
1408
1294
|
// Create trips upsert queue for preventing transaction deadlocks
|
|
1409
1295
|
this.upsertTripsFQ = fastq_1.default.promise(this.modelTrips.bulkUpsert, 1);
|
|
1410
1296
|
}
|