@sports-alliance/sports-lib 6.0.3 → 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.
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
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
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
-
//
|
|
222
|
-
fitDataObject.
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
.forEach((
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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
|
-
|
|
249
|
-
|
|
250
|
-
if (
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
activity.
|
|
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
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
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
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
|
|
309
|
-
activity.addStream(new ibi_stream_1.IBIStream(ibiData));
|
|
289
|
+
return activity;
|
|
310
290
|
});
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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.
|
|
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
|
},
|