@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.
Files changed (75) hide show
  1. package/db/example/{00_truncate_tables.sql → __truncate_tables.sql} +0 -0
  2. package/db/example/{01_departure_directions.sql → departure_directions.sql} +0 -0
  3. package/db/example/{02_pid_line_example_115.sql → pid_line_example_115.sql} +0 -0
  4. package/db/example/{03_ropidgtfs_dump.sql → ropid_gtfs_dump.sql} +27 -27
  5. package/db/example/{04_ropidvymi_example.sql → ropidvymi_example.sql} +0 -0
  6. package/db/example/{07_tmp_example.sql → tmp_example.sql} +0 -0
  7. package/db/example/{pb/trip_updates.pb → trip_updates.pb} +0 -0
  8. package/db/example/{pb/vehicle_positions.pb → vehicle_positions.pb} +0 -0
  9. package/db/example/{05_vehicle_positions_dump.sql → vehicle_positions_dump.sql} +0 -0
  10. package/db/example/{99_precomputed_tables.sql → zzz_precomputed_tables.sql} +0 -0
  11. package/dist/const.d.ts +0 -4
  12. package/dist/const.js +1 -6
  13. package/dist/const.js.map +1 -1
  14. package/dist/integration-engine/ropid-gtfs/RopidGTFSScheduledTripsModel.d.ts +1 -1
  15. package/dist/integration-engine/ropid-gtfs/RopidGTFSStopTimesModel.d.ts +0 -11
  16. package/dist/integration-engine/ropid-gtfs/RopidGTFSStopTimesModel.js +0 -34
  17. package/dist/integration-engine/ropid-gtfs/RopidGTFSStopTimesModel.js.map +1 -1
  18. package/dist/integration-engine/ropid-gtfs/RopidGTFSTripsModel.js +1 -2
  19. package/dist/integration-engine/ropid-gtfs/RopidGTFSTripsModel.js.map +1 -1
  20. package/dist/integration-engine/ropid-gtfs/RopidGTFSWorker.js +2 -2
  21. package/dist/integration-engine/ropid-gtfs/RopidGTFSWorker.js.map +1 -1
  22. package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsPositionsModel.d.ts → VehiclePositionsPositionsModel.d.ts} +3 -3
  23. package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsPositionsModel.js → VehiclePositionsPositionsModel.js} +3 -3
  24. package/dist/integration-engine/vehicle-positions/VehiclePositionsPositionsModel.js.map +1 -0
  25. package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsRunsMessagesModel.d.ts → VehiclePositionsRunsMessagesModel.d.ts} +0 -0
  26. package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsRunsMessagesModel.js → VehiclePositionsRunsMessagesModel.js} +5 -5
  27. package/dist/integration-engine/vehicle-positions/VehiclePositionsRunsMessagesModel.js.map +1 -0
  28. package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsRunsModel.d.ts → VehiclePositionsRunsModel.d.ts} +2 -2
  29. package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsRunsModel.js → VehiclePositionsRunsModel.js} +2 -2
  30. package/dist/integration-engine/vehicle-positions/VehiclePositionsRunsModel.js.map +1 -0
  31. package/dist/integration-engine/vehicle-positions/{transformations/VehiclePositionsRunsTransformation.d.ts → VehiclePositionsRunsTransformation.d.ts} +1 -1
  32. package/dist/integration-engine/vehicle-positions/{transformations/VehiclePositionsRunsTransformation.js → VehiclePositionsRunsTransformation.js} +1 -1
  33. package/dist/integration-engine/vehicle-positions/VehiclePositionsRunsTransformation.js.map +1 -0
  34. package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsStopsModel.d.ts → VehiclePositionsStopsModel.d.ts} +0 -0
  35. package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsStopsModel.js → VehiclePositionsStopsModel.js} +1 -1
  36. package/dist/integration-engine/vehicle-positions/VehiclePositionsStopsModel.js.map +1 -0
  37. package/dist/integration-engine/vehicle-positions/VehiclePositionsTransformation.d.ts +49 -0
  38. package/dist/integration-engine/vehicle-positions/{transformations/VehiclePositionsTransformation.js → VehiclePositionsTransformation.js} +45 -42
  39. package/dist/integration-engine/vehicle-positions/VehiclePositionsTransformation.js.map +1 -0
  40. package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsTripsModel.d.ts → VehiclePositionsTripsModel.d.ts} +7 -5
  41. package/dist/integration-engine/vehicle-positions/{models/VehiclePositionsTripsModel.js → VehiclePositionsTripsModel.js} +30 -48
  42. package/dist/integration-engine/vehicle-positions/VehiclePositionsTripsModel.js.map +1 -0
  43. package/dist/integration-engine/vehicle-positions/VehiclePositionsWorker.d.ts +90 -43
  44. package/dist/integration-engine/vehicle-positions/VehiclePositionsWorker.js +213 -327
  45. package/dist/integration-engine/vehicle-positions/VehiclePositionsWorker.js.map +1 -1
  46. package/dist/integration-engine/vehicle-positions/index.d.ts +5 -2
  47. package/dist/integration-engine/vehicle-positions/index.js +5 -2
  48. package/dist/integration-engine/vehicle-positions/index.js.map +1 -1
  49. package/dist/output-gateway/vehicle-positions/models/VehiclePositionsTripsModel.js +1 -1
  50. package/dist/output-gateway/vehicle-positions/models/VehiclePositionsTripsModel.js.map +1 -1
  51. package/dist/schema-definitions/vehicle-positions/index.d.ts +2 -9
  52. package/dist/schema-definitions/vehicle-positions/index.js +2 -18
  53. package/dist/schema-definitions/vehicle-positions/index.js.map +1 -1
  54. package/package.json +82 -83
  55. package/db/example/06_ropidgtfs_train_trips_stop_times.sql +0 -83
  56. package/dist/integration-engine/vehicle-positions/VehiclePositionsInterfaces.d.ts +0 -152
  57. package/dist/integration-engine/vehicle-positions/VehiclePositionsInterfaces.js +0 -3
  58. package/dist/integration-engine/vehicle-positions/VehiclePositionsInterfaces.js.map +0 -1
  59. package/dist/integration-engine/vehicle-positions/VehiclePositionsUtils.d.ts +0 -22
  60. package/dist/integration-engine/vehicle-positions/VehiclePositionsUtils.js +0 -53
  61. package/dist/integration-engine/vehicle-positions/VehiclePositionsUtils.js.map +0 -1
  62. package/dist/integration-engine/vehicle-positions/models/VehiclePositionsPositionsModel.js.map +0 -1
  63. package/dist/integration-engine/vehicle-positions/models/VehiclePositionsRunsMessagesModel.js.map +0 -1
  64. package/dist/integration-engine/vehicle-positions/models/VehiclePositionsRunsModel.js.map +0 -1
  65. package/dist/integration-engine/vehicle-positions/models/VehiclePositionsStopsModel.js.map +0 -1
  66. package/dist/integration-engine/vehicle-positions/models/VehiclePositionsTripsModel.js.map +0 -1
  67. package/dist/integration-engine/vehicle-positions/models/index.d.ts +0 -5
  68. package/dist/integration-engine/vehicle-positions/models/index.js +0 -18
  69. package/dist/integration-engine/vehicle-positions/models/index.js.map +0 -1
  70. package/dist/integration-engine/vehicle-positions/transformations/VehiclePositionsRunsTransformation.js.map +0 -1
  71. package/dist/integration-engine/vehicle-positions/transformations/VehiclePositionsTransformation.d.ts +0 -108
  72. package/dist/integration-engine/vehicle-positions/transformations/VehiclePositionsTransformation.js.map +0 -1
  73. package/dist/integration-engine/vehicle-positions/transformations/index.d.ts +0 -2
  74. package/dist/integration-engine/vehicle-positions/transformations/index.js +0 -15
  75. 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 RopidGTFSTripsModel_1 = require("../ropid-gtfs/RopidGTFSTripsModel");
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 positions = transformedData.positions.filter((position) => chunks[key].includes(position.trips_id));
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
- let positionsByIds = {};
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.setAndReturnScheduledTrips({
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 gtfs data for each trip
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
- for (const trip of promiseValues) {
157
- if (trip instanceof golemio_errors_1.CustomError) {
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 existingTripsPromiseValues) {
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
- const { shouldCreateNewPosition, trackingStatus } = VehiclePositionsUtils_1.VehiclePositionsUtils.determineNewPositionTracking(tripStopsSchedulesByBlockIds[trip.gtfs_block_id], trip, currentPosition);
197
- if (shouldCreateNewPosition) {
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 = existingTripsPromiseValues.length; i < imax; i += chunkSize) {
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: existingTripsPromiseValues.slice(i, i + chunkSize),
179
+ updatedTrips: foundedTripsPromiseValues.slice(i, i + chunkSize),
211
180
  }));
212
181
  }
213
182
  // gtfsId updating errors
214
- for (let i = 0, imax = existingTripsPromiseErrors.length; i < imax; i++) {
215
- helpers_1.IntegrationErrorHandler.handle(existingTripsPromiseErrors[i]);
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 === models_2.GTFSRouteTypeEnum.TRAIN
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
- let positionsByIds = {};
369
- for (const position of inputData.positions) {
370
- positionsByIds[position.trips_id] = position;
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
- continue;
405
- }
406
- const currentPosition = inputData.positions.find((position) => {
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, VehiclePositionsUtils_1.VehiclePositionsUtils.DELAY_COMPUTATION_CACHE_TTL);
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. For trip ids:${tripIds.slice(0, 10).join(",")}`, true, this.constructor.name, 5001, err);
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.setAndReturnScheduledTrips(input.run);
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 (!actualStopTimestampScheduled) {
528
- helpers_1.log.warn(`updateRunsGTFSTripId: actualStopTimestampScheduled is not provided for current run: ${JSON.stringify(input.run)}`);
529
- return;
530
- }
531
- const asts = (0, moment_timezone_1.default)(+actualStopTimestampScheduled);
532
- // current gtfs trip for run
533
- const gtfsCurrentTrip = schedule.find((el, i) => {
534
- return asts.isBetween((0, moment_timezone_1.default)(el.start_timestamp), (0, moment_timezone_1.default)(el.end_timestamp), "second", "[]");
535
- });
536
- let isCurrentTripTracking = false;
537
- if (gtfsCurrentTrip &&
538
- // tram is always on track while pushes messages only on stops
539
- (gtfsCurrentTrip.route_type === models_2.GTFSRouteTypeEnum.TRAM ||
540
- // when bus announces DEPARTURE TCP event, it means that trip is on track
541
- (gtfsCurrentTrip.route_type === models_2.GTFSRouteTypeEnum.BUS && event === const_1.TCPEventEnum.DEPARTURED) ||
542
- // when trip has set first stop time, and message timestamp is after scheduled start, set as tracking
543
- (asts.isSame((0, moment_timezone_1.default)(gtfsCurrentTrip.start_timestamp)) &&
544
- (0, moment_timezone_1.default)(msgTimestamp).isSameOrAfter((0, moment_timezone_1.default)(gtfsCurrentTrip.start_timestamp))) ||
545
- // of course when trip announcing some next stop time in schedule, then set as tracking
546
- asts.isAfter((0, moment_timezone_1.default)(gtfsCurrentTrip.start_timestamp)))) {
547
- isCurrentTripTracking = true;
548
- }
549
- const gtfsCurrentTripId = gtfsCurrentTrip && gtfsCurrentTrip.trip_id;
550
- if (!gtfsCurrentTripId) {
551
- helpers_1.log.warn(`updateRunsGTFSTripId: could not find current gtfsTrip for run: ${JSON.stringify(input)}`);
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
- const currentTrip = yield this.modelTrips.upsertRunTrip(input, gtfsCurrentTrip);
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.setAndReturnScheduledTrips = (scheduleData) => __awaiter(this, void 0, void 0, function* () {
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 }, VehiclePositionsUtils_1.VehiclePositionsUtils.RUN_TRIPS_CACHE_TTL);
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 === const_1.PositionTrackingEnum.TRACKING)
683
+ if (position.lat && position.lng && position.tracking === 2)
747
684
  return PositionHandlerEnum.TRACKING;
748
- if (position.tracking !== const_1.PositionTrackingEnum.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 === const_1.PositionTrackingEnum.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 === models_2.GTFSRouteTypeEnum.TRAM &&
986
+ if (((gtfsRouteType === _1.GTFSRouteTypeEnum.TRAM &&
1049
987
  currentPosition.properties.tcp_event === const_1.TCPEventEnum.ARRIVAL_ANNOUNCED) ||
1050
- (gtfsRouteType === models_2.GTFSRouteTypeEnum.BUS && currentPosition.properties.tcp_event === const_1.TCPEventEnum.V)) &&
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 === models_2.GTFSRouteTypeEnum.TRAM && currentPosition.properties.tcp_event === const_1.TCPEventEnum.V) {
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
- const shapesGeometryAnchorPoints = this.getShapesGeometryAnchorPoints(stopTimes.shape_id, shapes.shapes, stopTimes.stop_times);
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 = 0.1;
1173
- const distanceAfter = 0.05;
1174
- for (let i = 0; i < shapesGeometryAnchorPoints.length; i++) {
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 = thisStopSequence !== null
1222
- ? stopTimes.stop_times[lastStopSequence - 1].arrival_time_seconds
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: thisStopSequence !== null,
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: Math.round(shapesGeometryAnchorPoints[i].shape_dist_traveled * 100000) / 100000,
1238
- this_stop_sequence: thisStopSequence,
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
- return {
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, stops) => {
1227
+ this.getShapesGeometryAnchorPoints = (shapeId, shapes) => __awaiter(this, void 0, void 0, function* () {
1228
+ var _m;
1229
+ const shapesAnchorPoints = [];
1262
1230
  try {
1263
- let segmentShapes = [];
1264
- // Splits shapes array to multiple arrays "delimited" by stops
1265
- for (let st = 0; st < stops.length; st++) {
1266
- let currentSegment = [];
1267
- for (let sh = 0; sh < shapes.length; sh++) {
1268
- let shapePoint = Object.assign(Object.assign({}, shapes[sh]), { shape_at_stop: false });
1269
- if (stops[st].shape_dist_traveled === shapes[sh].shape_dist_traveled) {
1270
- shapePoint.shape_at_stop = true;
1271
- }
1272
- if (st < stops.length - 1 &&
1273
- shapePoint.shape_dist_traveled >= stops[st].shape_dist_traveled &&
1274
- shapePoint.shape_dist_traveled <= stops[st + 1].shape_dist_traveled) {
1275
- currentSegment.push(shapePoint);
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
- last_stop_sequence = stopCounter;
1301
- next_stop_sequence = stopCounter + 1;
1302
- return {
1303
- index,
1304
- coordinates: [
1305
- Math.round(segment.shape_pt_lon * 100000) / 100000,
1306
- Math.round(segment.shape_pt_lat * 100000) / 100000,
1307
- ],
1308
- last_stop_sequence,
1309
- next_stop_sequence,
1310
- shape_dist_traveled: Math.round(segment.shape_dist_traveled * 1000) / 1000,
1311
- this_stop_sequence,
1312
- };
1313
- });
1314
- stopCounter++;
1315
- // and lastly shape point for last stop as there is no segment for last stop
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
- return resultSegmentPoints;
1376
- };
1377
- this.modelPositions = new models_2.VehiclePositionsPositionsModel();
1378
- this.modelStops = new models_2.VehiclePositionsStopsModel();
1379
- this.modelRuns = new models_2.VehiclePositionsRunsModel();
1380
- this.transformationRuns = new transformations_1.VehiclePositionsRunsTransformation();
1381
- this.modelTrips = new models_2.VehiclePositionsTripsModel();
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.runsTrips.name + "Model", {
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.runsTrips.namespacePrefix,
1394
- }, new golemio_validator_1.Validator(vehicle_positions_1.VehiclePositions.runsTrips.name + "ModelValidator", vehicle_positions_1.VehiclePositions.runsTrips.outputMongooseSchemaObject));
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
  }