incyclist-services 1.3.26 → 1.3.28

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 (103) hide show
  1. package/lib/activities/base/convert/converter.d.ts +2 -1
  2. package/lib/activities/base/convert/converter.js +3 -0
  3. package/lib/activities/base/repo/db.d.ts +9 -0
  4. package/lib/activities/base/repo/db.js +47 -10
  5. package/lib/activities/base/utils/index.js +1 -1
  6. package/lib/activities/ride/duration.d.ts +2 -0
  7. package/lib/activities/ride/duration.js +20 -9
  8. package/lib/activities/ride/service.d.ts +67 -1
  9. package/lib/activities/ride/service.js +135 -109
  10. package/lib/activities/ride/stats.d.ts +4 -0
  11. package/lib/activities/ride/stats.js +30 -19
  12. package/lib/activities/upload/factory.d.ts +4 -1
  13. package/lib/activities/upload/factory.js +3 -1
  14. package/lib/activities/upload/strava.js +4 -5
  15. package/lib/activities/upload/velohero.d.ts +1 -2
  16. package/lib/activities/upload/velohero.js +17 -5
  17. package/lib/api/download/index.d.ts +0 -1
  18. package/lib/api/path/index.d.ts +1 -2
  19. package/lib/api/repository/json/index.js +2 -10
  20. package/lib/api/rest/RestApiClient.d.ts +1 -1
  21. package/lib/api/rest/incyclist.d.ts +1 -1
  22. package/lib/apps/base/api/base.js +5 -10
  23. package/lib/apps/base/api/strava/api.js +1 -1
  24. package/lib/apps/base/api/strava/types.js +1 -1
  25. package/lib/avatars/service.js +0 -1
  26. package/lib/base/service.d.ts +0 -1
  27. package/lib/base/types/observer.js +4 -4
  28. package/lib/base/types/singleton.js +1 -2
  29. package/lib/coaches/service.d.ts +0 -2
  30. package/lib/coaches/service.js +0 -9
  31. package/lib/devices/access/service.d.ts +0 -1
  32. package/lib/devices/access/service.js +1 -3
  33. package/lib/devices/configuration/service.d.ts +0 -1
  34. package/lib/devices/configuration/service.js +3 -6
  35. package/lib/devices/pairing/model.d.ts +0 -1
  36. package/lib/devices/pairing/service.d.ts +7 -3
  37. package/lib/devices/pairing/service.js +49 -52
  38. package/lib/devices/ride/model.d.ts +0 -1
  39. package/lib/devices/ride/service.d.ts +7 -1
  40. package/lib/devices/ride/service.js +107 -76
  41. package/lib/routes/base/api/index.d.ts +2 -2
  42. package/lib/routes/base/api/index.js +5 -4
  43. package/lib/routes/base/model/route.d.ts +1 -1
  44. package/lib/routes/base/model/route.js +0 -2
  45. package/lib/routes/base/model/tacx.js +0 -1
  46. package/lib/routes/base/parsers/bikelab.d.ts +1 -1
  47. package/lib/routes/base/parsers/epm.d.ts +5 -3
  48. package/lib/routes/base/parsers/epm.js +56 -48
  49. package/lib/routes/base/parsers/factory.d.ts +3 -2
  50. package/lib/routes/base/parsers/factory.js +3 -0
  51. package/lib/routes/base/parsers/gpx.js +1 -1
  52. package/lib/routes/base/parsers/incyclist.d.ts +1 -1
  53. package/lib/routes/base/parsers/incyclist.js +4 -11
  54. package/lib/routes/base/parsers/kwt.d.ts +1 -1
  55. package/lib/routes/base/parsers/tacx/TacxParser.js +3 -6
  56. package/lib/routes/base/parsers/utils.d.ts +0 -1
  57. package/lib/routes/base/parsers/utils.js +41 -31
  58. package/lib/routes/base/parsers/xml.d.ts +1 -0
  59. package/lib/routes/base/parsers/xml.js +59 -51
  60. package/lib/routes/base/utils/route.d.ts +1 -1
  61. package/lib/routes/base/utils/route.js +152 -111
  62. package/lib/routes/download/service.js +4 -1
  63. package/lib/routes/list/cards/FreeRideCard.d.ts +0 -3
  64. package/lib/routes/list/cards/FreeRideCard.js +0 -6
  65. package/lib/routes/list/cards/RouteCard.d.ts +1 -2
  66. package/lib/routes/list/cards/RouteCard.js +4 -3
  67. package/lib/routes/list/cards/base.js +6 -3
  68. package/lib/routes/list/lists/alternatives.js +3 -2
  69. package/lib/routes/list/lists/myroutes.js +4 -3
  70. package/lib/routes/list/lists/selected.js +4 -4
  71. package/lib/routes/list/loaders/api.d.ts +4 -2
  72. package/lib/routes/list/loaders/api.js +109 -74
  73. package/lib/routes/list/loaders/api_new.d.ts +29 -0
  74. package/lib/routes/list/loaders/api_new.js +232 -0
  75. package/lib/routes/list/loaders/db.d.ts +2 -0
  76. package/lib/routes/list/loaders/db.js +19 -14
  77. package/lib/routes/list/loaders/types.d.ts +1 -0
  78. package/lib/routes/list/loaders/types.js +8 -0
  79. package/lib/routes/list/service.d.ts +8 -0
  80. package/lib/routes/list/service.js +84 -48
  81. package/lib/routes/list/utils.js +4 -5
  82. package/lib/settings/user/service.d.ts +2 -2
  83. package/lib/utils/clone.js +1 -1
  84. package/lib/utils/geo.js +48 -42
  85. package/lib/utils/logging.js +1 -2
  86. package/lib/utils/math.js +6 -7
  87. package/lib/utils/merge.js +14 -11
  88. package/lib/utils/valid.js +1 -2
  89. package/lib/utils/vector.d.ts +2 -0
  90. package/lib/utils/vector.js +14 -14
  91. package/lib/utils/xml.d.ts +1 -1
  92. package/lib/workouts/base/api/index.d.ts +1 -1
  93. package/lib/workouts/base/api/index.js +1 -2
  94. package/lib/workouts/base/model/Segment.js +9 -13
  95. package/lib/workouts/base/model/Step.js +19 -26
  96. package/lib/workouts/base/parsers/factory.d.ts +1 -1
  97. package/lib/workouts/base/parsers/zwo.js +18 -20
  98. package/lib/workouts/list/cards/base.js +6 -3
  99. package/lib/workouts/list/loaders/db.js +1 -1
  100. package/lib/workouts/list/service.js +3 -3
  101. package/lib/workouts/ride/service.d.ts +2 -1
  102. package/lib/workouts/ride/service.js +29 -19
  103. package/package.json +13 -14
