@golemio/pid 2.2.1-dev.520392716 → 2.2.1-dev.526966885

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 (22) hide show
  1. package/db/example/08_update_delay_dump.sql +1977 -0
  2. package/db/migrations/postgresql/20220322111111-valid-to-attribute.js +50 -0
  3. package/db/migrations/postgresql/sqls/20220322111111-valid-to-attribute-down.sql +1 -0
  4. package/db/migrations/postgresql/sqls/20220322111111-valid-to-attribute-up.sql +1 -0
  5. package/dist/integration-engine/vehicle-positions/VehiclePositionsInterfaces.d.ts +2 -0
  6. package/dist/integration-engine/vehicle-positions/VehiclePositionsUtils.d.ts +17 -2
  7. package/dist/integration-engine/vehicle-positions/VehiclePositionsUtils.js +28 -1
  8. package/dist/integration-engine/vehicle-positions/VehiclePositionsUtils.js.map +1 -1
  9. package/dist/integration-engine/vehicle-positions/VehiclePositionsWorker.d.ts +30 -27
  10. package/dist/integration-engine/vehicle-positions/VehiclePositionsWorker.js +81 -32
  11. package/dist/integration-engine/vehicle-positions/VehiclePositionsWorker.js.map +1 -1
  12. package/dist/output-gateway/pid/PIDRouter.js +6 -0
  13. package/dist/output-gateway/pid/PIDRouter.js.map +1 -1
  14. package/dist/output-gateway/pid/models/RopidDeparturesModel.js +3 -5
  15. package/dist/output-gateway/pid/models/RopidDeparturesModel.js.map +1 -1
  16. package/dist/output-gateway/vehicle-positions/VehiclePositionsRouter.js +6 -0
  17. package/dist/output-gateway/vehicle-positions/VehiclePositionsRouter.js.map +1 -1
  18. package/dist/output-gateway/vehicle-positions/models/VehiclePositionsTripsModel.js +26 -9
  19. package/dist/output-gateway/vehicle-positions/models/VehiclePositionsTripsModel.js.map +1 -1
  20. package/dist/schema-definitions/vehicle-positions/index.js +2 -0
  21. package/dist/schema-definitions/vehicle-positions/index.js.map +1 -1
  22. package/package.json +3 -2
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ var dbm;
4
+ var type;
5
+ var seed;
6
+ var fs = require("fs");
7
+ var path = require("path");
8
+ var Promise;
9
+
10
+ /**
11
+ * We receive the dbmigrate dependency from dbmigrate initially.
12
+ * This enables us to not have to rely on NODE_PATH.
13
+ */
14
+ exports.setup = function (options, seedLink) {
15
+ dbm = options.dbmigrate;
16
+ type = dbm.dataType;
17
+ seed = seedLink;
18
+ Promise = options.Promise;
19
+ };
20
+
21
+ exports.up = function (db) {
22
+ var filePath = path.join(__dirname, "sqls", "20220322111111-valid-to-attribute-up.sql");
23
+ return new Promise(function (resolve, reject) {
24
+ fs.readFile(filePath, { encoding: "utf-8" }, function (err, data) {
25
+ if (err) return reject(err);
26
+ console.log("received data: " + data);
27
+ resolve(data);
28
+ });
29
+ }).then(function (data) {
30
+ return db.runSql(data);
31
+ });
32
+ };
33
+
34
+ exports.down = function (db) {
35
+ var filePath = path.join(__dirname, "sqls", "20220322111111-valid-to-attribute-down.sql");
36
+ return new Promise(function (resolve, reject) {
37
+ fs.readFile(filePath, { encoding: "utf-8" }, function (err, data) {
38
+ if (err) return reject(err);
39
+ console.log("received data: " + data);
40
+
41
+ resolve(data);
42
+ });
43
+ }).then(function (data) {
44
+ return db.runSql(data);
45
+ });
46
+ };
47
+
48
+ exports._meta = {
49
+ version: 1,
50
+ };
@@ -0,0 +1 @@
1
+ ALTER TABLE vehiclepositions_positions DROP COLUMN IF EXISTS valid_to;
@@ -0,0 +1 @@
1
+ ALTER TABLE vehiclepositions_positions ADD COLUMN valid_to bigint;
@@ -72,6 +72,7 @@ export interface IPositionToUpdate {
72
72
  this_stop_sequence?: number;
73
73
  this_stop_name?: string;
74
74
  tcp_event?: string | null;
75
+ valid_to: number;
75
76
  }
