@sports-alliance/sports-lib 6.0.1 → 6.0.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.
@@ -0,0 +1,49 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "Run Watch Mode",
6
+ "type": "node",
7
+ "request": "launch",
8
+ "runtimeExecutable": "npm",
9
+ "runtimeArgs": [
10
+ "run",
11
+ "watch"
12
+ ],
13
+ "console": "integratedTerminal"
14
+ },
15
+ {
16
+ "type": "pwa-node",
17
+ "request": "launch",
18
+ "name": "Debug Jest Tests",
19
+ "program": "${workspaceFolder}/node_modules/.bin/jest",
20
+ "args": [
21
+ "--runInBand",
22
+ "--watchAll=false"
23
+ ],
24
+ "console": "integratedTerminal",
25
+ "internalConsoleOptions": "neverOpen",
26
+ "disableOptimisticBPs": true,
27
+ "windows": {
28
+ "program": "${workspaceFolder}/node_modules/jest/bin/jest.js"
29
+ }
30
+ },
31
+ {
32
+ "type": "pwa-node",
33
+ "request": "launch",
34
+ "name": "Debug Current Test File",
35
+ "program": "${workspaceFolder}/node_modules/.bin/jest",
36
+ "args": [
37
+ "${fileBasenameNoExtension}",
38
+ "--runInBand",
39
+ "--watchAll=false"
40
+ ],
41
+ "console": "integratedTerminal",
42
+ "internalConsoleOptions": "neverOpen",
43
+ "disableOptimisticBPs": true,
44
+ "windows": {
45
+ "program": "${workspaceFolder}/node_modules/jest/bin/jest.js"
46
+ }
47
+ }
48
+ ]
49
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "version": "2.0.0",
3
+ "tasks": [
4
+ {
5
+ "type": "npm",
6
+ "script": "build",
7
+ "group": "build",
8
+ "problemMatcher": [],
9
+ "label": "npm: build",
10
+ "detail": "npm run clean && tsc --project tsconfig.lib.json"
11
+ },
12
+ {
13
+ "type": "npm",
14
+ "script": "watch",
15
+ "group": "build",
16
+ "isBackground": true,
17
+ "problemMatcher": {
18
+ "owner": "typescript",
19
+ "pattern": "$tsc",
20
+ "background": {
21
+ "activeOnStart": true,
22
+ "beginsPattern": {
23
+ "regexp": "^.*Starting compilation in watch mode.*$"
24
+ },
25
+ "endsPattern": {
26
+ "regexp": "^.*Found [0-9]+ errors.*$"
27
+ }
28
+ }
29
+ },
30
+ "label": "npm: watch",
31
+ "detail": "npm run build -- --watch"
32
+ }
33
+ ]
34
+ }
@@ -1,6 +1,10 @@
1
1
  import { DataInterface } from './data.interface';
2
+ import { DataAerobicTrainingEffect } from './data-aerobic-training-effect';
2
3
  import { UserUnitSettingsInterface } from '../users/settings/user.unit.settings.interface';
3
4
  import { Data } from './data';
5
+ export declare class DataTotalTrainingEffectLegacy extends DataAerobicTrainingEffect {
6
+ static type: string;
7
+ }
4
8
  /**
5
9
  * Only concrete classes no abstracts
6
10
  */
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DynamicDataLoader = exports.DataStore = void 0;
3
+ exports.DynamicDataLoader = exports.DataStore = exports.DataTotalTrainingEffectLegacy = void 0;
4
4
  const data_vertical_speed_1 = require("./data.vertical-speed");
5
5
  const data_temperature_1 = require("./data.temperature");
6
6
  const data_speed_1 = require("./data.speed");
@@ -146,7 +146,40 @@ const data_time_1 = require("./data.time");
146
146
  const helpers_1 = require("../events/utilities/helpers");
147
147
  const data_moving_time_1 = require("./data.moving-time");
148
148
  const data_swolf_50m_1 = require("./data.swolf-50m");
149
+ const data_timer_time_1 = require("./data.timer-time");
150
+ const data_active_lap_1 = require("./data-active-lap");
151
+ const data_active_lengths_1 = require("./data-active-lengths");
152
+ const data_anaerobic_training_effect_1 = require("./data-anaerobic-training-effect");
153
+ const data_total_cycles_1 = require("./data-total-cycles");
154
+ const data_power_intensity_factor_1 = require("./data.power-intensity-factor");
155
+ const data_power_normalized_1 = require("./data.power-normalized");
156
+ const data_power_pedal_smoothness_left_1 = require("./data.power-pedal-smoothness-left");
157
+ const data_power_pedal_smoothness_right_1 = require("./data.power-pedal-smoothness-right");
158
+ const data_power_torque_effectiveness_left_1 = require("./data.power-torque-effectiveness-left");
159
+ const data_power_torque_effectiveness_right_1 = require("./data.power-torque-effectiveness-right");
160
+ const data_power_training_stress_score_1 = require("./data.power-training-stress-score");
161
+ const data_power_work_1 = require("./data.power-work");
162
+ const data_power_down_1 = require("./data.power-down");
163
+ const data_power_up_1 = require("./data.power-up");
164
+ const data_target_power_zone_1 = require("./data.target-power-zone");
165
+ const data_target_heart_rate_zone_1 = require("./data.target-heart-rate-zone");
166
+ const data_target_speed_zone_1 = require("./data.target-speed-zone");
167
+ const data_target_distance_1 = require("./data.target-distance");
168
+ const data_target_time_1 = require("./data.target-time");
149
169
  const data_stance_time_balance_right_1 = require("./data-stance-time-balance-right");
