incyclist-services 1.7.48 → 1.7.49
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/cjs/activities/active-rides/service.js +4 -4
- package/lib/cjs/activities/base/convert/converter.js +1 -1
- package/lib/cjs/activities/base/convert/fit/index.js +1 -0
- package/lib/cjs/activities/base/convert/fit/local-fit.js +208 -0
- package/lib/cjs/activities/base/convert/tcx/tcx.js +3 -3
- package/lib/cjs/activities/base/repo/db.js +1 -1
- package/lib/cjs/activities/base/utils/activity.js +2 -3
- package/lib/cjs/activities/base/utils/helpers.js +1 -1
- package/lib/cjs/activities/ride/duration.js +1 -1
- package/lib/cjs/activities/ride/service.js +20 -19
- package/lib/cjs/apps/base/api/intervals/api.js +1 -1
- package/lib/cjs/apps/komoot/KomootAppConnection.js +1 -1
- package/lib/cjs/apps/velohero/VeloHeroAppConnection.js +1 -1
- package/lib/cjs/appstate/service.js +2 -1
- package/lib/cjs/base/types/observer.js +2 -2
- package/lib/cjs/coaches/coach.js +1 -1
- package/lib/cjs/coaches/service.js +1 -1
- package/lib/cjs/devices/access/service.js +1 -1
- package/lib/cjs/devices/configuration/service.js +5 -5
- package/lib/cjs/devices/page/service.js +1 -1
- package/lib/cjs/devices/pairing/service.js +7 -6
- package/lib/cjs/devices/ride/service.js +12 -10
- package/lib/cjs/maps/MapArea/MapArea.js +33 -33
- package/lib/cjs/maps/MapArea/options.js +27 -27
- package/lib/cjs/maps/MapArea/service.js +2 -2
- package/lib/cjs/maps/MapArea/utils.js +47 -47
- package/lib/cjs/ride/base/base.js +3 -2
- package/lib/cjs/ride/display/service.js +2 -2
- package/lib/cjs/ride/route/FreeRideDisplayService.js +4 -4
- package/lib/cjs/ride/route/GpxDisplayService.js +1 -1
- package/lib/cjs/ride/route/RLVDisplayService.js +4 -3
- package/lib/cjs/routes/base/model/route.js +1 -1
- package/lib/cjs/routes/base/parsers/bikelab.js +1 -1
- package/lib/cjs/routes/base/parsers/geometry.js +1 -1
- package/lib/cjs/routes/base/parsers/gpx.js +1 -1
- package/lib/cjs/routes/base/parsers/incyclist.js +2 -3
- package/lib/cjs/routes/base/parsers/utils.js +2 -2
- package/lib/cjs/routes/base/parsers/xml.js +10 -10
- package/lib/cjs/routes/base/utils/points.js +2 -2
- package/lib/cjs/routes/base/utils/route.js +18 -18
- package/lib/cjs/routes/download/service.js +2 -1
- package/lib/cjs/routes/free-ride/service.js +8 -8
- package/lib/cjs/routes/list/cards/RouteCard.js +2 -2
- package/lib/cjs/routes/list/lists/myroutes.js +1 -1
- package/lib/cjs/routes/list/loaders/StravaActivityLoader.js +3 -3
- package/lib/cjs/routes/list/loaders/api.js +0 -1
- package/lib/cjs/routes/list/service.js +6 -4
- package/lib/cjs/routes/sync/komoot/provider.js +1 -1
- package/lib/cjs/settings/bindings/json.js +3 -3
- package/lib/cjs/settings/display/user/service.js +2 -3
- package/lib/cjs/settings/service/service.js +2 -2
- package/lib/cjs/ui/service.js +4 -3
- package/lib/cjs/utils/formatting.js +3 -3
- package/lib/cjs/utils/geo.js +5 -4
- package/lib/cjs/utils/math.js +1 -1
- package/lib/cjs/utils/vector.js +10 -10
- package/lib/cjs/utils/xml.js +2 -2
- package/lib/cjs/video/VideoConversion.js +3 -3
- package/lib/cjs/video/VideoSyncHelper.js +14 -14
- package/lib/cjs/workouts/base/model/Segment.js +1 -1
- package/lib/cjs/workouts/base/model/Workout.js +2 -2
- package/lib/cjs/workouts/base/parsers/intervals/parser.js +1 -1
- package/lib/cjs/workouts/base/parsers/zwo/zwo.js +6 -5
- package/lib/cjs/workouts/calendar/sync/intervals/provider.js +1 -1
- package/lib/cjs/workouts/ride/service.js +2 -1
- package/lib/esm/activities/active-rides/service.js +4 -4
- package/lib/esm/activities/base/convert/converter.js +2 -2
- package/lib/esm/activities/base/convert/fit/index.js +1 -0
- package/lib/esm/activities/base/convert/fit/local-fit.js +205 -0
- package/lib/esm/activities/base/convert/tcx/tcx.js +3 -3
- package/lib/esm/activities/base/repo/db.js +1 -1
- package/lib/esm/activities/base/utils/activity.js +2 -3
- package/lib/esm/activities/base/utils/helpers.js +1 -1
- package/lib/esm/activities/ride/duration.js +1 -1
- package/lib/esm/activities/ride/service.js +20 -19
- package/lib/esm/apps/base/api/intervals/api.js +1 -1
- package/lib/esm/apps/komoot/KomootAppConnection.js +1 -1
- package/lib/esm/apps/velohero/VeloHeroAppConnection.js +1 -1
- package/lib/esm/appstate/service.js +2 -1
- package/lib/esm/base/types/observer.js +1 -1
- package/lib/esm/coaches/coach.js +1 -1
- package/lib/esm/coaches/service.js +1 -1
- package/lib/esm/devices/access/service.js +1 -1
- package/lib/esm/devices/configuration/service.js +5 -5
- package/lib/esm/devices/page/service.js +1 -1
- package/lib/esm/devices/pairing/service.js +7 -6
- package/lib/esm/devices/ride/service.js +12 -10
- package/lib/esm/maps/MapArea/MapArea.js +33 -33
- package/lib/esm/maps/MapArea/options.js +27 -27
- package/lib/esm/maps/MapArea/service.js +2 -2
- package/lib/esm/maps/MapArea/utils.js +47 -47
- package/lib/esm/ride/base/base.js +3 -2
- package/lib/esm/ride/display/service.js +2 -2
- package/lib/esm/ride/route/FreeRideDisplayService.js +4 -4
- package/lib/esm/ride/route/GpxDisplayService.js +1 -1
- package/lib/esm/ride/route/RLVDisplayService.js +4 -3
- package/lib/esm/routes/base/model/route.js +1 -1
- package/lib/esm/routes/base/parsers/bikelab.js +1 -1
- package/lib/esm/routes/base/parsers/geometry.js +1 -1
- package/lib/esm/routes/base/parsers/gpx.js +1 -1
- package/lib/esm/routes/base/parsers/incyclist.js +2 -3
- package/lib/esm/routes/base/parsers/utils.js +2 -2
- package/lib/esm/routes/base/parsers/xml.js +10 -10
- package/lib/esm/routes/base/utils/points.js +2 -2
- package/lib/esm/routes/base/utils/route.js +18 -18
- package/lib/esm/routes/download/service.js +2 -1
- package/lib/esm/routes/free-ride/service.js +8 -8
- package/lib/esm/routes/list/cards/RouteCard.js +2 -2
- package/lib/esm/routes/list/lists/myroutes.js +1 -1
- package/lib/esm/routes/list/loaders/StravaActivityLoader.js +2 -2
- package/lib/esm/routes/list/loaders/api.js +0 -1
- package/lib/esm/routes/list/service.js +6 -4
- package/lib/esm/routes/sync/komoot/provider.js +1 -1
- package/lib/esm/settings/bindings/json.js +3 -3
- package/lib/esm/settings/display/user/service.js +2 -3
- package/lib/esm/settings/service/service.js +2 -2
- package/lib/esm/ui/service.js +4 -3
- package/lib/esm/utils/formatting.js +3 -3
- package/lib/esm/utils/geo.js +5 -4
- package/lib/esm/utils/math.js +1 -1
- package/lib/esm/utils/vector.js +10 -10
- package/lib/esm/utils/xml.js +2 -2
- package/lib/esm/video/VideoConversion.js +3 -3
- package/lib/esm/video/VideoSyncHelper.js +14 -14
- package/lib/esm/workouts/base/model/Segment.js +1 -1
- package/lib/esm/workouts/base/model/Workout.js +2 -2
- package/lib/esm/workouts/base/parsers/intervals/parser.js +1 -1
- package/lib/esm/workouts/base/parsers/zwo/zwo.js +6 -5
- package/lib/esm/workouts/calendar/sync/intervals/provider.js +1 -1
- package/lib/esm/workouts/ride/service.js +2 -1
- package/lib/types/activities/base/convert/fit/index.d.ts +1 -0
- package/lib/types/activities/base/convert/fit/local-fit.d.ts +12 -0
- package/lib/types/api/download/index.d.ts +1 -1
- package/lib/types/api/mq/index.d.ts +1 -1
- package/lib/types/api/path/index.d.ts +1 -1
- package/lib/types/api/video/index.d.ts +1 -1
- package/lib/types/ride/base/types.d.ts +1 -1
- package/lib/types/routes/list/loaders/StravaActivityLoader.d.ts +1 -1
- package/lib/types/routes/page/types.d.ts +1 -2
- package/package.json +2 -1
|
@@ -392,9 +392,9 @@ let ActiveRidesService = (() => {
|
|
|
392
392
|
return 'Anonymous';
|
|
393
393
|
const names = ['Alex', 'Bart', 'Cosmas', 'Dirk', 'Ernesto', 'Frank', 'Guido', 'Hans', 'Irene', 'John', 'Kai', 'Lorenzo', 'Martin', 'Naijb', 'Oswaldo', 'Pete', 'Quentin', 'Rachel', 'Sophia', 'Trevor', 'Ute', 'Vivian', 'Wil', 'Xaver', 'Younes', 'Zoe'];
|
|
394
394
|
const fnKey = id.charAt(0).toLowerCase();
|
|
395
|
-
const idx = !isNaN(parseInt(fnKey)) ? parseInt(fnKey) : fnKey.
|
|
395
|
+
const idx = !Number.isNaN(Number.parseInt(fnKey)) ? Number.parseInt(fnKey) : (fnKey.codePointAt(0) ?? 0) - 96;
|
|
396
396
|
const lnKey = id.charAt(0).toUpperCase();
|
|
397
|
-
const ln = !isNaN(parseInt(lnKey)) ? '' : lnKey;
|
|
397
|
+
const ln = !Number.isNaN(Number.parseInt(lnKey)) ? '' : lnKey;
|
|
398
398
|
return `${names[idx]}${ln}`;
|
|
399
399
|
}
|
|
400
400
|
addCurrentActivity() {
|
|
@@ -567,7 +567,7 @@ let ActiveRidesService = (() => {
|
|
|
567
567
|
const logs = this.activity?.logs ?? [];
|
|
568
568
|
if (!logs.length)
|
|
569
569
|
return;
|
|
570
|
-
const point = logs
|
|
570
|
+
const point = logs.at(-1);
|
|
571
571
|
const { lat, lng, elevation, slope } = point;
|
|
572
572
|
return { lat, lng, elevation, slope };
|
|
573
573
|
}
|
|
@@ -807,7 +807,7 @@ let ActiveRidesService = (() => {
|
|
|
807
807
|
}
|
|
808
808
|
this.coaches = coaches.map(c => {
|
|
809
809
|
const props = c.getRidersListDisplayProperties();
|
|
810
|
-
|
|
810
|
+
const routeDistance = props.currentRideDistance;
|
|
811
811
|
const entry = { ...props,
|
|
812
812
|
ride: this.current?.ride,
|
|
813
813
|
};
|
|
@@ -9,7 +9,7 @@ class ActivityConverter {
|
|
|
9
9
|
static async convert(activity, format) {
|
|
10
10
|
if (!ActivityConverter.factory) {
|
|
11
11
|
ActivityConverter.factory = new factory_1.ActivityConverterFactory();
|
|
12
|
-
ActivityConverter.factory.add('fit', new fit_1.
|
|
12
|
+
ActivityConverter.factory.add('fit', new fit_1.LocalFitConverter());
|
|
13
13
|
ActivityConverter.factory.add('tcx', new tcx_1.TcxConverter());
|
|
14
14
|
}
|
|
15
15
|
return await ActivityConverter.factory.convert(activity, format);
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
3
|
+
var useValue = arguments.length > 2;
|
|
4
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
5
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
6
|
+
}
|
|
7
|
+
return useValue ? value : void 0;
|
|
8
|
+
};
|
|
9
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
10
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
11
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
12
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
13
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
14
|
+
var _, done = false;
|
|
15
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
16
|
+
var context = {};
|
|
17
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
18
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
19
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
20
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
21
|
+
if (kind === "accessor") {
|
|
22
|
+
if (result === void 0) continue;
|
|
23
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
24
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
25
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
26
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
27
|
+
}
|
|
28
|
+
else if (_ = accept(result)) {
|
|
29
|
+
if (kind === "field") initializers.unshift(_);
|
|
30
|
+
else descriptor[key] = _;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
34
|
+
done = true;
|
|
35
|
+
};
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.LocalFitConverter = void 0;
|
|
38
|
+
const fitsdk_1 = require("@garmin/fitsdk");
|
|
39
|
+
const gd_eventlog_1 = require("gd-eventlog");
|
|
40
|
+
const settings_1 = require("../../../../settings");
|
|
41
|
+
const decorators_1 = require("../../../../base/decorators");
|
|
42
|
+
const DEG_TO_SEMICIRCLES = (2 ** 31) / 180;
|
|
43
|
+
let LocalFitConverter = (() => {
|
|
44
|
+
let _instanceExtraInitializers = [];
|
|
45
|
+
let _getUserSettings_decorators;
|
|
46
|
+
return class LocalFitConverter {
|
|
47
|
+
static {
|
|
48
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
49
|
+
_getUserSettings_decorators = [decorators_1.Injectable];
|
|
50
|
+
__esDecorate(this, null, _getUserSettings_decorators, { kind: "method", name: "getUserSettings", static: false, private: false, access: { has: obj => "getUserSettings" in obj, get: obj => obj.getUserSettings }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
51
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
52
|
+
}
|
|
53
|
+
logger = __runInitializers(this, _instanceExtraInitializers);
|
|
54
|
+
constructor() {
|
|
55
|
+
this.logger = new gd_eventlog_1.EventLogger('LocalFitExporter');
|
|
56
|
+
}
|
|
57
|
+
async convert(activity) {
|
|
58
|
+
try {
|
|
59
|
+
this.logger.logEvent({ message: 'convert start', format: 'FIT' });
|
|
60
|
+
const fitActivity = this.getFitActivity(activity);
|
|
61
|
+
const data = this.encode(fitActivity);
|
|
62
|
+
this.logger.logEvent({ message: 'convert success', format: 'FIT' });
|
|
63
|
+
return data;
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
this.logger.logEvent({ message: 'convert result', format: 'FIT', result: 'error', reason: err.message });
|
|
67
|
+
throw err;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
getFitActivity(activity) {
|
|
71
|
+
const { id, title, time, timeTotal, timePause, distance } = activity;
|
|
72
|
+
const status = 'created';
|
|
73
|
+
const startTime = new Date(activity.startTime).toISOString();
|
|
74
|
+
const logs = activity.logs.map(this.mapLogToFit.bind(this));
|
|
75
|
+
const screenshots = [];
|
|
76
|
+
const laps = this.mapLapsToFit(activity.laps ?? [], activity.startTime);
|
|
77
|
+
const user = {
|
|
78
|
+
id: this.getUserSettings().get('uuid', undefined),
|
|
79
|
+
weight: activity.user.weight
|
|
80
|
+
};
|
|
81
|
+
return { id, title, status, logs, laps, startTime, time, timeTotal, timePause, distance, user, screenshots };
|
|
82
|
+
}
|
|
83
|
+
mapLapsToFit(laps, activityStartTime) {
|
|
84
|
+
const activityStartMs = new Date(activityStartTime).getTime();
|
|
85
|
+
return laps.map((lap, i) => {
|
|
86
|
+
const prevDistance = i > 0 ? laps[i - 1].distance : 0;
|
|
87
|
+
return {
|
|
88
|
+
lapNo: lap.num,
|
|
89
|
+
startTime: new Date(lap.startTime).toISOString(),
|
|
90
|
+
stopTime: new Date(lap.startTime + lap.rideTime * 1000).toISOString(),
|
|
91
|
+
lapDistance: lap.distance - prevDistance,
|
|
92
|
+
totalDistance: lap.distance,
|
|
93
|
+
lapTime: lap.rideTime,
|
|
94
|
+
totalTime: (lap.startTime - activityStartMs) / 1000 + lap.rideTime,
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
mapLogToFit(log) {
|
|
99
|
+
const { time, speed, slope, cadence: cadenceOrg, heartrate: heartrateOrg, distance, power: powerOrg, lat, lng, elevation } = log;
|
|
100
|
+
const cadence = Math.round(cadenceOrg);
|
|
101
|
+
const heartrate = Math.round(heartrateOrg);
|
|
102
|
+
const power = Math.round(powerOrg);
|
|
103
|
+
return { time, speed, slope, cadence, heartrate, distance, power, lat, lon: lng, elevation };
|
|
104
|
+
}
|
|
105
|
+
encode(activity) {
|
|
106
|
+
const encoder = new fitsdk_1.Encoder();
|
|
107
|
+
const startTime = new Date(activity.startTime);
|
|
108
|
+
encoder.onMesg(fitsdk_1.Profile.MesgNum.FILE_ID, {
|
|
109
|
+
type: 'activity',
|
|
110
|
+
manufacturer: 'development',
|
|
111
|
+
product: 0,
|
|
112
|
+
timeCreated: startTime,
|
|
113
|
+
});
|
|
114
|
+
encoder.onMesg(fitsdk_1.Profile.MesgNum.EVENT, {
|
|
115
|
+
timestamp: startTime,
|
|
116
|
+
event: 'timer',
|
|
117
|
+
eventType: 'start',
|
|
118
|
+
data: 0,
|
|
119
|
+
});
|
|
120
|
+
let lastTimestampMs = startTime.getTime();
|
|
121
|
+
activity.logs.forEach((log) => {
|
|
122
|
+
if (log.time != null) {
|
|
123
|
+
lastTimestampMs = startTime.getTime() + log.time * 1000;
|
|
124
|
+
}
|
|
125
|
+
const record = {
|
|
126
|
+
timestamp: new Date(lastTimestampMs),
|
|
127
|
+
};
|
|
128
|
+
if (log.lat != null && log.lon != null) {
|
|
129
|
+
record.positionLat = Math.round(log.lat * DEG_TO_SEMICIRCLES);
|
|
130
|
+
record.positionLong = Math.round(log.lon * DEG_TO_SEMICIRCLES);
|
|
131
|
+
}
|
|
132
|
+
if (log.elevation != null)
|
|
133
|
+
record.altitude = log.elevation;
|
|
134
|
+
if (log.heartrate != null)
|
|
135
|
+
record.heartRate = log.heartrate;
|
|
136
|
+
if (log.cadence != null)
|
|
137
|
+
record.cadence = log.cadence;
|
|
138
|
+
if (log.distance != null)
|
|
139
|
+
record.distance = log.distance;
|
|
140
|
+
if (log.speed != null)
|
|
141
|
+
record.speed = log.speed / 3.6;
|
|
142
|
+
if (log.power != null)
|
|
143
|
+
record.power = log.power;
|
|
144
|
+
if (log.slope != null)
|
|
145
|
+
record.grade = log.slope;
|
|
146
|
+
encoder.onMesg(fitsdk_1.Profile.MesgNum.RECORD, record);
|
|
147
|
+
});
|
|
148
|
+
const endTime = new Date(lastTimestampMs);
|
|
149
|
+
encoder.onMesg(fitsdk_1.Profile.MesgNum.EVENT, {
|
|
150
|
+
timestamp: endTime,
|
|
151
|
+
event: 'timer',
|
|
152
|
+
eventType: 'stopAll',
|
|
153
|
+
data: 0,
|
|
154
|
+
});
|
|
155
|
+
if (activity.laps.length > 0) {
|
|
156
|
+
activity.laps.forEach(lap => {
|
|
157
|
+
const lapStart = new Date(lap.startTime);
|
|
158
|
+
const lapEnd = new Date(lap.stopTime);
|
|
159
|
+
encoder.onMesg(fitsdk_1.Profile.MesgNum.LAP, {
|
|
160
|
+
timestamp: lapEnd,
|
|
161
|
+
startTime: lapStart,
|
|
162
|
+
totalElapsedTime: lap.lapTime,
|
|
163
|
+
totalTimerTime: lap.lapTime,
|
|
164
|
+
totalDistance: lap.lapDistance,
|
|
165
|
+
event: 'lap',
|
|
166
|
+
eventType: 'stop',
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
encoder.onMesg(fitsdk_1.Profile.MesgNum.LAP, {
|
|
172
|
+
timestamp: endTime,
|
|
173
|
+
startTime,
|
|
174
|
+
totalElapsedTime: activity.timeTotal,
|
|
175
|
+
totalTimerTime: activity.time,
|
|
176
|
+
totalDistance: activity.distance,
|
|
177
|
+
event: 'lap',
|
|
178
|
+
eventType: 'stop',
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
encoder.onMesg(fitsdk_1.Profile.MesgNum.SESSION, {
|
|
182
|
+
timestamp: endTime,
|
|
183
|
+
startTime,
|
|
184
|
+
totalElapsedTime: activity.timeTotal,
|
|
185
|
+
totalTimerTime: activity.time,
|
|
186
|
+
totalDistance: activity.distance,
|
|
187
|
+
sport: 'cycling',
|
|
188
|
+
subSport: 'virtualActivity',
|
|
189
|
+
event: 'session',
|
|
190
|
+
eventType: 'stopDisableAll',
|
|
191
|
+
});
|
|
192
|
+
encoder.onMesg(fitsdk_1.Profile.MesgNum.ACTIVITY, {
|
|
193
|
+
timestamp: endTime,
|
|
194
|
+
totalTimerTime: activity.time,
|
|
195
|
+
numSessions: 1,
|
|
196
|
+
type: 'manual',
|
|
197
|
+
event: 'activity',
|
|
198
|
+
eventType: 'stop',
|
|
199
|
+
});
|
|
200
|
+
const uint8Array = encoder.close();
|
|
201
|
+
return uint8Array.buffer;
|
|
202
|
+
}
|
|
203
|
+
getUserSettings() {
|
|
204
|
+
return (0, settings_1.useUserSettings)();
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
})();
|
|
208
|
+
exports.LocalFitConverter = LocalFitConverter;
|
|
@@ -112,7 +112,7 @@ class TcxConverter {
|
|
|
112
112
|
const lapEnd = new Date(startTime.valueOf() + end * 1000);
|
|
113
113
|
const points = trackPoints.filter(p => p.Time >= lapStart && p.Time < lapEnd);
|
|
114
114
|
const lastPointBeforeLap = trackPoints.filter(p => p.Time < lapStart)?.pop();
|
|
115
|
-
const lastPointInLap = points
|
|
115
|
+
const lastPointInLap = points.at(-1);
|
|
116
116
|
const distanceStart = lastPointBeforeLap?.DistanceMeters ?? 0;
|
|
117
117
|
const DistanceMeters = lastPointInLap?.DistanceMeters ? lastPointInLap.DistanceMeters - distanceStart : 0;
|
|
118
118
|
const lap = new tcx_builder_1.ActivityLap(lapStart, {
|
|
@@ -151,7 +151,7 @@ class TcxConverter {
|
|
|
151
151
|
if (!markers.length) {
|
|
152
152
|
return [{ start: 0, end: activityDuration }];
|
|
153
153
|
}
|
|
154
|
-
const final = steps
|
|
154
|
+
const final = steps.at(-1);
|
|
155
155
|
if (final.end < activityDuration) {
|
|
156
156
|
markers.push({ start: final.end, end: activityDuration });
|
|
157
157
|
}
|
|
@@ -189,7 +189,7 @@ class TcxConverter {
|
|
|
189
189
|
else {
|
|
190
190
|
lng = log?.lon;
|
|
191
191
|
}
|
|
192
|
-
if (!isNaN(Number(lat ?? 'XX')) && !isNaN(Number(lng ?? 'XX')))
|
|
192
|
+
if (!Number.isNaN(Number(lat ?? 'XX')) && !Number.isNaN(Number(lng ?? 'XX')))
|
|
193
193
|
tp.Position = new tcx_builder_1.Position(lat, lng);
|
|
194
194
|
return tp;
|
|
195
195
|
});
|
|
@@ -151,7 +151,7 @@ let Activity = (() => {
|
|
|
151
151
|
if (fileName)
|
|
152
152
|
exports.push({ type: 'json', file: fileName });
|
|
153
153
|
const formats = ['tcx', 'fit'];
|
|
154
|
-
for (
|
|
154
|
+
for (const type of formats) {
|
|
155
155
|
const details = this.details ?? {};
|
|
156
156
|
const file = details[`${type}FileName`] ?? fileName?.replace('.json', `.${type}`);
|
|
157
157
|
const fs = this.getBindings().fs;
|
|
@@ -178,9 +178,8 @@ let Activity = (() => {
|
|
|
178
178
|
observer.emit('export', { status: 'started', format });
|
|
179
179
|
}
|
|
180
180
|
try {
|
|
181
|
-
let data;
|
|
182
181
|
const converter = this.getActivityConverter();
|
|
183
|
-
data = await converter.convert(this.details, format);
|
|
182
|
+
const data = await converter.convert(this.details, format);
|
|
184
183
|
const fileName = this.details.fileName.replace('.json', `.${format}`);
|
|
185
184
|
await fs.writeFile(fileName, Buffer.from(data));
|
|
186
185
|
this.details[`${format}FileName`] = fileName;
|
|
@@ -35,7 +35,7 @@ const buildSummary = (activity, proposedName) => {
|
|
|
35
35
|
}
|
|
36
36
|
if (name === undefined && fileName !== undefined) {
|
|
37
37
|
const parts = fileName.split(/[/\\]/);
|
|
38
|
-
const match = /([^\\/]+)\.json/.exec(parts
|
|
38
|
+
const match = /([^\\/]+)\.json/.exec(parts.at(-1));
|
|
39
39
|
if (match?.[1])
|
|
40
40
|
name = match[1];
|
|
41
41
|
}
|
|
@@ -34,7 +34,7 @@ class ActivityDuration {
|
|
|
34
34
|
const realityFactor = (this.activity.realityFactor ?? 100) / 100;
|
|
35
35
|
this.checkIfCacheIsInvalid(routePos, route);
|
|
36
36
|
if (this.cache) {
|
|
37
|
-
|
|
37
|
+
const updateFrequency = this.getUpdateFrequency(time);
|
|
38
38
|
const timeSinceLastUpdate = Date.now() - this.cache.ts;
|
|
39
39
|
if (timeSinceLastUpdate < updateFrequency) {
|
|
40
40
|
const timeRemaining = this.cache.remaining.timeRemaining - (Date.now() - this.cache.ts) / 1000;
|
|
@@ -254,7 +254,8 @@ let ActivityRideService = (() => {
|
|
|
254
254
|
showLog = (showLog || this.current.isAutoResume) && (infoStr !== this.current.info);
|
|
255
255
|
this.current.info = infoStr;
|
|
256
256
|
}
|
|
257
|
-
catch {
|
|
257
|
+
catch {
|
|
258
|
+
}
|
|
258
259
|
if (showLog) {
|
|
259
260
|
this.logEvent({ message: 'Dashboard update', items: info.map(i => `${i.title}:${i.data[0]?.value ?? ''}:${i.data[1]?.value ?? ''}${i.data[1]?.label ? '(' + i.data[1]?.label + ')' : ''}`).join('|') });
|
|
260
261
|
}
|
|
@@ -318,7 +319,7 @@ let ActivityRideService = (() => {
|
|
|
318
319
|
speed = 0;
|
|
319
320
|
}
|
|
320
321
|
let distanceRemaining = (this.getTotalDistance() / 1000 - distance);
|
|
321
|
-
if (isNaN(distanceRemaining))
|
|
322
|
+
if (Number.isNaN(distanceRemaining))
|
|
322
323
|
distanceRemaining = undefined;
|
|
323
324
|
if (distanceRemaining < 0)
|
|
324
325
|
distanceRemaining = 0;
|
|
@@ -355,7 +356,7 @@ let ActivityRideService = (() => {
|
|
|
355
356
|
const heartrateDetails = { value: (0, utils_1.formatNumber)(stats?.hrm?.avg, 0), label: 'avg' };
|
|
356
357
|
const cadenceDetails = { value: (0, utils_1.formatNumber)(stats?.cadence?.avg, 0), label: 'avg' };
|
|
357
358
|
let elevationGainRemaining = this.getTotalElevation() - (this.current.elevationGainDisplay ?? 0);
|
|
358
|
-
if (isNaN(elevationGainRemaining))
|
|
359
|
+
if (Number.isNaN(elevationGainRemaining))
|
|
359
360
|
elevationGainRemaining = undefined;
|
|
360
361
|
if (elevationGainRemaining < 0)
|
|
361
362
|
elevationGainRemaining = 0;
|
|
@@ -403,7 +404,7 @@ let ActivityRideService = (() => {
|
|
|
403
404
|
if (this.isDonateShown) {
|
|
404
405
|
return true;
|
|
405
406
|
}
|
|
406
|
-
|
|
407
|
+
const trialGroup = 'A';
|
|
407
408
|
if (this.saveObserver || this.isSaveDone || trialGroup === 'B') {
|
|
408
409
|
const lastClicked = this.getUserSettings().getValue('state.donateClicked', 0);
|
|
409
410
|
if (Date.now() - lastClicked < 1000 * 60 * 60 * 24 * 365) {
|
|
@@ -536,7 +537,7 @@ let ActivityRideService = (() => {
|
|
|
536
537
|
}
|
|
537
538
|
this.current.route.details.points = points;
|
|
538
539
|
(0, route_1.validateRoute)(this.current.route);
|
|
539
|
-
this.current.route.details.distance = points
|
|
540
|
+
this.current.route.details.distance = points.at(-1).routeDistance;
|
|
540
541
|
(0, route_1.addDetails)(this.current.route, this.current.route.details);
|
|
541
542
|
}
|
|
542
543
|
getPrevRideStats(current) {
|
|
@@ -565,7 +566,7 @@ let ActivityRideService = (() => {
|
|
|
565
566
|
if (props.length > maxEntries) {
|
|
566
567
|
const currentIdx = props.findIndex(a => a.title === 'current');
|
|
567
568
|
if (currentIdx < maxEntries - 1) {
|
|
568
|
-
|
|
569
|
+
const deleted = props.splice(maxEntries - 1);
|
|
569
570
|
props.push({ title: `+${deleted.length}`, tsStart: null, distanceGap: '', timeGap: '' });
|
|
570
571
|
}
|
|
571
572
|
else if (currentIdx > maxEntries - 1) {
|
|
@@ -587,7 +588,7 @@ let ActivityRideService = (() => {
|
|
|
587
588
|
props.splice(maxEntries - 2, props.length - maxEntries);
|
|
588
589
|
}
|
|
589
590
|
else if (currentIdx === maxEntries - 1) {
|
|
590
|
-
|
|
591
|
+
const deleted = props.splice(currentIdx + 1, props.length - currentIdx);
|
|
591
592
|
props.push({ title: `+${deleted.length}`, tsStart: null, distanceGap: '', timeGap: '' });
|
|
592
593
|
props.splice(currentIdx - 1, 1);
|
|
593
594
|
}
|
|
@@ -601,7 +602,8 @@ let ActivityRideService = (() => {
|
|
|
601
602
|
logInfo = `(${props.length}/${prevRides.length})`
|
|
602
603
|
+ props.map(buildLog).join(',');
|
|
603
604
|
}
|
|
604
|
-
catch {
|
|
605
|
+
catch {
|
|
606
|
+
}
|
|
605
607
|
this.logEvent({ message: 'PrevRides', prevRides: logInfo });
|
|
606
608
|
return props;
|
|
607
609
|
}
|
|
@@ -621,7 +623,7 @@ let ActivityRideService = (() => {
|
|
|
621
623
|
const { distanceGap, routeDistance, lat, lng } = this.calculateDistanceGap(ai, sameTime, current);
|
|
622
624
|
const [C, U] = this.getUnitConversionShortcuts();
|
|
623
625
|
const speed = { value: C(sameTime.speed, 'speed', { digits: 1 }), unit: U('speed') };
|
|
624
|
-
|
|
626
|
+
const sameDistance = this.getRecordWithSameOrBiggerDistance(logs, current);
|
|
625
627
|
if (!sameDistance)
|
|
626
628
|
return null;
|
|
627
629
|
const timeGap = this.calculateTimeGap(sameDistance, current);
|
|
@@ -652,7 +654,7 @@ let ActivityRideService = (() => {
|
|
|
652
654
|
}
|
|
653
655
|
}
|
|
654
656
|
else {
|
|
655
|
-
res = (0, clone_1.default)(logs
|
|
657
|
+
res = (0, clone_1.default)(logs.at(-1));
|
|
656
658
|
}
|
|
657
659
|
return res;
|
|
658
660
|
}
|
|
@@ -694,7 +696,7 @@ let ActivityRideService = (() => {
|
|
|
694
696
|
const t = v === 0 ? Infinity : s / v;
|
|
695
697
|
sameDistance.time -= t;
|
|
696
698
|
const timeDelta = sameDistance.time - current.time;
|
|
697
|
-
|
|
699
|
+
const prefix = Math.sign(timeDelta) > 0 ? '+' : '-';
|
|
698
700
|
const timeGap = prefix + (Math.abs(timeDelta) < 60 ? `${Math.abs(timeDelta).toFixed(1)}s` : (0, utils_1.formatTime)(Math.abs(timeDelta), true));
|
|
699
701
|
return timeGap;
|
|
700
702
|
}
|
|
@@ -874,8 +876,7 @@ let ActivityRideService = (() => {
|
|
|
874
876
|
const fs = this.getFileSystemBinding();
|
|
875
877
|
emit('convert.start', format);
|
|
876
878
|
try {
|
|
877
|
-
|
|
878
|
-
data = await base_1.ActivityConverter.convert(this.activity, format);
|
|
879
|
+
const data = await base_1.ActivityConverter.convert(this.activity, format);
|
|
879
880
|
emit('convert.done', format, true);
|
|
880
881
|
if (format.toLowerCase() === 'fit') {
|
|
881
882
|
const fileName = await this.getTargetFileName('fit');
|
|
@@ -917,7 +918,7 @@ let ActivityRideService = (() => {
|
|
|
917
918
|
}
|
|
918
919
|
createLogRecord() {
|
|
919
920
|
const prevLogs = this.activity.logs;
|
|
920
|
-
const prev = prevLogs?.length ? prevLogs
|
|
921
|
+
const prev = prevLogs?.length ? prevLogs.at(-1) : undefined;
|
|
921
922
|
const time = this.activity.time;
|
|
922
923
|
const timeDelta = prev ? time - prev.time : time;
|
|
923
924
|
const deviceData = this.current?.deviceData;
|
|
@@ -934,9 +935,9 @@ let ActivityRideService = (() => {
|
|
|
934
935
|
slope: this.current.position?.slope,
|
|
935
936
|
elevation: this.current.position?.elevation
|
|
936
937
|
};
|
|
937
|
-
if (this.current?.position?.lat && !isNaN(this.current?.position?.lat))
|
|
938
|
+
if (this.current?.position?.lat && !Number.isNaN(this.current?.position?.lat))
|
|
938
939
|
log.lat = this.current?.position?.lat;
|
|
939
|
-
if (this.current?.position?.lng && !isNaN(this.current?.position?.lng)) {
|
|
940
|
+
if (this.current?.position?.lng && !Number.isNaN(this.current?.position?.lng)) {
|
|
940
941
|
log.lng = this.current?.position?.lng;
|
|
941
942
|
}
|
|
942
943
|
return log;
|
|
@@ -1080,7 +1081,7 @@ let ActivityRideService = (() => {
|
|
|
1080
1081
|
if (!route)
|
|
1081
1082
|
return 0;
|
|
1082
1083
|
const isLoop = (0, route_1.checkIsLoop)(route);
|
|
1083
|
-
const totalRouteDistance = this.current?.endPos ?? route.distance ?? route.points?.
|
|
1084
|
+
const totalRouteDistance = this.current?.endPos ?? route.distance ?? route.points?.at(-1)?.routeDistance;
|
|
1084
1085
|
if (isLoop) {
|
|
1085
1086
|
const currentLap = Math.floor((this.current.routeDistance ?? 0) / totalRouteDistance);
|
|
1086
1087
|
return totalRouteDistance - (this.activity.startPos ?? 0) + currentLap * totalRouteDistance;
|
|
@@ -1100,8 +1101,8 @@ let ActivityRideService = (() => {
|
|
|
1100
1101
|
if (!route)
|
|
1101
1102
|
return 0;
|
|
1102
1103
|
const isLoop = (0, route_1.checkIsLoop)(route);
|
|
1103
|
-
const totalRouteDistance = this.current?.endPos ?? route.distance ?? route.points?.
|
|
1104
|
-
let totalElevation = route.points?.
|
|
1104
|
+
const totalRouteDistance = this.current?.endPos ?? route.distance ?? route.points?.at(-1)?.routeDistance;
|
|
1105
|
+
let totalElevation = route.points?.at(-1)?.elevationGain ?? 0;
|
|
1105
1106
|
if (this.current?.endPos !== undefined && route.points) {
|
|
1106
1107
|
const endPosPoint = route.points.find(p => p.routeDistance >= this.current.endPos);
|
|
1107
1108
|
if (endPosPoint) {
|
|
@@ -57,7 +57,7 @@ class IntervalsApi extends base_1.AppApiBase {
|
|
|
57
57
|
Authorization: 'Bearer ' + this.config.accessToken
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
|
-
|
|
60
|
+
const url = `/athlete/0/activities${this.getUploadParams(request)}`;
|
|
61
61
|
const form = await this.createForm(url, { file: request.file }, reqOpts);
|
|
62
62
|
const response = await this.postForm(form);
|
|
63
63
|
if (response.data && !response.error && !response.data.error) {
|
|
@@ -186,7 +186,7 @@ let KomootAppConnection = (() => {
|
|
|
186
186
|
this.on('login-failure', () => { this._isConnecting = false; });
|
|
187
187
|
}
|
|
188
188
|
getCrypto() {
|
|
189
|
-
return (0, api_1.getBindings)().crypto ?? require('crypto');
|
|
189
|
+
return (0, api_1.getBindings)().crypto ?? require('node:crypto');
|
|
190
190
|
}
|
|
191
191
|
encrypt(algo) {
|
|
192
192
|
if (!this.credentials)
|
|
@@ -170,7 +170,7 @@ let VeloHeroAppConnection = (() => {
|
|
|
170
170
|
this.on('login-failure', () => { this._isConnecting = false; });
|
|
171
171
|
}
|
|
172
172
|
getCrypto() {
|
|
173
|
-
return (0, api_1.getBindings)().crypto ?? require('crypto');
|
|
173
|
+
return (0, api_1.getBindings)().crypto ?? require('node:crypto');
|
|
174
174
|
}
|
|
175
175
|
encrypt(algo) {
|
|
176
176
|
if (!this.credentials)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PromiseObserver = exports.Observer = void 0;
|
|
4
|
-
const
|
|
4
|
+
const node_events_1 = require("node:events");
|
|
5
5
|
const utils_1 = require("../../utils");
|
|
6
6
|
class Observer {
|
|
7
7
|
emitter;
|
|
8
8
|
constructor() {
|
|
9
|
-
this.emitter = new
|
|
9
|
+
this.emitter = new node_events_1.EventEmitter();
|
|
10
10
|
}
|
|
11
11
|
on(event, callback) {
|
|
12
12
|
this.emitter.on(event, callback);
|
package/lib/cjs/coaches/coach.js
CHANGED
|
@@ -138,7 +138,7 @@ let CoachesService = (() => {
|
|
|
138
138
|
if (startSettings.type === 'Route') {
|
|
139
139
|
pos = startSettings.startPos;
|
|
140
140
|
}
|
|
141
|
-
const lead = (isNaN(c.settings?.lead) ? 0 : c.settings?.lead) ?? 0;
|
|
141
|
+
const lead = (Number.isNaN(c.settings?.lead) ? 0 : c.settings?.lead) ?? 0;
|
|
142
142
|
c.setRoute(route);
|
|
143
143
|
c.setProgress(lead + pos);
|
|
144
144
|
c.setRiderPosition(pos);
|
|
@@ -287,7 +287,7 @@ let DeviceAccessService = (() => {
|
|
|
287
287
|
const onDataHandlers = {};
|
|
288
288
|
const { includeKnown = false } = props;
|
|
289
289
|
const isKnown = (adapters, deviceSettings) => {
|
|
290
|
-
if (adapters.
|
|
290
|
+
if (adapters.some(a => a.isEqual(deviceSettings))) {
|
|
291
291
|
return true;
|
|
292
292
|
}
|
|
293
293
|
if (filter.profile && deviceSettings.profile !== filter.profile) {
|
|
@@ -377,7 +377,7 @@ let DeviceConfigurationService = (() => {
|
|
|
377
377
|
const device = devices.find(d => d.udid === udid);
|
|
378
378
|
if (!device)
|
|
379
379
|
return;
|
|
380
|
-
let mode, settings
|
|
380
|
+
let mode, settings;
|
|
381
381
|
let modeObj;
|
|
382
382
|
let modes = [];
|
|
383
383
|
const adapter = this.getAdapterFromSetting(device.settings);
|
|
@@ -401,8 +401,8 @@ let DeviceConfigurationService = (() => {
|
|
|
401
401
|
if (!settings && modeObj) {
|
|
402
402
|
settings = modeObj.getSettings();
|
|
403
403
|
}
|
|
404
|
-
isERG = modeObj?.isERG() === true;
|
|
405
|
-
isSIM = modeObj?.isSIM() === true;
|
|
404
|
+
const isERG = modeObj?.isERG() === true;
|
|
405
|
+
const isSIM = modeObj?.isSIM() === true;
|
|
406
406
|
return { udid, mode, settings, isERG, isSIM, options };
|
|
407
407
|
}
|
|
408
408
|
catch (err) {
|
|
@@ -460,7 +460,7 @@ let DeviceConfigurationService = (() => {
|
|
|
460
460
|
capabilities.forEach(c => {
|
|
461
461
|
if (c.disabled || !c.selected)
|
|
462
462
|
return;
|
|
463
|
-
if (!devices.
|
|
463
|
+
if (!devices.some(d => d.udid === c.selected))
|
|
464
464
|
return;
|
|
465
465
|
const adapter = this.adapters[c.selected];
|
|
466
466
|
if (!adapter)
|
|
@@ -775,7 +775,7 @@ let DeviceConfigurationService = (() => {
|
|
|
775
775
|
if (!this.settings.capabilities)
|
|
776
776
|
this.settings.capabilities = [];
|
|
777
777
|
target.forEach(capability => {
|
|
778
|
-
if (!this.settings.capabilities.
|
|
778
|
+
if (!this.settings.capabilities.some(c => c.capability === capability))
|
|
779
779
|
this.settings.capabilities.push({ capability, devices: [], selected: undefined, disabled: false });
|
|
780
780
|
});
|
|
781
781
|
}
|
|
@@ -271,7 +271,7 @@ let DevicesPageService = (() => {
|
|
|
271
271
|
isSelected: d.selected,
|
|
272
272
|
onClick: (addAll) => { this.onDeviceSelected(d, addAll); }
|
|
273
273
|
}));
|
|
274
|
-
const disabled = devices.length > 0 && !devices.
|
|
274
|
+
const disabled = devices.length > 0 && !devices.some(d => d.isSelected);
|
|
275
275
|
return {
|
|
276
276
|
capability: this.openedCapability,
|
|
277
277
|
devices,
|