@swimedge/metrics 1.0.5 → 1.0.7
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/dist/index.d.ts +37 -17
- package/dist/index.js +125 -152
- package/dist/index.spec.js +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -6,19 +6,17 @@ export declare enum SwimType {
|
|
|
6
6
|
INDOOR = "indoorPool",
|
|
7
7
|
OPEN_WATER = "openWater"
|
|
8
8
|
}
|
|
9
|
-
export interface
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
lapStrokeRates?: number[];
|
|
19
|
-
lapDistancesPerStroke?: number[];
|
|
9
|
+
export interface SwimLap {
|
|
10
|
+
lapNumber?: number;
|
|
11
|
+
strokeCount?: number;
|
|
12
|
+
pace?: number;
|
|
13
|
+
strokeRate?: number;
|
|
14
|
+
distancePerStroke?: number;
|
|
15
|
+
strokeStyle?: string;
|
|
16
|
+
splitTime?: number;
|
|
17
|
+
swolfScore?: number;
|
|
20
18
|
}
|
|
21
|
-
export interface SwimSession
|
|
19
|
+
export interface SwimSession {
|
|
22
20
|
id: string;
|
|
23
21
|
watchSessionId?: string;
|
|
24
22
|
date: string;
|
|
@@ -57,6 +55,8 @@ export interface SwimSession extends SwimSessionLaps {
|
|
|
57
55
|
deviceType?: string;
|
|
58
56
|
osVersion?: string;
|
|
59
57
|
healthKitWorkoutId?: string;
|
|
58
|
+
lapData?: SwimLap[];
|
|
59
|
+
swimLaps?: SwimLap[];
|
|
60
60
|
}
|
|
61
61
|
export interface AggregatedSwimMetrics {
|
|
62
62
|
totalDistance: number;
|
|
@@ -105,7 +105,6 @@ export interface MetricDefinition {
|
|
|
105
105
|
description: string;
|
|
106
106
|
icon?: string;
|
|
107
107
|
isPerSession?: boolean;
|
|
108
|
-
isPerLap?: boolean;
|
|
109
108
|
formula?: string;
|
|
110
109
|
source?: string;
|
|
111
110
|
healthKitSource?: string;
|
|
@@ -118,18 +117,39 @@ export interface MetricDefinition {
|
|
|
118
117
|
swimTypes: SwimType[];
|
|
119
118
|
hasChart?: boolean;
|
|
120
119
|
formatter?: (session: SwimSession) => string | number | null;
|
|
121
|
-
lapFormatter?: (value: any) => string;
|
|
122
120
|
condition?: (session: SwimSession) => boolean;
|
|
123
121
|
}
|
|
124
|
-
export
|
|
122
|
+
export interface LapMetricDefinition {
|
|
123
|
+
key: keyof SwimLap;
|
|
124
|
+
label: string;
|
|
125
|
+
unit?: string;
|
|
126
|
+
category: MetricCategory;
|
|
127
|
+
description: string;
|
|
128
|
+
icon?: string;
|
|
129
|
+
formula?: string;
|
|
130
|
+
source?: string;
|
|
131
|
+
healthKitSource?: string;
|
|
132
|
+
isHealthKit?: boolean;
|
|
133
|
+
decimals?: number;
|
|
134
|
+
availableFrom: {
|
|
135
|
+
watch: boolean;
|
|
136
|
+
manual: boolean;
|
|
137
|
+
};
|
|
138
|
+
swimTypes: SwimType[];
|
|
139
|
+
lapFormatter?: (value: any) => string;
|
|
140
|
+
}
|
|
141
|
+
export declare const LAP_METRICS_REGISTRY: Record<keyof SwimLap, LapMetricDefinition>;
|
|
142
|
+
export declare const METRICS_REGISTRY: Partial<Record<keyof SwimSession, MetricDefinition>>;
|
|
125
143
|
export declare const MetricsHelper: {
|
|
126
|
-
getMetric: (key: keyof SwimSession) => MetricDefinition;
|
|
144
|
+
getMetric: (key: keyof SwimSession) => MetricDefinition | undefined;
|
|
127
145
|
getSessionMetrics: () => MetricDefinition[];
|
|
128
146
|
getChartMetrics: () => MetricDefinition[];
|
|
129
|
-
getLapMetrics: () =>
|
|
147
|
+
getLapMetrics: () => LapMetricDefinition[];
|
|
148
|
+
getLapMetric: (key: keyof SwimLap) => LapMetricDefinition;
|
|
130
149
|
getMetricsByCategory: (category: MetricCategory) => MetricDefinition[];
|
|
131
150
|
getMetricsBySwimType: (swimType: SwimType) => MetricDefinition[];
|
|
132
151
|
getIndoorMetrics: () => MetricDefinition[];
|
|
133
152
|
getOpenWaterMetrics: () => MetricDefinition[];
|
|
134
153
|
getAllMetricKeys: () => string[];
|
|
154
|
+
getAllLapMetricKeys: () => string[];
|
|
135
155
|
};
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Shared metrics registry for frontend, backend, and watch app
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.MetricsHelper = exports.METRICS_REGISTRY = exports.formatSwimType = exports.formatDistance = exports.formatHeartRate = exports.formatTime = exports.formatPace = exports.formatNumber = exports.MetricCategory = exports.SwimType = void 0;
|
|
7
|
+
exports.MetricsHelper = exports.METRICS_REGISTRY = exports.LAP_METRICS_REGISTRY = exports.formatSwimType = exports.formatDistance = exports.formatHeartRate = exports.formatTime = exports.formatPace = exports.formatNumber = exports.MetricCategory = exports.SwimType = void 0;
|
|
8
8
|
var SwimType;
|
|
9
9
|
(function (SwimType) {
|
|
10
10
|
SwimType["INDOOR"] = "indoorPool";
|
|
@@ -31,12 +31,13 @@ const formatPace = (pace) => {
|
|
|
31
31
|
};
|
|
32
32
|
exports.formatPace = formatPace;
|
|
33
33
|
const formatTime = (seconds) => {
|
|
34
|
-
const
|
|
35
|
-
const
|
|
34
|
+
const totalSeconds = Math.floor(seconds);
|
|
35
|
+
const mins = Math.floor(totalSeconds / 60);
|
|
36
|
+
const secs = totalSeconds % 60;
|
|
36
37
|
if (mins >= 60) {
|
|
37
38
|
const hours = Math.floor(mins / 60);
|
|
38
39
|
const remainingMins = mins % 60;
|
|
39
|
-
return `${hours}:${remainingMins.toString().padStart(2, '0')}`;
|
|
40
|
+
return `${hours}:${remainingMins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
|
|
40
41
|
}
|
|
41
42
|
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
|
42
43
|
};
|
|
@@ -60,6 +61,106 @@ const formatSwimType = (swimType) => {
|
|
|
60
61
|
}[swimType] || swimType);
|
|
61
62
|
};
|
|
62
63
|
exports.formatSwimType = formatSwimType;
|
|
64
|
+
exports.LAP_METRICS_REGISTRY = {
|
|
65
|
+
lapNumber: {
|
|
66
|
+
key: 'lapNumber',
|
|
67
|
+
label: 'Lap #',
|
|
68
|
+
category: MetricCategory.PERFORMANCE,
|
|
69
|
+
description: 'Lap number in the session',
|
|
70
|
+
decimals: 0,
|
|
71
|
+
availableFrom: { watch: true, manual: false },
|
|
72
|
+
swimTypes: [SwimType.INDOOR],
|
|
73
|
+
},
|
|
74
|
+
strokeCount: {
|
|
75
|
+
key: 'strokeCount',
|
|
76
|
+
label: 'Strokes',
|
|
77
|
+
unit: '',
|
|
78
|
+
category: MetricCategory.TECHNIQUE,
|
|
79
|
+
description: 'Number of strokes in this lap',
|
|
80
|
+
icon: 'hand-left-outline',
|
|
81
|
+
decimals: 0,
|
|
82
|
+
source: 'HealthKit: HKQuantityTypeIdentifierSwimmingStrokeCount per lap',
|
|
83
|
+
healthKitSource: 'HKQuantityTypeIdentifierSwimmingStrokeCount',
|
|
84
|
+
isHealthKit: true,
|
|
85
|
+
availableFrom: { watch: true, manual: false },
|
|
86
|
+
swimTypes: [SwimType.INDOOR],
|
|
87
|
+
},
|
|
88
|
+
pace: {
|
|
89
|
+
key: 'pace',
|
|
90
|
+
label: 'Pace',
|
|
91
|
+
unit: '/100m',
|
|
92
|
+
category: MetricCategory.PERFORMANCE,
|
|
93
|
+
description: 'Time per 100m for this lap',
|
|
94
|
+
decimals: 1,
|
|
95
|
+
availableFrom: { watch: true, manual: false },
|
|
96
|
+
swimTypes: [SwimType.INDOOR],
|
|
97
|
+
lapFormatter: (v) => (0, exports.formatPace)(v),
|
|
98
|
+
},
|
|
99
|
+
strokeRate: {
|
|
100
|
+
key: 'strokeRate',
|
|
101
|
+
label: 'SR',
|
|
102
|
+
unit: 'SPM',
|
|
103
|
+
category: MetricCategory.TECHNIQUE,
|
|
104
|
+
description: 'Strokes per minute for this lap',
|
|
105
|
+
icon: 'repeat-outline',
|
|
106
|
+
decimals: 1,
|
|
107
|
+
formula: 'Lap Strokes ÷ (Lap Time in Minutes)',
|
|
108
|
+
availableFrom: { watch: true, manual: false },
|
|
109
|
+
swimTypes: [SwimType.INDOOR],
|
|
110
|
+
},
|
|
111
|
+
distancePerStroke: {
|
|
112
|
+
key: 'distancePerStroke',
|
|
113
|
+
label: 'DPS',
|
|
114
|
+
unit: 'm',
|
|
115
|
+
category: MetricCategory.TECHNIQUE,
|
|
116
|
+
description: 'Distance per stroke for this lap',
|
|
117
|
+
icon: 'arrow-forward-outline',
|
|
118
|
+
decimals: 2,
|
|
119
|
+
formula: 'Lap Distance ÷ Lap Strokes',
|
|
120
|
+
availableFrom: { watch: true, manual: false },
|
|
121
|
+
swimTypes: [SwimType.INDOOR],
|
|
122
|
+
},
|
|
123
|
+
strokeStyle: {
|
|
124
|
+
key: 'strokeStyle',
|
|
125
|
+
label: 'Stroke',
|
|
126
|
+
category: MetricCategory.TECHNIQUE,
|
|
127
|
+
description: 'Swimming stroke used in this lap',
|
|
128
|
+
icon: 'list-outline',
|
|
129
|
+
availableFrom: { watch: true, manual: false },
|
|
130
|
+
swimTypes: [SwimType.INDOOR],
|
|
131
|
+
},
|
|
132
|
+
splitTime: {
|
|
133
|
+
key: 'splitTime',
|
|
134
|
+
label: 'Time',
|
|
135
|
+
unit: 's',
|
|
136
|
+
category: MetricCategory.PERFORMANCE,
|
|
137
|
+
description: 'Time taken for this lap',
|
|
138
|
+
icon: 'stopwatch-outline',
|
|
139
|
+
source: 'Tracked per lap completion',
|
|
140
|
+
availableFrom: { watch: true, manual: false },
|
|
141
|
+
swimTypes: [SwimType.INDOOR],
|
|
142
|
+
lapFormatter: (v) => (0, exports.formatTime)(v),
|
|
143
|
+
},
|
|
144
|
+
swolfScore: {
|
|
145
|
+
key: 'swolfScore',
|
|
146
|
+
label: 'SWOLF',
|
|
147
|
+
category: MetricCategory.TECHNIQUE,
|
|
148
|
+
description: 'SWOLF score for this lap',
|
|
149
|
+
decimals: 0,
|
|
150
|
+
availableFrom: { watch: true, manual: false },
|
|
151
|
+
swimTypes: [SwimType.INDOOR],
|
|
152
|
+
},
|
|
153
|
+
// calories: {
|
|
154
|
+
// key: 'calories',
|
|
155
|
+
// label: 'Cal',
|
|
156
|
+
// unit: 'kcal',
|
|
157
|
+
// category: MetricCategory.ENERGY,
|
|
158
|
+
// description: 'Calories burned in this lap',
|
|
159
|
+
// decimals: 0,
|
|
160
|
+
// availableFrom: { watch: true, manual: false },
|
|
161
|
+
// swimTypes: [SwimType.INDOOR],
|
|
162
|
+
// },
|
|
163
|
+
};
|
|
63
164
|
exports.METRICS_REGISTRY = {
|
|
64
165
|
distance: {
|
|
65
166
|
key: 'distance',
|
|
@@ -135,7 +236,7 @@ exports.METRICS_REGISTRY = {
|
|
|
135
236
|
availableFrom: { watch: true, manual: true },
|
|
136
237
|
swimTypes: [SwimType.INDOOR],
|
|
137
238
|
hasChart: true,
|
|
138
|
-
formatter: (s) => String(s.laps),
|
|
239
|
+
formatter: (s) => String(s.laps || 0),
|
|
139
240
|
condition: (s) => !!s.laps,
|
|
140
241
|
},
|
|
141
242
|
avgPace: {
|
|
@@ -343,51 +444,6 @@ exports.METRICS_REGISTRY = {
|
|
|
343
444
|
formatter: (s) => s.primaryStrokeType,
|
|
344
445
|
condition: (s) => !!s.primaryStrokeType,
|
|
345
446
|
},
|
|
346
|
-
lapSplitTimes: {
|
|
347
|
-
key: 'lapSplitTimes',
|
|
348
|
-
label: 'Time',
|
|
349
|
-
unit: 's',
|
|
350
|
-
category: MetricCategory.PERFORMANCE,
|
|
351
|
-
description: 'Individual lap times recorded during the session.',
|
|
352
|
-
icon: 'stopwatch-outline',
|
|
353
|
-
isPerLap: true,
|
|
354
|
-
source: 'Tracked per lap completion',
|
|
355
|
-
availableFrom: { watch: true, manual: false },
|
|
356
|
-
swimTypes: [SwimType.INDOOR],
|
|
357
|
-
formatter: (s) => `${s.lapSplitTimes.length} splits`,
|
|
358
|
-
lapFormatter: (v) => (0, exports.formatTime)(v),
|
|
359
|
-
condition: (s) => !!s.lapSplitTimes?.length,
|
|
360
|
-
},
|
|
361
|
-
lapHeartRates: {
|
|
362
|
-
key: 'lapHeartRates',
|
|
363
|
-
label: 'HR',
|
|
364
|
-
unit: 'bpm',
|
|
365
|
-
category: MetricCategory.HEALTH,
|
|
366
|
-
description: 'HR per lap',
|
|
367
|
-
icon: 'heart-outline',
|
|
368
|
-
isPerLap: true,
|
|
369
|
-
decimals: 0,
|
|
370
|
-
source: 'HealthKit: HKQuantityTypeIdentifierHeartRate sampled at lap completion',
|
|
371
|
-
healthKitSource: 'HKQuantityTypeIdentifierHeartRate',
|
|
372
|
-
isHealthKit: true,
|
|
373
|
-
availableFrom: { watch: true, manual: false },
|
|
374
|
-
swimTypes: [SwimType.INDOOR],
|
|
375
|
-
},
|
|
376
|
-
lapStrokeCounts: {
|
|
377
|
-
key: 'lapStrokeCounts',
|
|
378
|
-
label: 'Strokes',
|
|
379
|
-
unit: '',
|
|
380
|
-
category: MetricCategory.TECHNIQUE,
|
|
381
|
-
description: 'Strokes per lap',
|
|
382
|
-
icon: 'hand-left-outline',
|
|
383
|
-
isPerLap: true,
|
|
384
|
-
decimals: 0,
|
|
385
|
-
source: 'HealthKit: HKQuantityTypeIdentifierSwimmingStrokeCount per lap',
|
|
386
|
-
healthKitSource: 'HKQuantityTypeIdentifierSwimmingStrokeCount',
|
|
387
|
-
isHealthKit: true,
|
|
388
|
-
availableFrom: { watch: true, manual: false },
|
|
389
|
-
swimTypes: [SwimType.INDOOR],
|
|
390
|
-
},
|
|
391
447
|
id: {
|
|
392
448
|
key: 'id',
|
|
393
449
|
label: 'ID',
|
|
@@ -424,101 +480,6 @@ exports.METRICS_REGISTRY = {
|
|
|
424
480
|
availableFrom: { watch: false, manual: false },
|
|
425
481
|
swimTypes: [SwimType.INDOOR, SwimType.OPEN_WATER],
|
|
426
482
|
},
|
|
427
|
-
// HealthKit doesn't track turn times
|
|
428
|
-
/*lapTurnTimes: {
|
|
429
|
-
key: 'lapTurnTimes',
|
|
430
|
-
label: 'Turn',
|
|
431
|
-
unit: 's',
|
|
432
|
-
category: MetricCategory.TECHNIQUE,
|
|
433
|
-
description: 'Time spent turning at pool wall per lap',
|
|
434
|
-
icon: 'refresh-circle-outline',
|
|
435
|
-
isPerLap: true,
|
|
436
|
-
decimals: 2,
|
|
437
|
-
availableFrom: { watch: true, manual: false },
|
|
438
|
-
swimTypes: [SwimType.INDOOR],
|
|
439
|
-
formatter: formatAverageTurnTime,
|
|
440
|
-
condition: (s) => !!s.lapTurnTimes?.length,
|
|
441
|
-
},*/
|
|
442
|
-
lapStrokeTypes: {
|
|
443
|
-
key: 'lapStrokeTypes',
|
|
444
|
-
label: 'Stroke',
|
|
445
|
-
category: MetricCategory.TECHNIQUE,
|
|
446
|
-
description: 'Swimming stroke used per lap',
|
|
447
|
-
icon: 'list-outline',
|
|
448
|
-
isPerLap: true,
|
|
449
|
-
availableFrom: { watch: true, manual: false },
|
|
450
|
-
swimTypes: [SwimType.INDOOR],
|
|
451
|
-
formatter: (s) => `${s.lapStrokeTypes.length} types`,
|
|
452
|
-
condition: (s) => !!s.lapStrokeTypes?.length,
|
|
453
|
-
},
|
|
454
|
-
lapPaces: {
|
|
455
|
-
key: 'lapPaces',
|
|
456
|
-
label: 'Pace',
|
|
457
|
-
unit: '/100m',
|
|
458
|
-
category: MetricCategory.PERFORMANCE,
|
|
459
|
-
description: 'Pace per lap',
|
|
460
|
-
isPerLap: true,
|
|
461
|
-
decimals: 1,
|
|
462
|
-
availableFrom: { watch: true, manual: false },
|
|
463
|
-
swimTypes: [SwimType.INDOOR],
|
|
464
|
-
},
|
|
465
|
-
lapCalories: {
|
|
466
|
-
key: 'lapCalories',
|
|
467
|
-
label: 'Cal',
|
|
468
|
-
unit: 'kcal',
|
|
469
|
-
category: MetricCategory.ENERGY,
|
|
470
|
-
description: 'Calories per lap',
|
|
471
|
-
isPerLap: true,
|
|
472
|
-
decimals: 0,
|
|
473
|
-
availableFrom: { watch: true, manual: false },
|
|
474
|
-
swimTypes: [SwimType.INDOOR],
|
|
475
|
-
},
|
|
476
|
-
lapDistances: {
|
|
477
|
-
key: 'lapDistances',
|
|
478
|
-
label: 'Lap Distances',
|
|
479
|
-
unit: 'm',
|
|
480
|
-
category: MetricCategory.PERFORMANCE,
|
|
481
|
-
description: 'Distance per lap',
|
|
482
|
-
isPerLap: true,
|
|
483
|
-
availableFrom: { watch: true, manual: false },
|
|
484
|
-
swimTypes: [SwimType.INDOOR],
|
|
485
|
-
},
|
|
486
|
-
lapSwolfScores: {
|
|
487
|
-
key: 'lapSwolfScores',
|
|
488
|
-
label: 'SWOLF',
|
|
489
|
-
category: MetricCategory.TECHNIQUE,
|
|
490
|
-
description: 'SWOLF per lap',
|
|
491
|
-
isPerLap: true,
|
|
492
|
-
decimals: 0,
|
|
493
|
-
availableFrom: { watch: true, manual: false },
|
|
494
|
-
swimTypes: [SwimType.INDOOR],
|
|
495
|
-
},
|
|
496
|
-
lapStrokeRates: {
|
|
497
|
-
key: 'lapStrokeRates',
|
|
498
|
-
label: 'SR',
|
|
499
|
-
unit: 'SPM',
|
|
500
|
-
category: MetricCategory.TECHNIQUE,
|
|
501
|
-
description: 'Strokes per minute per lap',
|
|
502
|
-
icon: 'repeat-outline',
|
|
503
|
-
isPerLap: true,
|
|
504
|
-
decimals: 1,
|
|
505
|
-
formula: 'Lap Strokes ÷ (Lap Time in Minutes)',
|
|
506
|
-
availableFrom: { watch: true, manual: false },
|
|
507
|
-
swimTypes: [SwimType.INDOOR],
|
|
508
|
-
},
|
|
509
|
-
lapDistancesPerStroke: {
|
|
510
|
-
key: 'lapDistancesPerStroke',
|
|
511
|
-
label: 'DPS',
|
|
512
|
-
unit: 'm',
|
|
513
|
-
category: MetricCategory.TECHNIQUE,
|
|
514
|
-
description: 'Distance covered per stroke per lap',
|
|
515
|
-
icon: 'arrow-forward-outline',
|
|
516
|
-
isPerLap: true,
|
|
517
|
-
decimals: 2,
|
|
518
|
-
formula: 'Lap Distance ÷ Lap Strokes',
|
|
519
|
-
availableFrom: { watch: true, manual: false },
|
|
520
|
-
swimTypes: [SwimType.INDOOR],
|
|
521
|
-
},
|
|
522
483
|
poolLocation: {
|
|
523
484
|
key: 'poolLocation',
|
|
524
485
|
label: 'Pool Location',
|
|
@@ -612,15 +573,27 @@ exports.METRICS_REGISTRY = {
|
|
|
612
573
|
availableFrom: { watch: true, manual: false },
|
|
613
574
|
swimTypes: [SwimType.INDOOR, SwimType.OPEN_WATER],
|
|
614
575
|
},
|
|
576
|
+
lapData: {
|
|
577
|
+
key: 'lapData',
|
|
578
|
+
label: 'Lap Data',
|
|
579
|
+
category: MetricCategory.PERFORMANCE,
|
|
580
|
+
description: 'Detailed data for each lap',
|
|
581
|
+
isPerSession: true,
|
|
582
|
+
availableFrom: { watch: true, manual: false },
|
|
583
|
+
swimTypes: [SwimType.INDOOR],
|
|
584
|
+
condition: (s) => !!s.lapData?.length,
|
|
585
|
+
},
|
|
615
586
|
};
|
|
616
587
|
exports.MetricsHelper = {
|
|
617
588
|
getMetric: (key) => exports.METRICS_REGISTRY[key],
|
|
618
|
-
getSessionMetrics: () => Object.values(exports.METRICS_REGISTRY).filter((m) => m
|
|
619
|
-
getChartMetrics: () => Object.values(exports.METRICS_REGISTRY).filter((m) => m
|
|
620
|
-
getLapMetrics: () => Object.values(exports.
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
589
|
+
getSessionMetrics: () => Object.values(exports.METRICS_REGISTRY).filter((m) => m?.isPerSession),
|
|
590
|
+
getChartMetrics: () => Object.values(exports.METRICS_REGISTRY).filter((m) => m?.isPerSession && m?.hasChart),
|
|
591
|
+
getLapMetrics: () => Object.values(exports.LAP_METRICS_REGISTRY),
|
|
592
|
+
getLapMetric: (key) => exports.LAP_METRICS_REGISTRY[key],
|
|
593
|
+
getMetricsByCategory: (category) => Object.values(exports.METRICS_REGISTRY).filter((m) => m?.category === category),
|
|
594
|
+
getMetricsBySwimType: (swimType) => Object.values(exports.METRICS_REGISTRY).filter((m) => m?.swimTypes?.includes(swimType)),
|
|
595
|
+
getIndoorMetrics: () => Object.values(exports.METRICS_REGISTRY).filter((m) => m?.swimTypes?.includes(SwimType.INDOOR)),
|
|
596
|
+
getOpenWaterMetrics: () => Object.values(exports.METRICS_REGISTRY).filter((m) => m?.swimTypes?.includes(SwimType.OPEN_WATER)),
|
|
625
597
|
getAllMetricKeys: () => Object.keys(exports.METRICS_REGISTRY),
|
|
598
|
+
getAllLapMetricKeys: () => Object.keys(exports.LAP_METRICS_REGISTRY),
|
|
626
599
|
};
|
package/dist/index.spec.js
CHANGED
|
@@ -35,7 +35,7 @@ describe('Metrics Formatting Functions', () => {
|
|
|
35
35
|
it('should format time in seconds to mm:ss', () => {
|
|
36
36
|
expect((0, index_1.formatTime)(125)).toBe('2:05');
|
|
37
37
|
expect((0, index_1.formatTime)(90)).toBe('1:30');
|
|
38
|
-
expect((0, index_1.formatTime)(3665)).toBe('
|
|
38
|
+
expect((0, index_1.formatTime)(3665)).toBe('1:01:05');
|
|
39
39
|
});
|
|
40
40
|
it('should handle zero', () => {
|
|
41
41
|
expect((0, index_1.formatTime)(0)).toBe('0:00');
|