76
77
  export interface IProcessedPositions {
77
78
  context: IPositionsContext;
@@ -83,6 +84,7 @@ export interface IUpdatePositionsIteratorOptions {
83
84
  startDayTimestamp: number;
84
85
  context: IPositionsContext;
85
86
  computedPositions: IPositionToUpdate[];
87
+ gtfsRouteType: GTFSRouteTypeEnum;
86
88
  }
87
89
  export interface IShapeGeometryAnchorPoint {
88
90
  index: number;
@@ -1,7 +1,12 @@
1
+ import { Message as AMQPMessage } from "amqplib";
1
2
  import { PositionTrackingEnum } from "../../const";
2
3
  import { IUpdateDelayRunTripsData, IUpdateDelayTripsIdsData } from "./models";
3
- import { IPositionTransformationResult } from "./transformations";
4
+ import { IPositionTransformationResult, IVehiclePositionsRunInput } from "./transformations";
4
5
  import { TripStopsSchedule } from "./VehiclePositionsInterfaces";
6
+ interface IParsedRunsMessageData {
7
+ data: IVehiclePositionsRunInput;
8
+ timestamp: number;
9
+ }
5
10
  export declare class VehiclePositionsUtils {
6
11
  static TRIP_STOPS_CACHE_TTL: number;
7
12
  static RUN_TRIPS_CACHE_TTL: number;
@@ -9,7 +14,7 @@ export declare class VehiclePositionsUtils {
9
14
  /**
10
15
  * Determine whether to create new position and its tracking status (trains only for now)
11
16
  *
12
- * @param {TripStopsSchedule | undefined} tripStopSchedule - Cached trip stops for given block id (see Redis)
17
+ * @par {TripStopsSchedule | undefined} tripStopSchedule - Cached trip stops for given block id (see Redis)
13
18
  * @param {IUpdateDelayRunTripsData | IUpdateDelayTripsIdsData} trip - New trip
14
19
  * @param {IPositionTransformationResult} position - Current position
15
20
  */
@@ -22,4 +27,14 @@ export declare class VehiclePositionsUtils {
22
27
  * @param {IPositionTransformationResult} position - Current position
23
28
  */
24
29
  static determineTrackingStatus: (gtfsTripId: string, tripStopSchedule: TripStopsSchedule | undefined, position: IPositionTransformationResult) => PositionTrackingEnum;
30
+ /**
31
+ * Calculate default valid_to attribute
32
+ * return 5min + `origin_timestamp`
33
+ */
34
+ static getDefaultValidToAttribute: (origin_timestamp: number) => number;
35
+ /**
36
+ * Parse runs data from amqp message
37
+ */
38
+ static parseRunsMessageData: (msg: AMQPMessage) => IParsedRunsMessageData;
25
39
  }
40
+ export {};
@@ -2,6 +2,7 @@
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.VehiclePositionsUtils = void 0;
5
+ const golemio_errors_1 = require("@golemio/core/dist/shared/golemio-errors");
5
6
  const const_1 = require("../../const");
6
7
  const models_1 = require("./models");
7
8
  class VehiclePositionsUtils {
@@ -14,7 +15,7 @@ VehiclePositionsUtils.DELAY_COMPUTATION_CACHE_TTL = 7200; // 2 hours
14
15
  /**
15
16
  * Determine whether to create new position and its tracking status (trains only for now)
16
17
  *
17
- * @param {TripStopsSchedule | undefined} tripStopSchedule - Cached trip stops for given block id (see Redis)
18
+ * @par {TripStopsSchedule | undefined} tripStopSchedule - Cached trip stops for given block id (see Redis)
18
19
  * @param {IUpdateDelayRunTripsData | IUpdateDelayTripsIdsData} trip - New trip
19
20
  * @param {IPositionTransformationResult} position - Current position
20
21
  */
@@ -43,4 +44,30 @@ VehiclePositionsUtils.determineTrackingStatus = (gtfsTripId, tripStopSchedule, p
43
44
  const shouldBeTracking = cisLastStopIndex > -1;
44
45
  return shouldBeTracking ? const_1.PositionTrackingEnum.TRACKING : const_1.PositionTrackingEnum.NOT_TRACKING;
45
46
  };
47
+ /**
48
+ * Calculate default valid_to attribute
49
+ * return 5min + `origin_timestamp`
50
+ */
51
+ VehiclePositionsUtils.getDefaultValidToAttribute = (origin_timestamp) => {
52
+ return origin_timestamp + 5 * 60 * 60 * 1000;
53
+ };
54
+ /**
55
+ * Parse runs data from amqp message
56
+ */
57
+ VehiclePositionsUtils.parseRunsMessageData = (msg) => {
58
+ var _b;
59
+ let data;
60
+ let timestamp;
61
+ try {
62
+ timestamp = msg.properties.timestamp;
63
+ data = JSON.parse(msg.content.toString());
64
+ if (!((_b = data === null || data === void 0 ? void 0 : data.M) === null || _b === void 0 ? void 0 : _b.V)) {
65
+ throw new Error(`Unexpected runs message format: ${JSON.stringify(data)}`);
66
+ }
67
+ }
68
+ catch (err) {
69
+ throw new golemio_errors_1.CustomError("Error parsing message data.", true, _a.constructor.name, 2004, err);
70
+ }
71
+ return { data, timestamp };
72
+ };
46
73
  //# sourceMappingURL=VehiclePositionsUtils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VehiclePositionsUtils.js","sourceRoot":"","sources":["../../../src/integration-engine/vehicle-positions/VehiclePositionsUtils.ts"],"names":[],"mappings":";;;;AAAA,uCAAiD;AACjD,qCAAiG;AAIjG,MAAa,qBAAqB;;AAAlC,sDA+CC;;AA9CiB,0CAAoB,GAAG,KAAM,CAAA,CAAC,UAAU;AACxC,yCAAmB,GAAG,KAAM,CAAA,CAAC,UAAU;AACvC,iDAA2B,GAAG,IAAK,CAAA,CAAC,UAAU;AAE5D;;;;;;GAMG;AACW,kDAA4B,GAAG,CACzC,gBAA+C,EAC/C,IAAyD,EACzD,QAAuC,EACnB,EAAE;IACtB,IAAI,cAAc,GAAG,QAAQ,CAAC,QAAS,CAAC;IACxC,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,eAAe,IAAI,0BAAiB,CAAC,KAAK,EAAE;QAC9F,OAAO,cAAc,CAAC;KACzB;IAED,cAAc,GAAG,EAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,YAAY,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAC;IAC7F,OAAO,cAAc,CAAC;AAC1B,CAAE,CAAA;AAEF;;;;;;GAMG;AACW,6CAAuB,GAAG,CACpC,UAAkB,EAClB,gBAA+C,EAC/C,QAAuC,EACnB,EAAE;;IACtB,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,MAAA,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAG,UAAU,CAAC,mCAAI,EAAE,CAAC;IACvE,IAAI,CAAC,SAAS,EAAE;QACZ,OAAO,QAAQ,CAAC,QAAS,CAAC;KAC7B;IAED,MAAM,gBAAgB,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC/F,MAAM,gBAAgB,GAAG,gBAAgB,GAAG,CAAC,CAAC,CAAC;IAC/C,OAAO,gBAAgB,CAAC,CAAC,CAAC,4BAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,4BAAoB,CAAC,YAAY,CAAC;AAChG,CAAE,CAAA"}
1
+ {"version":3,"file":"VehiclePositionsUtils.js","sourceRoot":"","sources":["../../../src/integration-engine/vehicle-positions/VehiclePositionsUtils.ts"],"names":[],"mappings":";;;;AACA,6EAAuE;AACvE,uCAAiD;AACjD,qCAAiG;AASjG,MAAa,qBAAqB;;AAAlC,sDA0EC;;AAzEiB,0CAAoB,GAAG,KAAM,CAAA,CAAC,UAAU;AACxC,yCAAmB,GAAG,KAAM,CAAA,CAAC,UAAU;AACvC,iDAA2B,GAAG,IAAK,CAAA,CAAC,UAAU;AAE5D;;;;;;GAMG;AACW,kDAA4B,GAAG,CACzC,gBAA+C,EAC/C,IAAyD,EACzD,QAAuC,EACnB,EAAE;IACtB,IAAI,cAAc,GAAG,QAAQ,CAAC,QAAS,CAAC;IACxC,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,eAAe,IAAI,0BAAiB,CAAC,KAAK,EAAE;QAC9F,OAAO,cAAc,CAAC;KACzB;IAED,cAAc,GAAG,EAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,YAAY,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAC;IAC7F,OAAO,cAAc,CAAC;AAC1B,CAAE,CAAA;AAEF;;;;;;GAMG;AACW,6CAAuB,GAAG,CACpC,UAAkB,EAClB,gBAA+C,EAC/C,QAAuC,EACnB,EAAE;;IACtB,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,MAAA,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAG,UAAU,CAAC,mCAAI,EAAE,CAAC;IACvE,IAAI,CAAC,SAAS,EAAE;QACZ,OAAO,QAAQ,CAAC,QAAS,CAAC;KAC7B;IAED,MAAM,gBAAgB,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC/F,MAAM,gBAAgB,GAAG,gBAAgB,GAAG,CAAC,CAAC,CAAC;IAC/C,OAAO,gBAAgB,CAAC,CAAC,CAAC,4BAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,4BAAoB,CAAC,YAAY,CAAC;AAChG,CAAE,CAAA;AAEF;;;GAGG;AACW,gDAA0B,GAAG,CAAC,gBAAwB,EAAU,EAAE;IAC5E,OAAO,gBAAgB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACjD,CAAE,CAAA;AAEF;;GAEG;AACW,0CAAoB,GAAG,CAAC,GAAgB,EAA0B,EAAE;;IAC9E,IAAI,IAA+B,CAAC;IACpC,IAAI,SAAiB,CAAC;IACtB,IAAI;QACA,SAAS,GAAG,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;QACrC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,CAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,CAAC,0CAAE,CAAC,CAAA,EAAE;YACb,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;SAC9E;KACJ;IAAC,OAAO,GAAG,EAAE;QACV,MAAM,IAAI,4BAAW,CAAC,6BAA6B,EAAE,IAAI,EAAE,EAAI,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;KAChG;IAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAC/B,CAAE,CAAA"}
@@ -1,4 +1,4 @@
1
- /// <reference types="node" />
1
+ import { Message as AMQPMessage } from "amqplib";
2
2
  import { BaseWorker } from "@golemio/core/dist/integration-engine/workers";
3
3
  import { IVehiclePositionsRunCommon } from "./transformations";
4
4
  import type { IPropagateDelay } from "./VehiclePositionsInterfaces";
@@ -18,32 +18,27 @@ export declare class VehiclePositionsWorker extends BaseWorker {
18
18
  private upsertTripsFQ;
19
19
  private readonly queuePrefix;
20
20
  constructor();
21
- saveDataToDB: (msg: {
22
- content: Buffer;
23
- }) => Promise<void>;
24
- saveStopsToDB: (msg: {
25
- content: Buffer;
26
- }) => Promise<void>;
27
- updateGTFSTripId: (msg: {
28
- content: Buffer;
29
- }) => Promise<void>;
21
+ saveDataToDB: (msg: AMQPMessage) => Promise<void>;
22
+ saveStopsToDB: (msg: AMQPMessage) => Promise<void>;
23
+ updateGTFSTripId: (msg: AMQPMessage) => Promise<void>;
30
24
  generateGtfsRt: () => Promise<void>;
31
25
  private isUpdateDelayRunTripsIdsData;
32
26
  private mapDelayedPositionsToRunTrips;
33
27
  propagateDelayForGtfsTrip: (data: IPropagateDelay) => Promise<void>;
34
- propagateDelay: (msg: {
35
- content: Buffer;
36
- }) => Promise<void>;
37
- updateDelay: (msg: {
38
- content: Buffer;
39
- }) => Promise<void>;
28
+ propagateDelay: (msg: AMQPMessage) => Promise<void>;
29
+ updateDelay: (msg: AMQPMessage) => Promise<void>;
40
30
  /**
41
- * Queue listener method - triggers processing of TCP input gateway runs data
31
+ * Queue listener method - triggers processing of TCP input gateway tram runs data
42
32
  *
43
- * @param {object} msg - xml->json parsed run message
44
- * @returns {void}
33
+ * @param {AMQPMessage} msg - xml->json parsed run message
45
34
  */
46
- saveRunsToDB: (msg: Record<string, any>) => Promise<void>;
35
+ saveTramRunsToDB: (msg: AMQPMessage) => Promise<void>;
36
+ /**
37
+ * Queue listener method - triggers processing of TCP input gateway bus runs data
38
+ *
39
+ * @param {AMQPMessage} msg - xml->json parsed run message
40
+ */
41
+ saveBusRunsToDB: (msg: AMQPMessage) => Promise<void>;
47
42
  /**
48
43
  * Process not public trips from runs data
49
44
  *
@@ -54,18 +49,18 @@ export declare class VehiclePositionsWorker extends BaseWorker {
54
49
  /**
55
50
  * Queue listener method - processing trips from runs data
56
51
  *
57
- * @param {object} msg
52
+ * @param {AMQPMessage} msg
58
53
  * @returns {void}
59
54
  */
60
- updateRunsGTFSTripId: (msg: {
61
- content: Buffer;
62
- }) => Promise<void>;
55
+ updateRunsGTFSTripId: (msg: AMQPMessage) => Promise<void>;
63
56
  /**
64
57
  * Queue listener method - delete old data
65
58
  */
66
- deleteOldVehiclePositionsData: (msg: {
67
- content: Buffer;
68
- }) => Promise<void>;
59
+ deleteOldVehiclePositionsData: (msg: AMQPMessage) => Promise<void>;
60
+ /**
61
+ * Create/update and process transformed run
62
+ */
63
+ private processTransformedRun;
69
64
  /**
70
65
  * Helper runs method to search all trips that PT link can travel
71
66
  *
@@ -205,4 +200,12 @@ export declare class VehiclePositionsWorker extends BaseWorker {
205
200
  * @returns {ISegmentShape[]} - Result array of new shape points
206
201
  */
207
202
  private divideSegmentLine;
203
+ /**
204
+ * Calculates valid_to attribute value for updateDelay worker
205
+ *
206
+ * @param {number} i - Position index
207
+ * @param {ITripPositionsWithGTFS} tripPositions - Trip positions with shape anchors data
208
+ * @param {GTFSRouteTypeEnum} gtfsRouteType - Route Type Enum
209
+ */
210
+ private getValidToAttribute;
208
211
  }
@@ -471,36 +471,32 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
471
471
  }
472
472
  });
473
473
  /**
474
- * Queue listener method - triggers processing of TCP input gateway runs data
474
+ * Queue listener method - triggers processing of TCP input gateway tram runs data
475
475
  *
476
- * @param {object} msg - xml->json parsed run message
477
- * @returns {void}
476
+ * @param {AMQPMessage} msg - xml->json parsed run message
478
477
  */
479
- this.saveRunsToDB = (msg) => __awaiter(this, void 0, void 0, function* () {
480
- var _d;
481
- let data;
482
- let timestamp;
483
- try {
484
- timestamp = msg.properties.timestamp;
485
- data = JSON.parse(msg.content.toString());
486
- if (!((_d = data === null || data === void 0 ? void 0 : data.M) === null || _d === void 0 ? void 0 : _d.V)) {
487
- throw new Error(`Unexpected saveRunsToDB message format: ${JSON.stringify(data)}`);
488
- }
489
- }
490
- catch (err) {
491
- throw new golemio_errors_1.CustomError("Error parsing message data.", true, this.constructor.name, 2004, err);
478
+ this.saveTramRunsToDB = (msg) => __awaiter(this, void 0, void 0, function* () {
479
+ const { data, timestamp } = VehiclePositionsUtils_1.VehiclePositionsUtils.parseRunsMessageData(msg);
480
+ const transformedData = yield this.transformationRuns.transform({ data: data.M.V, timestamp });
481
+ for (const element of transformedData) {
482
+ yield this.processTransformedRun(element);
492
483
  }
484
+ });
485
+ /**
486
+ * Queue listener method - triggers processing of TCP input gateway bus runs data
487
+ *
488
+ * @param {AMQPMessage} msg - xml->json parsed run message
489
+ */
490
+ this.saveBusRunsToDB = (msg) => __awaiter(this, void 0, void 0, function* () {
491
+ var _d;
492
+ const { data, timestamp } = VehiclePositionsUtils_1.VehiclePositionsUtils.parseRunsMessageData(msg);
493
493
  const transformedData = yield this.transformationRuns.transform({ data: data.M.V, timestamp });
494
494
  for (const element of transformedData) {
495
- const record = yield this.modelRuns.getRunRecordForUpdate(element.run);
496
- let outputMsg;
497
- if (record) {
498
- outputMsg = yield this.modelRuns.updateAndAssociate(element, record.id);
499
- }
500
- else {
501
- outputMsg = yield this.modelRuns.createAndAssociate(element);
495
+ // Internal bus lines should not interfere with tram runs
496
+ if (((_d = element.run.route_id) === null || _d === void 0 ? void 0 : _d.length) < 3) {
497
+ continue;
502
498
  }
503
- yield this.sendMessageToExchange("workers." + this.queuePrefix + ".updateRunsGTFSTripId", JSON.stringify(outputMsg));
499
+ yield this.processTransformedRun(element);
504
500
  }
505
501
  });
506
502
  /**
@@ -519,7 +515,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
519
515
  /**
520
516
  * Queue listener method - processing trips from runs data
521
517
  *
522
- * @param {object} msg
518
+ * @param {AMQPMessage} msg
523
519
  * @returns {void}
524
520
  */
525
521
  this.updateRunsGTFSTripId = (msg) => __awaiter(this, void 0, void 0, function* () {
@@ -608,6 +604,20 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
608
604
  yield this.modelStops.deleteNHoursOldData(targetHours);
609
605
  yield this.modelPositions.deleteNHoursOldData(targetHours);
610
606
  });
607
+ /**
608
+ * Create/update and process transformed run
609
+ */
610
+ this.processTransformedRun = (element) => __awaiter(this, void 0, void 0, function* () {
611
+ const record = yield this.modelRuns.getRunRecordForUpdate(element.run);
612
+ let outputMsg;
613
+ if (record) {
614
+ outputMsg = yield this.modelRuns.updateAndAssociate(element, record.id);
615
+ }
616
+ else {
617
+ outputMsg = yield this.modelRuns.createAndAssociate(element);
618
+ }
619
+ yield this.sendMessageToExchange("workers." + this.queuePrefix + ".updateRunsGTFSTripId", JSON.stringify(outputMsg));
620
+ });
611
621
  /**
612
622
  * Helper runs method to search all trips that PT link can travel
613
623
  *
@@ -696,6 +706,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
696
706
  this.computePositions = (tripPositions) => __awaiter(this, void 0, void 0, function* () {
697
707
  const startTimestamp = parseInt(tripPositions.start_timestamp, 10);
698
708
  const startDayTimestamp = this.getStartDayTimestamp(startTimestamp, tripPositions.gtfsData.shapes_anchor_points[0].time_scheduled_seconds);
709
+ const gtfsRouteType = tripPositions.gtfs_route_type;
699
710
  return new Promise((resolve) => {
700
711
  const context = {
701
712
  atStopStreak: {
@@ -719,7 +730,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
719
730
  tripId: tripPositions.id,
720
731
  };
721
732
  const computedPositions = [];
722
- this.updatePositionsIterator(0, { tripPositions, startTimestamp, startDayTimestamp, context, computedPositions }, () => {
733
+ this.updatePositionsIterator(0, { tripPositions, startTimestamp, startDayTimestamp, context, computedPositions, gtfsRouteType }, () => {
723
734
  resolve({
724
735
  context,
725
736
  positions: computedPositions,
@@ -775,7 +786,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
775
786
  * @returns {void} - void
776
787
  */
777
788
  this.updatePositionsIterator = (i, options, cb) => __awaiter(this, void 0, void 0, function* () {
778
- const { tripPositions, startDayTimestamp, startTimestamp, context, computedPositions } = options;
789
+ const { tripPositions, startDayTimestamp, startTimestamp, context, computedPositions, gtfsRouteType } = options;
779
790
  if (i === tripPositions.positions.length) {
780
791
  return cb();
781
792
  }
@@ -791,6 +802,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
791
802
  tcp_event: position.tcp_event,
792
803
  });
793
804
  positionToUpdate = yield this.getEstimatedPoint(tripPositions.gtfsData, currentPosition, context, startDayTimestamp, tripPositions.gtfs_route_type);
805
+ positionToUpdate.valid_to = this.getValidToAttribute(i, tripPositions, gtfsRouteType);
794
806
  break;
795
807
  case PositionHandlerEnum.NOT_TRACKING:
796
808
  // if there is no previous positions with tracking status, set position as before_track
@@ -803,9 +815,9 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
803
815
  // if there is no delay to duplicate and DPP trip is far from start then invisible
804
816
  const setAsInvisible = !canDuplicatePropagatedDelay &&
805
817
  this.isDPPTripAndFarFromItsTrack(tripPositions.agency_name_scheduled, position.origin_timestamp, startTimestamp, [position.lng, position.lat], firstShapesAnchorPoint.coordinates);
806
- positionToUpdate = Object.assign({ id: position.id, next_stop_arrival_time: startDayTimestamp + firstStopTime.arrival_time_seconds * 1000, next_stop_departure_time: startDayTimestamp + firstStopTime.departure_time_seconds * 1000, next_stop_id: firstStopTime.stop_id, next_stop_sequence: firstStopTime.stop_sequence, next_stop_name: firstStopTime.stop.stop_name, shape_dist_traveled: firstStopTime.shape_dist_traveled, state_position: setAsInvisible ? const_1.StatePositionEnum.INVISIBLE : const_1.StatePositionEnum.BEFORE_TRACK, state_process: const_1.StateProcessEnum.PROCESSED }, (firstStopTime.stop_headsign && {
818
+ positionToUpdate = Object.assign(Object.assign({ id: position.id, next_stop_arrival_time: startDayTimestamp + firstStopTime.arrival_time_seconds * 1000, next_stop_departure_time: startDayTimestamp + firstStopTime.departure_time_seconds * 1000, next_stop_id: firstStopTime.stop_id, next_stop_sequence: firstStopTime.stop_sequence, next_stop_name: firstStopTime.stop.stop_name, shape_dist_traveled: firstStopTime.shape_dist_traveled, state_position: setAsInvisible ? const_1.StatePositionEnum.INVISIBLE : const_1.StatePositionEnum.BEFORE_TRACK, state_process: const_1.StateProcessEnum.PROCESSED }, (firstStopTime.stop_headsign && {
807
819
  last_stop_headsign: firstStopTime.stop_headsign,
808
- }));
820
+ })), { valid_to: this.getValidToAttribute(i, tripPositions, gtfsRouteType) });
809
821
  if (!setAsInvisible && canDuplicatePropagatedDelay) {
810
822
  positionToUpdate.delay = context.lastPositionBeforeTrackDelayed.delay;
811
823
  }
@@ -819,9 +831,9 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
819
831
  const lastStopTime = tripPositions.gtfsData.stop_times[tripPositions.gtfsData.stop_times.length - 1];
820
832
  // set as invisible if there are some AFTER_TRACK before
821
833
  const setAsInvisible = context.isLastPositionAfterTrack && statePosition === const_1.StatePositionEnum.AFTER_TRACK;
822
- positionToUpdate = Object.assign({ id: position.id, last_stop_arrival_time: startDayTimestamp + lastShapesAnchorPoint.time_scheduled_seconds * 1000, last_stop_departure_time: startDayTimestamp + lastShapesAnchorPoint.time_scheduled_seconds * 1000, last_stop_id: lastStopTime.stop_id, last_stop_sequence: lastShapesAnchorPoint.last_stop_sequence, shape_dist_traveled: lastShapesAnchorPoint.shape_dist_traveled, state_position: setAsInvisible ? const_1.StatePositionEnum.INVISIBLE : statePosition, state_process: const_1.StateProcessEnum.PROCESSED }, (lastStopTime.stop_headsign && {
834
+ positionToUpdate = Object.assign(Object.assign({ id: position.id, last_stop_arrival_time: startDayTimestamp + lastShapesAnchorPoint.time_scheduled_seconds * 1000, last_stop_departure_time: startDayTimestamp + lastShapesAnchorPoint.time_scheduled_seconds * 1000, last_stop_id: lastStopTime.stop_id, last_stop_sequence: lastShapesAnchorPoint.last_stop_sequence, shape_dist_traveled: lastShapesAnchorPoint.shape_dist_traveled, state_position: setAsInvisible ? const_1.StatePositionEnum.INVISIBLE : statePosition, state_process: const_1.StateProcessEnum.PROCESSED }, (lastStopTime.stop_headsign && {
823
835
  last_stop_headsign: lastStopTime.stop_headsign,
824
- }));
836
+ })), { valid_to: this.getValidToAttribute(i, tripPositions, gtfsRouteType) });
825
837
  }
826
838
  break;
827
839
  case PositionHandlerEnum.CANCELED:
@@ -829,6 +841,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
829
841
  id: position.id,
830
842
  state_position: const_1.StatePositionEnum.CANCELED,
831
843
  state_process: const_1.StateProcessEnum.PROCESSED,
844
+ valid_to: this.getValidToAttribute(i, tripPositions, gtfsRouteType),
832
845
  };
833
846
  break;
834
847
  case PositionHandlerEnum.DO_NOTHING:
@@ -1119,6 +1132,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
1119
1132
  last_stop_headsign: tripStopTimes[thisClosestPoint.last_stop_sequence - 1].stop_headsign || undefined,
1120
1133
  state_position: statePosition,
1121
1134
  state_process: const_1.StateProcessEnum.PROCESSED,
1135
+ valid_to: VehiclePositionsUtils_1.VehiclePositionsUtils.getDefaultValidToAttribute(currentPosition.properties.origin_timestamp),
1122
1136
  };
1123
1137
  }
1124
1138
  // next step
@@ -1145,7 +1159,7 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
1145
1159
  // init radius around GPS position ( 200 meters radius, 16 points polygon aka circle)
1146
1160
  const radius = turf.circle(currentPosition, 0.2, { steps: 16 });
1147
1161
  //Initial value
1148
- 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 &&
1162
+ 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, valid_to: VehiclePositionsUtils_1.VehiclePositionsUtils.getDefaultValidToAttribute(currentPosition.properties.origin_timestamp) }, (context &&
1149
1163
  ((_e = context.lastPositionTracking) === null || _e === void 0 ? void 0 : _e.properties.last_stop_sequence) && {
1150
1164
  shape_dist_traveled: (_f = context.lastPositionTracking) === null || _f === void 0 ? void 0 : _f.properties.shape_dist_traveled,
1151
1165
  last_stop_arrival_time: (_g = context.lastPositionTracking) === null || _g === void 0 ? void 0 : _g.properties.last_stop_arrival_time,
@@ -1391,6 +1405,41 @@ class VehiclePositionsWorker extends workers_1.BaseWorker {
1391
1405
  }
1392
1406
  return resultSegmentPoints;
1393
1407
  };
1408
+ /**
1409
+ * Calculates valid_to attribute value for updateDelay worker
1410
+ *
1411
+ * @param {number} i - Position index
1412
+ * @param {ITripPositionsWithGTFS} tripPositions - Trip positions with shape anchors data
1413
+ * @param {GTFSRouteTypeEnum} gtfsRouteType - Route Type Enum
1414
+ */
1415
+ this.getValidToAttribute = (positionIndex, tripPositions, gtfsRouteType) => {
1416
+ const position = tripPositions.positions[positionIndex];
1417
+ // For TRAM only:
1418
+ if (gtfsRouteType === models_2.GTFSRouteTypeEnum.TRAM) {
1419
+ // For all real stops:
1420
+ // return default valid to attribute + the time difference between departure and arrival
1421
+ if (position.state_position == "at_stop" &&
1422
+ position.last_stop_arrival_time != position.last_stop_departure_time &&
1423
+ position.last_stop_arrival_time &&
1424
+ position.last_stop_departure_time) {
1425
+ return (VehiclePositionsUtils_1.VehiclePositionsUtils.getDefaultValidToAttribute(position.origin_timestamp) +
1426
+ (position.last_stop_departure_time - position.last_stop_arrival_time));
1427
+ }
1428
+ // For final positions:
1429
+ // return default valid to attribute + the time difference between (next trip departure) and arrival
1430
+ /*
1431
+ if (position.state_position == "after_track" && position.last_stop_arrival_time) {
1432
+ return VehiclePositionsUtils.getDefaultValidToAttribute(position.origin_timestamp) +
1433
+ (
1434
+ //implement here: time difference between (next trip departure) and arrival
1435
+ )
1436
+ - position.last_stop_arrival_time;
1437
+ }
1438
+ */
1439
+ }
1440
+ // For all other positions:
1441
+ return VehiclePositionsUtils_1.VehiclePositionsUtils.getDefaultValidToAttribute(position.origin_timestamp);
1442
+ };
1394
1443
  this.modelPositions = new models_2.VehiclePositionsPositionsModel();
1395
1444
  this.modelStops = new models_2.VehiclePositionsStopsModel();
1396
1445
  this.modelRuns = new models_2.VehiclePositionsRunsModel();