@@ -1,6 +1,7 @@
1
1
  import { ActivityDetails } from "../model";
2
2
  import { ActivityConverterFactory } from "./factory";
3
3
  export declare class ActivityConverter {
4
- static factory?: ActivityConverterFactory;
4
+ protected static factory?: ActivityConverterFactory;
5
5
  static convert(activity: ActivityDetails, format: string): Promise<unknown>;
6
+ static _reset(): void;
6
7
  }
@@ -24,5 +24,8 @@ class ActivityConverter {
24
24
  return yield ActivityConverter.factory.convert(activity, format);
25
25
  });
26
26
  }
27
+ static _reset() {
28
+ ActivityConverter.factory = undefined;
29
+ }
27
30
  }
28
31
  exports.ActivityConverter = ActivityConverter;
@@ -24,6 +24,15 @@ export declare class ActivitiesRepository {
24
24
  getAll(): ActivityInfo[];
25
25
  getWithDetails(id: string): Promise<ActivityInfo>;
26
26
  search(criteria: ActivitySearchCriteria): Array<ActivityInfo>;
27
+ private checkIdFilter;
28
+ private checkHashFilter;
29
+ private checkStartPosFilter;
30
+ private checkEndPosFilter;
31
+ private checkRealityFactorFilter;
32
+ private checkIsSavedFilter;
33
+ private checkUploadStatusFilter;
34
+ private checkTimeFilter;
35
+ private checkDistanceFilter;
27
36
  protected writeRepo(): Promise<void>;
28
37
  protected write(enforce?: boolean): void;
29
38
  protected emitDone(): void;
@@ -78,7 +78,7 @@ let ActivitiesRepository = (() => {
78
78
  save(activity_1) {
79
79
  return __awaiter(this, arguments, void 0, function* (activity, writeDetails = true) {
80
80
  const stringify = (json) => { try {
81
- JSON.stringify(json);
81
+ return JSON.stringify(json);
82
82
  }
83
83
  catch (_a) { } };
84
84
  let prev;
@@ -146,31 +146,64 @@ let ActivitiesRepository = (() => {
146
146
  }
147
147
  search(criteria) {
148
148
  let result = this.activities;
149
+ result = this.checkIdFilter(result, criteria);
150
+ result = this.checkHashFilter(result, criteria);
151
+ result = this.checkStartPosFilter(result, criteria);
152
+ result = this.checkEndPosFilter(result, criteria);
153
+ result = this.checkRealityFactorFilter(result, criteria);
154
+ result = this.checkIsSavedFilter(result, criteria);
155
+ result = this.checkUploadStatusFilter(result, criteria);
156
+ result = this.checkTimeFilter(result, criteria);
157
+ result = this.checkDistanceFilter(result, criteria);
158
+ return result;
159
+ }
160
+ checkIdFilter(result, criteria) {
149
161
  if ((result === null || result === void 0 ? void 0 : result.length) > 0 && (criteria === null || criteria === void 0 ? void 0 : criteria.routeId)) {
150
162
  result = result.filter(ai => ai.summary.routeId === criteria.routeId);
151
163
  }
164
+ return result;
165
+ }
166
+ checkHashFilter(result, criteria) {
152
167
  if ((result === null || result === void 0 ? void 0 : result.length) > 0 && (criteria === null || criteria === void 0 ? void 0 : criteria.routeHash)) {
153
168
  result = result.filter(ai => ai.summary.routeHash === criteria.routeHash);
154
169
  }
170
+ return result;
171
+ }
172
+ checkStartPosFilter(result, criteria) {
155
173
  if ((result === null || result === void 0 ? void 0 : result.length) > 0 && (criteria === null || criteria === void 0 ? void 0 : criteria.startPos) !== undefined) {
156
174
  result = result.filter(ai => ai.summary.startPos === criteria.startPos);
157
175
  }
176
+ return result;
177
+ }
178
+ checkEndPosFilter(result, criteria) {
158
179
  if ((result === null || result === void 0 ? void 0 : result.length) > 0 && (criteria === null || criteria === void 0 ? void 0 : criteria.endPos) !== undefined) {
159
180
  result = result.filter(ai => ai.summary.endPos === criteria.endPos);
160
181
  }
182
+ return result;
183
+ }
184
+ checkRealityFactorFilter(result, criteria) {
161
185
  if ((result === null || result === void 0 ? void 0 : result.length) > 0 && (criteria === null || criteria === void 0 ? void 0 : criteria.realityFactor) !== undefined) {
162
186
  result = result.filter(ai => { var _a; return ((_a = ai.summary.realityFactor) !== null && _a !== void 0 ? _a : 100) === criteria.realityFactor; });
163
187
  }
188
+ return result;
189
+ }
190
+ checkIsSavedFilter(result, criteria) {
164
191
  if ((result === null || result === void 0 ? void 0 : result.length) > 0 && (criteria === null || criteria === void 0 ? void 0 : criteria.isSaved) !== undefined) {
165
192
  result = result.filter(ai => ai.summary.isSaved === criteria.isSaved);
166
193
  }
194
+ return result;
195
+ }
196
+ checkUploadStatusFilter(result, criteria) {
167
197
  if ((result === null || result === void 0 ? void 0 : result.length) > 0 && (criteria === null || criteria === void 0 ? void 0 : criteria.uploadStatus) !== undefined) {
168
198
  if (Array.isArray(criteria.uploadStatus)) {
169
199
  result = result.filter(ai => {
170
- const requested = criteria.uploadStatus;
171
- const actual = ai.summary.uploadStatus;
172
- const r = requested.sort().map(us => `${us.service}:${us.status}`).join(';');
173
- const a = actual.sort().map(us => `${us.service}:${us.status}`).join(';');
200
+ const requested = Array.from(criteria.uploadStatus);
201
+ const actual = Array.from(ai.summary.uploadStatus);
202
+ const sortFn = (a, b) => a.service.localeCompare(b.service);
203
+ requested.sort(sortFn);
204
+ actual.sort(sortFn);
205
+ const r = requested.map(us => `${us.service}:${us.status}`).join(';');
206
+ const a = actual.map(us => `${us.service}:${us.status}`).join(';');
174
207
  return r === a;
175
208
  });
176
209
  }
@@ -184,9 +217,15 @@ let ActivitiesRepository = (() => {
184
217
  });
185
218
  }
186
219
  }
220
+ return result;
221
+ }
222
+ checkTimeFilter(result, criteria) {
187
223
  if ((result === null || result === void 0 ? void 0 : result.length) > 0 && (criteria === null || criteria === void 0 ? void 0 : criteria.minTime) !== undefined) {
188
224
  result = result.filter(ai => ai.summary.rideTime >= criteria.minTime);
189
225
  }
226
+ return result;
227
+ }
228
+ checkDistanceFilter(result, criteria) {
190
229
  if ((result === null || result === void 0 ? void 0 : result.length) > 0 && (criteria === null || criteria === void 0 ? void 0 : criteria.minDistance) !== undefined) {
191
230
  result = result.filter(ai => ai.summary.distance >= criteria.minDistance);
192
231
  }
@@ -256,13 +295,12 @@ let ActivitiesRepository = (() => {
256
295
  yield this.bulkAddActivities(names);
257
296
  }
258
297
  if (cnt !== this.activities.length) {
259
- yield this.write(true);
298
+ this.write(true);
260
299
  }
261
300
  yield this.fixMissingHash();
262
301
  return;
263
302
  }
264
303
  yield this.buildFromLegacy();
265
- return;
266
304
  });
267
305
  }
268
306
  buildFromLegacy() {
@@ -272,7 +310,7 @@ let ActivitiesRepository = (() => {
272
310
  if (names) {
273
311
  yield this.bulkAddActivities(names);
274
312
  }
275
- yield this.write(true);
313
+ this.write(true);
276
314
  });
277
315
  }
278
316
  listActivities() {
@@ -293,7 +331,7 @@ let ActivitiesRepository = (() => {
293
331
  promises.push(this.loadDetails(ai.summary.name).then(() => { var _a, _b; return ai.summary.routeHash = (_b = (_a = ai.details) === null || _a === void 0 ? void 0 : _a.route) === null || _b === void 0 ? void 0 : _b.hash; }));
294
332
  });
295
333
  yield Promise.allSettled(promises);
296
- yield this.write(true);
334
+ this.write(true);
297
335
  }
298
336
  catch (err) {
299
337
  this.logError(err, 'fixMissingHash');
@@ -345,7 +383,6 @@ let ActivitiesRepository = (() => {
345
383
  }
346
384
  }
347
385
  });
348
- return;
349
386
  });
350
387
  }
