@golemio/pid 2.13.10-dev.1342209321 → 2.14.0

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 (30) hide show
  1. package/dist/integration-engine/vehicle-positions/ioc/Di.js +9 -14
  2. package/dist/integration-engine/vehicle-positions/ioc/Di.js.map +1 -1
  3. package/dist/integration-engine/vehicle-positions/ioc/VPContainerToken.d.ts +0 -3
  4. package/dist/integration-engine/vehicle-positions/ioc/VPContainerToken.js +0 -3
  5. package/dist/integration-engine/vehicle-positions/ioc/VPContainerToken.js.map +1 -1
  6. package/dist/integration-engine/vehicle-positions/workers/runs/helpers/regional-bus/RegionalBusMessageFilter.d.ts +4 -1
  7. package/dist/integration-engine/vehicle-positions/workers/runs/helpers/regional-bus/RegionalBusMessageFilter.js +27 -11
  8. package/dist/integration-engine/vehicle-positions/workers/runs/helpers/regional-bus/RegionalBusMessageFilter.js.map +1 -1
  9. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/helpers/PositionsManager.d.ts +12 -15
  10. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/helpers/PositionsManager.js +399 -419
  11. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/helpers/PositionsManager.js.map +1 -1
  12. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/helpers/ValidToCalculator.d.ts +6 -15
  13. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/helpers/ValidToCalculator.js +45 -71
  14. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/helpers/ValidToCalculator.js.map +1 -1
  15. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/helpers/mpv-net/MpvStopParser.d.ts +5 -0
  16. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/helpers/mpv-net/MpvStopParser.js +6 -1
  17. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/helpers/mpv-net/MpvStopParser.js.map +1 -1
  18. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/helpers/regional-bus/RegionalBusPositionsManager.d.ts +9 -12
  19. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/helpers/regional-bus/RegionalBusPositionsManager.js +347 -366
  20. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/helpers/regional-bus/RegionalBusPositionsManager.js.map +1 -1
  21. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/tasks/ProcessRegionalBusPositionsTask.d.ts +0 -1
  22. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/tasks/ProcessRegionalBusPositionsTask.js +4 -5
  23. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/tasks/ProcessRegionalBusPositionsTask.js.map +1 -1
  24. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/tasks/UpdateDelayTask.d.ts +0 -1
  25. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/tasks/UpdateDelayTask.js +5 -2
  26. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/tasks/UpdateDelayTask.js.map +1 -1
  27. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/transformations/MpvMessageTransformation.d.ts +6 -3
  28. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/transformations/MpvMessageTransformation.js +19 -8
  29. package/dist/integration-engine/vehicle-positions/workers/vehicle-positions/transformations/MpvMessageTransformation.js.map +1 -1
  30. package/package.json +3 -3
@@ -15,12 +15,6 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
- return c > 3 && r && Object.defineProperty(target, key, r), r;
23
- };
24
18
  var __importStar = (this && this.__importStar) || function (mod) {
25
19
  if (mod && mod.__esModule) return mod;
26
20
  var result = {};
@@ -28,12 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
28
22
  __setModuleDefault(result, mod);
29
23
  return result;
30
24
  };
31
- var __metadata = (this && this.__metadata) || function (k, v) {
32
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
33
- };
34
- var __param = (this && this.__param) || function (paramIndex, decorator) {
35
- return function (target, key) { decorator(target, key, paramIndex); }
36
- };
37
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
38
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
39
27
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -46,372 +34,365 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
46
34
  var __importDefault = (this && this.__importDefault) || function (mod) {
47
35
  return (mod && mod.__esModule) ? mod : { "default": mod };
48
36
  };
37
+ var _a;
49
38
  Object.defineProperty(exports, "__esModule", { value: true });
50
39
  exports.RegionalBusPositionsManager = void 0;
51
- const VPContainerToken_1 = require("../../../../ioc/VPContainerToken");
52
- const moment_timezone_1 = __importDefault(require("@golemio/core/dist/shared/moment-timezone"));
53
- const tsyringe_1 = require("@golemio/core/dist/shared/tsyringe");
54
40
  const turf = __importStar(require("@turf/turf"));
41
+ const moment_timezone_1 = __importDefault(require("@golemio/core/dist/shared/moment-timezone"));
55
42
  const const_1 = require("../../../../../../const");
56
43
  const DateTimeUtils_1 = require("../DateTimeUtils");
57
44
  const PositionHandlerEnum_1 = require("../PositionHandlerEnum");
58
- const ValidToCalculator_1 = require("../ValidToCalculator");
45
+ const ValidToCalculator_1 = __importDefault(require("../ValidToCalculator"));
59
46
  const AnchorPointSegmenter_1 = require("../anchor-points/AnchorPointSegmenter");
60
47
  const RegionalBusComputeDelayHelper_1 = require("./compute-positions/RegionalBusComputeDelayHelper");