170
+ const data_rider_position_change_event_1 = require("./data.rider-position-change-event");
171
+ const data_sport_profile_name_1 = require("./data.sport-profile-name");
172
+ const data_balance_1 = require("./data.balance");
173
+ const data_altitude_smooth_1 = require("./data.altitude-smooth");
174
+ const data_avg_stride_length_1 = require("./data.avg-stride-length");
175
+ const data_cycling_seated_time_1 = require("./data.cycling-seated-time");
176
+ const data_cycling_standing_time_1 = require("./data.cycling-standing-time");
177
+ const data_grade_smooth_1 = require("./data.grade-smooth");
178
+ // "Total Training effect" was renamed to "Aerobic Training Effect" in sports-lib 6.0
179
+ class DataTotalTrainingEffectLegacy extends data_aerobic_training_effect_1.DataAerobicTrainingEffect {
180
+ }
181
+ exports.DataTotalTrainingEffectLegacy = DataTotalTrainingEffectLegacy;
182
+ DataTotalTrainingEffectLegacy.type = 'Total Training effect';
150
183
  /**
151
184
  * Only concrete classes no abstracts
152
185
  */
@@ -227,6 +260,7 @@ exports.DataStore = {
227
260
  DataBatteryLifeEstimation: data_battery_life_estimation_1.DataBatteryLifeEstimation,
228
261
  DataFormPower: data_form_power_1.DataFormPower,
229
262
  DataLegStiffness: data_leg_stiffness_1.DataLegStiffness,
263
+ DataLegSpringStiffness: data_leg_stiffness_1.DataLegSpringStiffness,
230
264
  DataVerticalOscillation: data_vertical_oscillation_1.DataVerticalOscillation,
231
265
  DataAerobicTrainingEffect: data_aerobic_training_effect_1.DataAerobicTrainingEffect,
232
266
  DataFootPodUsed: data_foot_pod_used_1.DataFootPodUsed,
@@ -385,7 +419,36 @@ exports.DataStore = {
385
419
  DataStopAllEvent: data_stop_all_event_1.DataStopAllEvent,
386
420
  DataTime: data_time_1.DataTime,
387
421
  DataDistanceMiles: data_distance_1.DataDistanceMiles,
388
- DataMovingTime: data_moving_time_1.DataMovingTime
422
+ DataMovingTime: data_moving_time_1.DataMovingTime,
423
+ DataTimerTime: data_timer_time_1.DataTimerTime,
424
+ DataActiveLap: data_active_lap_1.DataActiveLap,
425
+ DataActiveLengths: data_active_lengths_1.DataActiveLengths,
426
+ DataAnaerobicTrainingEffect: data_anaerobic_training_effect_1.DataAnaerobicTrainingEffect,
427
+ DataTotalCycles: data_total_cycles_1.DataTotalCycles,
428
+ DataPowerIntensityFactor: data_power_intensity_factor_1.DataPowerIntensityFactor,
429
+ DataPowerNormalized: data_power_normalized_1.DataPowerNormalized,
430
+ DataPowerPedalSmoothnessLeft: data_power_pedal_smoothness_left_1.DataPowerPedalSmoothnessLeft,
431
+ DataPowerPedalSmoothnessRight: data_power_pedal_smoothness_right_1.DataPowerPedalSmoothnessRight,
432
+ DataPowerTorqueEffectivenessLeft: data_power_torque_effectiveness_left_1.DataPowerTorqueEffectivenessLeft,
433
+ DataPowerTorqueEffectivenessRight: data_power_torque_effectiveness_right_1.DataPowerTorqueEffectivenessRight,
434
+ DataPowerTrainingStressScore: data_power_training_stress_score_1.DataPowerTrainingStressScore,
435
+ DataPowerWork: data_power_work_1.DataPowerWork,
436
+ DataRiderPositionChangeEvent: data_rider_position_change_event_1.DataRiderPositionChangeEvent,
437
+ DataSportProfileName: data_sport_profile_name_1.DataSportProfileName,
438
+ DataBalance: data_balance_1.DataBalance,
439
+ DataAltitudeSmooth: data_altitude_smooth_1.DataAltitudeSmooth,
440
+ DataAvgStrideLength: data_avg_stride_length_1.DataAvgStrideLength,
441
+ DataCyclingSeatedTime: data_cycling_seated_time_1.DataCyclingSeatedTime,
442
+ DataCyclingStandingTime: data_cycling_standing_time_1.DataCyclingStandingTime,
443
+ DataGradeSmooth: data_grade_smooth_1.DataGradeSmooth,
444
+ DataPowerDown: data_power_down_1.DataPowerDown,
445
+ DataPowerUp: data_power_up_1.DataPowerUp,
446
+ DataTargetPowerZone: data_target_power_zone_1.DataTargetPowerZone,
447
+ DataTargetHeartRateZone: data_target_heart_rate_zone_1.DataTargetHeartRateZone,
448
+ DataTargetSpeedZone: data_target_speed_zone_1.DataTargetSpeedZone,
449
+ DataTargetDistance: data_target_distance_1.DataTargetDistance,
450
+ DataTargetTime: data_target_time_1.DataTargetTime,
451
+ DataTotalTrainingEffectLegacy
389
452
  };
390
453
  class DynamicDataLoader {
391
454
  static getDataInstanceFromDataType(dataType, opts) {
@@ -1,6 +1,12 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
4
10
  };
5
11
  Object.defineProperty(exports, "__esModule", { value: true });
6
12
  exports.EventImporterFIT = void 0;
@@ -107,222 +113,223 @@ const parsing_event_lib_error_1 = require("../../../../errors/parsing-event-lib.
107
113
  const data_power_down_1 = require("../../../../data/data.power-down");
108
114
  const data_power_up_1 = require("../../../../data/data.power-up");
109
115
  const importer_fit_development_device_names_1 = require("./importer.fit.development.device.names");
110
- // eslint-disable-next-line @typescript-eslint/no-var-requires
111
- const fit_file_parser_1 = __importDefault(require("fit-file-parser"));
112
116
  // Threshold to detect that session.timestamp are not trustable (when exceeding 15% of session.total_elapsed_time)
113
117
  const INVALID_DATES_ELAPSED_TIME_RATIO_THRESHOLD = 1.15;
114
118
  class EventImporterFIT {
115
119
  static getFromArrayBuffer(arrayBuffer, options = activity_parsing_options_1.ActivityParsingOptions.DEFAULT, name = 'New Event') {
116
- return new Promise((resolve, reject) => {
117
- const fitFileParser = new fit_file_parser_1.default({
118
- force: true,
119
- speedUnit: 'm/s',
120
- lengthUnit: 'm',
121
- temperatureUnit: 'celsius',
122
- elapsedRecordField: false,
123
- mode: 'both'
124
- });
125
- fitFileParser.parse(arrayBuffer, (error, fitDataObject) => {
126
- if (error) {
127
- // For now, assume any error from parser on this file means it's broken/empty in a way we treat as EmptyEventLibError
128
- // to satisfy existing tests. Or ideally we wrap in a generic EventLibError.
129
- // But test expects EmptyEventLibError.
130
- reject(new empty_event_sports_libs_error_1.EmptyEventLibError());
131
- return;
132
- }
133
- if (!fitDataObject || !fitDataObject.sessions) {
134
- reject(new empty_event_sports_libs_error_1.EmptyEventLibError());
135
- return;
136
- }
137
- // Iterate over the sessions and create their activities
138
- const activities = fitDataObject.sessions.map((sessionObject) => {
139
- // Get the activity from the sessionObject
140
- const activity = this.getActivityFromSessionObject(sessionObject, fitDataObject, options);
141
- // Go over the laps
142
- sessionObject.laps.forEach((sessionLapObject, index) => {
143
- activity.addLap(this.getLapFromSessionLapObject(sessionLapObject, activity, index));
144
- });
145
- // Go over the hr zone info
146
- if (sessionObject.time_in_hr_zone && sessionObject.time_in_hr_zone.length) {
147
- // Add the stats
148
- if ((0, helpers_1.isNumber)(sessionObject.time_in_hr_zone[0])) {
149
- activity.addStat(new data_heart_rate_zone_one_duration_1.DataHeartRateZoneOneDuration(sessionObject.time_in_hr_zone[0]));
150
- }
151
- if ((0, helpers_1.isNumber)(sessionObject.time_in_hr_zone[1])) {
152
- activity.addStat(new data_heart_rate_zone_two_duration_1.DataHeartRateZoneTwoDuration(sessionObject.time_in_hr_zone[1]));
153
- }
154
- if ((0, helpers_1.isNumber)(sessionObject.time_in_hr_zone[2])) {
155
- activity.addStat(new data_heart_rate_zone_three_duration_1.DataHeartRateZoneThreeDuration(sessionObject.time_in_hr_zone[2]));
156
- }
157
- if ((0, helpers_1.isNumber)(sessionObject.time_in_hr_zone[3])) {
158
- activity.addStat(new data_heart_rate_zone_four_duration_1.DataHeartRateZoneFourDuration(sessionObject.time_in_hr_zone[3]));
159
- }
160
- if ((0, helpers_1.isNumber)(sessionObject.time_in_hr_zone[4])) {
161
- activity.addStat(new data_heart_rate_zone_five_duration_1.DataHeartRateZoneFiveDuration(sessionObject.time_in_hr_zone[4]));
162
- }
163
- const hrIntensityZones = new intensity_zones_1.IntensityZones(data_heart_rate_1.DataHeartRate.type);
164
- hrIntensityZones.zone1Duration = sessionObject.time_in_hr_zone[0] || 0;
165
- hrIntensityZones.zone2Duration = sessionObject.time_in_hr_zone[1] || 0;
166
- hrIntensityZones.zone3Duration = sessionObject.time_in_hr_zone[2] || 0;
167
- hrIntensityZones.zone4Duration = sessionObject.time_in_hr_zone[3] || 0;
168
- hrIntensityZones.zone5Duration = sessionObject.time_in_hr_zone[4] || 0;
169
- activity.intensityZones.push(hrIntensityZones);
170
- }
171
- // Go over the power zone info
172
- if (sessionObject.time_in_power_zone && sessionObject.time_in_power_zone.length) {
173
- if ((0, helpers_1.isNumber)(sessionObject.time_in_power_zone[0])) {
174
- activity.addStat(new data_power_zone_one_duration_1.DataPowerZoneOneDuration(sessionObject.time_in_power_zone[0]));
175
- }
176
- if ((0, helpers_1.isNumber)(sessionObject.time_in_power_zone[1])) {
177
- activity.addStat(new data_power_zone_two_duration_1.DataPowerZoneTwoDuration(sessionObject.time_in_power_zone[1]));
178
- }
179
- if ((0, helpers_1.isNumber)(sessionObject.time_in_power_zone[2])) {
180
- activity.addStat(new data_power_zone_three_duration_1.DataPowerZoneThreeDuration(sessionObject.time_in_power_zone[2]));
181
- }
182
- if ((0, helpers_1.isNumber)(sessionObject.time_in_power_zone[3])) {
183
- activity.addStat(new data_power_zone_four_duration_1.DataPowerZoneFourDuration(sessionObject.time_in_power_zone[3]));
184
- }
185
- if ((0, helpers_1.isNumber)(sessionObject.time_in_power_zone[4])) {
186
- activity.addStat(new data_power_zone_five_duration_1.DataPowerZoneFiveDuration(sessionObject.time_in_power_zone[4]));
187
- }
188
- const powerIntensityZones = new intensity_zones_1.IntensityZones(data_power_1.DataPower.type);
189
- powerIntensityZones.zone1Duration = sessionObject.time_in_power_zone[0] || 0;
190
- powerIntensityZones.zone2Duration = sessionObject.time_in_power_zone[1] || 0;
191
- powerIntensityZones.zone3Duration = sessionObject.time_in_power_zone[2] || 0;
192
- powerIntensityZones.zone4Duration = sessionObject.time_in_power_zone[3] || 0;
193
- powerIntensityZones.zone5Duration = sessionObject.time_in_power_zone[4] || 0;
194
- activity.intensityZones.push(powerIntensityZones);
120
+ return __awaiter(this, void 0, void 0, function* () {
121
+ const { default: FitFileParser } = yield (new Function('return import("fit-file-parser")'))();
122
+ return new Promise((resolve, reject) => {
123
+ const fitFileParser = new FitFileParser({
124
+ force: true,
125
+ speedUnit: 'm/s',
126
+ lengthUnit: 'm',
127
+ temperatureUnit: 'celsius',
128
+ elapsedRecordField: false,
129
+ mode: 'both'
130
+ });
131
+ fitFileParser.parse(arrayBuffer, (error, fitDataObject) => {
132
+ if (error) {
133
+ // For now, assume any error from parser on this file means it's broken/empty in a way we treat as EmptyEventLibError
134
+ // to satisfy existing tests. Or ideally we wrap in a generic EventLibError.
135
+ // But test expects EmptyEventLibError.
136
+ reject(new empty_event_sports_libs_error_1.EmptyEventLibError());
137
+ return;
195
138
  }
196
- // Go over the speed zone info
197
- if (sessionObject.time_in_speed_zone && sessionObject.time_in_speed_zone.length) {
198
- if ((0, helpers_1.isNumber)(sessionObject.time_in_speed_zone[0])) {
199
- activity.addStat(new data_speed_zone_one_duration_1.DataSpeedZoneOneDuration(sessionObject.time_in_speed_zone[0]));
200
- }
201
- if ((0, helpers_1.isNumber)(sessionObject.time_in_speed_zone[1])) {
202
- activity.addStat(new data_speed_zone_two_duration_1.DataSpeedZoneTwoDuration(sessionObject.time_in_speed_zone[1]));
203
- }
204
- if ((0, helpers_1.isNumber)(sessionObject.time_in_speed_zone[2])) {
205
- activity.addStat(new data_speed_zone_three_duration_1.DataSpeedZoneThreeDuration(sessionObject.time_in_speed_zone[2]));
206
- }
207
- if ((0, helpers_1.isNumber)(sessionObject.time_in_speed_zone[3])) {
208
- activity.addStat(new data_speed_zone_four_duration_1.DataSpeedZoneFourDuration(sessionObject.time_in_speed_zone[3]));
209
- }
210
- if ((0, helpers_1.isNumber)(sessionObject.time_in_speed_zone[4])) {
211
- activity.addStat(new data_speed_zone_five_duration_1.DataSpeedZoneFiveDuration(sessionObject.time_in_speed_zone[4]));
212
- }
213
- const speedIntensityZones = new intensity_zones_1.IntensityZones(data_speed_1.DataSpeed.type);
214
- speedIntensityZones.zone1Duration = sessionObject.time_in_speed_zone[0] || 0;
215
- speedIntensityZones.zone2Duration = sessionObject.time_in_speed_zone[1] || 0;
216
- speedIntensityZones.zone3Duration = sessionObject.time_in_speed_zone[2] || 0;
217
- speedIntensityZones.zone4Duration = sessionObject.time_in_speed_zone[3] || 0;
218
- speedIntensityZones.zone5Duration = sessionObject.time_in_speed_zone[4] || 0;
219
- activity.intensityZones.push(speedIntensityZones);
139
+ if (!fitDataObject || !fitDataObject.sessions) {
140
+ reject(new empty_event_sports_libs_error_1.EmptyEventLibError());
141
+ return;
220
142
  }
221
- // Add the events
222
- fitDataObject.events
223
- .filter((activityEvent) => {
224
- return activityEvent.timestamp >= activity.startDate && activityEvent.timestamp <= activity.endDate;
225
- })
226
- .forEach((activityEvent) => {
227
- if (activityEvent.event === 'timer') {
228
- switch (activityEvent.event_type) {
229
- case 'start':
230
- activity.addEvent(new data_start_event_1.DataStartEvent(activity.getDateIndex(activityEvent.timestamp)));
231
- break;
232
- case 'stop':
233
- activity.addEvent(new data_stop_event_1.DataStopEvent(activity.getDateIndex(activityEvent.timestamp)));
234
- break;
235
- case 'stop_all':
236
- activity.addEvent(new data_stop_all_event_1.DataStopAllEvent(activity.getDateIndex(activityEvent.timestamp)));
237
- break;
238
- default:
239
- break;
143
+ // Iterate over the sessions and create their activities
144
+ const activities = fitDataObject.sessions.map((sessionObject) => {
145
+ // Get the activity from the sessionObject
146
+ const activity = this.getActivityFromSessionObject(sessionObject, fitDataObject, options);
147
+ // Go over the laps
148
+ sessionObject.laps.forEach((sessionLapObject, index) => {
149
+ activity.addLap(this.getLapFromSessionLapObject(sessionLapObject, activity, index));
150
+ });
151
+ // Go over the hr zone info
152
+ if (sessionObject.time_in_hr_zone && sessionObject.time_in_hr_zone.length) {
153
+ // Add the stats
154
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_hr_zone[0])) {
155
+ activity.addStat(new data_heart_rate_zone_one_duration_1.DataHeartRateZoneOneDuration(sessionObject.time_in_hr_zone[0]));
240
156
  }
157
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_hr_zone[1])) {
158
+ activity.addStat(new data_heart_rate_zone_two_duration_1.DataHeartRateZoneTwoDuration(sessionObject.time_in_hr_zone[1]));
159
+ }
160
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_hr_zone[2])) {
161
+ activity.addStat(new data_heart_rate_zone_three_duration_1.DataHeartRateZoneThreeDuration(sessionObject.time_in_hr_zone[2]));
162
+ }
163
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_hr_zone[3])) {
164
+ activity.addStat(new data_heart_rate_zone_four_duration_1.DataHeartRateZoneFourDuration(sessionObject.time_in_hr_zone[3]));
165
+ }
166
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_hr_zone[4])) {
167
+ activity.addStat(new data_heart_rate_zone_five_duration_1.DataHeartRateZoneFiveDuration(sessionObject.time_in_hr_zone[4]));
168
+ }
169
+ const hrIntensityZones = new intensity_zones_1.IntensityZones(data_heart_rate_1.DataHeartRate.type);
170
+ hrIntensityZones.zone1Duration = sessionObject.time_in_hr_zone[0] || 0;
171
+ hrIntensityZones.zone2Duration = sessionObject.time_in_hr_zone[1] || 0;
172
+ hrIntensityZones.zone3Duration = sessionObject.time_in_hr_zone[2] || 0;
173
+ hrIntensityZones.zone4Duration = sessionObject.time_in_hr_zone[3] || 0;
174
+ hrIntensityZones.zone5Duration = sessionObject.time_in_hr_zone[4] || 0;
175
+ activity.intensityZones.push(hrIntensityZones);
241
176
  }
242
- else if (activityEvent.event === 'power_down') {
243
- activity.addEvent(new data_power_down_1.DataPowerDown(activity.getDateIndex(activityEvent.timestamp)));
244
- }
245
- else if (activityEvent.event === 'power_up') {
246
- activity.addEvent(new data_power_up_1.DataPowerUp(activity.getDateIndex(activityEvent.timestamp)));
177
+ // Go over the power zone info
178
+ if (sessionObject.time_in_power_zone && sessionObject.time_in_power_zone.length) {
179
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_power_zone[0])) {
180
+ activity.addStat(new data_power_zone_one_duration_1.DataPowerZoneOneDuration(sessionObject.time_in_power_zone[0]));
181
+ }
182
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_power_zone[1])) {
183
+ activity.addStat(new data_power_zone_two_duration_1.DataPowerZoneTwoDuration(sessionObject.time_in_power_zone[1]));
184
+ }
185
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_power_zone[2])) {
186
+ activity.addStat(new data_power_zone_three_duration_1.DataPowerZoneThreeDuration(sessionObject.time_in_power_zone[2]));
187
+ }
188
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_power_zone[3])) {
189
+ activity.addStat(new data_power_zone_four_duration_1.DataPowerZoneFourDuration(sessionObject.time_in_power_zone[3]));
190
+ }
191
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_power_zone[4])) {
192
+ activity.addStat(new data_power_zone_five_duration_1.DataPowerZoneFiveDuration(sessionObject.time_in_power_zone[4]));
193
+ }
194
+ const powerIntensityZones = new intensity_zones_1.IntensityZones(data_power_1.DataPower.type);
195
+ powerIntensityZones.zone1Duration = sessionObject.time_in_power_zone[0] || 0;
196
+ powerIntensityZones.zone2Duration = sessionObject.time_in_power_zone[1] || 0;
197
+ powerIntensityZones.zone3Duration = sessionObject.time_in_power_zone[2] || 0;
198
+ powerIntensityZones.zone4Duration = sessionObject.time_in_power_zone[3] || 0;
199
+ powerIntensityZones.zone5Duration = sessionObject.time_in_power_zone[4] || 0;
200
+ activity.intensityZones.push(powerIntensityZones);
247
201
  }
248
- else if (activityEvent.event === 'rider_position_change') {
249
- const positionChange = activityEvent.data;
250
- if (positionChange === data_cycling_position_1.RiderPosition.SEATED ||
251
- positionChange === data_cycling_position_1.RiderPosition.STANDING ||
252
- positionChange === data_cycling_position_1.RiderPosition.TRANSITION_TO_SEATED ||
253
- positionChange === data_cycling_position_1.RiderPosition.TRANSITION_TO_STANDING) {
254
- activity.addEvent(new data_rider_position_change_event_1.DataRiderPositionChangeEvent(activity.getDateIndex(activityEvent.timestamp), positionChange));
202
+ // Go over the speed zone info
203
+ if (sessionObject.time_in_speed_zone && sessionObject.time_in_speed_zone.length) {
204
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_speed_zone[0])) {
205
+ activity.addStat(new data_speed_zone_one_duration_1.DataSpeedZoneOneDuration(sessionObject.time_in_speed_zone[0]));
206
+ }
207
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_speed_zone[1])) {
208
+ activity.addStat(new data_speed_zone_two_duration_1.DataSpeedZoneTwoDuration(sessionObject.time_in_speed_zone[1]));
209
+ }
210
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_speed_zone[2])) {
211
+ activity.addStat(new data_speed_zone_three_duration_1.DataSpeedZoneThreeDuration(sessionObject.time_in_speed_zone[2]));
212
+ }
213
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_speed_zone[3])) {
214
+ activity.addStat(new data_speed_zone_four_duration_1.DataSpeedZoneFourDuration(sessionObject.time_in_speed_zone[3]));
255
215
  }
216
+ if ((0, helpers_1.isNumber)(sessionObject.time_in_speed_zone[4])) {
217
+ activity.addStat(new data_speed_zone_five_duration_1.DataSpeedZoneFiveDuration(sessionObject.time_in_speed_zone[4]));
218
+ }
219
+ const speedIntensityZones = new intensity_zones_1.IntensityZones(data_speed_1.DataSpeed.type);
220
+ speedIntensityZones.zone1Duration = sessionObject.time_in_speed_zone[0] || 0;
221
+ speedIntensityZones.zone2Duration = sessionObject.time_in_speed_zone[1] || 0;
222
+ speedIntensityZones.zone3Duration = sessionObject.time_in_speed_zone[2] || 0;
223
+ speedIntensityZones.zone4Duration = sessionObject.time_in_speed_zone[3] || 0;
224
+ speedIntensityZones.zone5Duration = sessionObject.time_in_speed_zone[4] || 0;
225
+ activity.intensityZones.push(speedIntensityZones);
256
226
  }