351
388
  writeDetails(activity) {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildSummary = void 0;
4
4
  const buildSummary = (activity, proposedName) => {
5
5
  var _a;
6
- const { id, title, route, screenshots, startTime: startTimeUTC, time: rideTime, distance, startPos, endPos, segment, realityFactor = 100, links, laps } = activity;
6
+ const { id, title, route, screenshots, startTime: startTimeUTC, time: rideTime, distance, startPos, endPos, realityFactor = 100, links, laps } = activity;
7
7
  const name = proposedName !== null && proposedName !== void 0 ? proposedName : activity.name;
8
8
  const routeId = route === null || route === void 0 ? void 0 : route.id;
9
9
  const routeHash = route === null || route === void 0 ? void 0 : route.hash;
@@ -25,6 +25,8 @@ export declare class ActivityDuration {
25
25
  protected cache: RemainingTimeCache;
26
26
  constructor(activity: ActivityDetails);
27
27
  getRemainingTime(props: RemainingTimeProps): number;
28
+ private checkIfCacheIsInvalid;
29
+ protected getUpdateFrequency(time: number): number;
28
30
  protected calculateRemainingTime(route: Route, routePos: number, power: number, m: number, v?: number, realityFactor?: number, endPos?: number): Array<RemainingInfo>;
29
31
  }
30
32
  export {};
@@ -22,20 +22,17 @@ class ActivityDuration {
22
22
  this.logger = new gd_eventlog_1.EventLogger('ActivityDuration');
23
23
  }
24
24
  getRemainingTime(props) {
25
- var _a, _b;
25
+ var _a, _b, _c;
26
26
  try {
27
27
  const { route, routePos, power, speed = 0, endPos } = props || {};
28
28
  const { stats, time = 0, user } = this.activity;
29
29
  const calcPower = ((_a = stats === null || stats === void 0 ? void 0 : stats.power) === null || _a === void 0 ? void 0 : _a.avg) || power;
30
- const m = (user.weight || 75) + 10;
30
+ const m = ((_b = user.weight) !== null && _b !== void 0 ? _b : 75) + 10;
31
31
  const v = speed / 3.6;
32
- const realityFactor = ((_b = this.activity.realityFactor) !== null && _b !== void 0 ? _b : 100) / 100;
33
- if ((routePos > route.distance) ||
34
- (this.cache && this.cache.totalDistance !== route.distance)) {
35
- delete this.cache;
36
- }
32
+ const realityFactor = ((_c = this.activity.realityFactor) !== null && _c !== void 0 ? _c : 100) / 100;
33
+ this.checkIfCacheIsInvalid(routePos, route);
37
34
  if (this.cache) {
38
- const updateFrequency = time > 300 ? 3000 : (time > 150 ? 5000 : 10000);
35
+ let updateFrequency = this.getUpdateFrequency(time);
39
36
  const timeSinceLastUpdate = Date.now() - this.cache.ts;
40
37
  if (timeSinceLastUpdate < updateFrequency) {
41
38
  const timeRemaining = this.cache.remaining.timeRemaining - (Date.now() - this.cache.ts) / 1000;
@@ -56,13 +53,27 @@ class ActivityDuration {
56
53
  return undefined;
57
54
  }
58
55
  }
56
+ checkIfCacheIsInvalid(routePos, route) {
57
+ if ((routePos > route.distance) ||
58
+ (this.cache && this.cache.totalDistance !== route.distance)) {
59
+ delete this.cache;
60
+ }
61
+ }
62
+ getUpdateFrequency(time) {
63
+ let updateFrequency = 10000;
64
+ if (time > 150)
65
+ updateFrequency = 5000;
66
+ if (time > 300)
67
+ updateFrequency = 3000;
68
+ return updateFrequency;
69
+ }
59
70
  calculateRemainingTime(route, routePos, power, m, v = 0, realityFactor = 1, endPos) {
60
71
  if (!route)
61
72
  return;
62
73
  const gpxData = route.points;
63
74
  const isLap = (0, route_1.checkIsLoop)(route);
64
75
  const lapDistance = isLap ? routePos % route.distance : routePos;
65
- const totalDistance = endPos !== undefined ? endPos : route.distance;
76
+ const totalDistance = endPos !== null && endPos !== void 0 ? endPos : route.distance;
66
77
  const fromStart = [];
67
78
  let vPrev = v;
68
79
  let timeSinceStart = 0;
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import { IncyclistService } from "../../base/service";
3
2
  import { Observer, PromiseObserver } from "../../base/types/observer";
4
3
  import { DeviceData } from "incyclist-devices";
@@ -60,6 +59,64 @@ export declare class ActivityRideService extends IncyclistService {
60
59
  resume(requester?: 'user' | 'system'): void;
61
60
  ignoreEndPos(): void;
62
61
  getDashboardDisplayProperties(): any[];
62
+ protected buildDashboardInfo(currentValues: any, avgMaxStats: any, display: any): any[];
63
+ protected getCurrentValues(): {
64
+ distance: number;
65
+ time: number;
66
+ speed: number;
67
+ power: number;
68
+ slope: number;
69
+ heartrate: number;
70
+ cadence: number;
71
+ timeRemaining: number;
72
+ distanceRemaining: number;
73
+ };
74
+ protected getAverageValues(): {
75
+ speedDetails: {
76
+ value: string;
77
+ label: string;
78
+ };
79
+ powerDetails: {
80
+ value: string;
81
+ label: string;
82
+ };
83
+ heartrateDetails: {
84
+ value: string;
85
+ label: string;
86
+ };
87
+ cadenceDetails: {
88
+ value: string;
89
+ label: string;
90
+ };
91
+ elevationGain: {
92
+ value: string;
93
+ label: string;
94
+ unit: string;
95
+ };
96
+ };
97
+ protected getMaximumValues(): {
98
+ speedDetails: {
99
+ value: string;
100
+ label: string;
101
+ };
102
+ powerDetails: {
103
+ value: string;
104
+ label: string;
105
+ };
106
+ heartrateDetails: {
107
+ value: string;
108
+ label: string;
109
+ };
110
+ cadenceDetails: {
111
+ value: string;
112
+ label: string;
113
+ };
114
+ elevationGain: {
115
+ value: string;
116
+ label: string;
117
+ unit: string;
118
+ };
119
+ };
63
120
  getActivitySummaryDisplayProperties(): ActivitySummaryDisplayProperties;
64
121
  getActivity(): ActivityDetails;
65
122
  setTitle(title: string): void;
@@ -71,6 +128,15 @@ export declare class ActivityRideService extends IncyclistService {
71
128
  getPrevRideStats(current: ActivityLogRecord): PastActivityInfo;
72
129
  getPrevRidesListDisplay(maxEntries?: number): Array<PrevRidesListDisplayProps>;
73
130
  protected getPrevActivityLog(ai: ActivityInfo, current: ActivityLogRecord): PastActivityLogEntry | null;
131
+ protected getRecordWithSameOrBiggerTime(logs: any, current: any): any;
132
+ protected calculateDistanceGap(ai: ActivityInfo, res: any, current: any): {
133
+ distanceGap: string;
134
+ routeDistance: any;
135
+ lat: any;
136
+ lng: any;
137
+ };
138
+ protected calculateTimeGap(sameDistance: any, current: any): string;
139
+ protected getRecordWithSameOrBiggerDistance(logs: any, current: any): any;
74
140
  protected getCurrentActivityLog(ai: ActivityInfo, current: ActivityLogRecord): PastActivityLogEntry | null;
75
141
  protected onPositionUpdate(position: RoutePoint): void;
76
142
  protected onDeviceData(data: DeviceData): void;
@@ -186,60 +186,12 @@ let ActivityRideService = (() => {
186
186
  delete this.current.endPos;
187
187
  }
188
188
  getDashboardDisplayProperties() {
189
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2;
190
189
  try {
191
- const distance = ((_b = (_a = this.activity) === null || _a === void 0 ? void 0 : _a.distance) !== null && _b !== void 0 ? _b : 0) / 1000;
192
- const speed = ((_c = this.current.deviceData.speed) !== null && _c !== void 0 ? _c : 0);
193
- const power = ((_d = this.current.deviceData.power) !== null && _d !== void 0 ? _d : 0);
194
- const slope = (_e = this.current.position) === null || _e === void 0 ? void 0 : _e.slope;
195
- const heartrate = this.current.deviceData.heartrate;
196
- const cadence = ((_f = this.current.deviceData.cadence) !== null && _f !== void 0 ? _f : 0);
197
- const time = (_h = (_g = this.activity) === null || _g === void 0 ? void 0 : _g.time) !== null && _h !== void 0 ? _h : 0;
190
+ const currentValues = this.getCurrentValues();
191
+ const { time } = currentValues;
198
192
  const display = Math.floor(time / 3) % 2;
199
- let distanceRemaining = (this.getTotalDistance() / 1000 - distance);
200
- if (isNaN(distanceRemaining))
201
- distanceRemaining = undefined;
202
- if (distanceRemaining < 0)
203
- distanceRemaining = 0;
204
- const timeRemaining = this.durationCalculator.getRemainingTime({ route: this.current.route, speed: this.current.deviceData.speed, routePos: this.activity.distance + ((_j = this.activity.startPos) !== null && _j !== void 0 ? _j : 0), endPos: this.current.endPos });
205
- let speedDetails, powerDetails, elevationGain, heartrateDetails, cadenceDetails;
206
- const stats = (_k = this.activity) === null || _k === void 0 ? void 0 : _k.stats;
207
- if (display === 0) {
208
- speedDetails = { value: (0, utils_1.formatNumber)((_l = stats === null || stats === void 0 ? void 0 : stats.speed) === null || _l === void 0 ? void 0 : _l.max, 1), label: 'max' };
209
- powerDetails = { value: (0, utils_1.formatNumber)((_m = stats === null || stats === void 0 ? void 0 : stats.power) === null || _m === void 0 ? void 0 : _m.max, 0), label: 'max' };
210
- heartrateDetails = { value: (0, utils_1.formatNumber)((_o = stats === null || stats === void 0 ? void 0 : stats.hrm) === null || _o === void 0 ? void 0 : _o.max, 0), label: 'max' };
211
- cadenceDetails = { value: (0, utils_1.formatNumber)((_p = stats === null || stats === void 0 ? void 0 : stats.cadence) === null || _p === void 0 ? void 0 : _p.max, 0), label: 'max' };
212
- elevationGain = { value: (0, utils_1.formatNumber)((_q = this.current.elevationGainDisplay) !== null && _q !== void 0 ? _q : 0, 0), label: 'elev gain', unit: 'm' };
213
- }
214
- else {
215
- speedDetails = { value: (0, utils_1.formatNumber)((_r = stats === null || stats === void 0 ? void 0 : stats.speed) === null || _r === void 0 ? void 0 : _r.avg, 1), label: 'avg' };
216
- powerDetails = { value: (0, utils_1.formatNumber)((_s = stats === null || stats === void 0 ? void 0 : stats.power) === null || _s === void 0 ? void 0 : _s.avg, 0), label: 'avg' };
217
- heartrateDetails = { value: (0, utils_1.formatNumber)((_t = stats === null || stats === void 0 ? void 0 : stats.hrm) === null || _t === void 0 ? void 0 : _t.avg, 0), label: 'avg' };
218
- cadenceDetails = { value: (0, utils_1.formatNumber)((_u = stats === null || stats === void 0 ? void 0 : stats.cadence) === null || _u === void 0 ? void 0 : _u.avg, 0), label: 'avg' };
219
- let elevationGainRemaining = this.getTotalElevation() - ((_v = this.current.elevationGainDisplay) !== null && _v !== void 0 ? _v : 0);
220
- if (isNaN(elevationGainRemaining))
221
- elevationGainRemaining = undefined;
222
- if (elevationGainRemaining < 0)
223
- elevationGainRemaining = 0;
224
- const value = elevationGainRemaining !== undefined ? `-${(0, utils_1.formatNumber)(elevationGainRemaining, 0)}` : undefined;
225
- elevationGain = { value, label: 'elev gain', unit: 'm' };
226
- }
227
- const info = [];
228
- info.push({ title: 'Time', data: [
229
- { value: (0, utils_1.formatTime)(time, true) },
230
- { value: timeRemaining !== undefined ? `-${(0, utils_1.formatTime)(timeRemaining, true)}` : undefined }
231
- ]
232
- }),
233
- info.push({ title: 'Distance', data: [{ value: (0, utils_1.formatNumber)(distance, 2), unit: 'km' }, { value: distanceRemaining !== undefined ? `-${(0, utils_1.formatNumber)(distanceRemaining, 2)}` : undefined }] });
234
- info.push({ title: 'Speed', data: [{ value: (0, utils_1.formatNumber)(speed, 1), unit: 'km/h' }, speedDetails], dataState: (_w = this.current.dataState) === null || _w === void 0 ? void 0 : _w.speed });
235
- info.push({ title: 'Power', data: [{ value: (0, utils_1.formatNumber)(power, 0), unit: 'W' }, powerDetails], dataState: (_x = this.current.dataState) === null || _x === void 0 ? void 0 : _x.power });
236
- if (((_y = this.activity) === null || _y === void 0 ? void 0 : _y.routeType) !== 'Free-Ride') {
237
- const rf = (_0 = (_z = this.activity) === null || _z === void 0 ? void 0 : _z.realityFactor) !== null && _0 !== void 0 ? _0 : 100;
238
- const slopeInfo = rf === 100 ? '' : `RF ${rf.toFixed(0)}%`;
239
- info.push({ title: 'Slope', data: [{ value: (0, utils_1.formatNumber)(slope, 1), unit: '%', info: slopeInfo }, elevationGain] });
240
- }
241
- info.push({ title: 'Heartrate', data: [{ value: (0, utils_1.formatNumber)(heartrate, 0), unit: 'bpm' }, heartrateDetails], dataState: (_1 = this.current.dataState) === null || _1 === void 0 ? void 0 : _1.heartrate });
242
- info.push({ title: 'Cadence', data: [{ value: (0, utils_1.formatNumber)(cadence, 0), unit: 'rpm' }, cadenceDetails], dataState: (_2 = this.current.dataState) === null || _2 === void 0 ? void 0 : _2.cadence });
193
+ const avgMaxStats = (display === 0) ? this.getAverageValues() : this.getMaximumValues();
194
+ const info = this.buildDashboardInfo(currentValues, avgMaxStats, display);
243
195
  this.logger.logEvent({ message: 'Dashboard update', items: info.map(i => { var _a, _b, _c, _d; return `${i.title}:${((_a = i.data[0]) === null || _a === void 0 ? void 0 : _a.value) || ''}:${((_b = i.data[1]) === null || _b === void 0 ? void 0 : _b.value) || ''}${((_c = i.data[1]) === null || _c === void 0 ? void 0 : _c.label) ? '(' + ((_d = i.data[1]) === null || _d === void 0 ? void 0 : _d.label) + ')' : ''}`; }).join('|') });
244
196
  return info;
245
197
  }
@@ -248,6 +200,72 @@ let ActivityRideService = (() => {
248
200
  return [];
249
201
  }
250
202
  }
203
+ buildDashboardInfo(currentValues, avgMaxStats, display) {
204
+ var _a, _b, _c, _d, _e, _f, _g;
205
+ const { distance, time, speed, power, slope, heartrate, cadence, distanceRemaining, timeRemaining } = currentValues;
206
+ const { speedDetails, powerDetails, elevationGain, heartrateDetails, cadenceDetails } = avgMaxStats;
207
+ const info = [];
208
+ info.push({
209
+ title: 'Time', data: [
210
+ { value: (0, utils_1.formatTime)(time, true) },
211
+ { value: timeRemaining !== undefined ? `-${(0, utils_1.formatTime)(timeRemaining, true)}` : undefined }
212
+ ]
213
+ });
214
+ info.push({ title: 'Distance', data: [{ value: (0, utils_1.formatNumber)(distance, 2), unit: 'km' }, { value: distanceRemaining !== undefined ? `-${(0, utils_1.formatNumber)(distanceRemaining, 2)}` : undefined }] });
215
+ info.push({ title: 'Speed', data: [{ value: (0, utils_1.formatNumber)(speed, 1), unit: 'km/h' }, speedDetails], dataState: (_a = this.current.dataState) === null || _a === void 0 ? void 0 : _a.speed });
216
+ info.push({ title: 'Power', data: [{ value: (0, utils_1.formatNumber)(power, 0), unit: 'W' }, powerDetails], dataState: (_b = this.current.dataState) === null || _b === void 0 ? void 0 : _b.power });
217
+ if (((_c = this.activity) === null || _c === void 0 ? void 0 : _c.routeType) !== 'Free-Ride') {
218
+ const rf = (_e = (_d = this.activity) === null || _d === void 0 ? void 0 : _d.realityFactor) !== null && _e !== void 0 ? _e : 100;
219
+ const slopeInfo = rf === 100 ? '' : `RF ${rf.toFixed(0)}%`;
220
+ info.push({ title: 'Slope', data: [{ value: (0, utils_1.formatNumber)(slope, 1), unit: '%', info: slopeInfo }, elevationGain] });
221
+ }
222
+ info.push({ title: 'Heartrate', data: [{ value: (0, utils_1.formatNumber)(heartrate, 0), unit: 'bpm' }, heartrateDetails], dataState: (_f = this.current.dataState) === null || _f === void 0 ? void 0 : _f.heartrate });
223
+ info.push({ title: 'Cadence', data: [{ value: (0, utils_1.formatNumber)(cadence, 0), unit: 'rpm' }, cadenceDetails], dataState: (_g = this.current.dataState) === null || _g === void 0 ? void 0 : _g.cadence });
224
+ return info;
225
+ }
226
+ getCurrentValues() {
227
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
228
+ const distance = ((_b = (_a = this.activity) === null || _a === void 0 ? void 0 : _a.distance) !== null && _b !== void 0 ? _b : 0) / 1000;
229
+ const speed = ((_c = this.current.deviceData.speed) !== null && _c !== void 0 ? _c : 0);
230
+ const power = ((_d = this.current.deviceData.power) !== null && _d !== void 0 ? _d : 0);
231
+ const slope = (_e = this.current.position) === null || _e === void 0 ? void 0 : _e.slope;
232
+ const heartrate = this.current.deviceData.heartrate;
233
+ const cadence = ((_f = this.current.deviceData.cadence) !== null && _f !== void 0 ? _f : 0);
234
+ const time = (_h = (_g = this.activity) === null || _g === void 0 ? void 0 : _g.time) !== null && _h !== void 0 ? _h : 0;
235
+ let distanceRemaining = (this.getTotalDistance() / 1000 - distance);
236
+ if (isNaN(distanceRemaining))
237
+ distanceRemaining = undefined;
238
+ if (distanceRemaining < 0)
239
+ distanceRemaining = 0;
240
+ const timeRemaining = this.durationCalculator.getRemainingTime({ route: this.current.route, speed: this.current.deviceData.speed, routePos: this.activity.distance + ((_j = this.activity.startPos) !== null && _j !== void 0 ? _j : 0), endPos: this.current.endPos });
241
+ return { distance, time, speed, power, slope, heartrate, cadence, timeRemaining, distanceRemaining };
242
+ }
243
+ getAverageValues() {
244
+ var _a, _b, _c, _d, _e, _f;
245
+ const stats = (_a = this.activity) === null || _a === void 0 ? void 0 : _a.stats;
246
+ const speedDetails = { value: (0, utils_1.formatNumber)((_b = stats === null || stats === void 0 ? void 0 : stats.speed) === null || _b === void 0 ? void 0 : _b.max, 1), label: 'max' };
247
+ const powerDetails = { value: (0, utils_1.formatNumber)((_c = stats === null || stats === void 0 ? void 0 : stats.power) === null || _c === void 0 ? void 0 : _c.max, 0), label: 'max' };
248
+ const heartrateDetails = { value: (0, utils_1.formatNumber)((_d = stats === null || stats === void 0 ? void 0 : stats.hrm) === null || _d === void 0 ? void 0 : _d.max, 0), label: 'max' };
249
+ const cadenceDetails = { value: (0, utils_1.formatNumber)((_e = stats === null || stats === void 0 ? void 0 : stats.cadence) === null || _e === void 0 ? void 0 : _e.max, 0), label: 'max' };
250
+ const elevationGain = { value: (0, utils_1.formatNumber)((_f = this.current.elevationGainDisplay) !== null && _f !== void 0 ? _f : 0, 0), label: 'elev gain', unit: 'm' };
251
+ return { speedDetails, powerDetails, heartrateDetails, cadenceDetails, elevationGain };
252
+ }
253
+ getMaximumValues() {
254
+ var _a, _b, _c, _d, _e, _f;
255
+ const stats = (_a = this.activity) === null || _a === void 0 ? void 0 : _a.stats;
256
+ const speedDetails = { value: (0, utils_1.formatNumber)((_b = stats === null || stats === void 0 ? void 0 : stats.speed) === null || _b === void 0 ? void 0 : _b.avg, 1), label: 'avg' };
257
+ const powerDetails = { value: (0, utils_1.formatNumber)((_c = stats === null || stats === void 0 ? void 0 : stats.power) === null || _c === void 0 ? void 0 : _c.avg, 0), label: 'avg' };
258
+ const heartrateDetails = { value: (0, utils_1.formatNumber)((_d = stats === null || stats === void 0 ? void 0 : stats.hrm) === null || _d === void 0 ? void 0 : _d.avg, 0), label: 'avg' };
259
+ const cadenceDetails = { value: (0, utils_1.formatNumber)((_e = stats === null || stats === void 0 ? void 0 : stats.cadence) === null || _e === void 0 ? void 0 : _e.avg, 0), label: 'avg' };
260
+ let elevationGainRemaining = this.getTotalElevation() - ((_f = this.current.elevationGainDisplay) !== null && _f !== void 0 ? _f : 0);
261
+ if (isNaN(elevationGainRemaining))
262
+ elevationGainRemaining = undefined;
263
+ if (elevationGainRemaining < 0)
264
+ elevationGainRemaining = 0;
265
+ const value = elevationGainRemaining !== undefined ? `-${(0, utils_1.formatNumber)(elevationGainRemaining, 0)}` : undefined;
266
+ const elevationGain = { value, label: 'elev gain', unit: 'm' };
267
+ return { speedDetails, powerDetails, heartrateDetails, cadenceDetails, elevationGain };
268
+ }
251
269
  getActivitySummaryDisplayProperties() {
252
270
  var _a, _b;
253
271
  try {
@@ -312,7 +330,7 @@ let ActivityRideService = (() => {
312
330
  this.convert('FIT');
313
331
  }
314
332
  else {
315
- convertSuccess == (yield this.convert('FIT'));
333
+ convertSuccess = yield this.convert('FIT');
316
334
  if (convertSuccess)
317
335
  format = 'FIT';
318
336
  }
@@ -368,9 +386,9 @@ let ActivityRideService = (() => {
368
386
  if (logs.length === 0)
369
387
  return logs;
370
388
  logs.push(this.getCurrentActivityLog(activities[0], current));
371
- const sorted = logs.sort((a, b) => b.distance - a.distance);
372
- this.current.prevRidesLogs = sorted;
373
- return sorted;
389
+ logs.sort((a, b) => b.distance - a.distance);
390
+ this.current.prevRidesLogs = logs;
391
+ return logs;
374
392
  }
375
393
  getPrevRidesListDisplay(maxEntries = 12) {
376
394
  const prevRides = this.current.prevRidesLogs;
@@ -384,7 +402,6 @@ let ActivityRideService = (() => {
384
402
  return Object.assign({ position, avatar }, a);
385
403
  });
386
404
  if (props.length > maxEntries) {
387
- const len = props.length;
388
405
  const currentIdx = props.findIndex(a => a.title === 'current');
389
406
  if (currentIdx < maxEntries - 1) {
390
407
  let deleted = props.splice(maxEntries - 1);
@@ -425,7 +442,6 @@ let ActivityRideService = (() => {
425
442
  return props;
426
443
  }
427
444
  getPrevActivityLog(ai, current) {
428
- var _a, _b, _c;
429
445
  try {
430
446
  if (!ai.details || !ai.summary) {
431
447
  return null;
@@ -434,57 +450,16 @@ let ActivityRideService = (() => {
434
450
  const totalDistance = ai.summary.distance;
435
451
  if (!(current === null || current === void 0 ? void 0 : current.distance) || current.distance > totalDistance)
436
452
  return null;
437
- let prev = undefined;
438
- let res = (0, clone_1.default)(logs.find((log, idx) => {
439
- if (log.time >= current.time) {
440
- if (idx > 0)
441
- prev = logs[idx - 1];
442
- return true;
443
- }
444
- return false;
445
- }));
446
- if (!res) {
447
- res = (0, clone_1.default)(logs[logs.length - 1]);
448
- if (!res) {
449
- return null;
450
- }
451
- }
452
- else {
453
- if (Math.abs(res.time - current.time) > 0.1) {
454
- const t = res.time - current.time;
455
- const v = res.speed / 3.6;
456
- res.distance -= (v * t);
457
- }
458
- }
459
- const distanceDelta = current.distance - res.distance;
460
- const { power, heartrate, distance, speed } = res;
461
- const routeDistance = res.distance + ai.summary.startPos;
462
- let lat, lng;
463
- if ((_c = (_b = (_a = this.current) === null || _a === void 0 ? void 0 : _a.route) === null || _b === void 0 ? void 0 : _b.description) === null || _c === void 0 ? void 0 : _c.hasGpx) {
464
- const point = (0, route_1.getPosition)(this.current.route, { distance: routeDistance, nearest: true });
465
- lat = point === null || point === void 0 ? void 0 : point.lat;
466
- lng = point === null || point === void 0 ? void 0 : point.lng;
467
- }
468
- let prefix = Math.sign(distanceDelta) > 0 ? '+' : '';
469
- const distanceGap = prefix + (Math.abs(distanceDelta) > 1000 ? `${(distanceDelta / 1000).toFixed(1)}km` : `${distanceDelta.toFixed(0)}m`);
470
- prev = undefined;
471
- res = (0, clone_1.default)(logs.find((log, idx) => {
472
- if (log.distance >= current.distance) {
473
- if (idx > 0)
474
- prev = logs[idx - 1];
475
- return true;
476
- }
477
- return false;
478
- }));
479
- if (!res)
453
+ let prefix = '';
454
+ const sameTime = this.getRecordWithSameOrBiggerTime(logs, current);
455
+ if (!sameTime)
480
456
  return null;
481
- const s = res.distance - current.distance;
482
- const v = res.speed / 3.6;
483
- const t = v === 0 ? Infinity : s / v;
484
- res.time -= t;
485
- const timeDelta = res.time - current.time;
486
- prefix = Math.sign(timeDelta) > 0 ? '+' : '-';
487
- const timeGap = prefix + (Math.abs(timeDelta) < 60 ? `${Math.abs(timeDelta).toFixed(1)}s` : (0, utils_1.formatTime)(Math.abs(timeDelta), true));
457
+ const { power, heartrate, distance, speed } = sameTime;
458
+ const { distanceGap, routeDistance, lat, lng } = this.calculateDistanceGap(ai, sameTime, current);
459
+ let sameDistance = this.getRecordWithSameOrBiggerDistance(logs, current);
460
+ if (!sameDistance)
461
+ return null;
462
+ const timeGap = this.calculateTimeGap(sameDistance, current);
488
463
  const routeHash = ai.summary.routeHash;
489
464
  const routeId = ai.summary.routeId;
490
465
  const tsStart = ai.summary.startTime;
@@ -497,6 +472,58 @@ let ActivityRideService = (() => {
497
472
  return null;
498
473
  }
499
474
  }
475
+ getRecordWithSameOrBiggerTime(logs, current) {
476
+ let res = (0, clone_1.default)(logs.find((log) => {
477
+ if (log.time >= current.time) {
478
+ return true;
479
+ }
480
+ return false;
481
+ }));
482
+ if (res) {
483
+ if (Math.abs(res.time - current.time) > 0.1) {
484
+ const t = res.time - current.time;
485
+ const v = res.speed / 3.6;
486
+ res.distance -= (v * t);
487
+ }
488
+ }
489
+ else {
490
+ res = (0, clone_1.default)(logs[logs.length - 1]);
491
+ }
492
+ return res;
493
+ }
494
+ calculateDistanceGap(ai, res, current) {
495
+ var _a, _b, _c;
496
+ const distanceDelta = current.distance - res.distance;
497
+ const routeDistance = res.distance + ai.summary.startPos;
498
+ let lat, lng;
499
+ if ((_c = (_b = (_a = this.current) === null || _a === void 0 ? void 0 : _a.route) === null || _b === void 0 ? void 0 : _b.description) === null || _c === void 0 ? void 0 : _c.hasGpx) {
500
+ const point = (0, route_1.getPosition)(this.current.route, { distance: routeDistance, nearest: true });
501
+ lat = point === null || point === void 0 ? void 0 : point.lat;
502
+ lng = point === null || point === void 0 ? void 0 : point.lng;
503
+ }
504
+ let prefix = Math.sign(distanceDelta) > 0 ? '+' : '';
505
+ const distanceGap = prefix + (Math.abs(distanceDelta) > 1000 ? `${(distanceDelta / 1000).toFixed(1)}km` : `${distanceDelta.toFixed(0)}m`);
506
+ return { distanceGap, routeDistance, lat, lng };
507
+ }
508
+ calculateTimeGap(sameDistance, current) {
509
+ const s = sameDistance.distance - current.distance;
510
+ const v = sameDistance.speed / 3.6;
511
+ const t = v === 0 ? Infinity : s / v;
512
+ sameDistance.time -= t;
513
+ const timeDelta = sameDistance.time - current.time;
514
+ let prefix = Math.sign(timeDelta) > 0 ? '+' : '-';
515
+ const timeGap = prefix + (Math.abs(timeDelta) < 60 ? `${Math.abs(timeDelta).toFixed(1)}s` : (0, utils_1.formatTime)(Math.abs(timeDelta), true));
516
+ return timeGap;
517
+ }
518
+ getRecordWithSameOrBiggerDistance(logs, current) {
519
+ const res = (0, clone_1.default)(logs.find((log) => {
520
+ if (log.distance >= current.distance) {
521
+ return true;
522
+ }
523
+ return false;
524
+ }));
525
+ return res;
526
+ }
500
527
  getCurrentActivityLog(ai, current) {
501
528
  try {
502
529
  const timeGap = '';
@@ -505,7 +532,6 @@ let ActivityRideService = (() => {
505
532
  const routeId = ai.summary.routeId;
506
533
  const tsStart = ai.summary.startTime;
507
534
  const title = 'current';
508
- const routeDistance = current.distance;
509
535
  const { power, heartrate, distance, speed, lat, lng } = current;
510
536
  const calculate = { routeHash, routeId, tsStart, title, power, heartrate, speed, distance, timeGap, distanceGap, lat, lng };
511
537
  calculate.routeDistance = calculate.distance + ai.summary.startPos;