61
- let RegionalBusPositionsManager = exports.RegionalBusPositionsManager = class RegionalBusPositionsManager {
62
- constructor(validToCalculator) {
63
- this.validToCalculator = validToCalculator;
64
- /**
65
- * Compute positions and return computed positions
66
- *
67
- * @param {ITripPositionsWithGTFS} tripPositions - Trip positions with shape anchors data
68
- * @returns {Promise<IProcessedPositions>} - Returns computed/updated positions
69
- */
70
- this.computePositions = (tripPositions) => __awaiter(this, void 0, void 0, function* () {
71
- const startTimestamp = tripPositions.start_timestamp.getTime();
72
- const startDayTimestamp = this.getStartDayTimestamp(startTimestamp, tripPositions.gtfsData.shapes_anchor_points[0].time_scheduled_seconds);
73
- const gtfsRouteType = tripPositions.gtfs_route_type;
74
- const context = this.getCurrentContext(tripPositions);
75
- const computedPositions = [];
76
- return this.updatePositions({
77
- tripPositions,
78
- startTimestamp,
79
- startDayTimestamp,
80
- endTimestamp: null,
81
- context,
82
- computedPositions,
83
- gtfsRouteType,
84
- });
85
- });
86
- /**
87
- * Takes position one by one, set proper handler for type of position, and do the process of position
88
- */
89
- this.updatePositions = (options) => __awaiter(this, void 0, void 0, function* () {
90
- var _a, _b, _c, _d, _e;
91
- const { tripPositions, startDayTimestamp, startTimestamp, context, computedPositions, gtfsRouteType } = options;
92
- for (let i = 0; i < tripPositions.positions.length; i++) {
93
- const position = tripPositions.positions[i];
94
- let positionToUpdate = null;
95
- // situations
96
- switch (this.setPositionUpdateHandler(position)) {
97
- case PositionHandlerEnum_1.PositionHandlerEnum.TRACKING:
98
- const currentPosition = turf.point([position.lng, position.lat], {
99
- id: position.id,
100
- origin_time: position.origin_time,
101
- origin_timestamp: position.origin_timestamp,
102
- scheduled_timestamp: position.scheduled_timestamp,
103
- this_stop_id: position.this_stop_id,
104
- tcp_event: position.tcp_event,
105
- });
106
- positionToUpdate = yield this.getEstimatedPoint(tripPositions.gtfsData, currentPosition, context, startDayTimestamp);
107
- positionToUpdate = RegionalBusComputeDelayHelper_1.RegionalBusComputeDelayHelper.updatePositionToUpdate(context, positionToUpdate, position, gtfsRouteType);
108
- positionToUpdate.bearing = (_a = position.bearing) !== null && _a !== void 0 ? _a : positionToUpdate.bearing;
109
- break;
110
- case PositionHandlerEnum_1.PositionHandlerEnum.NOT_TRACKING:
111
- // if there is no previous positions with tracking status, set position as before_track
112
- if (context.lastPositionTracking === null) {
113
- const firstStopTime = tripPositions.gtfsData.stop_times[0];
114
- positionToUpdate = Object.assign({ id: position.id, next_stop_arrival_time: new Date(startDayTimestamp + firstStopTime.arrival_time_seconds * 1000), next_stop_departure_time: new Date(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: const_1.StatePositionEnum.BEFORE_TRACK, state_process: const_1.StateProcessEnum.PROCESSED }, (firstStopTime.stop_headsign && {
115
- last_stop_headsign: firstStopTime.stop_headsign,
116
- }));
117
- if (positionToUpdate.state_position === const_1.StatePositionEnum.BEFORE_TRACK) {
118
- positionToUpdate.delay = 0;
119
- }
120
- }
121
- else {
122
- // if there is tracking 2 position with same origin_timestamp then this position is duplicate
123
- const statePosition = position.origin_timestamp.getTime() === context.lastPositionOriginTimestamp ||
124
- tripPositions.positions.findIndex((positionItem) => positionItem.origin_timestamp.getTime() === position.origin_timestamp.getTime() &&
125
- positionItem.is_tracked) >= 0
126
- ? const_1.StatePositionEnum.DUPLICATE
127
- : const_1.StatePositionEnum.AFTER_TRACK;
128
- const lastShapesAnchorPoint = tripPositions.gtfsData.shapes_anchor_points[tripPositions.gtfsData.shapes_anchor_points.length - 1];
129
- const lastStopTime = tripPositions.gtfsData.stop_times[tripPositions.gtfsData.stop_times.length - 1];
130
- positionToUpdate = Object.assign({ id: position.id, last_stop_arrival_time: new Date(startDayTimestamp + lastShapesAnchorPoint.time_scheduled_seconds * 1000), last_stop_departure_time: new Date(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: statePosition, state_process: const_1.StateProcessEnum.PROCESSED }, (lastStopTime.stop_headsign && {
131
- last_stop_headsign: lastStopTime.stop_headsign,
132
- }));
133
- positionToUpdate = RegionalBusComputeDelayHelper_1.RegionalBusComputeDelayHelper.updatePositionToUpdate(context, positionToUpdate, position, gtfsRouteType);
134
- }
135
- break;
136
- case PositionHandlerEnum_1.PositionHandlerEnum.DO_NOTHING:
137
- default:
138
- break;
139
- }
140
- // if not null push to update
141
- if (positionToUpdate) {
142
- (_b = positionToUpdate.is_tracked) !== null && _b !== void 0 ? _b : (positionToUpdate.is_tracked = position.is_tracked);
143
- positionToUpdate.valid_to = this.validToCalculator.getValidToAttribute(positionToUpdate, position, gtfsRouteType, tripPositions.gtfsData, startTimestamp);
144
- computedPositions.push(positionToUpdate);
145
- }
146
- context.lastPositionState = (_c = positionToUpdate === null || positionToUpdate === void 0 ? void 0 : positionToUpdate.state_position) !== null && _c !== void 0 ? _c : position.state_position;
147
- // set last known BEFORE_TRACK_DELAYED position
148
- if (position.state_position === const_1.StatePositionEnum.BEFORE_TRACK_DELAYED) {
149
- context.lastPositionBeforeTrackDelayed = {
150
- delay: (_d = positionToUpdate === null || positionToUpdate === void 0 ? void 0 : positionToUpdate.delay) !== null && _d !== void 0 ? _d : position.delay,
151
- origin_timestamp: (_e = positionToUpdate === null || positionToUpdate === void 0 ? void 0 : positionToUpdate.origin_timestamp) !== null && _e !== void 0 ? _e : position.origin_timestamp,
152
- };
153
- }
154
- // set last position tracking (only for at_stop and on_track)
155
- if ((positionToUpdate === null || positionToUpdate === void 0 ? void 0 : positionToUpdate.state_position) === const_1.StatePositionEnum.AT_STOP ||
156
- (positionToUpdate === null || positionToUpdate === void 0 ? void 0 : positionToUpdate.state_position) === const_1.StatePositionEnum.ON_TRACK ||
157
- position.state_position === const_1.StatePositionEnum.AT_STOP ||
158
- position.state_position === const_1.StatePositionEnum.ON_TRACK) {
159
- context.lastPositionTracking = turf.point([position.lng, position.lat], Object.assign(Object.assign({}, position), positionToUpdate));
160
- }
161
- // set new first position at stop streak if this stop seqence is set and it is not same as before
162
- if (positionToUpdate
163
- ? positionToUpdate.this_stop_sequence &&
164
- context.atStopStreak.stop_sequence !== positionToUpdate.this_stop_sequence
165
- : position.this_stop_sequence && context.atStopStreak.stop_sequence !== position.this_stop_sequence) {
166
- context.atStopStreak.stop_sequence = positionToUpdate
167
- ? positionToUpdate.this_stop_sequence
168
- : position.this_stop_sequence;
169
- context.atStopStreak.firstPositionTimestamp = position.origin_timestamp.getTime();
170
- context.atStopStreak.firstPositionDelay = positionToUpdate ? positionToUpdate.delay : position.delay;
171
- }
172
- // IF currently valid updated position / position was processed before
173
- // and it is NOT AT_STOP
174
- // then disrupt atStopStreak
175
- if (positionToUpdate && !positionToUpdate.this_stop_sequence) {
176
- context.atStopStreak.stop_sequence = null;
177
- }
178
- else if (!positionToUpdate && !position.this_stop_sequence) {
179
- context.atStopStreak.stop_sequence = null;
48
+ class RegionalBusPositionsManager {
49
+ }
50
+ exports.RegionalBusPositionsManager = RegionalBusPositionsManager;
51
+ _a = RegionalBusPositionsManager;
52
+ /**
53
+ * Compute positions and return computed positions
54
+ *
55
+ * @param {ITripPositionsWithGTFS} tripPositions - Trip positions with shape anchors data
56
+ * @returns {Promise<IProcessedPositions>} - Returns computed/updated positions
57
+ */
58
+ RegionalBusPositionsManager.computePositions = (tripPositions) => __awaiter(void 0, void 0, void 0, function* () {
59
+ const startTimestamp = tripPositions.start_timestamp.getTime();
60
+ const startDayTimestamp = _a.getStartDayTimestamp(startTimestamp, tripPositions.gtfsData.shapes_anchor_points[0].time_scheduled_seconds);
61
+ const gtfsRouteType = tripPositions.gtfs_route_type;
62
+ const context = RegionalBusPositionsManager.getCurrentContext(tripPositions);
63
+ const computedPositions = [];
64
+ return RegionalBusPositionsManager.updatePositions({
65
+ tripPositions,
66
+ startTimestamp,
67
+ startDayTimestamp,
68
+ endTimestamp: null,
69
+ context,
70
+ computedPositions,
71
+ gtfsRouteType,
72
+ });
73
+ });
74
+ /**
75
+ * Takes position one by one, set proper handler for type of position, and do the process of position
76
+ */
77
+ RegionalBusPositionsManager.updatePositions = (options) => __awaiter(void 0, void 0, void 0, function* () {
78
+ var _b, _c, _d, _e, _f;
79
+ const { tripPositions, startDayTimestamp, startTimestamp, context, computedPositions, gtfsRouteType } = options;
80
+ for (let i = 0; i < tripPositions.positions.length; i++) {
81
+ const position = tripPositions.positions[i];
82
+ let positionToUpdate = null;
83
+ // situations
84
+ switch (_a.setPositionUpdateHandler(position)) {
85
+ case PositionHandlerEnum_1.PositionHandlerEnum.TRACKING:
86
+ const currentPosition = turf.point([position.lng, position.lat], {
87
+ id: position.id,
88
+ origin_time: position.origin_time,
89
+ origin_timestamp: position.origin_timestamp,
90
+ scheduled_timestamp: position.scheduled_timestamp,
91
+ this_stop_id: position.this_stop_id,
92
+ tcp_event: position.tcp_event,
93
+ });
94
+ positionToUpdate = yield _a.getEstimatedPoint(tripPositions.gtfsData, currentPosition, context, startDayTimestamp);
95
+ positionToUpdate = RegionalBusComputeDelayHelper_1.RegionalBusComputeDelayHelper.updatePositionToUpdate(context, positionToUpdate, position, gtfsRouteType);
96
+ positionToUpdate.bearing = (_b = position.bearing) !== null && _b !== void 0 ? _b : positionToUpdate.bearing;
97
+ break;
98
+ case PositionHandlerEnum_1.PositionHandlerEnum.NOT_TRACKING:
99
+ // if there is no previous positions with tracking status, set position as before_track
100
+ if (context.lastPositionTracking === null) {
101
+ const firstStopTime = tripPositions.gtfsData.stop_times[0];
102
+ positionToUpdate = Object.assign({ id: position.id, next_stop_arrival_time: new Date(startDayTimestamp + firstStopTime.arrival_time_seconds * 1000), next_stop_departure_time: new Date(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: const_1.StatePositionEnum.BEFORE_TRACK, state_process: const_1.StateProcessEnum.PROCESSED }, (firstStopTime.stop_headsign && {
103
+ last_stop_headsign: firstStopTime.stop_headsign,
104
+ }));
105
+ if (positionToUpdate.state_position === const_1.StatePositionEnum.BEFORE_TRACK) {
106
+ positionToUpdate.delay = 0;
107
+ }
180
108
  }
181
- // duplicated position should not be considered at all
182
- if ((positionToUpdate === null || positionToUpdate === void 0 ? void 0 : positionToUpdate.state_position) !== const_1.StatePositionEnum.DUPLICATE) {
183
- context.lastPositionId = position.id;
184
- context.lastPositionCanceled = position.is_canceled;
185
- context.lastPositionOriginTimestamp = position.origin_timestamp.getTime();
186
- RegionalBusComputeDelayHelper_1.RegionalBusComputeDelayHelper.updateContext(context, positionToUpdate, position, gtfsRouteType);
109
+ else {
110
+ // if there is tracking 2 position with same origin_timestamp then this position is duplicate
111
+ const statePosition = position.origin_timestamp.getTime() === context.lastPositionOriginTimestamp ||
112
+ tripPositions.positions.findIndex((positionItem) => positionItem.origin_timestamp.getTime() === position.origin_timestamp.getTime() &&
113
+ positionItem.is_tracked) >= 0
114
+ ? const_1.StatePositionEnum.DUPLICATE
115
+ : const_1.StatePositionEnum.AFTER_TRACK;
116
+ const lastShapesAnchorPoint = tripPositions.gtfsData.shapes_anchor_points[tripPositions.gtfsData.shapes_anchor_points.length - 1];
117
+ const lastStopTime = tripPositions.gtfsData.stop_times[tripPositions.gtfsData.stop_times.length - 1];
118
+ positionToUpdate = Object.assign({ id: position.id, last_stop_arrival_time: new Date(startDayTimestamp + lastShapesAnchorPoint.time_scheduled_seconds * 1000), last_stop_departure_time: new Date(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: statePosition, state_process: const_1.StateProcessEnum.PROCESSED }, (lastStopTime.stop_headsign && {
119
+ last_stop_headsign: lastStopTime.stop_headsign,
120
+ }));
121
+ positionToUpdate = RegionalBusComputeDelayHelper_1.RegionalBusComputeDelayHelper.updatePositionToUpdate(context, positionToUpdate, position, gtfsRouteType);
187
122
  }
188
- }
189
- return {
190
- context,
191
- positions: computedPositions,
123
+ break;
124
+ case PositionHandlerEnum_1.PositionHandlerEnum.DO_NOTHING:
125
+ default:
126
+ break;
127
+ }
128
+ // if not null push to update
129
+ if (positionToUpdate) {
130
+ (_c = positionToUpdate.is_tracked) !== null && _c !== void 0 ? _c : (positionToUpdate.is_tracked = position.is_tracked);
131
+ positionToUpdate.valid_to = ValidToCalculator_1.default.getValidToAttribute(positionToUpdate, position, gtfsRouteType, tripPositions.gtfsData, startTimestamp, startDayTimestamp);
132
+ computedPositions.push(positionToUpdate);
133
+ }
134
+ context.lastPositionState = (_d = positionToUpdate === null || positionToUpdate === void 0 ? void 0 : positionToUpdate.state_position) !== null && _d !== void 0 ? _d : position.state_position;
135
+ // set last known BEFORE_TRACK_DELAYED position
136
+ if (position.state_position === const_1.StatePositionEnum.BEFORE_TRACK_DELAYED) {
137
+ context.lastPositionBeforeTrackDelayed = {
138
+ delay: (_e = positionToUpdate === null || positionToUpdate === void 0 ? void 0 : positionToUpdate.delay) !== null && _e !== void 0 ? _e : position.delay,
139
+ origin_timestamp: (_f = positionToUpdate === null || positionToUpdate === void 0 ? void 0 : positionToUpdate.origin_timestamp) !== null && _f !== void 0 ? _f : position.origin_timestamp,
192
140
  };
141
+ }
142
+ // set last position tracking (only for at_stop and on_track)
143
+ if ((positionToUpdate === null || positionToUpdate === void 0 ? void 0 : positionToUpdate.state_position) === const_1.StatePositionEnum.AT_STOP ||
144
+ (positionToUpdate === null || positionToUpdate === void 0 ? void 0 : positionToUpdate.state_position) === const_1.StatePositionEnum.ON_TRACK ||
145
+ position.state_position === const_1.StatePositionEnum.AT_STOP ||
146
+ position.state_position === const_1.StatePositionEnum.ON_TRACK) {
147
+ context.lastPositionTracking = turf.point([position.lng, position.lat], Object.assign(Object.assign({}, position), positionToUpdate));
148
+ }
149
+ // set new first position at stop streak if this stop seqence is set and it is not same as before
150
+ if (positionToUpdate
151
+ ? positionToUpdate.this_stop_sequence &&
152
+ context.atStopStreak.stop_sequence !== positionToUpdate.this_stop_sequence
153
+ : position.this_stop_sequence && context.atStopStreak.stop_sequence !== position.this_stop_sequence) {
154
+ context.atStopStreak.stop_sequence = positionToUpdate
155
+ ? positionToUpdate.this_stop_sequence
156
+ : position.this_stop_sequence;
157
+ context.atStopStreak.firstPositionTimestamp = position.origin_timestamp.getTime();
158
+ context.atStopStreak.firstPositionDelay = positionToUpdate ? positionToUpdate.delay : position.delay;
159
+ }
160
+ // IF currently valid updated position / position was processed before
161
+ // and it is NOT AT_STOP
162
+ // then disrupt atStopStreak
163
+ if (positionToUpdate && !positionToUpdate.this_stop_sequence) {
164
+ context.atStopStreak.stop_sequence = null;
165
+ }
166
+ else if (!positionToUpdate && !position.this_stop_sequence) {
167
+ context.atStopStreak.stop_sequence = null;
168
+ }
169
+ // duplicated position should not be considered at all
170
+ if ((positionToUpdate === null || positionToUpdate === void 0 ? void 0 : positionToUpdate.state_position) !== const_1.StatePositionEnum.DUPLICATE) {
171
+ context.lastPositionId = position.id;
172
+ context.lastPositionCanceled = position.is_canceled;
173
+ context.lastPositionOriginTimestamp = position.origin_timestamp.getTime();
174
+ RegionalBusComputeDelayHelper_1.RegionalBusComputeDelayHelper.updateContext(context, positionToUpdate, position, gtfsRouteType);
175
+ }
176
+ }
177
+ return {
178
+ context,
179
+ positions: computedPositions,
180
+ };
181
+ });
182
+ RegionalBusPositionsManager.getCurrentContext = (tripPositions) => {
183
+ var _b;
184
+ const context = (_b = tripPositions.last_position_context) !== null && _b !== void 0 ? _b : {
185
+ atStopStreak: {
186
+ stop_sequence: null,
187
+ firstPositionTimestamp: null,
188
+ firstPositionDelay: null,
189
+ },
190
+ lastPositionLastStop: {
191
+ id: null,
192
+ sequence: null,
193
+ arrival_time: null,
194
+ arrival_delay: null,
195
+ departure_time: null,
196
+ departure_delay: null,
197
+ },
198
+ lastPositionDelay: null,
199
+ lastPositionId: null,
200
+ lastPositionOriginTimestamp: null,
201
+ lastPositionTracking: null,
202
+ lastPositionCanceled: null,
203
+ lastPositionBeforeTrackDelayed: null,
204
+ lastPositionState: null,
205
+ tripId: tripPositions.id,
206
+ };
207
+ return context;
208
+ };
209
+ /**
210
+ * Decide how to process input position data
211
+ *
212
+ * @param {IVPTripsPositionAttributes} position - Input vehiclepositions_positions row data
213
+ * @returns {PositionHandlerEnum} - Returns action handler enum
214
+ */
215
+ RegionalBusPositionsManager.setPositionUpdateHandler = (position) => {
216
+ if (position.state_process === const_1.StateProcessEnum.PROCESSED)
217
+ return PositionHandlerEnum_1.PositionHandlerEnum.DO_NOTHING;
218
+ else if (position.is_tracked)
219
+ return PositionHandlerEnum_1.PositionHandlerEnum.TRACKING;
220
+ else
221
+ return PositionHandlerEnum_1.PositionHandlerEnum.NOT_TRACKING;
222
+ };
223
+ /**
224
+ * Returns estimate of point on shape, where the trip should be with appropriate delay
225
+ *
226
+ * @param {IShapeAnchorPoint[]} tripShapePoints - Precalculated trip shape equidistant points with scheduled times
227
+ * @param {Feature<Point, ICurrentPositionProperties>} currentPosition - Current position of trip
228
+ * @param {IVPTripsLastPositionContext | null} context - Context state, holds information about previous positions
229
+ * @param {number} startDayTimestamp - Unix timestamp of midnight before trip starts
230
+ * @returns {IPositionToUpdate} - Position object to update
231
+ */
232
+ RegionalBusPositionsManager.getEstimatedPoint = (tripGtfsData, currentPosition, context, startDayTimestamp) => {
233
+ var _b, _c, _d, _e, _f, _g, _h, _j;
234
+ const anchorPointSegmenter = new AnchorPointSegmenter_1.AnchorPointSegmenter(tripGtfsData.shapes_anchor_points, currentPosition);
235
+ const defaultStatePosition = const_1.StatePositionEnum.OFF_TRACK;
236
+ // Initial value
237
+ let estimatedPoint = Object.assign({ id: currentPosition.properties.id, state_position: defaultStatePosition, state_process: const_1.StateProcessEnum.PROCESSED, tcp_event: currentPosition.properties.tcp_event, valid_to: ValidToCalculator_1.default.getDefaultValidToAttribute(currentPosition.properties.origin_timestamp) }, (context &&
238
+ ((_b = context.lastPositionTracking) === null || _b === void 0 ? void 0 : _b.properties.last_stop_sequence) && {
239
+ shape_dist_traveled: (_c = context.lastPositionTracking) === null || _c === void 0 ? void 0 : _c.properties.shape_dist_traveled,
240
+ last_stop_arrival_time: ((_d = context.lastPositionTracking) === null || _d === void 0 ? void 0 : _d.properties.last_stop_arrival_time)
241
+ ? new Date((_e = context.lastPositionTracking) === null || _e === void 0 ? void 0 : _e.properties.last_stop_arrival_time)
242
+ : undefined,
243
+ last_stop_departure_time: ((_f = context.lastPositionTracking) === null || _f === void 0 ? void 0 : _f.properties.last_stop_departure_time)
244
+ ? new Date((_g = context.lastPositionTracking) === null || _g === void 0 ? void 0 : _g.properties.last_stop_departure_time)
245
+ : undefined,
246
+ last_stop_sequence: (_h = context.lastPositionTracking) === null || _h === void 0 ? void 0 : _h.properties.last_stop_sequence,
247
+ last_stop_id: (_j = context.lastPositionTracking) === null || _j === void 0 ? void 0 : _j.properties.last_stop_id,
248
+ }));
249
+ let lastStopSequence = null;
250
+ if ((context === null || context === void 0 ? void 0 : context.lastPositionState) === const_1.StatePositionEnum.BEFORE_TRACK) {
251
+ lastStopSequence = 1;
252
+ }
253
+ else if (context === null || context === void 0 ? void 0 : context.lastPositionTracking) {
254
+ lastStopSequence = context.lastPositionTracking.properties.last_stop_sequence;
255
+ }
256
+ const closesPoint = anchorPointSegmenter.getClosesPoint(lastStopSequence);
257
+ if (!closesPoint) {
258
+ return estimatedPoint;
259
+ }
260
+ return _a.getClosestPoint(currentPosition, context, startDayTimestamp, closesPoint, tripGtfsData);
261
+ };
262
+ /**
263
+ * Picks only one closest point for multiple possible points based on delay of last position and stop times
264
+ *
265
+ * @param {Feature<Point, ICurrentPositionProperties>} currentPosition - Feature Point of current position
266
+ * @param {IVPTripsLastPositionContext | null} context - Context state, holds information about previous positions
267
+ * @param {number} startDayTimestamp - Unix timestamp of start of the day
268
+ * @param {IShapeAnchorPoint[]} closestPts - All closest points of possible segments
269
+ * @param {IComputationTrip} tripGtfsData - GTFS data and all set of known positions
270
+ * @returns {IPositionToUpdate} - Result point as position to update in DB
271
+ */
272
+ RegionalBusPositionsManager.getClosestPoint = (currentPosition, context, startDayTimestamp, thisClosestPoint, tripGtfsData) => {
273
+ // want to find minimum difference of our prediction, where the bus should be
274
+ let minTimeRealDiff = Infinity;
275
+ const tripShapePoints = tripGtfsData.shapes_anchor_points;
276
+ const tripStopTimes = tripGtfsData.stop_times;
277
+ const firstTripShapePoint = tripShapePoints[0];
278
+ const lastTripShapePoint = tripShapePoints[tripShapePoints.length - 1];
279
+ const timeScheduledTimestamp = DateTimeUtils_1.DateTimeUtils.getStopDateTimeForDayStart(
280
+ // take stop arrival time if is point at stop
281
+ thisClosestPoint.this_stop_sequence
282
+ ? tripStopTimes[thisClosestPoint.this_stop_sequence - 1].arrival_time_seconds
283
+ : thisClosestPoint.time_scheduled_seconds, startDayTimestamp);
284
+ let timeDelayInSeconds = Math.round((currentPosition.properties.origin_timestamp.getTime() - timeScheduledTimestamp.getTime()) / 1000);
285
+ // lets correct delay if it is at stop
286
+ if (thisClosestPoint.this_stop_sequence) {
287
+ const thisStopSequence = thisClosestPoint.this_stop_sequence;
288
+ timeDelayInSeconds = _a.getCorrectedTimeDelay(timeDelayInSeconds, context, currentPosition, thisStopSequence, {
289
+ departureTime: tripStopTimes[thisStopSequence - 1].departure_time_seconds,
290
+ arrivalTime: tripStopTimes[thisStopSequence - 1].arrival_time_seconds,
193
291
  });
194
- this.getCurrentContext = (tripPositions) => {
195
- var _a;
196
- const context = (_a = tripPositions.last_position_context) !== null && _a !== void 0 ? _a : {
197
- atStopStreak: {
198
- stop_sequence: null,
199
- firstPositionTimestamp: null,
200
- firstPositionDelay: null,
201
- },
202
- lastPositionLastStop: {
203
- id: null,
204
- sequence: null,
205
- arrival_time: null,
206
- arrival_delay: null,
207
- departure_time: null,
208
- departure_delay: null,
209
- },
210
- lastPositionDelay: null,
211
- lastPositionId: null,
212
- lastPositionOriginTimestamp: null,
213
- lastPositionTracking: null,
214
- lastPositionCanceled: null,
215
- lastPositionBeforeTrackDelayed: null,
216
- lastPositionState: null,
217
- tripId: tripPositions.id,
218
- };
219
- return context;
220
- };
221
- /**
222
- * Decide how to process input position data
223
- *
224
- * @param {IVPTripsPositionAttributes} position - Input vehiclepositions_positions row data
225
- * @returns {PositionHandlerEnum} - Returns action handler enum
226
- */
227
- this.setPositionUpdateHandler = (position) => {
228
- if (position.state_process === const_1.StateProcessEnum.PROCESSED)
229
- return PositionHandlerEnum_1.PositionHandlerEnum.DO_NOTHING;
230
- else if (position.is_tracked)
231
- return PositionHandlerEnum_1.PositionHandlerEnum.TRACKING;
232
- else
233
- return PositionHandlerEnum_1.PositionHandlerEnum.NOT_TRACKING;
234
- };
235
- /**
236
- * Returns estimate of point on shape, where the trip should be with appropriate delay
237
- *
238
- * @param {IShapeAnchorPoint[]} tripShapePoints - Precalculated trip shape equidistant points with scheduled times
239
- * @param {Feature<Point, ICurrentPositionProperties>} currentPosition - Current position of trip
240
- * @param {IVPTripsLastPositionContext | null} context - Context state, holds information about previous positions
241
- * @param {number} startDayTimestamp - Unix timestamp of midnight before trip starts
242
- * @returns {IPositionToUpdate} - Position object to update
243
- */
244
- this.getEstimatedPoint = (tripGtfsData, currentPosition, context, startDayTimestamp) => {
245
- var _a, _b, _c, _d, _e, _f, _g, _h;
246
- const anchorPointSegmenter = new AnchorPointSegmenter_1.AnchorPointSegmenter(tripGtfsData.shapes_anchor_points, currentPosition);
247
- const defaultStatePosition = const_1.StatePositionEnum.OFF_TRACK;
248
- // Initial value
249
- let estimatedPoint = Object.assign({ id: currentPosition.properties.id, state_position: defaultStatePosition, state_process: const_1.StateProcessEnum.PROCESSED, tcp_event: currentPosition.properties.tcp_event, valid_to: this.validToCalculator.getDefaultValidToAttribute(currentPosition.properties.origin_timestamp) }, (context &&
250
- ((_a = context.lastPositionTracking) === null || _a === void 0 ? void 0 : _a.properties.last_stop_sequence) && {
251
- shape_dist_traveled: (_b = context.lastPositionTracking) === null || _b === void 0 ? void 0 : _b.properties.shape_dist_traveled,
252
- last_stop_arrival_time: ((_c = context.lastPositionTracking) === null || _c === void 0 ? void 0 : _c.properties.last_stop_arrival_time)
253
- ? new Date((_d = context.lastPositionTracking) === null || _d === void 0 ? void 0 : _d.properties.last_stop_arrival_time)
254
- : undefined,
255
- last_stop_departure_time: ((_e = context.lastPositionTracking) === null || _e === void 0 ? void 0 : _e.properties.last_stop_departure_time)
256
- ? new Date((_f = context.lastPositionTracking) === null || _f === void 0 ? void 0 : _f.properties.last_stop_departure_time)
257
- : undefined,
258
- last_stop_sequence: (_g = context.lastPositionTracking) === null || _g === void 0 ? void 0 : _g.properties.last_stop_sequence,
259
- last_stop_id: (_h = context.lastPositionTracking) === null || _h === void 0 ? void 0 : _h.properties.last_stop_id,
260
- }));
261
- let lastStopSequence = null;
262
- if ((context === null || context === void 0 ? void 0 : context.lastPositionState) === const_1.StatePositionEnum.BEFORE_TRACK) {
263
- lastStopSequence = 1;
264
- }
265
- else if (context === null || context === void 0 ? void 0 : context.lastPositionTracking) {
266
- lastStopSequence = context.lastPositionTracking.properties.last_stop_sequence;
267
- }
268
- const closesPoint = anchorPointSegmenter.getClosesPoint(lastStopSequence);
269
- if (!closesPoint) {
270
- return estimatedPoint;
271
- }
272
- return this.getClosestPoint(currentPosition, context, startDayTimestamp, closesPoint, tripGtfsData);
273
- };
274
- /**
275
- * Picks only one closest point for multiple possible points based on delay of last position and stop times
276
- *
277
- * @param {Feature<Point, ICurrentPositionProperties>} currentPosition - Feature Point of current position
278
- * @param {IVPTripsLastPositionContext | null} context - Context state, holds information about previous positions
279
- * @param {number} startDayTimestamp - Unix timestamp of start of the day
280
- * @param {IShapeAnchorPoint[]} closestPts - All closest points of possible segments
281
- * @param {IComputationTrip} tripGtfsData - GTFS data and all set of known positions
282
- * @returns {IPositionToUpdate} - Result point as position to update in DB
283
- */
284
- this.getClosestPoint = (currentPosition, context, startDayTimestamp, thisClosestPoint, tripGtfsData) => {
285
- // want to find minimum difference of our prediction, where the bus should be
286
- let minTimeRealDiff = Infinity;
287
- const tripShapePoints = tripGtfsData.shapes_anchor_points;
288
- const tripStopTimes = tripGtfsData.stop_times;
289
- const firstTripShapePoint = tripShapePoints[0];
290
- const lastTripShapePoint = tripShapePoints[tripShapePoints.length - 1];
291
- const timeScheduledTimestamp = DateTimeUtils_1.DateTimeUtils.getStopDateTimeForDayStart(
292
- // take stop arrival time if is point at stop
293
- thisClosestPoint.this_stop_sequence
294
- ? tripStopTimes[thisClosestPoint.this_stop_sequence - 1].arrival_time_seconds
295
- : thisClosestPoint.time_scheduled_seconds, startDayTimestamp);
296
- let timeDelayInSeconds = Math.round((currentPosition.properties.origin_timestamp.getTime() - timeScheduledTimestamp.getTime()) / 1000);
297
- // lets correct delay if it is at stop
298
- if (thisClosestPoint.this_stop_sequence) {
299
- const thisStopSequence = thisClosestPoint.this_stop_sequence;
300
- timeDelayInSeconds = this.getCorrectedTimeDelay(timeDelayInSeconds, context, currentPosition, thisStopSequence, {
301
- departureTime: tripStopTimes[thisStopSequence - 1].departure_time_seconds,
302
- arrivalTime: tripStopTimes[thisStopSequence - 1].arrival_time_seconds,
303
- });
304
- // delay can not be negative if the vehicle is at the first stop
305
- if (thisStopSequence === firstTripShapePoint.this_stop_sequence) {
306
- timeDelayInSeconds = Math.max(timeDelayInSeconds, 0);
307
- }
308
- }
309
- const statePosition = this.determineStatePosition(thisClosestPoint, lastTripShapePoint);
310
- const thisStopSequence = thisClosestPoint.this_stop_sequence;
311
- const lastStopSequence = thisClosestPoint.last_stop_sequence;
312
- const nextStopSequence = thisClosestPoint.next_stop_sequence;
313
- // save it for result
314
- const estimatedPoint = {
315
- id: currentPosition.properties.id,
316
- bearing: thisClosestPoint.bearing,
317
- shape_dist_traveled: Math.round(thisClosestPoint.shape_dist_traveled * 1000) / 1000,
318
- next_stop_id: tripStopTimes[nextStopSequence - 1].stop_id,
319
- last_stop_id: tripStopTimes[lastStopSequence - 1].stop_id,
320
- next_stop_name: tripStopTimes[nextStopSequence - 1].stop.stop_name,
321
- last_stop_name: tripStopTimes[lastStopSequence - 1].stop.stop_name,
322
- next_stop_sequence: nextStopSequence,
323
- last_stop_sequence: lastStopSequence,
324
- next_stop_arrival_time: DateTimeUtils_1.DateTimeUtils.getStopDateTimeForDayStart(tripStopTimes[nextStopSequence - 1].arrival_time_seconds, startDayTimestamp),
325
- last_stop_arrival_time: DateTimeUtils_1.DateTimeUtils.getStopDateTimeForDayStart(tripStopTimes[lastStopSequence - 1].arrival_time_seconds, startDayTimestamp),
326
- next_stop_departure_time: DateTimeUtils_1.DateTimeUtils.getStopDateTimeForDayStart(tripStopTimes[nextStopSequence - 1].departure_time_seconds, startDayTimestamp),
327
- last_stop_departure_time: DateTimeUtils_1.DateTimeUtils.getStopDateTimeForDayStart(tripStopTimes[lastStopSequence - 1].departure_time_seconds, startDayTimestamp),
328
- delay: statePosition === const_1.StatePositionEnum.AFTER_TRACK ? 0 : timeDelayInSeconds,
329
- this_stop_id: (statePosition === const_1.StatePositionEnum.AT_STOP &&
330
- thisStopSequence &&
331
- tripStopTimes[thisStopSequence - 1].stop_id) ||
332
- undefined,
333
- this_stop_name: (statePosition === const_1.StatePositionEnum.AT_STOP &&
334
- thisStopSequence &&
335
- tripStopTimes[thisStopSequence - 1].stop.stop_name) ||
336
- undefined,
337
- this_stop_sequence: (statePosition === const_1.StatePositionEnum.AT_STOP && thisStopSequence) || undefined,
338
- last_stop_headsign: tripStopTimes[lastStopSequence - 1].stop_headsign || undefined,
339
- state_position: statePosition,
340
- state_process: const_1.StateProcessEnum.PROCESSED,
341
- valid_to: this.validToCalculator.getDefaultValidToAttribute(currentPosition.properties.origin_timestamp),
342
- is_tracked: statePosition !== const_1.StatePositionEnum.AFTER_TRACK,
343
- };
344
- return estimatedPoint;
345
- };
346
- /**
347
- * Corrects time delay at stop with dwelling time
348
- *
349
- * @param {number} timeDelay - Initial computed delay in seconds, can be negative for trip ahead
350
- * @param {IVPTripsLastPositionContext | null} context - Context state, holds information about previous positions
351
- * @param {Feature<Point, ICurrentPositionProperties>} currentPosition - Feature Point of current position
352
- * @param {IShapeAnchorPoint} thisClosestPoint - Closest point of shape anchors
353
- * @param { departureTime: number; arrivalTime: number } stopTimes - departure and arrival stop times in seconds
354
- * @returns {number} - Result delay in seconds, can be negative for trip ahead
355
- */
356
- this.getCorrectedTimeDelay = (timeDelay, context, currentPosition, thisStopSequence, stopTimes) => {
357
- // compute dwell time in stop, most common is zero
358
- const stopDwellTimeSeconds = stopTimes.departureTime - stopTimes.arrivalTime;
359
- // if dwell time is sheduled as zero, return initial computed delay
360
- if (stopDwellTimeSeconds <= 0) {
361
- return timeDelay;
362
- }
363
- // if last position was not in this same stop or there is no last position at all
364
- if (!context || context.atStopStreak.stop_sequence !== thisStopSequence) {
365
- // timeDelay >= 0 trip is DELAYED
366
- // we presume it will lower delay by shortening its scheduled dwell time,
367
- // cant go under zero of course, trip should not go ahead
368
- // else trip is AHeAD
369
- // left computed delay as it was
370
- return timeDelay >= 0 ? Math.max(timeDelay - stopDwellTimeSeconds, 0) : timeDelay;
371
- }
372
- // we presume that first position at same stop is real arrival time
373
- if (context.atStopStreak.firstPositionDelay >= 0) {
374
- // trip was DELAYED before
375
- // we presume it will lower delay by shortening its scheduled dwell time,
376
- // cant go under zero of course, trip should not go ahead
377
- return Math.max(timeDelay - stopDwellTimeSeconds, 0);
378
- }
379
- // trip was AHEAD before
380
- // real dwell time so far
381
- const realDwellTimeSeconds = Math.round((currentPosition.properties.origin_timestamp.getTime() - context.atStopStreak.firstPositionTimestamp) / 1000);
382
- // if real dwell is longer than scheduled, then add to negative delay time
383
- return context.atStopStreak.firstPositionDelay + Math.max(realDwellTimeSeconds - stopDwellTimeSeconds, 0);
384
- };
385
- /**
386
- * Compute UTC timestamp of start of day when trip starts
387
- *
388
- * @param {number} startTimestamp - Unix timestamp of start of the trip
389
- * @param {number} firstStopTimeScheduledSeconds - Number of seconds from midnight of first stop departure
390
- * @returns {number} - Returns unix timestamp in milliseconds.
391
- */
392
- this.getStartDayTimestamp = (startTimestamp, firstStopTimeScheduledSeconds) => {
393
- let startDayTimestamp = moment_timezone_1.default.utc(startTimestamp).tz("Europe/Prague").startOf("day");
394
- const stopTimeDayOverflow = Math.floor(firstStopTimeScheduledSeconds / (60 * 60 * 24));
395
- // if trip has 24+ stop times set real startDay to yesterday
396
- if (stopTimeDayOverflow > 0) {
397
- startDayTimestamp.subtract(1, "day");
398
- }
399
- return startDayTimestamp.valueOf();
400
- };
401
- this.determineStatePosition = (thisClosestPoint, lastTripPoint) => {
402
- if (thisClosestPoint.last_stop_sequence >= lastTripPoint.last_stop_sequence) {
403
- return const_1.StatePositionEnum.AFTER_TRACK;
404
- }
405
- else if (thisClosestPoint.this_stop_sequence) {
406
- return const_1.StatePositionEnum.AT_STOP;
407
- }
408
- return const_1.StatePositionEnum.ON_TRACK;
409
- };
292
+ // delay can not be negative if the vehicle is at the first stop
293
+ if (thisStopSequence === firstTripShapePoint.this_stop_sequence) {
294
+ timeDelayInSeconds = Math.max(timeDelayInSeconds, 0);
295
+ }
296
+ }
297
+ const statePosition = _a.determineStatePosition(thisClosestPoint, lastTripShapePoint);
298
+ const thisStopSequence = thisClosestPoint.this_stop_sequence;
299
+ const lastStopSequence = thisClosestPoint.last_stop_sequence;
300
+ const nextStopSequence = thisClosestPoint.next_stop_sequence;
301
+ // save it for result
302
+ const estimatedPoint = {
303
+ id: currentPosition.properties.id,
304
+ bearing: thisClosestPoint.bearing,
305
+ shape_dist_traveled: Math.round(thisClosestPoint.shape_dist_traveled * 1000) / 1000,
306
+ next_stop_id: tripStopTimes[nextStopSequence - 1].stop_id,
307
+ last_stop_id: tripStopTimes[lastStopSequence - 1].stop_id,
308
+ next_stop_name: tripStopTimes[nextStopSequence - 1].stop.stop_name,
309
+ last_stop_name: tripStopTimes[lastStopSequence - 1].stop.stop_name,
310
+ next_stop_sequence: nextStopSequence,
311
+ last_stop_sequence: lastStopSequence,
312
+ next_stop_arrival_time: DateTimeUtils_1.DateTimeUtils.getStopDateTimeForDayStart(tripStopTimes[nextStopSequence - 1].arrival_time_seconds, startDayTimestamp),
313
+ last_stop_arrival_time: DateTimeUtils_1.DateTimeUtils.getStopDateTimeForDayStart(tripStopTimes[lastStopSequence - 1].arrival_time_seconds, startDayTimestamp),
314
+ next_stop_departure_time: DateTimeUtils_1.DateTimeUtils.getStopDateTimeForDayStart(tripStopTimes[nextStopSequence - 1].departure_time_seconds, startDayTimestamp),
315
+ last_stop_departure_time: DateTimeUtils_1.DateTimeUtils.getStopDateTimeForDayStart(tripStopTimes[lastStopSequence - 1].departure_time_seconds, startDayTimestamp),
316
+ delay: statePosition === const_1.StatePositionEnum.AFTER_TRACK ? 0 : timeDelayInSeconds,
317
+ this_stop_id: (statePosition === const_1.StatePositionEnum.AT_STOP &&
318
+ thisStopSequence &&
319
+ tripStopTimes[thisStopSequence - 1].stop_id) ||
320
+ undefined,
321
+ this_stop_name: (statePosition === const_1.StatePositionEnum.AT_STOP &&
322
+ thisStopSequence &&
323
+ tripStopTimes[thisStopSequence - 1].stop.stop_name) ||
324
+ undefined,
325
+ this_stop_sequence: (statePosition === const_1.StatePositionEnum.AT_STOP && thisStopSequence) || undefined,
326
+ last_stop_headsign: tripStopTimes[lastStopSequence - 1].stop_headsign || undefined,
327
+ state_position: statePosition,
328
+ state_process: const_1.StateProcessEnum.PROCESSED,
329
+ valid_to: ValidToCalculator_1.default.getDefaultValidToAttribute(currentPosition.properties.origin_timestamp),
330
+ is_tracked: statePosition !== const_1.StatePositionEnum.AFTER_TRACK,
331
+ };
332
+ return estimatedPoint;
333
+ };
334
+ /**
335
+ * Corrects time delay at stop with dwelling time
336
+ *
337
+ * @param {number} timeDelay - Initial computed delay in seconds, can be negative for trip ahead
338
+ * @param {IVPTripsLastPositionContext | null} context - Context state, holds information about previous positions
339
+ * @param {Feature<Point, ICurrentPositionProperties>} currentPosition - Feature Point of current position
340
+ * @param {IShapeAnchorPoint} thisClosestPoint - Closest point of shape anchors
341
+ * @param { departureTime: number; arrivalTime: number } stopTimes - departure and arrival stop times in seconds
342
+ * @returns {number} - Result delay in seconds, can be negative for trip ahead
343
+ */
344
+ RegionalBusPositionsManager.getCorrectedTimeDelay = (timeDelay, context, currentPosition, thisStopSequence, stopTimes) => {
345
+ // compute dwell time in stop, most common is zero
346
+ const stopDwellTimeSeconds = stopTimes.departureTime - stopTimes.arrivalTime;
347
+ // if dwell time is sheduled as zero, return initial computed delay
348
+ if (stopDwellTimeSeconds <= 0) {
349
+ return timeDelay;
350
+ }
351
+ // if last position was not in this same stop or there is no last position at all
352
+ if (!context || context.atStopStreak.stop_sequence !== thisStopSequence) {
353
+ // timeDelay >= 0 trip is DELAYED
354
+ // we presume it will lower delay by shortening its scheduled dwell time,
355
+ // cant go under zero of course, trip should not go ahead
356
+ // else trip is AHeAD
357
+ // left computed delay as it was
358
+ return timeDelay >= 0 ? Math.max(timeDelay - stopDwellTimeSeconds, 0) : timeDelay;
359
+ }
360
+ // we presume that first position at same stop is real arrival time
361
+ if (context.atStopStreak.firstPositionDelay >= 0) {
362
+ // trip was DELAYED before
363
+ // we presume it will lower delay by shortening its scheduled dwell time,
364
+ // cant go under zero of course, trip should not go ahead
365
+ return Math.max(timeDelay - stopDwellTimeSeconds, 0);
366
+ }
367
+ // trip was AHEAD before
368
+ // real dwell time so far
369
+ const realDwellTimeSeconds = Math.round((currentPosition.properties.origin_timestamp.getTime() - context.atStopStreak.firstPositionTimestamp) / 1000);
370
+ // if real dwell is longer than scheduled, then add to negative delay time
371
+ return context.atStopStreak.firstPositionDelay + Math.max(realDwellTimeSeconds - stopDwellTimeSeconds, 0);
372
+ };
373
+ /**
374
+ * Compute UTC timestamp of start of day when trip starts
375
+ *
376
+ * @param {number} startTimestamp - Unix timestamp of start of the trip
377
+ * @param {number} firstStopTimeScheduledSeconds - Number of seconds from midnight of first stop departure
378
+ * @returns {number} - Returns unix timestamp in milliseconds.
379
+ */
380
+ RegionalBusPositionsManager.getStartDayTimestamp = (startTimestamp, firstStopTimeScheduledSeconds) => {
381
+ let startDayTimestamp = moment_timezone_1.default.utc(startTimestamp).tz("Europe/Prague").startOf("day");
382
+ const stopTimeDayOverflow = Math.floor(firstStopTimeScheduledSeconds / (60 * 60 * 24));
383
+ // if trip has 24+ stop times set real startDay to yesterday
384
+ if (stopTimeDayOverflow > 0) {
385
+ startDayTimestamp.subtract(1, "day");
386
+ }
387
+ return startDayTimestamp.valueOf();
388
+ };
389
+ RegionalBusPositionsManager.determineStatePosition = (thisClosestPoint, lastTripPoint) => {
390
+ if (thisClosestPoint.last_stop_sequence >= lastTripPoint.last_stop_sequence) {
391
+ return const_1.StatePositionEnum.AFTER_TRACK;
392
+ }
393
+ else if (thisClosestPoint.this_stop_sequence) {
394
+ return const_1.StatePositionEnum.AT_STOP;
410
395
  }
396
+ return const_1.StatePositionEnum.ON_TRACK;
411
397
  };
412
- exports.RegionalBusPositionsManager = RegionalBusPositionsManager = __decorate([
413
- (0, tsyringe_1.injectable)(),
414
- __param(0, (0, tsyringe_1.inject)(VPContainerToken_1.VPContainerToken.ValidToCalculator)),
415
- __metadata("design:paramtypes", [ValidToCalculator_1.ValidToCalculator])
416
- ], RegionalBusPositionsManager);
417
398
  //# sourceMappingURL=RegionalBusPositionsManager.js.map