257
- });
258
- // Get the samples..
259
- // Test if activity is lengths based
260
- // Indeed when based on lengths, an activity do not provides samples under records object (e.g. Pool swimming activities)
261
- // Note: this is how Strava generate streams for this kind of activities
262
- const isLengthsBased = this.isLengthsBased(sessionObject);
263
- const samples = isLengthsBased
264
- ? this.generateSamplesFromLengths(sessionObject)
265
- : fitDataObject.records.filter((record) => {
266
- return record.timestamp >= activity.startDate && record.timestamp <= activity.endDate;
227
+ // Add the events
228
+ fitDataObject.events
229
+ .filter((activityEvent) => {
230
+ return activityEvent.timestamp >= activity.startDate && activityEvent.timestamp <= activity.endDate;
231
+ })
232
+ .forEach((activityEvent) => {
233
+ if (activityEvent.event === 'timer') {
234
+ switch (activityEvent.event_type) {
235
+ case 'start':
236
+ activity.addEvent(new data_start_event_1.DataStartEvent(activity.getDateIndex(activityEvent.timestamp)));
237
+ break;
238
+ case 'stop':
239
+ activity.addEvent(new data_stop_event_1.DataStopEvent(activity.getDateIndex(activityEvent.timestamp)));
240
+ break;
241
+ case 'stop_all':
242
+ activity.addEvent(new data_stop_all_event_1.DataStopAllEvent(activity.getDateIndex(activityEvent.timestamp)));
243
+ break;
244
+ default:
245
+ break;
246
+ }
247
+ }
248
+ else if (activityEvent.event === 'power_down') {
249
+ activity.addEvent(new data_power_down_1.DataPowerDown(activity.getDateIndex(activityEvent.timestamp)));
250
+ }
251
+ else if (activityEvent.event === 'power_up') {
252
+ activity.addEvent(new data_power_up_1.DataPowerUp(activity.getDateIndex(activityEvent.timestamp)));
253
+ }
254
+ else if (activityEvent.event === 'rider_position_change') {
255
+ const positionChange = activityEvent.data;
256
+ if (positionChange === data_cycling_position_1.RiderPosition.SEATED ||
257
+ positionChange === data_cycling_position_1.RiderPosition.STANDING ||
258
+ positionChange === data_cycling_position_1.RiderPosition.TRANSITION_TO_SEATED ||
259
+ positionChange === data_cycling_position_1.RiderPosition.TRANSITION_TO_STANDING) {
260
+ activity.addEvent(new data_rider_position_change_event_1.DataRiderPositionChangeEvent(activity.getDateIndex(activityEvent.timestamp), positionChange));
261
+ }
262
+ }
267
263
  });
268
- // Setup sample info which could be use when getting sample values
269
- const hasPowerMeter = samples.findIndex((sample) => Number.isFinite((0, helpers_1.isNumber)(sample.power) ? sample.power : (0, helpers_1.isNumber)(sample.Power) ? sample.Power : sample.RP_Power)) !== -1;
270
- const samplesInfo = { hasPowerMeter: hasPowerMeter };
271
- importer_fit_mapper_1.FITSampleMapper.forEach(sampleMapping => {
272
- // @todo not sure if we need to check for number only ...
273
- const subjectSamples = (samples.filter((sample) => (0, helpers_1.isNumber)(sampleMapping.getSampleValue(sample, samplesInfo))));
274
- if (subjectSamples.length) {
275
- // When we create a stream here it has the length of the activity elapsed time (end-start) filled with nulls.
276
- // We keep nulls in order to preserve the array length.
277
- activity.addStream(activity.createStream(sampleMapping.dataType));
278
- subjectSamples.forEach(subjectSample => {
279
- activity.addDataToStream(sampleMapping.dataType, new Date(subjectSample.timestamp), sampleMapping.getSampleValue(subjectSample, samplesInfo));
264
+ // Get the samples..
265
+ // Test if activity is lengths based
266
+ // Indeed when based on lengths, an activity do not provides samples under records object (e.g. Pool swimming activities)
267
+ // Note: this is how Strava generate streams for this kind of activities
268
+ const isLengthsBased = this.isLengthsBased(sessionObject);
269
+ const samples = isLengthsBased
270
+ ? this.generateSamplesFromLengths(sessionObject)
271
+ : fitDataObject.records.filter((record) => {
272
+ return record.timestamp >= activity.startDate && record.timestamp <= activity.endDate;
280
273
  });
281
- }
282
- });
283
- return activity;
284
- });
285
- // If there are no activities to parse ....
286
- if (!activities.length) {
287
- reject(new empty_event_sports_libs_error_1.EmptyEventLibError());
288
- return;
289
- }
290
- // Get the HRV to IBI if exist
291
- if (fitDataObject.hrv && fitDataObject.hrv.length) {
292
- activities.forEach((activity) => {
293
- let timeSum = 0;
294
- const ibiData = fitDataObject.hrv
295
- .reduce((ibiArray, hrvRecord) => ibiArray.concat(hrvRecord.time), [])
296
- .map((ibi) => ibi * 1000)
297
- .filter((ibi) => {
298
- // debugger;
299
- // Some Garmin devices return a record of 65.535 (65535) for some reason so exlcude those
300
- if (ibi === 65535) {
301
- // timeSum += ibi;
302
- return false;
274
+ // Setup sample info which could be use when getting sample values
275
+ const hasPowerMeter = samples.findIndex((sample) => Number.isFinite((0, helpers_1.isNumber)(sample.power) ? sample.power : (0, helpers_1.isNumber)(sample.Power) ? sample.Power : sample.RP_Power)) !== -1;
276
+ const samplesInfo = { hasPowerMeter: hasPowerMeter };
277
+ importer_fit_mapper_1.FITSampleMapper.forEach(sampleMapping => {
278
+ // @todo not sure if we need to check for number only ...
279
+ const subjectSamples = (samples.filter((sample) => (0, helpers_1.isNumber)(sampleMapping.getSampleValue(sample, samplesInfo))));
280
+ if (subjectSamples.length) {
281
+ // When we create a stream here it has the length of the activity elapsed time (end-start) filled with nulls.
282
+ // We keep nulls in order to preserve the array length.
283
+ activity.addStream(activity.createStream(sampleMapping.dataType));
284
+ subjectSamples.forEach(subjectSample => {
285
+ activity.addDataToStream(sampleMapping.dataType, new Date(subjectSample.timestamp), sampleMapping.getSampleValue(subjectSample, samplesInfo));
286
+ });
303
287
  }
304
- timeSum += ibi;
305
- const ibiDataDate = new Date(activities[0].startDate.getTime() + timeSum);
306
- return ibiDataDate >= activity.startDate && ibiDataDate <= activity.endDate;
307
288
  });
308
- // set the IBI
309
- activity.addStream(new ibi_stream_1.IBIStream(ibiData));
289
+ return activity;
310
290
  });
311
- }
312
- // Parse the device infos
313
- if (fitDataObject.device_infos && fitDataObject.device_infos.length) {
314
- activities.forEach(activity => {
315
- activity.creator.devices = this.getDeviceInfos(fitDataObject.device_infos);
316
- });
317
- }
318
- // Create an event
319
- // @todo check if the start and end date can derive from the file
320
- const event = new event_1.Event(name, activities[0].startDate, activities[activities.length - 1].endDate, file_type_enum_1.FileType.FIT);
321
- activities.forEach(activity => event.addActivity(activity));
322
- // debugger;
323
- event_utilities_1.EventUtilities.generateStatsForAll(event);
324
- // debugger;
325
- resolve(event);
291
+ // If there are no activities to parse ....
292
+ if (!activities.length) {
293
+ reject(new empty_event_sports_libs_error_1.EmptyEventLibError());
294
+ return;
295
+ }
296
+ // Get the HRV to IBI if exist
297
+ if (fitDataObject.hrv && fitDataObject.hrv.length) {
298
+ activities.forEach((activity) => {
299
+ let timeSum = 0;
300
+ const ibiData = fitDataObject.hrv
301
+ .reduce((ibiArray, hrvRecord) => ibiArray.concat(hrvRecord.time), [])
302
+ .map((ibi) => ibi * 1000)
303
+ .filter((ibi) => {
304
+ // debugger;
305
+ // Some Garmin devices return a record of 65.535 (65535) for some reason so exlcude those
306
+ if (ibi === 65535) {
307
+ // timeSum += ibi;
308
+ return false;
309
+ }
310
+ timeSum += ibi;
311
+ const ibiDataDate = new Date(activities[0].startDate.getTime() + timeSum);
312
+ return ibiDataDate >= activity.startDate && ibiDataDate <= activity.endDate;
313
+ });
314
+ // set the IBI
315
+ activity.addStream(new ibi_stream_1.IBIStream(ibiData));
316
+ });
317
+ }
318
+ // Parse the device infos
319
+ if (fitDataObject.device_infos && fitDataObject.device_infos.length) {
320
+ activities.forEach(activity => {
321
+ activity.creator.devices = this.getDeviceInfos(fitDataObject.device_infos);
322
+ });
323
+ }
324
+ // Create an event
325
+ // @todo check if the start and end date can derive from the file
326
+ const event = new event_1.Event(name, activities[0].startDate, activities[activities.length - 1].endDate, file_type_enum_1.FileType.FIT);
327
+ activities.forEach(activity => event.addActivity(activity));
328
+ // debugger;
329
+ event_utilities_1.EventUtilities.generateStatsForAll(event);
330
+ // debugger;
331
+ resolve(event);
332
+ });
326
333
  });
327
334
  });
