incyclist-services 1.5.13 → 1.5.15
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/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/maps/MapArea/MapArea.d.ts +2 -0
- package/lib/maps/MapArea/MapArea.js +14 -0
- package/lib/maps/MapArea/options.d.ts +1 -1
- package/lib/maps/MapArea/options.js +96 -68
- package/lib/maps/MapArea/service.d.ts +3 -3
- package/lib/maps/MapArea/service.js +13 -20
- package/lib/maps/MapArea/types.d.ts +2 -0
- package/lib/maps/MapArea/utils.d.ts +2 -1
- package/lib/maps/MapArea/utils.js +1 -1
- package/lib/ride/base/types.d.ts +25 -4
- package/lib/ride/display/service.js +17 -11
- package/lib/ride/route/FreeRideDisplayService.d.ts +39 -16
- package/lib/ride/route/FreeRideDisplayService.js +345 -92
- package/lib/ride/route/RLVDisplayService.d.ts +36 -0
- package/lib/ride/route/RLVDisplayService.js +137 -0
- package/lib/ride/route/RouteDisplayService.js +2 -1
- package/lib/routes/base/parsers/geojson.d.ts +16 -0
- package/lib/routes/base/parsers/geojson.js +2 -0
- package/lib/routes/base/parsers/geometry.d.ts +28 -0
- package/lib/routes/base/parsers/geometry.js +137 -0
- package/lib/routes/base/parsers/incyclist.d.ts +7 -4
- package/lib/routes/base/parsers/incyclist.js +34 -18
- package/lib/routes/base/parsers/xml.d.ts +2 -2
- package/lib/routes/base/types/index.d.ts +1 -1
- package/lib/routes/base/utils/route.d.ts +1 -1
- package/lib/routes/base/utils/route.js +24 -2
- package/lib/routes/free-ride/service.d.ts +4 -2
- package/lib/routes/free-ride/service.js +161 -46
- package/lib/video/ConvertSession.d.ts +5 -0
- package/lib/video/ConvertSession.js +62 -0
- package/lib/video/VideoConversion.d.ts +13 -0
- package/lib/video/VideoConversion.js +105 -0
- package/lib/video/VideoSyncHelper.d.ts +25 -0
- package/lib/video/VideoSyncHelper.js +145 -0
- package/lib/video/index.d.ts +3 -0
- package/lib/video/index.js +19 -0
- package/lib/video/types.d.ts +12 -0
- package/lib/video/types.js +2 -0
- package/package.json +5 -5
package/lib/index.d.ts
CHANGED
|
@@ -13,4 +13,5 @@ export * from './routes';
|
|
|
13
13
|
export * from './services';
|
|
14
14
|
export { useUserSettings, initUserSettings, UserSettingsService, UserSettingsBinding, IUserSettingsBinding } from './settings';
|
|
15
15
|
export * from './utils';
|
|
16
|
+
export * from './video';
|
|
16
17
|
export * from './workouts';
|
package/lib/index.js
CHANGED
|
@@ -34,4 +34,5 @@ Object.defineProperty(exports, "initUserSettings", { enumerable: true, get: func
|
|
|
34
34
|
Object.defineProperty(exports, "UserSettingsService", { enumerable: true, get: function () { return settings_1.UserSettingsService; } });
|
|
35
35
|
Object.defineProperty(exports, "UserSettingsBinding", { enumerable: true, get: function () { return settings_1.UserSettingsBinding; } });
|
|
36
36
|
__exportStar(require("./utils"), exports);
|
|
37
|
+
__exportStar(require("./video"), exports);
|
|
37
38
|
__exportStar(require("./workouts"), exports);
|
|
@@ -6,6 +6,7 @@ export declare class MapArea implements IMapArea {
|
|
|
6
6
|
protected queryLocation: IncyclistNode;
|
|
7
7
|
protected bounds: Boundary;
|
|
8
8
|
protected logger: EventLogger;
|
|
9
|
+
protected lastUsed: number;
|
|
9
10
|
constructor(data: FreeRideDataSet, queryLocation: IncyclistNode, bounds: Boundary);
|
|
10
11
|
getQueryLocation(): IncyclistNode;
|
|
11
12
|
getBoundary(): Boundary;
|
|
@@ -13,6 +14,7 @@ export declare class MapArea implements IMapArea {
|
|
|
13
14
|
getWay(id: string): IncyclistWay;
|
|
14
15
|
getNode(id: string): IncyclistNode;
|
|
15
16
|
getStats(): Record<string, number>;
|
|
17
|
+
getLastUsed(): number;
|
|
16
18
|
isWithinBoundary(location: LatLng): boolean;
|
|
17
19
|
getNearestPath(point: IncyclistNode): NearestPathInfo;
|
|
18
20
|
getFirstBranch(way: WayInfo, ignore?: string): SplitPointInfo;
|
|
@@ -14,6 +14,7 @@ class MapArea {
|
|
|
14
14
|
this.queryLocation = queryLocation;
|
|
15
15
|
this.bounds = bounds;
|
|
16
16
|
this.logger = new gd_eventlog_1.EventLogger('MapArea');
|
|
17
|
+
this.lastUsed = Date.now();
|
|
17
18
|
this.correctRoundabouts();
|
|
18
19
|
}
|
|
19
20
|
getQueryLocation() {
|
|
@@ -23,22 +24,30 @@ class MapArea {
|
|
|
23
24
|
return this.bounds;
|
|
24
25
|
}
|
|
25
26
|
getWays() {
|
|
27
|
+
this.lastUsed = Date.now();
|
|
26
28
|
return this.data.ways;
|
|
27
29
|
}
|
|
28
30
|
getWay(id) {
|
|
31
|
+
this.lastUsed = Date.now();
|
|
29
32
|
return this.data.waysLookup[id];
|
|
30
33
|
}
|
|
31
34
|
getNode(id) {
|
|
35
|
+
this.lastUsed = Date.now();
|
|
32
36
|
return this.data.nodesLookup[id];
|
|
33
37
|
}
|
|
34
38
|
getStats() {
|
|
35
39
|
return this.data.typeStats;
|
|
36
40
|
}
|
|
41
|
+
getLastUsed() {
|
|
42
|
+
return this.lastUsed;
|
|
43
|
+
}
|
|
37
44
|
isWithinBoundary(location) {
|
|
45
|
+
this.lastUsed = Date.now();
|
|
38
46
|
return (0, utils_1.isWithinBoundary)(location, this.bounds);
|
|
39
47
|
}
|
|
40
48
|
getNearestPath(point) {
|
|
41
49
|
var _a, _b;
|
|
50
|
+
this.lastUsed = Date.now();
|
|
42
51
|
const ways = (_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a.ways) !== null && _b !== void 0 ? _b : [];
|
|
43
52
|
if (!(ways === null || ways === void 0 ? void 0 : ways.length))
|
|
44
53
|
return;
|
|
@@ -55,6 +64,7 @@ class MapArea {
|
|
|
55
64
|
return min;
|
|
56
65
|
}
|
|
57
66
|
getFirstBranch(way, ignore) {
|
|
67
|
+
this.lastUsed = Date.now();
|
|
58
68
|
if ((way === null || way === void 0 ? void 0 : way.path) === undefined)
|
|
59
69
|
return;
|
|
60
70
|
let pFound = undefined;
|
|
@@ -78,6 +88,7 @@ class MapArea {
|
|
|
78
88
|
return pFound;
|
|
79
89
|
}
|
|
80
90
|
splitAtFirstBranch(way) {
|
|
91
|
+
this.lastUsed = Date.now();
|
|
81
92
|
if ((way === null || way === void 0 ? void 0 : way.path) === undefined)
|
|
82
93
|
return;
|
|
83
94
|
const path = [...way.path];
|
|
@@ -107,6 +118,7 @@ class MapArea {
|
|
|
107
118
|
return result;
|
|
108
119
|
}
|
|
109
120
|
splitAtCrossingPoint(way, crossing) {
|
|
121
|
+
this.lastUsed = Date.now();
|
|
110
122
|
if ((way === null || way === void 0 ? void 0 : way.path) === undefined || (crossing === null || crossing === void 0 ? void 0 : crossing.idx) === undefined || (crossing === null || crossing === void 0 ? void 0 : crossing.point) === undefined)
|
|
111
123
|
return;
|
|
112
124
|
const { point, idx: crossingIdx, distance } = crossing;
|
|
@@ -172,6 +184,7 @@ class MapArea {
|
|
|
172
184
|
return res;
|
|
173
185
|
}
|
|
174
186
|
buildSegmentInfo(from, parts) {
|
|
187
|
+
this.lastUsed = Date.now();
|
|
175
188
|
const segments = [];
|
|
176
189
|
const points = [];
|
|
177
190
|
parts.forEach((option, i) => {
|
|
@@ -188,6 +201,7 @@ class MapArea {
|
|
|
188
201
|
}
|
|
189
202
|
getHeading(way, position = 'start') {
|
|
190
203
|
var _a;
|
|
204
|
+
this.lastUsed = Date.now();
|
|
191
205
|
if (((_a = way === null || way === void 0 ? void 0 : way.path) === null || _a === void 0 ? void 0 : _a.length) < 2)
|
|
192
206
|
return;
|
|
193
207
|
let fullWay = this.getWay(way.id);
|
|
@@ -17,7 +17,7 @@ export declare class OptionManager {
|
|
|
17
17
|
protected getOptionsRoundabout(location: IncyclistNode, w: IncyclistWay, options: FreeRideContinuation[]): any;
|
|
18
18
|
protected getWay(props: string | IncyclistWay): IncyclistWay;
|
|
19
19
|
protected getNode(props?: string | IncyclistNode): IncyclistNode;
|
|
20
|
-
getRemaining(partial: IncyclistWay): IncyclistWay;
|
|
20
|
+
protected getRemaining(partial: IncyclistWay): IncyclistWay;
|
|
21
21
|
protected findClosestPoint(path: IncyclistNode[], point: IncyclistNode, exclude: IncyclistNode): number;
|
|
22
22
|
getOptionsOnCurrentWay(location: IncyclistNode, way: IncyclistWay, options: Array<FreeRideContinuation>): Array<FreeRideContinuation>;
|
|
23
23
|
protected logError(err: Error, fn: string, args?: any): void;
|
|
@@ -32,7 +32,7 @@ class OptionManager {
|
|
|
32
32
|
const options = [];
|
|
33
33
|
const parts = this.map.splitAtCrossingPoint(way, crossing);
|
|
34
34
|
const { segments, points } = this.map.buildSegmentInfo(way, parts);
|
|
35
|
-
for (const segment of segments) {
|
|
35
|
+
for (const segment of segments !== null && segments !== void 0 ? segments : []) {
|
|
36
36
|
try {
|
|
37
37
|
const path = segment.path;
|
|
38
38
|
const opts = yield this.getNextOptions(segment);
|
|
@@ -65,51 +65,71 @@ class OptionManager {
|
|
|
65
65
|
}
|
|
66
66
|
getNextOptions(from, props) {
|
|
67
67
|
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const way = Object.assign(Object.assign({}, this.getWay(from.id)), { path: from.path });
|
|
72
|
-
let location = way.path[way.path.length - 1];
|
|
73
|
-
if (location.id === undefined) {
|
|
74
|
-
if (way.path.length > 1)
|
|
75
|
-
location = way.path[way.path.length - 2];
|
|
76
|
-
else {
|
|
68
|
+
var _a;
|
|
69
|
+
try {
|
|
70
|
+
if ((from === null || from === void 0 ? void 0 : from.id) === undefined || (from === null || from === void 0 ? void 0 : from.path) === undefined || (from === null || from === void 0 ? void 0 : from.path.length) < 1) {
|
|
77
71
|
return [];
|
|
78
72
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
this.setMap(map);
|
|
87
|
-
}
|
|
88
|
-
const node = this.getNode(location);
|
|
89
|
-
const remaining = this.getRemaining(way);
|
|
90
|
-
let options = [];
|
|
91
|
-
if (node !== undefined) {
|
|
92
|
-
node.ways.forEach((wid) => {
|
|
93
|
-
if (wid === remaining.id) {
|
|
94
|
-
options = this.getOptionsOnCurrentWay(node, remaining, options);
|
|
73
|
+
let originalWay = this.getWay(from.id);
|
|
74
|
+
if (!originalWay) {
|
|
75
|
+
const map = this.service.getMap(from.path[0]);
|
|
76
|
+
const query = { id: from.id, path: from.path, map: map };
|
|
77
|
+
originalWay = this.getWay(query);
|
|
78
|
+
if (!originalWay) {
|
|
79
|
+
return [];
|
|
95
80
|
}
|
|
81
|
+
}
|
|
82
|
+
const way = Object.assign(Object.assign({}, originalWay), { path: from.path });
|
|
83
|
+
let location = way.path[way.path.length - 1];
|
|
84
|
+
if (location.id === undefined) {
|
|
85
|
+
if (way.path.length > 1)
|
|
86
|
+
location = way.path[way.path.length - 2];
|
|
96
87
|
else {
|
|
97
|
-
|
|
98
|
-
options = this.checkOptionsOnDifferentWay(node, w, options);
|
|
88
|
+
return [];
|
|
99
89
|
}
|
|
90
|
+
}
|
|
91
|
+
const map = yield this.service.load(location);
|
|
92
|
+
if (!map) {
|
|
93
|
+
if (!this.map)
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.setMap(map);
|
|
98
|
+
}
|
|
99
|
+
const node = this.getNode(location);
|
|
100
|
+
const remaining = this.getRemaining(way);
|
|
101
|
+
let options = [];
|
|
102
|
+
if (node !== undefined) {
|
|
103
|
+
node.ways.forEach((wid) => {
|
|
104
|
+
if (wid === remaining.id) {
|
|
105
|
+
options = this.getOptionsOnCurrentWay(node, remaining, options);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const w = this.getWay(wid);
|
|
109
|
+
options = this.checkOptionsOnDifferentWay(node, w, options);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const currentDirection = this.map.getHeading(way, 'end');
|
|
114
|
+
options.forEach((option) => {
|
|
115
|
+
const direction = this.map.getHeading(option, 'start');
|
|
116
|
+
option.direction = direction - currentDirection;
|
|
117
|
+
if (option.direction > 180)
|
|
118
|
+
option.direction = option.direction - 360;
|
|
100
119
|
});
|
|
120
|
+
if (props === null || props === void 0 ? void 0 : props.minDistance) {
|
|
121
|
+
yield this.checkMinDistance(options, props.minDistance);
|
|
122
|
+
}
|
|
123
|
+
if (options === null || options === void 0 ? void 0 : options.length) {
|
|
124
|
+
const fromNode = (_a = from.path) === null || _a === void 0 ? void 0 : _a[from.path.length - 2];
|
|
125
|
+
options = options.filter(o => o.path.length > 0 && o.path[1].id !== fromNode.id);
|
|
126
|
+
}
|
|
127
|
+
return options;
|
|
101
128
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
option.direction = direction - currentDirection;
|
|
106
|
-
if (option.direction > 180)
|
|
107
|
-
option.direction = option.direction - 360;
|
|
108
|
-
});
|
|
109
|
-
if (props === null || props === void 0 ? void 0 : props.minDistance) {
|
|
110
|
-
yield this.checkMinDistance(options, props.minDistance);
|
|
129
|
+
catch (err) {
|
|
130
|
+
this.logError(err, 'getNextOptions');
|
|
131
|
+
return [];
|
|
111
132
|
}
|
|
112
|
-
return options;
|
|
113
133
|
});
|
|
114
134
|
}
|
|
115
135
|
checkMinDistance(options, minDistance) {
|
|
@@ -293,8 +313,10 @@ class OptionManager {
|
|
|
293
313
|
if (typeof props === 'string') {
|
|
294
314
|
return (0, clone_1.default)((_a = this.map) === null || _a === void 0 ? void 0 : _a.getWay(props));
|
|
295
315
|
}
|
|
296
|
-
if (props.id !== undefined)
|
|
297
|
-
|
|
316
|
+
if (props.id !== undefined) {
|
|
317
|
+
const map = (_b = props.map) !== null && _b !== void 0 ? _b : this.map;
|
|
318
|
+
return (0, clone_1.default)(map.getWay(props.id));
|
|
319
|
+
}
|
|
298
320
|
}
|
|
299
321
|
getNode(props) {
|
|
300
322
|
var _a, _b;
|
|
@@ -311,37 +333,43 @@ class OptionManager {
|
|
|
311
333
|
}
|
|
312
334
|
}
|
|
313
335
|
getRemaining(partial) {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
lastOriginal = originalWay.path[originalWay.path.length - 1];
|
|
332
|
-
}
|
|
333
|
-
if (last.id === lastOriginal.id) {
|
|
334
|
-
return Object.assign(Object.assign({}, originalWay), { path: [], roundabout: false });
|
|
335
|
-
}
|
|
336
|
-
if (idxLast !== -1 && idxPrev !== -1) {
|
|
337
|
-
if (idxPrev < idxLast)
|
|
338
|
-
newPath = path.slice(idxLast);
|
|
336
|
+
try {
|
|
337
|
+
const originalWay = this.getWay(partial);
|
|
338
|
+
const path = originalWay.path;
|
|
339
|
+
const roundabout = (0, utils_1.isRoundabout)(originalWay);
|
|
340
|
+
if (roundabout)
|
|
341
|
+
return Object.assign(Object.assign({}, originalWay), { roundabout });
|
|
342
|
+
let newPath = path;
|
|
343
|
+
const last = partial.path[partial.path.length - 1];
|
|
344
|
+
const prev = partial.path[partial.path.length - 2];
|
|
345
|
+
const idxLast = path.findIndex((p) => (0, utils_1.pointEquals)(p, last));
|
|
346
|
+
let idxPrev = path.findIndex((p) => (0, utils_1.pointEquals)(p, prev));
|
|
347
|
+
if (idxPrev === -1)
|
|
348
|
+
idxPrev = this.findClosestPoint(path, prev, last);
|
|
349
|
+
let lastOriginal;
|
|
350
|
+
if (idxPrev > idxLast) {
|
|
351
|
+
lastOriginal = originalWay.path[0];
|
|
352
|
+
}
|
|
339
353
|
else {
|
|
340
|
-
|
|
341
|
-
|
|
354
|
+
lastOriginal = originalWay.path[originalWay.path.length - 1];
|
|
355
|
+
}
|
|
356
|
+
if (last.id === lastOriginal.id) {
|
|
357
|
+
return Object.assign(Object.assign({}, originalWay), { path: [], roundabout: false });
|
|
342
358
|
}
|
|
359
|
+
if (idxLast !== -1 && idxPrev !== -1) {
|
|
360
|
+
if (idxPrev < idxLast)
|
|
361
|
+
newPath = path.slice(idxLast);
|
|
362
|
+
else {
|
|
363
|
+
newPath = path.slice(0, idxLast + 1);
|
|
364
|
+
newPath.reverse();
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return Object.assign(Object.assign({}, originalWay), { path: newPath, roundabout });
|
|
368
|
+
}
|
|
369
|
+
catch (err) {
|
|
370
|
+
this.logError(err, 'getRemaining');
|
|
371
|
+
return Object.assign(Object.assign({}, partial), { path: [], roundabout: false });
|
|
343
372
|
}
|
|
344
|
-
return Object.assign(Object.assign({}, originalWay), { path: newPath, roundabout });
|
|
345
373
|
}
|
|
346
374
|
findClosestPoint(path, point, exclude) {
|
|
347
375
|
let found = -1;
|
|
@@ -9,8 +9,8 @@ type MapAreaRecord = {
|
|
|
9
9
|
lastUsed: number;
|
|
10
10
|
radius: number;
|
|
11
11
|
};
|
|
12
|
-
export declare const getMapInfo: (m:
|
|
13
|
-
export declare const getMapsInfo: (maps:
|
|
12
|
+
export declare const getMapInfo: (m: MapAreaRecord) => string;
|
|
13
|
+
export declare const getMapsInfo: (maps: Record<string, MapAreaRecord>, key: string) => string;
|
|
14
14
|
export declare class MapAreaService extends IncyclistService implements IMapAreaService {
|
|
15
15
|
protected static consts: {
|
|
16
16
|
DEFAULT_RADIUS: number;
|
|
@@ -32,7 +32,7 @@ export declare class MapAreaService extends IncyclistService implements IMapArea
|
|
|
32
32
|
protected iv: NodeJS.Timeout;
|
|
33
33
|
constructor();
|
|
34
34
|
load(location: IncyclistNode): Promise<IMapArea>;
|
|
35
|
-
getMap(location: IncyclistNode):
|
|
35
|
+
getMap(location: IncyclistNode): IMapArea;
|
|
36
36
|
getOptionManager(): OptionManager;
|
|
37
37
|
setFilter(filter: Array<string> | null): void;
|
|
38
38
|
protected findBestMap(location: IncyclistNode): Promise<IMapArea | undefined>;
|
|
@@ -66,19 +66,22 @@ const getMapInfo = (m) => {
|
|
|
66
66
|
try {
|
|
67
67
|
const boundary = m.map.getBoundary();
|
|
68
68
|
const bInfo = `${boundary.northeast.lat},${boundary.northeast.lng},${boundary.southwest.lat},${boundary.southwest.lng}`;
|
|
69
|
-
return `${m.radius},
|
|
69
|
+
return `${m.radius},{${bInfo}}`;
|
|
70
70
|
}
|
|
71
|
-
catch (
|
|
71
|
+
catch (err) {
|
|
72
|
+
console.log('# ERROR', err);
|
|
72
73
|
return '';
|
|
73
74
|
}
|
|
74
75
|
};
|
|
75
76
|
exports.getMapInfo = getMapInfo;
|
|
76
77
|
const getMapsInfo = (maps, key) => {
|
|
78
|
+
var _a;
|
|
77
79
|
try {
|
|
78
80
|
const m = maps[key];
|
|
79
|
-
|
|
81
|
+
const time = Number((Date.now() - ((_a = m.map.getLastUsed()) !== null && _a !== void 0 ? _a : m.lastUsed)) / 1000).toFixed(1);
|
|
82
|
+
return `${key}:${(0, exports.getMapInfo)(m)}:age=${time}s`;
|
|
80
83
|
}
|
|
81
|
-
catch (
|
|
84
|
+
catch (_b) {
|
|
82
85
|
return '';
|
|
83
86
|
}
|
|
84
87
|
};
|
|
@@ -131,7 +134,6 @@ let MapAreaService = (() => {
|
|
|
131
134
|
const records = this.getMapsForLocation(location);
|
|
132
135
|
let updateRequired = true;
|
|
133
136
|
let minDist = Number.MAX_VALUE;
|
|
134
|
-
let minPct;
|
|
135
137
|
let best;
|
|
136
138
|
do {
|
|
137
139
|
if (records.length === 0)
|
|
@@ -144,17 +146,13 @@ let MapAreaService = (() => {
|
|
|
144
146
|
updateRequired = dist > (radius / 5);
|
|
145
147
|
if (!updateRequired) {
|
|
146
148
|
minDist = dist;
|
|
147
|
-
minPct = minDist / radius * 100;
|
|
148
149
|
best = record;
|
|
149
150
|
}
|
|
150
151
|
else if (dist < minDist) {
|
|
151
152
|
minDist = dist;
|
|
152
|
-
minPct = minDist / radius * 100;
|
|
153
153
|
}
|
|
154
154
|
yield (0, utils_2.waitNextTick)();
|
|
155
155
|
} while (records.length > 0 && updateRequired);
|
|
156
|
-
const { lat, lng, id } = location;
|
|
157
|
-
this.logEvent({ message: 'distance between previous overpass request', location: { lat, lng, id }, dist: minDist, pct: minPct, updateRequired, map: (0, exports.getMapInfo)(best === null || best === void 0 ? void 0 : best.map) });
|
|
158
156
|
return best === null || best === void 0 ? void 0 : best.map;
|
|
159
157
|
});
|
|
160
158
|
}
|
|
@@ -195,22 +193,16 @@ let MapAreaService = (() => {
|
|
|
195
193
|
}
|
|
196
194
|
addMap(map, location) {
|
|
197
195
|
this.current = map;
|
|
198
|
-
|
|
199
|
-
this.
|
|
196
|
+
const record = { map, lastUsed: Date.now(), radius: this.radius };
|
|
197
|
+
this.maps[this.mapsKey(location)] = record;
|
|
198
|
+
const mapInfo = `${location.lat},${location.lng},${(0, exports.getMapInfo)(record)}`;
|
|
199
|
+
this.logEvent({ message: 'Map added', map: mapInfo, cnt: Object.keys(this.maps).length, maps: Object.keys(this.maps).map(k => (0, exports.getMapsInfo)(this.maps, k)) });
|
|
200
200
|
}
|
|
201
201
|
getMapsForLocation(location) {
|
|
202
202
|
return Object.values(this.maps).filter(m => m.map.isWithinBoundary(location));
|
|
203
203
|
}
|
|
204
204
|
createMapData(openmapData) {
|
|
205
|
-
var _a, _b;
|
|
206
|
-
let ts = Date.now();
|
|
207
205
|
const data = (0, utils_1.parseMapData)(openmapData, this.filter);
|
|
208
|
-
let ts1 = Date.now();
|
|
209
|
-
this.logger.logEvent({ message: 'Parse', duration: (ts1 - ts),
|
|
210
|
-
ways: (_a = data === null || data === void 0 ? void 0 : data.ways.length) !== null && _a !== void 0 ? _a : 0,
|
|
211
|
-
nodes: Object.keys((_b = data === null || data === void 0 ? void 0 : data.nodesLookup) !== null && _b !== void 0 ? _b : {}).length,
|
|
212
|
-
typeStats: data === null || data === void 0 ? void 0 : data.typeStats
|
|
213
|
-
});
|
|
214
206
|
if (data !== undefined) {
|
|
215
207
|
this.loaded = 'success';
|
|
216
208
|
}
|
|
@@ -250,8 +242,9 @@ let MapAreaService = (() => {
|
|
|
250
242
|
this.iv = undefined;
|
|
251
243
|
}
|
|
252
244
|
garbageCollection() {
|
|
245
|
+
const tsLastUsed = (m) => { var _a; return (_a = m.map.getLastUsed()) !== null && _a !== void 0 ? _a : m.lastUsed; };
|
|
253
246
|
const now = Date.now();
|
|
254
|
-
const maps = Object.values(this.maps).filter(m => now - m
|
|
247
|
+
const maps = Object.values(this.maps).filter(m => now - tsLastUsed(m) < 1000 * 60 * 5);
|
|
255
248
|
const keyLastUsed = this.mapsKey(this.current.getQueryLocation());
|
|
256
249
|
const deleteTarget = maps.filter(m => this.mapsKey(m.map.getQueryLocation()) !== keyLastUsed);
|
|
257
250
|
if (deleteTarget.length > MAX_MAPS) {
|
|
@@ -39,6 +39,7 @@ export type FreeRideContinuation = {
|
|
|
39
39
|
};
|
|
40
40
|
export interface IMapAreaService {
|
|
41
41
|
load(location: IncyclistNode): Promise<IMapArea>;
|
|
42
|
+
getMap(location: IncyclistNode): IMapArea;
|
|
42
43
|
}
|
|
43
44
|
export type Boundary = {
|
|
44
45
|
southwest: LatLng;
|
|
@@ -104,6 +105,7 @@ export interface IncyclistWay extends WayInfo {
|
|
|
104
105
|
name: string;
|
|
105
106
|
tags: Record<string, any>;
|
|
106
107
|
bounds: OverpassBounds;
|
|
108
|
+
map?: IMapArea;
|
|
107
109
|
roundabout?: boolean;
|
|
108
110
|
originalId?: string;
|
|
109
111
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { Vector } from "../../utils";
|
|
2
2
|
import { LatLng } from "../../utils/geo";
|
|
3
3
|
import { Boundary, CrossingInfo, IncyclistNode, IncyclistWay, FreeRideDataSet, SplitPointInfo, PathCrossingInfo, WayInfo } from "./types";
|
|
4
|
+
import { RoutePoint } from "../../routes/base/types";
|
|
4
5
|
export declare function addNode(node: number, nodesLookup: Record<string, IncyclistNode>, id: number, path: Array<IncyclistNode>): void;
|
|
5
6
|
export declare function addWay(w: IncyclistWay, ways: Array<IncyclistWay>, waysLookup: Record<string, IncyclistWay>): void;
|
|
6
7
|
export declare function updateTypeStats(types: Record<string, number>, type: string): void;
|
|
7
8
|
export declare function parseMapData(str: JSON | string, filter: any): FreeRideDataSet;
|
|
8
9
|
export declare function splitAtIndex(way: any, idxSplit: any): any[][];
|
|
9
|
-
export declare function concatPaths(path: IncyclistNode[], path2: IncyclistNode[], position: 'before' | 'after'): void;
|
|
10
|
+
export declare function concatPaths(path: IncyclistNode[] | RoutePoint[], path2: IncyclistNode[] | RoutePoint[], position: 'before' | 'after'): void;
|
|
10
11
|
export declare function splitAtPointInfo(way: WayInfo, split: SplitPointInfo): Array<Array<IncyclistNode>>;
|
|
11
12
|
export declare function isRoundabout(w: IncyclistWay, strictCheck?: boolean): boolean;
|
|
12
13
|
export declare function removeDuplicates(options: any): any;
|
|
@@ -126,7 +126,7 @@ function splitAtIndex(way, idxSplit) {
|
|
|
126
126
|
return result;
|
|
127
127
|
}
|
|
128
128
|
function concatPaths(path, path2, position) {
|
|
129
|
-
const append =
|
|
129
|
+
const append = path2.map(p => (Object.assign({}, p)));
|
|
130
130
|
if (position === 'after') {
|
|
131
131
|
append.shift();
|
|
132
132
|
path.push(...append);
|
package/lib/ride/base/types.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { ActiveRideListAvatar, ActivityDetails, PrevRidesListDisplayProps, Scree
|
|
|
9
9
|
import { Workout } from "../../workouts";
|
|
10
10
|
import { FreeRideOption } from "../../routes/list/types";
|
|
11
11
|
import { MapViewPort } from "../route/types";
|
|
12
|
+
import { LatLng } from "../../utils/geo";
|
|
12
13
|
export type RideType = 'Free-Ride' | 'GPX' | 'Video' | 'Workout';
|
|
13
14
|
export type CurrentRideState = 'Idle' | 'Starting' | 'Started' | 'Active' | 'Paused' | 'Error' | 'Finished';
|
|
14
15
|
export type CurrentRideDeviceState = 'Starting' | 'Started' | 'Error';
|
|
@@ -53,21 +54,41 @@ export interface RouteDisplayProps extends IRideModeServiceDisplayProps {
|
|
|
53
54
|
upcomingElevation?: OverlayDisplayProps;
|
|
54
55
|
totalElevation?: OverlayDisplayProps;
|
|
55
56
|
}
|
|
57
|
+
export interface VideoDisplayProps {
|
|
58
|
+
src: any;
|
|
59
|
+
playback: 'native' | 'converted';
|
|
60
|
+
startTime?: number;
|
|
61
|
+
observer: Observer;
|
|
62
|
+
muted?: boolean;
|
|
63
|
+
onPlaybackUpdate?: (time: number, rate: number) => void;
|
|
64
|
+
onLoaded?: () => void;
|
|
65
|
+
onPlaybackError?: (error: string) => void;
|
|
66
|
+
onLoadError?: (error: string) => void;
|
|
67
|
+
}
|
|
68
|
+
export interface RLVDisplayProps extends RouteDisplayProps {
|
|
69
|
+
video?: VideoDisplayProps;
|
|
70
|
+
}
|
|
56
71
|
export interface MapOverlayDisplayProps extends OverlayDisplayProps {
|
|
57
72
|
viewport?: MapViewPort;
|
|
58
73
|
viewportOverwrite?: boolean;
|
|
74
|
+
center?: LatLng;
|
|
75
|
+
bounds?: Number[][];
|
|
59
76
|
onViewportChange?: (viewport: MapViewPort) => void;
|
|
60
77
|
}
|
|
61
78
|
export interface GpxDisplayProps extends RouteDisplayProps {
|
|
62
79
|
rideView: 'sv' | 'map' | 'sat';
|
|
63
80
|
}
|
|
64
|
-
export interface
|
|
65
|
-
options?: FreeRideOption[];
|
|
81
|
+
export interface RouteOptionDisplayProps {
|
|
66
82
|
optionsDelay?: number;
|
|
67
83
|
optionsId?: string;
|
|
68
84
|
onOptionsVisibleChanged: (visible: boolean) => void;
|
|
85
|
+
isNearby?: boolean;
|
|
86
|
+
distance?: number;
|
|
87
|
+
turn?: boolean;
|
|
69
88
|
}
|
|
70
|
-
export interface
|
|
89
|
+
export interface FreeRideDisplayProps extends GpxDisplayProps {
|
|
90
|
+
options?: FreeRideOption[];
|
|
91
|
+
optionProps?: RouteOptionDisplayProps;
|
|
71
92
|
}
|
|
72
93
|
export interface StartOverlayProps {
|
|
73
94
|
mode: RideType;
|
|
@@ -76,7 +97,7 @@ export interface StartOverlayProps {
|
|
|
76
97
|
readyToStart: boolean;
|
|
77
98
|
}
|
|
78
99
|
export interface OverlayDisplayProps {
|
|
79
|
-
show
|
|
100
|
+
show?: boolean;
|
|
80
101
|
minimized?: boolean;
|
|
81
102
|
}
|
|
82
103
|
export interface PrevRidesDisplayProps extends OverlayDisplayProps {
|
|
@@ -61,9 +61,9 @@ const utils_1 = require("../../utils");
|
|
|
61
61
|
const base_1 = require("../base/base");
|
|
62
62
|
const FreeRideDisplayService_1 = require("../route/FreeRideDisplayService");
|
|
63
63
|
const FollowRouteDisplayService_1 = require("../route/FollowRouteDisplayService");
|
|
64
|
-
const VideoDisplayService_1 = require("../route/VideoDisplayService");
|
|
65
64
|
const WorkoutDisplayService_1 = require("../workout/WorkoutDisplayService");
|
|
66
65
|
const api_1 = require("../../api");
|
|
66
|
+
const RLVDisplayService_1 = require("../route/RLVDisplayService");
|
|
67
67
|
let RideDisplayService = (() => {
|
|
68
68
|
let _classDecorators = [types_1.Singleton];
|
|
69
69
|
let _classDescriptor;
|
|
@@ -359,8 +359,11 @@ let RideDisplayService = (() => {
|
|
|
359
359
|
if (!this.type) {
|
|
360
360
|
try {
|
|
361
361
|
this.type = this.detectRideType();
|
|
362
|
+
console.log('#ride type', this.type);
|
|
363
|
+
}
|
|
364
|
+
catch (err) {
|
|
365
|
+
console.log('# error detecting ride type', err);
|
|
362
366
|
}
|
|
363
|
-
catch (_a) { }
|
|
364
367
|
}
|
|
365
368
|
return this.type;
|
|
366
369
|
}
|
|
@@ -375,14 +378,14 @@ let RideDisplayService = (() => {
|
|
|
375
378
|
return (_a = this.getWorkoutRide().getWorkout()) !== null && _a !== void 0 ? _a : this.getWorkoutList().getSelected();
|
|
376
379
|
}
|
|
377
380
|
get route() {
|
|
378
|
-
var _a;
|
|
381
|
+
var _a, _b;
|
|
379
382
|
const route = this.getRouteList().getSelected();
|
|
380
383
|
const settings = this.getRouteList().getStartSettings();
|
|
381
384
|
if (!route && (settings === null || settings === void 0 ? void 0 : settings.type) === 'Free-Ride') {
|
|
382
385
|
return this.getRideModeService().getCurrentRoute();
|
|
383
386
|
}
|
|
384
387
|
if (((_a = route === null || route === void 0 ? void 0 : route.description) === null || _a === void 0 ? void 0 : _a.hasVideo) && (settings === null || settings === void 0 ? void 0 : settings.type) === 'Route') {
|
|
385
|
-
return this.getRideModeService().getCurrentRoute();
|
|
388
|
+
return (_b = this.getRideModeService().getCurrentRoute()) !== null && _b !== void 0 ? _b : route;
|
|
386
389
|
}
|
|
387
390
|
return route;
|
|
388
391
|
}
|
|
@@ -445,18 +448,21 @@ let RideDisplayService = (() => {
|
|
|
445
448
|
(_a = this.observer) === null || _a === void 0 ? void 0 : _a.emit('state-update', this.state);
|
|
446
449
|
}
|
|
447
450
|
detectRideType() {
|
|
448
|
-
var _a
|
|
451
|
+
var _a;
|
|
452
|
+
const route = this.getRouteList().getSelected();
|
|
449
453
|
const startSettings = this.getRouteList().getStartSettings();
|
|
450
454
|
const workout = this.getWorkoutList().getSelected();
|
|
451
455
|
if ((startSettings === null || startSettings === void 0 ? void 0 : startSettings.type) === 'Free-Ride') {
|
|
452
456
|
return 'Free-Ride';
|
|
453
457
|
}
|
|
454
|
-
if (!(
|
|
458
|
+
if (!(route === null || route === void 0 ? void 0 : route.details) && !!workout) {
|
|
455
459
|
return 'Workout';
|
|
456
460
|
}
|
|
457
|
-
if (!(
|
|
458
|
-
|
|
459
|
-
|
|
461
|
+
if (!(route === null || route === void 0 ? void 0 : route.details)) {
|
|
462
|
+
console.log('# this.route?.details', route === null || route === void 0 ? void 0 : route.details, route);
|
|
463
|
+
throw new Error('unknown ride type');
|
|
464
|
+
}
|
|
465
|
+
return ((_a = route === null || route === void 0 ? void 0 : route.description) === null || _a === void 0 ? void 0 : _a.hasVideo) ? 'Video' : 'GPX';
|
|
460
466
|
}
|
|
461
467
|
getRideModeService(overwrite) {
|
|
462
468
|
if (this.displayService && !overwrite)
|
|
@@ -466,7 +472,7 @@ let RideDisplayService = (() => {
|
|
|
466
472
|
switch (type) {
|
|
467
473
|
case 'Free-Ride': return new FreeRideDisplayService_1.FreeRideDisplayService();
|
|
468
474
|
case 'GPX': return new FollowRouteDisplayService_1.FollowRouteDisplayService();
|
|
469
|
-
case 'Video': return new
|
|
475
|
+
case 'Video': return new RLVDisplayService_1.RLVDisplayService();
|
|
470
476
|
case 'Workout': return new WorkoutDisplayService_1.WorkoutDisplayService();
|
|
471
477
|
default:
|
|
472
478
|
return new base_1.RideModeService();
|
|
@@ -567,13 +573,13 @@ let RideDisplayService = (() => {
|
|
|
567
573
|
console.log('# lap completed', oldLap, newLap);
|
|
568
574
|
}
|
|
569
575
|
onRouteUpdated(route) {
|
|
570
|
-
console.log('# route updated', this.route.points);
|
|
571
576
|
this.getActivityRide().onRouteUpdate(route.points);
|
|
572
577
|
}
|
|
573
578
|
onRouteCompleted() {
|
|
574
579
|
var _a;
|
|
575
580
|
if (this.state !== 'Active' && this.state !== 'Paused')
|
|
576
581
|
return;
|
|
582
|
+
console.log('# route completed', this.getWorkoutRide().inUse());
|
|
577
583
|
if (this.getWorkoutRide().inUse()) {
|
|
578
584
|
this.getRouteList().unselect();
|
|
579
585
|
this.type = 'Workout';
|