@sports-alliance/sports-lib 7.2.2 → 7.2.4

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.
@@ -167,6 +167,7 @@ const data_age_1 = require("../../../../data/data.age");
167
167
  const data_gender_1 = require("../../../../data/data.gender");
168
168
  const data_avg_grit_1 = require("../../../../data/data.avg-grit");
169
169
  const data_jump_event_1 = require("../../../../data/data.jump-event");
170
+ const data_jump_stats_1 = require("../../../../data/data.jump-stats");
170
171
  // Threshold to detect that session.timestamp are not trustable (when exceeding 15% of session.total_elapsed_time)
171
172
  const INVALID_DATES_ELAPSED_TIME_RATIO_THRESHOLD = 1.15;
172
173
  class EventImporterFIT {
@@ -184,7 +185,7 @@ class EventImporterFIT {
184
185
  mode: 'both'
185
186
  });
186
187
  fitFileParser.parse(arrayBuffer, (error, fitDataObject) => {
187
- var _a;
188
+ var _a, _b;
188
189
  if (error) {
189
190
  // For now, assume any error from parser on this file means it's broken/empty in a way we treat as EmptyEventLibError
190
191
  // to satisfy existing tests. Or ideally we wrap in a generic EventLibError.
@@ -217,6 +218,17 @@ class EventImporterFIT {
217
218
  });
218
219
  });
219
220
  }
221
+ // Check for jumps data at the top level
222
+ if (fitDataObject.jumps && fitDataObject.jumps.length > 0) {
223
+ (_b = fitDataObject.sessions) === null || _b === void 0 ? void 0 : _b.forEach((session) => {
224
+ const sessionStartTime = new Date(session.start_time).getTime();
225
+ const sessionEndTime = sessionStartTime + (session.total_elapsed_time || 0) * 1000;
226
+ session.jumps = fitDataObject.jumps.filter((jump) => {
227
+ const jumpTime = new Date(jump.timestamp).getTime();
228
+ return jumpTime >= sessionStartTime && jumpTime < sessionEndTime;
229
+ });
230
+ });
231
+ }
220
232
  // Iterate over the sessions and create their activities
221
233
  const activities = fitDataObject.sessions.map((sessionObject) => {
222
234
  // Get the activity from the sessionObject
@@ -351,7 +363,12 @@ class EventImporterFIT {
351
363
  activity.addEvent(new data_jump_event_1.DataJumpEvent(activity.getDateIndex(jump.timestamp), {
352
364
  distance: jump.distance,
353
365
  height: jump.height,
354
- score: jump.score
366
+ score: jump.score,
367
+ hang_time: jump.hang_time,
368
+ position_lat: jump.position_lat,
369
+ position_long: jump.position_long,
370
+ speed: jump.speed,
371
+ rotations: jump.rotations
355
372
  }));
356
373
  });
357
374
  }
