incyclist-services 1.5.4 → 1.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/devices/ride/service.js +5 -3
- package/lib/ride/display/service.js +2 -2
- package/lib/routes/base/parsers/incyclist.d.ts +1 -0
- package/lib/routes/base/parsers/incyclist.js +13 -2
- package/lib/routes/base/utils/points.d.ts +1 -0
- package/lib/routes/base/utils/points.js +227 -148
- package/package.json +1 -1
|
@@ -129,9 +129,11 @@ let DeviceRideService = (() => {
|
|
|
129
129
|
return this.rideAdapters;
|
|
130
130
|
this.rideAdapters = this.adapters = this.getConfiguredAdapters(true);
|
|
131
131
|
const controlDevice = (_b = (_a = this.adapters.find(d => d.capabilities.includes('control'))) !== null && _a !== void 0 ? _a : this.adapters.find(d => d.capabilities.includes('power'))) !== null && _b !== void 0 ? _b : this.adapters.find(d => d.capabilities.includes('speed'));
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
if (controlDevice) {
|
|
133
|
+
this.rideAdapters.forEach(ai => {
|
|
134
|
+
ai.isControl = (ai.udid === controlDevice.udid);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
135
137
|
if (!this.simulatorEnforced)
|
|
136
138
|
return this.adapters;
|
|
137
139
|
const adapter = incyclist_devices_1.AdapterFactory.create({ interface: 'simulator', name: 'Simulator' });
|
|
@@ -130,7 +130,7 @@ let RideDisplayService = (() => {
|
|
|
130
130
|
this.logEvent({ message: 'overlay shown', overlay: 'start overlay' });
|
|
131
131
|
}
|
|
132
132
|
catch (err) {
|
|
133
|
-
this.logError(err, '
|
|
133
|
+
this.logError(err, 'start');
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
startWithMissingSensors() {
|
|
@@ -409,7 +409,7 @@ let RideDisplayService = (() => {
|
|
|
409
409
|
this.state = 'Idle';
|
|
410
410
|
}
|
|
411
411
|
catch (err) {
|
|
412
|
-
this.logError(err, '
|
|
412
|
+
this.logError(err, 'stopRide');
|
|
413
413
|
}
|
|
414
414
|
delete this.type;
|
|
415
415
|
delete this.displayService;
|
|
@@ -4,6 +4,7 @@ import { RoutePoint } from '../types';
|
|
|
4
4
|
import { XMLParser, XmlParserContext } from './xml';
|
|
5
5
|
export declare class IncyclistXMLParser extends XMLParser {
|
|
6
6
|
static readonly SCHEME = "gpx-import";
|
|
7
|
+
constructor();
|
|
7
8
|
protected loadDescription(context: XmlParserContext): Promise<void>;
|
|
8
9
|
protected loadPoints(context: XmlParserContext): Promise<void>;
|
|
9
10
|
protected processCuts(data: JSONObject, route: RouteApiDetail): void;
|
|
@@ -10,12 +10,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.IncyclistXMLParser = void 0;
|
|
13
|
+
const gd_eventlog_1 = require("gd-eventlog");
|
|
13
14
|
const utils_1 = require("../../../utils");
|
|
14
15
|
const utils_2 = require("../utils");
|
|
15
16
|
const points_1 = require("../utils/points");
|
|
16
17
|
const gpx_1 = require("./gpx");
|
|
17
18
|
const xml_1 = require("./xml");
|
|
18
19
|
class IncyclistXMLParser extends xml_1.XMLParser {
|
|
20
|
+
constructor() {
|
|
21
|
+
super();
|
|
22
|
+
this.logger = new gd_eventlog_1.EventLogger('IncyclistParser');
|
|
23
|
+
}
|
|
19
24
|
loadDescription(context) {
|
|
20
25
|
const _super = Object.create(null, {
|
|
21
26
|
loadDescription: { get: () => super.loadDescription }
|
|
@@ -58,8 +63,14 @@ class IncyclistXMLParser extends xml_1.XMLParser {
|
|
|
58
63
|
try {
|
|
59
64
|
if (context.data['autoCorrect']) {
|
|
60
65
|
const gpx = yield new gpx_1.GPXParser({ addTime: true, keepZero: true }).import(gpxFile);
|
|
61
|
-
|
|
62
|
-
(0, points_1.fixAnomalies)(
|
|
66
|
+
const points = [...gpx.details.points];
|
|
67
|
+
const { fixed, time, error } = (0, points_1.fixAnomalies)(points);
|
|
68
|
+
this.logger.logEvent({ message: 'gpx file autocorrect', cntFixed: fixed, duration: time, error: error === null || error === void 0 ? void 0 : error.message });
|
|
69
|
+
if (error) {
|
|
70
|
+
route.points = gpx.details.points;
|
|
71
|
+
}
|
|
72
|
+
route.points = route.points.filter(p => p.distance !== 0);
|
|
73
|
+
route.points.forEach((p, idx) => { p.cnt = idx; });
|
|
63
74
|
(0, utils_2.validateRoute)(route);
|
|
64
75
|
}
|
|
65
76
|
else {
|
|
@@ -12,6 +12,7 @@ interface Anomaly {
|
|
|
12
12
|
retry?: number;
|
|
13
13
|
}
|
|
14
14
|
export declare const calculateSpeed: (points: RoutePoint[], idx: number) => number;
|
|
15
|
+
export declare const getPointsWithSpeed: (points: RoutePoint[]) => RoutePointEval[];
|
|
15
16
|
export declare const detectAnomalies: (points: RoutePoint[], maxCount?: number) => Anomaly[];
|
|
16
17
|
export declare const fixAnomaly: (anomaly: Anomaly, points: RoutePoint[]) => void;
|
|
17
18
|
export declare const fixAnomalies: (points: RoutePoint[], maxAttempts?: number) => {
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fixAnomalies = exports.fixAnomaly = exports.detectAnomalies = exports.calculateSpeed = void 0;
|
|
4
|
-
const MAX_LOOKUP =
|
|
3
|
+
exports.fixAnomalies = exports.fixAnomaly = exports.detectAnomalies = exports.getPointsWithSpeed = exports.calculateSpeed = void 0;
|
|
4
|
+
const MAX_LOOKUP = 100;
|
|
5
|
+
const isJump = (v1, v2) => {
|
|
6
|
+
if (v2 === v1 || v1 < 0.2 || v2 < 0.2)
|
|
7
|
+
return false;
|
|
8
|
+
return (Math.abs(v2 - v1) > 3) ||
|
|
9
|
+
(v2 > v1 * 1.4 && Math.abs(v2 - v1) > 2);
|
|
10
|
+
};
|
|
5
11
|
const calculateSpeed = (points, idx) => {
|
|
6
12
|
const p = points === null || points === void 0 ? void 0 : points[idx];
|
|
7
13
|
if (!p || idx === 0)
|
|
@@ -11,51 +17,73 @@ const calculateSpeed = (points, idx) => {
|
|
|
11
17
|
return speed;
|
|
12
18
|
};
|
|
13
19
|
exports.calculateSpeed = calculateSpeed;
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
return [];
|
|
17
|
-
const data = points.map((p, idx) => {
|
|
20
|
+
const getPointsWithSpeed = (points) => {
|
|
21
|
+
return points.map((p, idx) => {
|
|
18
22
|
const d = Object.assign({}, p);
|
|
19
23
|
d.speed = (0, exports.calculateSpeed)(points, idx);
|
|
20
24
|
return d;
|
|
21
25
|
});
|
|
26
|
+
};
|
|
27
|
+
exports.getPointsWithSpeed = getPointsWithSpeed;
|
|
28
|
+
const detectAnomalies = (points, maxCount) => {
|
|
29
|
+
if (points[0].time === undefined)
|
|
30
|
+
return [];
|
|
31
|
+
const data = (0, exports.getPointsWithSpeed)(points);
|
|
22
32
|
const anomalies = [];
|
|
23
33
|
let lastValidSpeedIdx = 0;
|
|
24
34
|
let done = false;
|
|
25
35
|
const isSpeedJump = (p1, p2) => {
|
|
26
|
-
return
|
|
27
|
-
p2.speed > p1.speed * 1.5 && p2.speed > 2 ||
|
|
28
|
-
Math.abs(p2.speed - p1.speed) > 3;
|
|
36
|
+
return isJump(p1.speed, p2.speed);
|
|
29
37
|
};
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
const isCloseToNull = (p) => {
|
|
39
|
+
return (p.distance < 0.5 || p.speed < 0.5);
|
|
40
|
+
};
|
|
41
|
+
const onNullValueDetected = (point, idx) => {
|
|
42
|
+
const speedPrev = data[idx - 1].speed;
|
|
43
|
+
if (speedPrev < 2)
|
|
33
44
|
return;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
const speedNext = data[idx + 1].speed;
|
|
46
|
+
if (speedPrev > speedNext && !isJump(speedPrev / 2, speedNext)) {
|
|
47
|
+
anomalies.push({ idx: idx - 1, type: 'speedJump', point, nextNullIdx: idx });
|
|
48
|
+
}
|
|
49
|
+
let nextJumpIdx;
|
|
50
|
+
const idxPrev = lastValidSpeedIdx === 0 ? idx - 1 : lastValidSpeedIdx;
|
|
51
|
+
for (let j = idx + 1; j < idx + MAX_LOOKUP && nextJumpIdx === undefined; j++) {
|
|
52
|
+
if (isSpeedJump(data[idxPrev], data[j])) {
|
|
53
|
+
nextJumpIdx = j;
|
|
41
54
|
}
|
|
42
|
-
anomalies.push({ idx, type: 'noDistance', point, nextJumpIdx });
|
|
43
55
|
}
|
|
56
|
+
anomalies.push({ idx, type: 'noDistance', point, nextJumpIdx });
|
|
57
|
+
};
|
|
58
|
+
const onSpeedJumpDetected = (point, idx) => {
|
|
44
59
|
const prevPoint = data[lastValidSpeedIdx];
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
let nextJumpIdx, nextNullIdx;
|
|
61
|
+
if (prevPoint.speed === 0) {
|
|
62
|
+
anomalies.push({ idx: lastValidSpeedIdx, type: 'noDistance', point });
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
let nextJumpFound = false;
|
|
66
|
+
for (let j = idx + 1; j < idx + MAX_LOOKUP && !nextJumpFound && nextNullIdx === undefined; j++) {
|
|
67
|
+
if (isCloseToNull(data[j])) {
|
|
68
|
+
nextNullIdx = j;
|
|
69
|
+
}
|
|
70
|
+
else if (j > idx + 1 && isSpeedJump(data[j], data[j - 1])) {
|
|
71
|
+
nextJumpFound = true;
|
|
72
|
+
continue;
|
|
56
73
|
}
|
|
57
|
-
anomalies.push({ idx, type: 'speedJump', point, nextNullIdx });
|
|
58
74
|
}
|
|
75
|
+
anomalies.push({ idx, type: 'speedJump', point, nextNullIdx, nextJumpIdx });
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
data.forEach((point, idx) => {
|
|
79
|
+
var _a;
|
|
80
|
+
if (idx === 0 || done)
|
|
81
|
+
return;
|
|
82
|
+
if (point.speed === 0 || point.distance === 0) {
|
|
83
|
+
onNullValueDetected(point, idx);
|
|
84
|
+
}
|
|
85
|
+
else if (isSpeedJump(data[lastValidSpeedIdx], point)) {
|
|
86
|
+
onSpeedJumpDetected(point, idx);
|
|
59
87
|
}
|
|
60
88
|
if (!!maxCount && anomalies.length > maxCount - 1) {
|
|
61
89
|
done = true;
|
|
@@ -70,119 +98,10 @@ const detectAnomalies = (points, maxCount) => {
|
|
|
70
98
|
exports.detectAnomalies = detectAnomalies;
|
|
71
99
|
const fixAnomaly = (anomaly, points) => {
|
|
72
100
|
if (anomaly.type === 'speedJump') {
|
|
73
|
-
|
|
74
|
-
const idx = anomaly.idx;
|
|
75
|
-
const idxNull = anomaly.nextNullIdx;
|
|
76
|
-
let offset;
|
|
77
|
-
if (idxNull === idx + 1) {
|
|
78
|
-
offset = ((0, exports.calculateSpeed)(points, idx) - (0, exports.calculateSpeed)(points, idxNull)) / 2;
|
|
79
|
-
const t = points[idx].time - points[idx - 1].time;
|
|
80
|
-
const vPrev = (0, exports.calculateSpeed)(points, idx);
|
|
81
|
-
const v = vPrev - offset;
|
|
82
|
-
const d = v * t;
|
|
83
|
-
const dOffset = points[idx].distance - d;
|
|
84
|
-
points[idx].distance = d;
|
|
85
|
-
points[idx].routeDistance -= dOffset;
|
|
86
|
-
const t0 = points[idxNull].time - points[idxNull - 1].time;
|
|
87
|
-
const v0 = offset;
|
|
88
|
-
points[idxNull].distance += v0 * t0;
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
const offsetEnd = (0, exports.calculateSpeed)(points, idxNull - 1) - (0, exports.calculateSpeed)(points, idx - 1);
|
|
92
|
-
const offsetStart = (0, exports.calculateSpeed)(points, idx) - (0, exports.calculateSpeed)(points, idx - 1);
|
|
93
|
-
const offsetAverage = (offsetStart + offsetEnd) / 2;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (anomaly.nextNullIdx !== undefined) {
|
|
97
|
-
const idx = anomaly.idx;
|
|
98
|
-
const idxNull = anomaly.nextNullIdx;
|
|
99
|
-
const offsetNext = idxNull === idx + 1 ? (0, exports.calculateSpeed)(points, idx) / 2 : (0, exports.calculateSpeed)(points, idxNull - 1);
|
|
100
|
-
const offsetPrev = idxNull === idx + 1 ? offsetNext : (0, exports.calculateSpeed)(points, idx) - (0, exports.calculateSpeed)(points, idx - 1);
|
|
101
|
-
const offset = (offsetNext + offsetPrev) / 2;
|
|
102
|
-
const t = points[idx].time - points[idx - 1].time;
|
|
103
|
-
const vPrev = (0, exports.calculateSpeed)(points, idx);
|
|
104
|
-
const v = vPrev - offset;
|
|
105
|
-
const d = v * t;
|
|
106
|
-
const dOffset = points[idx].distance - d;
|
|
107
|
-
points[idx].distance = d;
|
|
108
|
-
points[idx].routeDistance -= dOffset;
|
|
109
|
-
for (let j = idx + 1; j < idxNull; j++) {
|
|
110
|
-
points[j].routeDistance -= dOffset;
|
|
111
|
-
}
|
|
112
|
-
const t0 = points[idxNull].time - points[idxNull - 1].time;
|
|
113
|
-
const v0 = offset;
|
|
114
|
-
points[idxNull].distance = v0 * t0;
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
const idx = anomaly.idx;
|
|
118
|
-
const next = points === null || points === void 0 ? void 0 : points[idx + 1];
|
|
119
|
-
const prev = points === null || points === void 0 ? void 0 : points[idx - 1];
|
|
120
|
-
if (next && prev) {
|
|
121
|
-
next.distance = next.routeDistance - prev.routeDistance;
|
|
122
|
-
}
|
|
123
|
-
points.splice(idx, 1);
|
|
124
|
-
}
|
|
101
|
+
fixSpeedJump(anomaly, points);
|
|
125
102
|
}
|
|
126
103
|
else if (anomaly.type === 'noDistance') {
|
|
127
|
-
|
|
128
|
-
const next = points === null || points === void 0 ? void 0 : points[idx + 1];
|
|
129
|
-
const prev = points === null || points === void 0 ? void 0 : points[idx - 1];
|
|
130
|
-
if (anomaly.nextJumpIdx !== undefined) {
|
|
131
|
-
const endIdx = anomaly.nextJumpIdx;
|
|
132
|
-
const vEnd = (0, exports.calculateSpeed)(points, endIdx);
|
|
133
|
-
const vStart = (0, exports.calculateSpeed)(points, endIdx - 1);
|
|
134
|
-
if (endIdx === idx + 1) {
|
|
135
|
-
const offset = vEnd / 2;
|
|
136
|
-
const t0 = points[idx].time - points[idx - 1].time;
|
|
137
|
-
const v0 = offset;
|
|
138
|
-
const d0 = v0 * t0;
|
|
139
|
-
points[idx].distance = d0;
|
|
140
|
-
points[idx].routeDistance += d0;
|
|
141
|
-
const t = points[endIdx].time - points[endIdx - 1].time;
|
|
142
|
-
const vPrev = (0, exports.calculateSpeed)(points, endIdx);
|
|
143
|
-
const v = vPrev - offset;
|
|
144
|
-
const d = v * t;
|
|
145
|
-
points[endIdx].distance = d;
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
const offset = vEnd - vStart;
|
|
149
|
-
for (let j = anomaly.idx; j < endIdx; j++) {
|
|
150
|
-
const t = points[j].time - points[j - 1].time;
|
|
151
|
-
const vPrev = (0, exports.calculateSpeed)(points, j);
|
|
152
|
-
const v = vPrev + offset;
|
|
153
|
-
const d = v * t;
|
|
154
|
-
const dOffset = points[j].distance - d;
|
|
155
|
-
points[j].distance = d;
|
|
156
|
-
points[j].routeDistance += dOffset;
|
|
157
|
-
}
|
|
158
|
-
const t = points[endIdx].time - points[endIdx - 1].time;
|
|
159
|
-
const vPrev = (0, exports.calculateSpeed)(points, endIdx);
|
|
160
|
-
const v = vPrev - offset;
|
|
161
|
-
const d = v * t;
|
|
162
|
-
points[endIdx].distance = d;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
if (idx > 2 && idx < points.length - 2) {
|
|
167
|
-
const s = points[idx + 2].routeDistance - points[idx - 2].routeDistance;
|
|
168
|
-
const t = points[idx + 2].time - points[idx - 2].time;
|
|
169
|
-
const avgSpeed = s / t;
|
|
170
|
-
const nextSpeed = (0, exports.calculateSpeed)(points, idx + 1);
|
|
171
|
-
const prevSpeed = (0, exports.calculateSpeed)(points, idx - 1);
|
|
172
|
-
if ((Math.abs(prevSpeed - avgSpeed) - Math.abs(nextSpeed - avgSpeed)) > 0.5) {
|
|
173
|
-
points[idx].distance = points[idx].routeDistance - points[idx - 2].routeDistance;
|
|
174
|
-
points.splice(idx - 1, 1);
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
next.distance = next.routeDistance - prev.routeDistance;
|
|
178
|
-
points.splice(idx, 1);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
next.distance = next.routeDistance - prev.routeDistance;
|
|
183
|
-
points.splice(idx, 1);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
104
|
+
fixNoDistance(anomaly, points);
|
|
186
105
|
}
|
|
187
106
|
};
|
|
188
107
|
exports.fixAnomaly = fixAnomaly;
|
|
@@ -194,19 +113,23 @@ const fixAnomalies = (points, maxAttempts = 1000) => {
|
|
|
194
113
|
let prev;
|
|
195
114
|
let stuck = false;
|
|
196
115
|
let error;
|
|
116
|
+
let retry = 0;
|
|
197
117
|
const fixedRecords = [];
|
|
198
118
|
try {
|
|
199
119
|
do {
|
|
200
120
|
anomalies = (0, exports.detectAnomalies)(points, 1);
|
|
201
121
|
if (anomalies.length > 0) {
|
|
202
122
|
const current = anomalies[0];
|
|
203
|
-
if ((prev === null || prev === void 0 ? void 0 : prev.idx) === current.idx) {
|
|
123
|
+
if ((prev === null || prev === void 0 ? void 0 : prev.idx) === current.idx && ++retry > 5) {
|
|
204
124
|
stuck = true;
|
|
205
125
|
continue;
|
|
206
126
|
}
|
|
207
|
-
else
|
|
208
|
-
|
|
209
|
-
current.
|
|
127
|
+
else {
|
|
128
|
+
retry = 0;
|
|
129
|
+
if ((prev === null || prev === void 0 ? void 0 : prev.type) === current.type && (prev === null || prev === void 0 ? void 0 : prev.type) === 'speedJump' && current.idx > (prev === null || prev === void 0 ? void 0 : prev.idx) && current.idx < (prev === null || prev === void 0 ? void 0 : prev.nextNullIdx)) {
|
|
130
|
+
current.nextNullIdx = prev.nextNullIdx;
|
|
131
|
+
current.retry = ((_a = prev.retry) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
132
|
+
}
|
|
210
133
|
}
|
|
211
134
|
(0, exports.fixAnomaly)(anomalies[0], points);
|
|
212
135
|
fixedRecords.push(anomalies[0]);
|
|
@@ -223,5 +146,161 @@ const fixAnomalies = (points, maxAttempts = 1000) => {
|
|
|
223
146
|
return { fixed, time: tsStop - tsStart, fixedRecords, error };
|
|
224
147
|
};
|
|
225
148
|
exports.fixAnomalies = fixAnomalies;
|
|
226
|
-
const
|
|
149
|
+
const fixNoDistance = (anomaly, points) => {
|
|
150
|
+
const idx = anomaly.idx;
|
|
151
|
+
const next = points === null || points === void 0 ? void 0 : points[idx + 1];
|
|
152
|
+
const prev = points === null || points === void 0 ? void 0 : points[idx - 1];
|
|
153
|
+
const fixNullWithoutJump = () => {
|
|
154
|
+
if (idx > 2 && idx < points.length - 2) {
|
|
155
|
+
const s = points[idx + 2].routeDistance - points[idx - 2].routeDistance;
|
|
156
|
+
const t = points[idx + 2].time - points[idx - 2].time;
|
|
157
|
+
const avgSpeed = s / t;
|
|
158
|
+
const nextSpeed = (0, exports.calculateSpeed)(points, idx + 1);
|
|
159
|
+
const prevSpeed = (0, exports.calculateSpeed)(points, idx - 1);
|
|
160
|
+
if ((Math.abs(prevSpeed - avgSpeed) - Math.abs(nextSpeed - avgSpeed)) > 0.5) {
|
|
161
|
+
points[idx].distance = points[idx].routeDistance - points[idx - 2].routeDistance;
|
|
162
|
+
points.splice(idx - 1, 1);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
next.distance = next.routeDistance - prev.routeDistance;
|
|
166
|
+
points.splice(idx, 1);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
next.distance = next.routeDistance - prev.routeDistance;
|
|
171
|
+
points.splice(idx, 1);
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
const fixNullFollowedByJump = () => {
|
|
175
|
+
const endIdx = anomaly.nextJumpIdx;
|
|
176
|
+
const vEnd = (0, exports.calculateSpeed)(points, endIdx);
|
|
177
|
+
const vStart = (0, exports.calculateSpeed)(points, endIdx - 1);
|
|
178
|
+
if (endIdx === idx + 1) {
|
|
179
|
+
const offset = vEnd / 2;
|
|
180
|
+
const t0 = points[idx].time - points[idx - 1].time;
|
|
181
|
+
const v0 = offset;
|
|
182
|
+
const d0 = v0 * t0;
|
|
183
|
+
points[idx].distance = d0;
|
|
184
|
+
points[idx].routeDistance += d0;
|
|
185
|
+
const t = points[endIdx].time - points[endIdx - 1].time;
|
|
186
|
+
const vPrev = (0, exports.calculateSpeed)(points, endIdx);
|
|
187
|
+
const v = vPrev - offset;
|
|
188
|
+
const d = v * t;
|
|
189
|
+
points[endIdx].distance = d;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
const offset = vEnd - vStart;
|
|
193
|
+
for (let j = anomaly.idx; j < endIdx; j++) {
|
|
194
|
+
const t = points[j].time - points[j - 1].time;
|
|
195
|
+
const vPrev = (0, exports.calculateSpeed)(points, j);
|
|
196
|
+
const v = vPrev + offset;
|
|
197
|
+
const d = v * t;
|
|
198
|
+
const dOffset = points[j].distance - d;
|
|
199
|
+
points[j].distance = d;
|
|
200
|
+
points[j].routeDistance += dOffset;
|
|
201
|
+
}
|
|
202
|
+
const t = points[endIdx].time - points[endIdx - 1].time;
|
|
203
|
+
const vPrev = (0, exports.calculateSpeed)(points, endIdx);
|
|
204
|
+
const v = vPrev - offset;
|
|
205
|
+
const d = v * t;
|
|
206
|
+
points[endIdx].distance = d;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
if (anomaly.nextJumpIdx !== undefined) {
|
|
210
|
+
fixNullFollowedByJump();
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
fixNullWithoutJump();
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
const fixSpeedJump = (anomaly, points) => {
|
|
217
|
+
const fixJumpFollowedByNull = () => {
|
|
218
|
+
const idx = anomaly.idx;
|
|
219
|
+
const idxNull = anomaly.nextNullIdx;
|
|
220
|
+
const vIssue = (0, exports.calculateSpeed)(points, idx);
|
|
221
|
+
let offset;
|
|
222
|
+
if (idx + 1 === idxNull) {
|
|
223
|
+
offset = vIssue / 2;
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
const vEnd = (0, exports.calculateSpeed)(points, idxNull - 1);
|
|
227
|
+
const vStart = (0, exports.calculateSpeed)(points, idx - 1);
|
|
228
|
+
let vTarget;
|
|
229
|
+
const v1 = vIssue - vStart;
|
|
230
|
+
const v2 = vIssue - v1;
|
|
231
|
+
if (vStart > vEnd) {
|
|
232
|
+
vTarget = Math.max(v1, v2);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
vTarget = isJump(v1, v2) ? (v1 + v2) / 2 : Math.min(v1, v2);
|
|
236
|
+
}
|
|
237
|
+
offset = vIssue - vTarget;
|
|
238
|
+
}
|
|
239
|
+
let t = points[idx].time - points[idx - 1].time;
|
|
240
|
+
let v = vIssue - offset;
|
|
241
|
+
let s = v * t;
|
|
242
|
+
let dOffset = points[idx].distance - s;
|
|
243
|
+
points[idx].distance = s;
|
|
244
|
+
points[idx].routeDistance -= dOffset;
|
|
245
|
+
v = offset;
|
|
246
|
+
for (let j = idx + 1; j < idxNull; j++) {
|
|
247
|
+
t = points[j].time - points[j - 1].time;
|
|
248
|
+
s = v * t;
|
|
249
|
+
v = offset = (0, exports.calculateSpeed)(points, j);
|
|
250
|
+
dOffset = points[j].distance - s;
|
|
251
|
+
points[j].distance = s;
|
|
252
|
+
points[j].routeDistance -= dOffset;
|
|
253
|
+
}
|
|
254
|
+
t = points[idxNull].time - points[idxNull - 1].time;
|
|
255
|
+
v = offset;
|
|
256
|
+
points[idxNull].distance = v * t;
|
|
257
|
+
};
|
|
258
|
+
const fixJumpFollowedByNullRetry = () => {
|
|
259
|
+
const idx = anomaly.idx;
|
|
260
|
+
const idxNull = anomaly.nextNullIdx;
|
|
261
|
+
let offset;
|
|
262
|
+
if (idxNull === idx + 1) {
|
|
263
|
+
offset = ((0, exports.calculateSpeed)(points, idx) - (0, exports.calculateSpeed)(points, idxNull)) / 2;
|
|
264
|
+
const t = points[idx].time - points[idx - 1].time;
|
|
265
|
+
const vPrev = (0, exports.calculateSpeed)(points, idx);
|
|
266
|
+
const v = vPrev - offset;
|
|
267
|
+
const d = v * t;
|
|
268
|
+
const dOffset = points[idx].distance - d;
|
|
269
|
+
points[idx].distance = d;
|
|
270
|
+
points[idx].routeDistance -= dOffset;
|
|
271
|
+
const t0 = points[idxNull].time - points[idxNull - 1].time;
|
|
272
|
+
const v0 = offset;
|
|
273
|
+
points[idxNull].distance += v0 * t0;
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const fixJumpFollowedByJump = () => {
|
|
277
|
+
const idx = anomaly.idx;
|
|
278
|
+
const current = points === null || points === void 0 ? void 0 : points[idx];
|
|
279
|
+
const next = points === null || points === void 0 ? void 0 : points[idx + 1];
|
|
280
|
+
const v = ((0, exports.calculateSpeed)(points, idx) + (0, exports.calculateSpeed)(points, idx + 1)) / 2;
|
|
281
|
+
const t = points[idx].time - points[idx - 1].time;
|
|
282
|
+
const d = v * t;
|
|
283
|
+
const offset = current.distance - d;
|
|
284
|
+
current.distance = d;
|
|
285
|
+
current.routeDistance -= offset;
|
|
286
|
+
next.distance += offset;
|
|
287
|
+
};
|
|
288
|
+
if (anomaly.nextNullIdx !== undefined && anomaly.retry > 0) {
|
|
289
|
+
fixJumpFollowedByNullRetry();
|
|
290
|
+
}
|
|
291
|
+
else if (anomaly.nextNullIdx !== undefined) {
|
|
292
|
+
fixJumpFollowedByNull();
|
|
293
|
+
}
|
|
294
|
+
else if (anomaly.nextJumpIdx !== undefined) {
|
|
295
|
+
fixJumpFollowedByJump();
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
const idx = anomaly.idx;
|
|
299
|
+
const next = points === null || points === void 0 ? void 0 : points[idx + 1];
|
|
300
|
+
const prev = points === null || points === void 0 ? void 0 : points[idx - 1];
|
|
301
|
+
if (next && prev) {
|
|
302
|
+
next.distance = next.routeDistance - prev.routeDistance;
|
|
303
|
+
}
|
|
304
|
+
points.splice(idx, 1);
|
|
305
|
+
}
|
|
227
306
|
};
|