328
335
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sports-alliance/sports-lib",
3
- "version": "6.0.1",
3
+ "version": "6.0.4",
4
4
  "description": "A Library to for importing / exporting and processing GPX, TCX, FIT and JSON files from services such as Strava, Movescount, Garmin, Polar etc",
5
5
  "keywords": [
6
6
  "gpx",
@@ -29,8 +29,8 @@
29
29
  "clean": "rimraf ./lib/",
30
30
  "generate:docs": "npm run build && typedoc --out docs --target es6 --theme minimal --mode file src",
31
31
  "lint:fix": "eslint . --ext ts --fix",
32
- "test": "jest",
33
- "test-coverage": "jest --coverage",
32
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest",
33
+ "test-coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
34
34
  "prettier:fix": "prettier --write .",
35
35
  "prepare": "husky install"
36
36
  },
@@ -46,7 +46,7 @@
46
46
  "license": "SEE LICENSE IN LICENSE.md",
47
47
  "dependencies": {
48
48
  "fast-xml-parser": "^3.20.3",
49
- "fit-file-parser": "^2.0.4",
49
+ "fit-file-parser": "^2.0.5",
50
50
  "geolib": "^3.3.1",
51
51
  "gpx-builder": "^3.7.8",
52
52
  "kalmanjs": "^1.1.0",