@@ -626,13 +643,6 @@ class EventImporterFIT {
626
643
  const activity = new activity_1.Activity(startDate, endDate, this.getActivityTypeFromSessionObject(sessionObject), this.getCreatorFromFitDataObject(fitDataObject), options);
627
644
  // Set the activity stats
628
645
  this.getStatsFromObject(sessionObject, activity, false).forEach(stat => activity.addStat(stat));
629
- // Check for VO2 Max in jumps
630
- if (fitDataObject.jumps && fitDataObject.jumps.length) {
631
- const jumpWithMets = fitDataObject.jumps.find((j) => j.enhanced_mets);
632
- if (jumpWithMets) {
633
- activity.addStat(new data_vo2_max_1.DataVO2Max(jumpWithMets.enhanced_mets * 3.5));
634
- }
635
- }
636
646
  // Check for User Profile
637
647
  if (fitDataObject.user_profile) {
638
648
  const userProfile = fitDataObject.user_profile;
@@ -1085,6 +1095,94 @@ class EventImporterFIT {
1085
1095
  if ((0, helpers_1.isNumberOrString)(object.avg_vam)) {
1086
1096
  stats.push(new data_avg_vam_1.DataAvgVAM(object.avg_vam));
1087
1097
  }
1098
+ // Jump Statistics
1099
+ if (object.jumps && object.jumps.length > 0) {
1100
+ const jumps = object.jumps;
1101
+ let count = 0;
1102
+ let hangTimeSum = 0, hangTimeMin = Number.MAX_VALUE, hangTimeMax = -Number.MAX_VALUE;
1103
+ let distanceSum = 0, distanceMin = Number.MAX_VALUE, distanceMax = -Number.MAX_VALUE;
1104
+ let speedSum = 0, speedMin = Number.MAX_VALUE, speedMax = -Number.MAX_VALUE;
1105
+ let rotationsSum = 0, rotationsMin = Number.MAX_VALUE, rotationsMax = -Number.MAX_VALUE;
1106
+ let scoreSum = 0, scoreMin = Number.MAX_VALUE, scoreMax = -Number.MAX_VALUE;
1107
+ let heightSum = 0, heightMin = Number.MAX_VALUE, heightMax = -Number.MAX_VALUE;
1108
+ jumps.forEach((j) => {
1109
+ count++;
1110
+ // Hangtime
1111
+ if (Number.isFinite(j.hang_time)) {
1112
+ hangTimeSum += j.hang_time;
1113
+ hangTimeMin = Math.min(hangTimeMin, j.hang_time);
1114
+ hangTimeMax = Math.max(hangTimeMax, j.hang_time);
1115
+ }
1116
+ // Distance
1117
+ if (Number.isFinite(j.distance)) {
1118
+ distanceSum += j.distance;
1119
+ distanceMin = Math.min(distanceMin, j.distance);
1120
+ distanceMax = Math.max(distanceMax, j.distance);
1121
+ }
1122
+ // Speed
1123
+ if (Number.isFinite(j.speed)) {
1124
+ speedSum += j.speed;
1125
+ speedMin = Math.min(speedMin, j.speed);
1126
+ speedMax = Math.max(speedMax, j.speed);
1127
+ }
1128
+ // Rotations
1129
+ if (Number.isFinite(j.rotations)) {
1130
+ rotationsSum += j.rotations;
1131
+ rotationsMin = Math.min(rotationsMin, j.rotations);
1132
+ rotationsMax = Math.max(rotationsMax, j.rotations);
1133
+ }
1134
+ // Score
1135
+ if (Number.isFinite(j.score)) {
1136
+ scoreSum += j.score;
1137
+ scoreMin = Math.min(scoreMin, j.score);
1138
+ scoreMax = Math.max(scoreMax, j.score);
1139
+ }
1140
+ // Height
1141
+ if (Number.isFinite(j.height)) {
1142
+ heightSum += j.height;
1143
+ heightMin = Math.min(heightMin, j.height);
1144
+ heightMax = Math.max(heightMax, j.height);
1145
+ }
1146
+ });
1147
+ if (count > 0) {
1148
+ if (hangTimeMin !== Number.MAX_VALUE)
1149
+ stats.push(new data_jump_stats_1.DataJumpHangTimeMin(hangTimeMin));
1150
+ if (hangTimeMax !== -Number.MAX_VALUE)
1151
+ stats.push(new data_jump_stats_1.DataJumpHangTimeMax(hangTimeMax));
1152
+ if (hangTimeSum > 0)
1153
+ stats.push(new data_jump_stats_1.DataJumpHangTimeAvg(hangTimeSum / count)); // Assuming count is correct divisor for existing values
1154
+ if (distanceMin !== Number.MAX_VALUE)
1155
+ stats.push(new data_jump_stats_1.DataJumpDistanceMin(distanceMin));
1156
+ if (distanceMax !== -Number.MAX_VALUE)
1157
+ stats.push(new data_jump_stats_1.DataJumpDistanceMax(distanceMax));
1158
+ if (distanceSum > 0)
1159
+ stats.push(new data_jump_stats_1.DataJumpDistanceAvg(distanceSum / count));
1160
+ if (speedMin !== Number.MAX_VALUE)
1161
+ stats.push(new data_jump_stats_1.DataJumpSpeedMin(speedMin));
1162
+ if (speedMax !== -Number.MAX_VALUE)
1163
+ stats.push(new data_jump_stats_1.DataJumpSpeedMax(speedMax));
1164
+ if (speedSum > 0)
1165
+ stats.push(new data_jump_stats_1.DataJumpSpeedAvg(speedSum / count));
1166
+ if (rotationsMin !== Number.MAX_VALUE)
1167
+ stats.push(new data_jump_stats_1.DataJumpRotationsMin(rotationsMin));
1168
+ if (rotationsMax !== -Number.MAX_VALUE)
1169
+ stats.push(new data_jump_stats_1.DataJumpRotationsMax(rotationsMax));
1170
+ if (rotationsSum > 0)
1171
+ stats.push(new data_jump_stats_1.DataJumpRotationsAvg(rotationsSum / count));
1172
+ if (scoreMin !== Number.MAX_VALUE)
1173
+ stats.push(new data_jump_stats_1.DataJumpScoreMin(scoreMin));
1174
+ if (scoreMax !== -Number.MAX_VALUE)
1175
+ stats.push(new data_jump_stats_1.DataJumpScoreMax(scoreMax));
1176
+ if (scoreSum > 0)
1177
+ stats.push(new data_jump_stats_1.DataJumpScoreAvg(scoreSum / count));
1178
+ if (heightMin !== Number.MAX_VALUE)
1179
+ stats.push(new data_jump_stats_1.DataJumpHeightMin(heightMin));
1180
+ if (heightMax !== -Number.MAX_VALUE)
1181
+ stats.push(new data_jump_stats_1.DataJumpHeightMax(heightMax));
1182
+ if (heightSum > 0)
1183
+ stats.push(new data_jump_stats_1.DataJumpHeightAvg(heightSum / count));
1184
+ }
1185
+ }
1088
1186
  return stats;
1089
1187
  }
1090
1188
  static getCreatorFromFitDataObject(fitDataObject) {
@@ -47,7 +47,6 @@ const path = __importStar(require("path"));
47
47
  const importer_fit_1 = require("./importer.fit");
48
48
  const data_aerobic_training_effect_1 = require("../../../../data/data-aerobic-training-effect");
49
49
  const data_anaerobic_training_effect_1 = require("../../../../data/data-anaerobic-training-effect");
50
- const data_vo2_max_1 = require("../../../../data/data.vo2-max");
51
50
  const data_recovery_time_1 = require("../../../../data/data.recovery-time");
52
51
  const data_avg_respiration_rate_1 = require("../../../../data/data.avg-respiration-rate");
53
52
  const data_heart_rate_zone_five_duration_1 = require("../../../../data/data.heart-rate-zone-five-duration");
@@ -146,10 +145,6 @@ describe('EventImporterFIT MTB Jumps', () => {
146
145
  const anaerobic = activity.getStat(data_anaerobic_training_effect_1.DataAnaerobicTrainingEffect.type);
147
146
  expect(anaerobic).toBeDefined();
148
147
  expect(anaerobic.getValue()).toBe(2);
149
- // VO2 Max
150
- const vo2Max = activity.getStat(data_vo2_max_1.DataVO2Max.type);
151
- expect(vo2Max).toBeDefined();
152
- expect(vo2Max.getValue()).toBeCloseTo(57.0633, 4);
153
148
  expect(activity.getStat(data_temperature_max_1.DataTemperatureMax.type).getValue()).toBe(19);
154
149
  expect(activity.getStat(data_temperature_min_1.DataTemperatureMin.type).getValue()).toBe(7);
155
150
  // Positions
@@ -200,13 +195,46 @@ describe('EventImporterFIT MTB Jumps', () => {
200
195
  // Check Jumps
201
196
  const jumpEvents = activity.getAllEvents().filter((e) => e.getType() === data_jump_event_1.DataJumpEvent.type);
202
197
  expect(jumpEvents.length).toBeGreaterThan(0);
198
+ expect(jumpEvents.length).toBe(11);
203
199
  const jump = jumpEvents[0];
204
200
  expect(jump.jumpData).toBeDefined();
205
- expect((0, helpers_1.isNumber)(jump.jumpData.distance)).toBeTruthy();
206
- expect((0, helpers_1.isNumber)(jump.jumpData.height)).toBeTruthy();
207
- expect((0, helpers_1.isNumber)(jump.jumpData.score)).toBeTruthy();
201
+ expect((0, helpers_1.isNumber)(jump.jumpData.distance.getValue())).toBeTruthy();
202
+ expect((0, helpers_1.isNumber)(jump.jumpData.score.getValue())).toBeTruthy();
203
+ // Verify new jump fields with expected values
204
+ expect(jump.jumpData.distance.getValue()).toBeCloseTo(2.069, 2);
205
+ expect(jump.jumpData.hang_time.getValue()).toBeCloseTo(0.36, 2);
206
+ expect(jump.jumpData.score.getValue()).toBeCloseTo(62.44, 1);
207
+ expect(jump.jumpData.position_lat.getValue()).toBeCloseTo(39.6679, 3);
208
+ expect(jump.jumpData.position_long.getValue()).toBeCloseTo(20.8382, 3);
209
+ expect(jump.jumpData.speed.getValue()).toBeCloseTo(5.748, 2);
208
210
  console.log(`Found ${jumpEvents.length} jumps.`);
209
211
  console.log('First jump:', jump.jumpData);
212
+ // Verify Jump Statistics (Min, Max, Avg)
213
+ const { DataJumpDistanceAvg, DataJumpDistanceMax, DataJumpDistanceMin, DataJumpHangTimeAvg, DataJumpHangTimeMax, DataJumpHangTimeMin, DataJumpHeightAvg, DataJumpHeightMax, DataJumpHeightMin, DataJumpRotationsAvg, DataJumpRotationsMax, DataJumpRotationsMin, DataJumpScoreAvg, DataJumpScoreMax, DataJumpScoreMin, DataJumpSpeedAvg, DataJumpSpeedMax, DataJumpSpeedMin } = yield Promise.resolve().then(() => __importStar(require('../../../../data/data.jump-stats')));
214
+ // Hangtime
215
+ expect(activity.getStat(DataJumpHangTimeMin.type).getValue()).toBeCloseTo(0.36, 2);
216
+ expect(activity.getStat(DataJumpHangTimeMax.type).getValue()).toBeCloseTo(0.696, 3);
217
+ expect(activity.getStat(DataJumpHangTimeAvg.type).getValue()).toBeCloseTo(0.45, 2);
218
+ // Distance
219
+ expect(activity.getStat(DataJumpDistanceMin.type).getValue()).toBeCloseTo(1.40, 2);
220
+ expect(activity.getStat(DataJumpDistanceMax.type).getValue()).toBeCloseTo(4.68, 2);
221
+ expect(activity.getStat(DataJumpDistanceAvg.type).getValue()).toBeCloseTo(3.02, 2);
222
+ // Speed
223
+ expect(activity.getStat(DataJumpSpeedMin.type).getValue()).toBeCloseTo(3.88, 2);
224
+ expect(activity.getStat(DataJumpSpeedMax.type).getValue()).toBeCloseTo(8.995, 3);
225
+ expect(activity.getStat(DataJumpSpeedAvg.type).getValue()).toBeCloseTo(6.55, 2);
226
+ // Score
227
+ expect(activity.getStat(DataJumpScoreMin.type).getValue()).toBeCloseTo(53.9, 1);
228
+ expect(activity.getStat(DataJumpScoreMax.type).getValue()).toBeCloseTo(122.6, 1);
229
+ expect(activity.getStat(DataJumpScoreAvg.type).getValue()).toBeCloseTo(81.8, 1);
230
+ // Rotations (Should be undefined for this file)
231
+ expect(activity.getStat(DataJumpRotationsMin.type)).toBeUndefined();
232
+ expect(activity.getStat(DataJumpRotationsMax.type)).toBeUndefined();
233
+ expect(activity.getStat(DataJumpRotationsAvg.type)).toBeUndefined();
234
+ // Height (Should be undefined for this file)
235
+ expect(activity.getStat(DataJumpHeightMin.type)).toBeUndefined();
236
+ expect(activity.getStat(DataJumpHeightMax.type)).toBeUndefined();
237
+ expect(activity.getStat(DataJumpHeightAvg.type)).toBeUndefined();
210
238
  // We can check if we can find a sample with Grit.
211
239
  // In sports-lib, samples are often accessed via activity.getStream(type) or similar, BUT
212
240
  // importer creates `DataPoint`s? Or `DataSample`s?
@@ -71,6 +71,8 @@ export * from './data/data.heart-rate-avg';
71
71
  export * from './data/data.heart-rate-max';
72
72
  export * from './data/data.heart-rate-min';
73
73
  export * from './data/data.ibi';
74
+ export * from './data/data.event';
75
+ export * from './data/data.jump-event';
74
76
  export * from './data/data.interface';
75
77
  export * from './data/data.latitude-degrees';
76
78
  export * from './data/data.left-balance';
package/lib/cjs/index.js CHANGED
@@ -101,6 +101,8 @@ __exportStar(require("./data/data.heart-rate-avg"), exports);
101
101
  __exportStar(require("./data/data.heart-rate-max"), exports);
102
102
  __exportStar(require("./data/data.heart-rate-min"), exports);
103
103
  __exportStar(require("./data/data.ibi"), exports);
104
+ __exportStar(require("./data/data.event"), exports);
105
+ __exportStar(require("./data/data.jump-event"), exports);
104
106
  __exportStar(require("./data/data.interface"), exports);
105
107
  __exportStar(require("./data/data.latitude-degrees"), exports);
106
108
  __exportStar(require("./data/data.left-balance"), exports);
@@ -1,3 +1,4 @@
1
1
  import { DataNumber } from './data.number';
2
2
  export declare abstract class DataEvent extends DataNumber {
3
+ get timestamp(): number;
3
4
  }
@@ -1,12 +1,33 @@
1
1
  import { DataEvent } from './data.event';
2
+ import { DataDistance } from './data.distance';
3
+ import { DataSpeed } from './data.speed';
4
+ import { DataDuration } from './data.duration';
5
+ import { DataNumber } from './data.number';
6
+ import { DataLatitudeDegrees } from './data.latitude-degrees';
7
+ import { DataLongitudeDegrees } from './data.longitude-degrees';
8
+ export declare class DataScore extends DataNumber {
9
+ static type: string;
10
+ }
11
+ export declare class DataRotations extends DataNumber {
12
+ static type: string;
13
+ }
2
14
  export interface JumpEventInterface {
3
- distance: number;
4
- height: number;
5
- score: number;
15
+ distance: DataDistance;
16
+ height?: DataDistance;
17
+ score: DataScore;
18
+ hang_time?: DataDuration;
19
+ position_lat?: DataLatitudeDegrees;
20
+ position_long?: DataLongitudeDegrees;
21
+ speed?: DataSpeed;
22
+ rotations?: DataRotations;
6
23
  }
7
24
  export declare class DataJumpEvent extends DataEvent {
8
- jumpData: JumpEventInterface;
9
25
  static type: string;
10
- constructor(timestamp: number, jumpData: JumpEventInterface);
26
+ jumpData: JumpEventInterface;
27
+ constructor(timestampOrObj: number | {
28
+ timestamp: number;
29
+ jumpData: any;
30
+ }, jumpData?: any);
31
+ private hydrate;
11
32
  toJSON(): any;
12
33
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,91 @@
1
+ import { DataNumber } from './data.number';
2
+ export declare class DataJumpHangTimeMin extends DataNumber {
3
+ static type: string;
4
+ static unit: string;
5
+ constructor(value: number);
6
+ }
7
+ export declare class DataJumpHangTimeMax extends DataNumber {
8
+ static type: string;
9
+ static unit: string;
10
+ constructor(value: number);
11
+ }
12
+ export declare class DataJumpHangTimeAvg extends DataNumber {
13
+ static type: string;
14
+ static unit: string;
15
+ constructor(value: number);
16
+ }
17
+ export declare class DataJumpDistanceMin extends DataNumber {
18
+ static type: string;
19
+ static unit: string;
20
+ constructor(value: number);
21
+ }
22
+ export declare class DataJumpDistanceMax extends DataNumber {
23
+ static type: string;
24
+ static unit: string;
25
+ constructor(value: number);
26
+ }
27
+ export declare class DataJumpDistanceAvg extends DataNumber {
28
+ static type: string;
29
+ static unit: string;
30
+ constructor(value: number);
31
+ }
32
+ export declare class DataJumpSpeedMin extends DataNumber {
33
+ static type: string;
34
+ static unit: string;
35
+ constructor(value: number);
36
+ }
37
+ export declare class DataJumpSpeedMax extends DataNumber {
38
+ static type: string;
39
+ static unit: string;
40
+ constructor(value: number);
41
+ }
42
+ export declare class DataJumpSpeedAvg extends DataNumber {
43
+ static type: string;
44
+ static unit: string;
45
+ constructor(value: number);
46
+ }
47
+ export declare class DataJumpRotationsMin extends DataNumber {
48
+ static type: string;
49
+ static unit: string;
50
+ constructor(value: number);
51
+ }
52
+ export declare class DataJumpRotationsMax extends DataNumber {
53
+ static type: string;
54
+ static unit: string;
55
+ constructor(value: number);
56
+ }
57
+ export declare class DataJumpRotationsAvg extends DataNumber {
58
+ static type: string;
59
+ static unit: string;
60
+ constructor(value: number);
61
+ }
62
+ export declare class DataJumpScoreMin extends DataNumber {
63
+ static type: string;
64
+ static unit: string;
65
+ constructor(value: number);
66
+ }
67
+ export declare class DataJumpScoreMax extends DataNumber {
68
+ static type: string;
69
+ static unit: string;
70
+ constructor(value: number);
71
+ }
72
+ export declare class DataJumpScoreAvg extends DataNumber {
73
+ static type: string;
74
+ static unit: string;
75
+ constructor(value: number);
76
+ }
77
+ export declare class DataJumpHeightMin extends DataNumber {
78
+ static type: string;
79
+ static unit: string;
80
+ constructor(value: number);
81
+ }
82
+ export declare class DataJumpHeightMax extends DataNumber {
83
+ static type: string;
84
+ static unit: string;
85
+ constructor(value: number);
86
+ }
87
+ export declare class DataJumpHeightAvg extends DataNumber {
88
+ static type: string;
89
+ static unit: string;
90
+ constructor(value: number);
91
+ }
@@ -3,5 +3,8 @@ import { RiderPosition } from './data.cycling-position';
3
3
  export declare class DataRiderPositionChangeEvent extends DataEvent {
4
4
  static type: string;
5
5
  positionChange: RiderPosition;
6
- constructor(index: number, positionChange: RiderPosition);
6
+ constructor(indexOrObj: number | {
7
+ index: number;
8
+ positionChange: RiderPosition;
9
+ }, positionChange?: RiderPosition);
7
10
  }
@@ -71,6 +71,8 @@ export * from './data/data.heart-rate-avg';
71
71
  export * from './data/data.heart-rate-max';
72
72
  export * from './data/data.heart-rate-min';
73
73
  export * from './data/data.ibi';
74
+ export * from './data/data.event';
75
+ export * from './data/data.jump-event';
74
76
  export * from './data/data.interface';
75
77
  export * from './data/data.latitude-degrees';
76
78
  export * from './data/data.left-balance';