@golemio/pid 2.1.13-dev.510658546 → 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} +31 -54
- 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 +231 -366
- 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 -30
- package/dist/integration-engine/vehicle-positions/VehiclePositionsUtils.js +0 -58
- 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,76 +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, gtfsTripIds]) => __awaiter(this, void 0, void 0, function* () {
|
|
178
|
-
const tripStops = yield acc;
|
|
179
|
-
try {
|
|
180
|
-
tripStops[blockId] = yield this.setAndReturnTripStopsSchedule(blockId, [...gtfsTripIds]);
|
|
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
|
-
if (trip.gtfs_block_id) {
|
|
192
|
-
// Determine current position tracking status
|
|
193
|
-
currentPosition.tracking = VehiclePositionsUtils_1.VehiclePositionsUtils.determineTrackingStatus(trip.gtfs_trip_id, tripStopsSchedulesByBlockIds[trip.gtfs_block_id], currentPosition);
|
|
194
|
-
}
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
if (!currentPosition) {
|
|
198
|
-
continue;
|
|
199
166
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (shouldCreateNewPosition) {
|
|
203
|
-
// duplicate position with new created trip for second trip
|
|
167
|
+
else {
|
|
168
|
+
// duplicate position with new created trip for second train trip
|
|
204
169
|
const newPosition = Object.assign({}, currentPosition);
|
|
205
170
|
newPosition.trips_id = trip.id;
|
|
206
|
-
newPosition.tracking = newPositionTrackingStatus;
|
|
207
171
|
inputData.positions.push(newPosition);
|
|
208
172
|
}
|
|
209
173
|
}
|
|
210
174
|
yield this.modelPositions.save(inputData.positions);
|
|
211
175
|
// successfully updated gtfs ids
|
|
212
|
-
for (let i = 0, chunkSize = 100, imax =
|
|
176
|
+
for (let i = 0, chunkSize = 100, imax = foundedTripsPromiseValues.length; i < imax; i += chunkSize) {
|
|
213
177
|
yield this.sendMessageToExchange("workers." + this.queuePrefix + ".updateDelay", JSON.stringify({
|
|
214
178
|
positions: [],
|
|
215
|
-
updatedTrips:
|
|
179
|
+
updatedTrips: foundedTripsPromiseValues.slice(i, i + chunkSize),
|
|
216
180
|
}));
|
|
217
181
|
}
|
|
218
182
|
// gtfsId updating errors
|
|
219
|
-
for (let i = 0, imax =
|
|
220
|
-
helpers_1.IntegrationErrorHandler.handle(
|
|
183
|
+
for (let i = 0, imax = foundedTripsPromiseErrors.length; i < imax; i++) {
|
|
184
|
+
helpers_1.IntegrationErrorHandler.handle(foundedTripsPromiseErrors[i]);
|
|
221
185
|
}
|
|
222
186
|
});
|
|
223
|
-
this.generateGtfsRt = () => __awaiter(this, void 0, void 0, function* () {
|
|
187
|
+
this.generateGtfsRt = (msg) => __awaiter(this, void 0, void 0, function* () {
|
|
224
188
|
const results = yield this.modelTrips.findAllForGTFSRt();
|
|
225
189
|
const updatesMessage = gtfsRealtime.FeedMessage.create();
|
|
226
190
|
const positionsMessage = gtfsRealtime.FeedMessage.create();
|
|
@@ -241,7 +205,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
241
205
|
tripId: r.gtfs_trip_id,
|
|
242
206
|
routeId: r.gtfs_route_id,
|
|
243
207
|
};
|
|
244
|
-
const vehicleDescriptor = Object.assign({ id: r.gtfs_route_type ===
|
|
208
|
+
const vehicleDescriptor = Object.assign({ id: r.gtfs_route_type === _1.GTFSRouteTypeEnum.TRAIN
|
|
245
209
|
? "train-" + r.cis_trip_number
|
|
246
210
|
: "service-" + r.gtfs_route_type + "-" + r.vehicle_registration_number }, (r.vehicle_registration_number && {
|
|
247
211
|
label: r.vehicle_registration_number,
|
|
@@ -370,67 +334,32 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
370
334
|
const tripIds = inputData.updatedTrips.map((trip) => trip.id);
|
|
371
335
|
if (((_b = inputData.positions) === null || _b === void 0 ? void 0 : _b.length) > 0) {
|
|
372
336
|
// unique ids in input data in key-value (id-positions) structure
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
}
|
|
377
|
-
// unique
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
if (!trip.gtfs_block_id) {
|
|
383
|
-
continue;
|
|
384
|
-
}
|
|
385
|
-
if (!tripsIdsByBlockIds[trip.gtfs_block_id]) {
|
|
386
|
-
tripsIdsByBlockIds[trip.gtfs_block_id] = trip.id;
|
|
337
|
+
const positionsByIds = inputData.positions.reduce((acc, position) => {
|
|
338
|
+
acc[position.trips_id] = position;
|
|
339
|
+
return acc;
|
|
340
|
+
}, {});
|
|
341
|
+
// unique block_id's and its parent input trips_id in key-value (block_id-trips_id) structure
|
|
342
|
+
const blockIdsToParentTripsId = inputData.updatedTrips.reduce((acc, currentTrip) => {
|
|
343
|
+
if (!acc[currentTrip.gtfs_block_id]) {
|
|
344
|
+
// init key value pair if not exists
|
|
345
|
+
acc[currentTrip.gtfs_block_id] = currentTrip.id;
|
|
387
346
|
}
|
|
388
347
|
else {
|
|
389
|
-
// save only the shorter trip_id (it is the raw input id with no suffixes)
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
gtfsTripIdsByBlockIds[trip.gtfs_block_id] = new Set();
|
|
395
|
-
}
|
|
396
|
-
if (trip.gtfs_trip_id) {
|
|
397
|
-
gtfsTripIdsByBlockIds[trip.gtfs_block_id].add(trip.gtfs_trip_id);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
// Get cached schedule for each unique block_id
|
|
401
|
-
const tripStopsSchedulesByBlockIds = yield Object.entries(gtfsTripIdsByBlockIds).reduce((acc, [blockId, gtfsTripIds]) => __awaiter(this, void 0, void 0, function* () {
|
|
402
|
-
const tripStops = yield acc;
|
|
403
|
-
try {
|
|
404
|
-
const schedule = yield this.setAndReturnTripStopsSchedule(blockId, [...gtfsTripIds]);
|
|
405
|
-
tripStops[blockId] = schedule;
|
|
406
|
-
}
|
|
407
|
-
catch (err) {
|
|
408
|
-
helpers_1.IntegrationErrorHandler.handle(err);
|
|
348
|
+
// otherwise save only the shorter trip_id (it is the raw input id with no suffixes)
|
|
349
|
+
acc[currentTrip.gtfs_block_id] =
|
|
350
|
+
acc[currentTrip.gtfs_block_id] > currentTrip.id
|
|
351
|
+
? currentTrip.id
|
|
352
|
+
: acc[currentTrip.gtfs_block_id];
|
|
409
353
|
}
|
|
410
354
|
return acc;
|
|
411
|
-
}
|
|
355
|
+
}, {});
|
|
412
356
|
// duplicate positions for trips with block_ids
|
|
413
357
|
for (const trip of inputData.updatedTrips) {
|
|
414
|
-
if (positionsByIds[trip.id]) {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
}
|
|
419
|
-
continue;
|
|
420
|
-
}
|
|
421
|
-
const currentPosition = inputData.positions.find((position) => {
|
|
422
|
-
return position.trips_id === tripsIdsByBlockIds[trip.gtfs_block_id];
|
|
423
|
-
});
|
|
424
|
-
if (!currentPosition) {
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
|
-
// Determine position duplication and new position tracking status
|
|
428
|
-
const { shouldCreateNewPosition, trackingStatus: newPositionTrackingStatus } = VehiclePositionsUtils_1.VehiclePositionsUtils.determineNewPositionTracking(tripStopsSchedulesByBlockIds[trip.gtfs_block_id], trip, currentPosition);
|
|
429
|
-
if (shouldCreateNewPosition) {
|
|
430
|
-
// duplicate position with new created trip for second trip
|
|
431
|
-
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
|
+
}));
|
|
432
362
|
newPosition.trips_id = trip.id;
|
|
433
|
-
newPosition.tracking = newPositionTrackingStatus;
|
|
434
363
|
inputData.positions.push(newPosition);
|
|
435
364
|
}
|
|
436
365
|
}
|
|
@@ -453,7 +382,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
453
382
|
helpers_1.log.debug("Delay Computation data (Redis) was not found. (gtfsTripId = " + trip.gtfs_trip_id + ")");
|
|
454
383
|
try {
|
|
455
384
|
const gtfs = yield this.getResultObjectForDelayCalculation(trip.gtfs_trip_id);
|
|
456
|
-
yield this.delayComputationTripsModel.set("trip_id", gtfs,
|
|
385
|
+
yield this.delayComputationTripsModel.set("trip_id", gtfs, 7200);
|
|
457
386
|
trip.gtfsData = gtfs;
|
|
458
387
|
}
|
|
459
388
|
catch (err) {
|
|
@@ -470,7 +399,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
470
399
|
}));
|
|
471
400
|
}
|
|
472
401
|
catch (err) {
|
|
473
|
-
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);
|
|
474
403
|
}
|
|
475
404
|
}
|
|
476
405
|
});
|
|
@@ -527,8 +456,9 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
527
456
|
* @returns {void}
|
|
528
457
|
*/
|
|
529
458
|
this.updateRunsGTFSTripId = (msg) => __awaiter(this, void 0, void 0, function* () {
|
|
459
|
+
var e_1, _e;
|
|
530
460
|
const input = JSON.parse(msg.content.toString());
|
|
531
|
-
const schedule = yield this.
|
|
461
|
+
const schedule = yield this.getScheduledTrips(input.run);
|
|
532
462
|
const { actual_stop_timestamp_scheduled: actualStopTimestampScheduled, msg_timestamp: msgTimestamp, events: event, } = input.run_message;
|
|
533
463
|
const delayMsg = {
|
|
534
464
|
updatedTrips: [],
|
|
@@ -543,51 +473,62 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
543
473
|
}
|
|
544
474
|
return;
|
|
545
475
|
}
|
|
546
|
-
if (
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
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
|
+
}
|
|
571
529
|
}
|
|
572
530
|
else {
|
|
573
|
-
|
|
574
|
-
yield this.modelPositions.upsertRunPosition(input, gtfsCurrentTrip, isCurrentTripTracking);
|
|
575
|
-
delayMsg.updatedTrips.push(currentTrip);
|
|
576
|
-
}
|
|
577
|
-
// last/next gtfs trip for run
|
|
578
|
-
const gtfsLastNextTrips = schedule.filter((el) => {
|
|
579
|
-
return (((asts.clone().subtract(15, "minutes") <= (0, moment_timezone_1.default)(el.end_timestamp) && (0, moment_timezone_1.default)(el.end_timestamp) <= asts) ||
|
|
580
|
-
(asts <= (0, moment_timezone_1.default)(el.start_timestamp) && (0, moment_timezone_1.default)(el.start_timestamp) <= asts.clone().add(60, "minutes"))) &&
|
|
581
|
-
el.trip_id !== (gtfsCurrentTrip === null || gtfsCurrentTrip === void 0 ? void 0 : gtfsCurrentTrip.trip_id));
|
|
582
|
-
});
|
|
583
|
-
for (const gtfsTrip of gtfsLastNextTrips) {
|
|
584
|
-
const trip = yield this.modelTrips.upsertRunTrip(input, gtfsTrip);
|
|
585
|
-
yield this.modelPositions.upsertRunPosition(input, gtfsTrip, false);
|
|
586
|
-
delayMsg.updatedTrips.push(trip);
|
|
587
|
-
}
|
|
588
|
-
// send to updateDelay only if there are some trips updated
|
|
589
|
-
if (delayMsg.updatedTrips.length > 0) {
|
|
590
|
-
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)}`);
|
|
591
532
|
}
|
|
592
533
|
});
|
|
593
534
|
/**
|
|
@@ -617,7 +558,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
617
558
|
*
|
|
618
559
|
* @returns {string[]} array of tripIds
|
|
619
560
|
*/
|
|
620
|
-
this.
|
|
561
|
+
this.getScheduledTrips = (scheduleData) => __awaiter(this, void 0, void 0, function* () {
|
|
621
562
|
const { route_id, run_number, msg_last_timestamp } = scheduleData;
|
|
622
563
|
const scheduledTripIds = yield this.runTripsModel.get(`${route_id}_${run_number}`);
|
|
623
564
|
if (!(scheduledTripIds === null || scheduledTripIds === void 0 ? void 0 : scheduledTripIds.schedule)) {
|
|
@@ -627,36 +568,11 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
627
568
|
el.start_timestamp = (0, moment_timezone_1.default)(el.start_timestamp).tz("Europe/Prague").format();
|
|
628
569
|
el.end_timestamp = (0, moment_timezone_1.default)(el.end_timestamp).tz("Europe/Prague").format();
|
|
629
570
|
});
|
|
630
|
-
yield this.runTripsModel.set(`${route_id}_${run_number}`, { schedule: result },
|
|
571
|
+
yield this.runTripsModel.set(`${route_id}_${run_number}`, { schedule: result }, 21600);
|
|
631
572
|
return result;
|
|
632
573
|
}
|
|
633
574
|
return scheduledTripIds.schedule;
|
|
634
575
|
});
|
|
635
|
-
/**
|
|
636
|
-
* Get trip stops schedule by block id
|
|
637
|
-
*
|
|
638
|
-
* @param {string} blockId - Target gtfs block id
|
|
639
|
-
* @param {string} tripIds - List of inserted gtfs trip ids
|
|
640
|
-
*/
|
|
641
|
-
this.setAndReturnTripStopsSchedule = (blockId, tripIds) => __awaiter(this, void 0, void 0, function* () {
|
|
642
|
-
const schedule = yield this.tripStopsModel.get(blockId);
|
|
643
|
-
if (schedule) {
|
|
644
|
-
return schedule;
|
|
645
|
-
}
|
|
646
|
-
try {
|
|
647
|
-
const tripStops = yield this.modelGTFSStopTimes.findTripStops(tripIds);
|
|
648
|
-
const tripStopsSchedule = tripStops.reduce((acc, curr) => {
|
|
649
|
-
acc[curr.trip_id] = { trip_stops: curr.trip_stops };
|
|
650
|
-
return acc;
|
|
651
|
-
}, {});
|
|
652
|
-
yield this.tripStopsModel.set(blockId, tripStopsSchedule, VehiclePositionsUtils_1.VehiclePositionsUtils.TRIP_STOPS_CACHE_TTL);
|
|
653
|
-
return tripStopsSchedule;
|
|
654
|
-
}
|
|
655
|
-
catch (err) {
|
|
656
|
-
helpers_1.log.warn("Unable to retrieve trip stops", err);
|
|
657
|
-
return {};
|
|
658
|
-
}
|
|
659
|
-
});
|
|
660
576
|
/**
|
|
661
577
|
* Takes all newly computed positions and saves it, then save the last ones to the trips
|
|
662
578
|
*
|
|
@@ -764,9 +680,9 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
764
680
|
return PositionHandlerEnum.DO_NOTHING;
|
|
765
681
|
if (position.is_canceled)
|
|
766
682
|
return PositionHandlerEnum.CANCELED;
|
|
767
|
-
if (position.lat && position.lng && position.tracking ===
|
|
683
|
+
if (position.lat && position.lng && position.tracking === 2)
|
|
768
684
|
return PositionHandlerEnum.TRACKING;
|
|
769
|
-
if (position.tracking !==
|
|
685
|
+
if (position.tracking !== 2)
|
|
770
686
|
return PositionHandlerEnum.NOT_TRACKING;
|
|
771
687
|
return PositionHandlerEnum.NOT_TRACKING;
|
|
772
688
|
};
|
|
@@ -816,7 +732,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
816
732
|
}
|
|
817
733
|
else {
|
|
818
734
|
// if there is tracking 2 position with same origin_timestamp then this position is duplicate
|
|
819
|
-
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)
|
|
820
736
|
? const_1.StatePositionEnum.DUPLICATE
|
|
821
737
|
: const_1.StatePositionEnum.AFTER_TRACK;
|
|
822
738
|
const lastShapesAnchorPoint = tripPositions.gtfsData.shapes_anchor_points[tripPositions.gtfsData.shapes_anchor_points.length - 1];
|
|
@@ -909,6 +825,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
909
825
|
.valueOf();
|
|
910
826
|
};
|
|
911
827
|
// FIND ALL SHAPE POINTS IN POLYGON CIRCLE, GET SEGMENTS WITH CONSEQUENTING POINTS
|
|
828
|
+
// TODO this should a class method
|
|
912
829
|
this.getShapePointsAroundPosition = (tripShapePoints, radius) => __awaiter(this, void 0, void 0, function* () {
|
|
913
830
|
const ptsInRadius = [];
|
|
914
831
|
let segmentIndex = 0;
|
|
@@ -1066,9 +983,9 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1066
983
|
if (Math.abs(timeRealDiff) < Math.abs(minTimeRealDiff)) {
|
|
1067
984
|
minTimeRealDiff = timeRealDiff;
|
|
1068
985
|
// push trip into nearest at_stop shape anchor point if trip "P" event (tram) / "V" event (bus)
|
|
1069
|
-
if (((gtfsRouteType ===
|
|
986
|
+
if (((gtfsRouteType === _1.GTFSRouteTypeEnum.TRAM &&
|
|
1070
987
|
currentPosition.properties.tcp_event === const_1.TCPEventEnum.ARRIVAL_ANNOUNCED) ||
|
|
1071
|
-
(gtfsRouteType ===
|
|
988
|
+
(gtfsRouteType === _1.GTFSRouteTypeEnum.BUS && currentPosition.properties.tcp_event === const_1.TCPEventEnum.V)) &&
|
|
1072
989
|
thisClosestPoint.this_stop_sequence === null) {
|
|
1073
990
|
let movingShapePointIndex = thisClosestPoint.index;
|
|
1074
991
|
while (thisClosestPoint.this_stop_sequence === null && movingShapePointIndex < lastTripShapePoint.index) {
|
|
@@ -1083,7 +1000,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1083
1000
|
statePosition = const_1.StatePositionEnum.ON_TRACK;
|
|
1084
1001
|
}
|
|
1085
1002
|
// if tram position has "V" avent tram is after track
|
|
1086
|
-
if (gtfsRouteType ===
|
|
1003
|
+
if (gtfsRouteType === _1.GTFSRouteTypeEnum.TRAM && currentPosition.properties.tcp_event === const_1.TCPEventEnum.V) {
|
|
1087
1004
|
statePosition = const_1.StatePositionEnum.AFTER_TRACK;
|
|
1088
1005
|
thisClosestPoint = lastTripShapePoint;
|
|
1089
1006
|
timeDelay = null;
|
|
@@ -1145,17 +1062,17 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1145
1062
|
* @returns {IPositionToUpdate} - Position object to update
|
|
1146
1063
|
*/
|
|
1147
1064
|
this.getEstimatedPoint = (tripGtfsData, currentPosition, context, startDayTimestamp, gtfsRouteType) => __awaiter(this, void 0, void 0, function* () {
|
|
1148
|
-
var
|
|
1065
|
+
var _f, _g, _h, _j, _k, _l;
|
|
1149
1066
|
// init radius around GPS position ( 200 meters radius, 16 points polygon aka circle)
|
|
1150
1067
|
const radius = turf.circle(currentPosition, 0.2, { steps: 16 });
|
|
1151
1068
|
//Initial value
|
|
1152
1069
|
let estimatedPoint = Object.assign({ id: currentPosition.properties.id, state_position: const_1.StatePositionEnum.OFF_TRACK, state_process: const_1.StateProcessEnum.PROCESSED, tcp_event: currentPosition.properties.tcp_event }, (context &&
|
|
1153
|
-
((
|
|
1154
|
-
shape_dist_traveled: (
|
|
1155
|
-
last_stop_arrival_time: (
|
|
1156
|
-
last_stop_departure_time: (
|
|
1157
|
-
last_stop_sequence: (
|
|
1158
|
-
last_stop_id: (
|
|
1070
|
+
((_f = context.lastPositionTracking) === null || _f === void 0 ? void 0 : _f.properties.last_stop_sequence) && {
|
|
1071
|
+
shape_dist_traveled: (_g = context.lastPositionTracking) === null || _g === void 0 ? void 0 : _g.properties.shape_dist_traveled,
|
|
1072
|
+
last_stop_arrival_time: (_h = context.lastPositionTracking) === null || _h === void 0 ? void 0 : _h.properties.last_stop_arrival_time,
|
|
1073
|
+
last_stop_departure_time: (_j = context.lastPositionTracking) === null || _j === void 0 ? void 0 : _j.properties.last_stop_departure_time,
|
|
1074
|
+
last_stop_sequence: (_k = context.lastPositionTracking) === null || _k === void 0 ? void 0 : _k.properties.last_stop_sequence,
|
|
1075
|
+
last_stop_id: (_l = context.lastPositionTracking) === null || _l === void 0 ? void 0 : _l.properties.last_stop_id,
|
|
1159
1076
|
}));
|
|
1160
1077
|
// returns array of segments (row of points) of shape anchor points around gps
|
|
1161
1078
|
const ptsInRadius = yield this.getShapePointsAroundPosition(tripGtfsData.shapes_anchor_points, radius);
|
|
@@ -1186,13 +1103,59 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1186
1103
|
if (!stopTimes || !stopTimes.stop_times || stopTimes.stop_times.length === 0) {
|
|
1187
1104
|
throw new Error(`"trip.stop_times" was not found for id ${tripId}.`);
|
|
1188
1105
|
}
|
|
1189
|
-
|
|
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;
|
|
1190
1111
|
// MAKING COPY
|
|
1191
1112
|
const shapePoints = [];
|
|
1192
1113
|
// const to determine shape points of stops (in meters)
|
|
1193
|
-
const distanceBefore =
|
|
1194
|
-
const distanceAfter =
|
|
1195
|
-
|
|
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
|
+
}
|
|
1196
1159
|
let bearing = 0;
|
|
1197
1160
|
// add bearing from shape computed for previous shapePoint
|
|
1198
1161
|
if (i > 0) {
|
|
@@ -1210,37 +1173,13 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1210
1173
|
bearing = shapePoints[i - 1].bearing;
|
|
1211
1174
|
}
|
|
1212
1175
|
}
|
|
1213
|
-
// init values
|
|
1214
|
-
let thisStopSequence = null;
|
|
1215
|
-
let lastStopSequence = shapesGeometryAnchorPoints[i].last_stop_sequence;
|
|
1216
|
-
let nextStopSequence = shapesGeometryAnchorPoints[i].next_stop_sequence;
|
|
1217
|
-
// these are origin stop_times shape point fron shapes table, clearly at stops points
|
|
1218
|
-
if (shapesGeometryAnchorPoints[i].this_stop_sequence) {
|
|
1219
|
-
thisStopSequence = shapesGeometryAnchorPoints[i].this_stop_sequence;
|
|
1220
|
-
}
|
|
1221
|
-
// if is shape anchor point in close distance AFTER LAST stop, then set it also AT STOP
|
|
1222
|
-
else if (i > 0 &&
|
|
1223
|
-
shapesGeometryAnchorPoints[i].shape_dist_traveled -
|
|
1224
|
-
stopTimes.stop_times[shapesGeometryAnchorPoints[i].last_stop_sequence - 1].shape_dist_traveled <=
|
|
1225
|
-
distanceAfter) {
|
|
1226
|
-
thisStopSequence = shapesGeometryAnchorPoints[i].last_stop_sequence;
|
|
1227
|
-
}
|
|
1228
|
-
// if is shape anchor point in close distance BEFORE NEXT stop, then set it also AT STOP
|
|
1229
|
-
else if (i < shapesGeometryAnchorPoints.length - 1 &&
|
|
1230
|
-
stopTimes.stop_times[shapesGeometryAnchorPoints[i].next_stop_sequence - 1].shape_dist_traveled -
|
|
1231
|
-
shapesGeometryAnchorPoints[i].shape_dist_traveled <=
|
|
1232
|
-
distanceBefore) {
|
|
1233
|
-
thisStopSequence = shapesGeometryAnchorPoints[i].next_stop_sequence;
|
|
1234
|
-
lastStopSequence = shapesGeometryAnchorPoints[i].next_stop_sequence;
|
|
1235
|
-
nextStopSequence = Math.min(shapesGeometryAnchorPoints[i].next_stop_sequence + 1, stopTimes.stop_times.length);
|
|
1236
|
-
}
|
|
1237
1176
|
const distanceFromLastStop = Math.round((shapesGeometryAnchorPoints[i].shape_dist_traveled -
|
|
1238
1177
|
stopTimes.stop_times[lastStopSequence - 1].shape_dist_traveled) *
|
|
1239
1178
|
1000) / 1000;
|
|
1240
1179
|
// if is trip at stop than set departure by this stop
|
|
1241
1180
|
// between stops do linear interpolation from departure from last stop and arrival of next stop
|
|
1242
|
-
const timeScheduledSeconds =
|
|
1243
|
-
? stopTimes.stop_times[lastStopSequence - 1].
|
|
1181
|
+
const timeScheduledSeconds = stopNearby.at_stop
|
|
1182
|
+
? stopTimes.stop_times[lastStopSequence - 1].departure_time_seconds
|
|
1244
1183
|
: stopTimes.stop_times[lastStopSequence - 1].departure_time_seconds +
|
|
1245
1184
|
Math.round(((stopTimes.stop_times[nextStopSequence - 1].arrival_time_seconds -
|
|
1246
1185
|
stopTimes.stop_times[lastStopSequence - 1].departure_time_seconds) *
|
|
@@ -1249,22 +1188,29 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1249
1188
|
stopTimes.stop_times[lastStopSequence - 1].shape_dist_traveled));
|
|
1250
1189
|
shapePoints.push({
|
|
1251
1190
|
index: i,
|
|
1252
|
-
at_stop:
|
|
1191
|
+
at_stop: stopNearby.at_stop,
|
|
1253
1192
|
bearing,
|
|
1254
1193
|
coordinates: shapesGeometryAnchorPoints[i].coordinates,
|
|
1255
1194
|
distance_from_last_stop: distanceFromLastStop,
|
|
1256
1195
|
last_stop_sequence: lastStopSequence,
|
|
1257
1196
|
next_stop_sequence: nextStopSequence,
|
|
1258
|
-
shape_dist_traveled:
|
|
1259
|
-
this_stop_sequence:
|
|
1197
|
+
shape_dist_traveled: shapesGeometryAnchorPoints[i].shape_dist_traveled,
|
|
1198
|
+
this_stop_sequence: stopNearby.at_stop ? stopNearby.this_stop_sequence : null,
|
|
1260
1199
|
time_scheduled_seconds: timeScheduledSeconds,
|
|
1261
1200
|
});
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
trip_id: tripId,
|
|
1265
|
-
stop_times: stopTimes.stop_times,
|
|
1266
|
-
shapes_anchor_points: shapePoints,
|
|
1201
|
+
// next step
|
|
1202
|
+
shapesAnchorPointsIterator(i + 1, cb);
|
|
1267
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
|
+
});
|
|
1268
1214
|
}
|
|
1269
1215
|
catch (err) {
|
|
1270
1216
|
helpers_1.log.error(err);
|
|
@@ -1276,156 +1222,75 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
|
|
|
1276
1222
|
*
|
|
1277
1223
|
* @param {string} shapeId - GTFS shape id
|
|
1278
1224
|
* @param {ITransformedTripShape[]} shapes - GTFS shape points
|
|
1279
|
-
* @param {IStopTime[]} stops
|
|
1280
1225
|
* @returns {IShapeGeometryAnchorPoint[]} - Result array of geometry points along trip track shape
|
|
1281
1226
|
*/
|
|
1282
|
-
this.getShapesGeometryAnchorPoints = (shapeId, shapes,
|
|
1227
|
+
this.getShapesGeometryAnchorPoints = (shapeId, shapes) => __awaiter(this, void 0, void 0, function* () {
|
|
1228
|
+
var _m;
|
|
1229
|
+
const shapesAnchorPoints = [];
|
|
1283
1230
|
try {
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
if (currentSegment.length) {
|
|
1300
|
-
segmentShapes.push(currentSegment);
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
let segmentArr = [];
|
|
1304
|
-
// concat arrays of stop divided segments with distributed shape points
|
|
1305
|
-
for (const segment of segmentShapes) {
|
|
1306
|
-
segmentArr = [...segmentArr, ...this.divideSegmentLine(segment)];
|
|
1307
|
-
}
|
|
1308
|
-
// Make initial shapesGeometryAnchorPoints
|
|
1309
|
-
let stopCounter = 0;
|
|
1310
|
-
const resultArr = segmentArr.map((segment, index) => {
|
|
1311
|
-
let this_stop_sequence;
|
|
1312
|
-
let last_stop_sequence;
|
|
1313
|
-
let next_stop_sequence;
|
|
1314
|
-
if (segment.shape_at_stop) {
|
|
1315
|
-
stopCounter++;
|
|
1316
|
-
this_stop_sequence = stopCounter;
|
|
1317
|
-
}
|
|
1318
|
-
else {
|
|
1319
|
-
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();
|
|
1320
1244
|
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
resultArr.push({
|
|
1338
|
-
index: resultArr.length,
|
|
1339
|
-
coordinates: [
|
|
1340
|
-
Math.round(shapes[shapes.length - 1].shape_pt_lon * 100000) / 100000,
|
|
1341
|
-
Math.round(shapes[shapes.length - 1].shape_pt_lat * 100000) / 100000,
|
|
1342
|
-
],
|
|
1343
|
-
last_stop_sequence: stopCounter,
|
|
1344
|
-
next_stop_sequence: stopCounter,
|
|
1345
|
-
shape_dist_traveled: Math.round(shapes[shapes.length - 1].shape_dist_traveled * 1000) / 1000,
|
|
1346
|
-
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
|
+
});
|
|
1347
1261
|
});
|
|
1348
|
-
return resultArr;
|
|
1349
1262
|
}
|
|
1350
1263
|
catch (err) {
|
|
1351
1264
|
helpers_1.log.error(err);
|
|
1352
1265
|
helpers_1.log.error(shapeId);
|
|
1353
|
-
return
|
|
1266
|
+
return shapesAnchorPoints;
|
|
1354
1267
|
}
|
|
1355
|
-
};
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
* @param {number} distance - Minimal distance for two consequent shape points
|
|
1363
|
-
* @returns {ISegmentShape[]} - Result array of new shape points
|
|
1364
|
-
*/
|
|
1365
|
-
this.divideSegmentLine = (segmentArr, distance = config_1.config.vehiclePositions.stepBetweenPoints) => {
|
|
1366
|
-
const shapeId = segmentArr[0].shape_id;
|
|
1367
|
-
const shapeCount = segmentArr.length;
|
|
1368
|
-
const startShapeDistTraveled = segmentArr[0].shape_dist_traveled;
|
|
1369
|
-
const endShapeDistTraveled = segmentArr[shapeCount - 1].shape_dist_traveled;
|
|
1370
|
-
const shapeDistLength = endShapeDistTraveled - startShapeDistTraveled;
|
|
1371
|
-
const segmentLine = turf.lineString(segmentArr.map((s) => {
|
|
1372
|
-
return [s.shape_pt_lon, s.shape_pt_lat];
|
|
1373
|
-
}));
|
|
1374
|
-
// because we dont believe source shape distances, rather compute length with turf.js
|
|
1375
|
-
const segmentLength = turf.length(segmentLine);
|
|
1376
|
-
const middlePointsCount = Math.floor(segmentLength / distance);
|
|
1377
|
-
const distanceOffset = (segmentLength - distance * middlePointsCount) / 2;
|
|
1378
|
-
// put first shape point
|
|
1379
|
-
const resultSegmentPoints = [
|
|
1380
|
-
Object.assign(Object.assign({}, segmentArr[0]), { shape_pt_sequence: 1 }),
|
|
1381
|
-
];
|
|
1382
|
-
// for each middle point create acording shape point with interpolated origin shape dist traveled
|
|
1383
|
-
for (let i = 0; i < middlePointsCount; i++) {
|
|
1384
|
-
const currentDistance = i * distance + distanceOffset;
|
|
1385
|
-
const currentDistDistance = (shapeDistLength / segmentLength) * currentDistance;
|
|
1386
|
-
const newPoint = turf.along(segmentLine, i * distance + distanceOffset);
|
|
1387
|
-
resultSegmentPoints.push({
|
|
1388
|
-
shape_id: shapeId,
|
|
1389
|
-
shape_at_stop: false,
|
|
1390
|
-
shape_pt_sequence: resultSegmentPoints.length + 1,
|
|
1391
|
-
shape_pt_lat: newPoint.geometry.coordinates[1],
|
|
1392
|
-
shape_pt_lon: newPoint.geometry.coordinates[0],
|
|
1393
|
-
shape_dist_traveled: startShapeDistTraveled + currentDistDistance,
|
|
1394
|
-
});
|
|
1395
|
-
}
|
|
1396
|
-
return resultSegmentPoints;
|
|
1397
|
-
};
|
|
1398
|
-
this.modelPositions = new models_2.VehiclePositionsPositionsModel();
|
|
1399
|
-
this.modelStops = new models_2.VehiclePositionsStopsModel();
|
|
1400
|
-
this.modelRuns = new models_2.VehiclePositionsRunsModel();
|
|
1401
|
-
this.transformationRuns = new transformations_1.VehiclePositionsRunsTransformation();
|
|
1402
|
-
this.modelTrips = new models_2.VehiclePositionsTripsModel();
|
|
1403
|
-
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();
|
|
1404
1275
|
this.delayComputationTripsModel = new models_1.RedisModel(ropid_gtfs_1.RopidGTFS.delayComputationTrips.name + "Model", {
|
|
1405
1276
|
decodeDataAfterGet: JSON.parse,
|
|
1406
1277
|
encodeDataBeforeSave: JSON.stringify,
|
|
1407
1278
|
isKeyConstructedFromData: true,
|
|
1408
1279
|
prefix: ropid_gtfs_1.RopidGTFS.delayComputationTrips.mongoCollectionName,
|
|
1409
1280
|
}, new golemio_validator_1.Validator(ropid_gtfs_1.RopidGTFS.delayComputationTrips.name + "ModelValidator", ropid_gtfs_1.RopidGTFS.delayComputationTrips.outputMongooseSchemaObject));
|
|
1410
|
-
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", {
|
|
1411
1282
|
decodeDataAfterGet: JSON.parse,
|
|
1412
1283
|
encodeDataBeforeSave: JSON.stringify,
|
|
1413
1284
|
isKeyConstructedFromData: false,
|
|
1414
|
-
prefix: vehicle_positions_1.VehiclePositions.
|
|
1415
|
-
}, 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));
|
|
1416
1287
|
this.queuePrefix = config_1.config.RABBIT_EXCHANGE_NAME + "." + vehicle_positions_1.VehiclePositions.name.toLowerCase();
|
|
1417
1288
|
this.gtfsRtModel = new models_1.RedisModel("GTFSRealTimeModel", {
|
|
1418
1289
|
isKeyConstructedFromData: false,
|
|
1419
1290
|
prefix: "files:gtfsRt",
|
|
1420
1291
|
});
|
|
1421
|
-
this.tripStopsModel = new models_1.RedisModel(vehicle_positions_1.VehiclePositions.tripStops.name + "Model", {
|
|
1422
|
-
decodeDataAfterGet: JSON.parse,
|
|
1423
|
-
encodeDataBeforeSave: JSON.stringify,
|
|
1424
|
-
isKeyConstructedFromData: false,
|
|
1425
|
-
prefix: vehicle_positions_1.VehiclePositions.tripStops.namespacePrefix,
|
|
1426
|
-
}, new golemio_validator_1.Validator(vehicle_positions_1.VehiclePositions.tripStops.name + "ModelValidator", vehicle_positions_1.VehiclePositions.tripStops.outputMongooseSchemaObject));
|
|
1427
|
-
this.modelGTFSTrips = new RopidGTFSTripsModel_1.RopidGTFSTripsModel();
|
|
1428
1292
|
this.modelGTFSStopTimes = new RopidGTFSStopTimesModel_1.RopidGTFSStopTimesModel();
|
|
1293
|
+
this.modelGTFSTrips = new RopidGTFSTripsModel_1.RopidGTFSTripsModel();
|
|
1429
1294
|
// Create trips upsert queue for preventing transaction deadlocks
|
|
1430
1295
|
this.upsertTripsFQ = fastq_1.default.promise(this.modelTrips.bulkUpsert, 1);
|
|
1431
1296
|
}
|