@sports-alliance/sports-lib
Version:
A Library to for importing / exporting and processing GPX, TCX, FIT and JSON files from services such as Strava, Movescount, Garmin, Polar etc
274 lines (273 loc) • 13 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Activity = exports.MAX_ACTIVITY_DURATION = void 0;
var activity_types_1 = require("./activity.types");
var duration_class_abstract_1 = require("../duration/duration.class.abstract");
var data_latitude_degrees_1 = require("../data/data.latitude-degrees");
var data_longitude_degrees_1 = require("../data/data.longitude-degrees");
var stream_1 = require("../streams/stream");
var helpers_1 = require("../events/utilities/helpers");
var data_power_1 = require("../data/data.power");
var data_start_event_1 = require("../data/data.start-event");
var data_stop_event_1 = require("../data/data.stop-event");
var data_stop_all_event_1 = require("../data/data.stop-all-event");
var data_time_1 = require("../data/data.time");
var activity_utilities_1 = require("../events/utilities/activity.utilities");
exports.MAX_ACTIVITY_DURATION = 1 * 1 * 30 * 24 * 60 * 60 * 1000; // 1 month
var Activity = /** @class */ (function (_super) {
__extends(Activity, _super);
function Activity(startDate, endDate, type, creator, name) {
if (name === void 0) { name = ''; }
var _this = _super.call(this, startDate, endDate) || this;
_this.intensityZones = []; // maybe rename
_this.laps = [];
_this.streams = [];
_this.events = [];
if (!startDate || !endDate) {
throw new Error('Start and end dates are required');
}
if (endDate < startDate) {
throw new Error('Activity end date is before the start date and that is not acceptable');
}
if (+endDate - +startDate > exports.MAX_ACTIVITY_DURATION) {
throw new Error('Activity duration is over 1 month and that is not supported');
}
_this.type = type;
_this.creator = creator;
_this.name = name;
return _this;
}
Activity.prototype.createStream = function (type) {
return new stream_1.Stream(type, Array(activity_utilities_1.ActivityUtilities.getDataLength(this.startDate, this.endDate)).fill(null));
};
Activity.prototype.addDataToStream = function (type, date, value) {
this.getStreamData(type)[this.getDateIndex(date)] = value;
return this;
};
Activity.prototype.addStream = function (stream) {
if (this.streams.find(function (activityStream) { return activityStream.type === stream.type; })) {
throw new Error("Duplicate type of stream when adding " + stream.type + " to activity " + this.getID());
}
this.streams.push(stream);
return this;
};
Activity.prototype.clearStreams = function () {
this.streams = [];
return this;
};
Activity.prototype.removeStream = function (streamType) {
var stream = streamType instanceof stream_1.Stream ? streamType : this.getStream(streamType);
this.streams = this.streams.filter(function (activityStream) { return stream !== activityStream; });
return this;
};
Activity.prototype.addStreams = function (streams) {
var _a;
(_a = this.streams).push.apply(_a, streams);
return this;
};
Activity.prototype.getAllStreams = function () {
return this.streams;
};
// @todo needs more logic improvement and transparency
Activity.prototype.getAllExportableStreams = function () {
return this.getAllStreams().filter(function (stream) { return stream.isExportable(); });
};
Activity.prototype.hasStreamData = function (streamType, startDate, endDate) {
try {
this.getStreamData(streamType, startDate, endDate);
}
catch (e) {
return false;
}
return true;
};
Activity.prototype.hasPositionData = function (startDate, endDate) {
return (this.hasStreamData(data_latitude_degrees_1.DataLatitudeDegrees.type, startDate, endDate) &&
this.hasStreamData(data_longitude_degrees_1.DataLongitudeDegrees.type, startDate, endDate));
};
Activity.prototype.isTrainer = function () {
return Activity.TRAINER_TYPES.indexOf(this.type) !== -1;
};
Activity.prototype.hasPowerMeter = function () {
return this.hasStreamData(data_power_1.DataPower.type);
};
Activity.prototype.getStream = function (streamType) {
var find = this.streams.find(function (stream) { return stream.type === streamType; });
if (!find) {
throw Error("No stream found with type " + streamType);
}
return find;
};
Activity.prototype.getStreamData = function (streamType, startDate, endDate) {
var _this = this;
var stream = streamType instanceof stream_1.Stream ? streamType : this.getStream(streamType);
if (!startDate && !endDate) {
return stream.getData();
}
if (startDate && endDate) {
return stream
.getData()
.filter(function (value, index) { return new Date(_this.startDate.getTime() + index * 1000) <= endDate; })
.filter(function (value, index) { return new Date(_this.startDate.getTime() + index * 1000) >= startDate; });
}
if (startDate) {
return stream.getData().filter(function (value, index) { return new Date(_this.startDate.getTime() + index * 1000) > startDate; });
}
if (endDate) {
return stream.getData().filter(function (value, index) { return new Date(_this.startDate.getTime() + index * 1000) < endDate; });
}
return [];
};
// @todo see how this fits with the filtering on the stream class
/**
* Gets the data array of an activity stream excluding the non numeric ones
* @todo include strings and all data abstract types
* @param streamType
* @param startDate
* @param endDate
*/
Activity.prototype.getSquashedStreamData = function (streamType, startDate, endDate) {
return this.getStreamData(streamType, startDate, endDate).filter(function (data) { return helpers_1.isNumber(data); });
};
Activity.prototype.getPositionData = function (startDate, endDate) {
var latitudeStreamData = this.getStreamData(data_latitude_degrees_1.DataLatitudeDegrees.type, startDate, endDate);
var longitudeStreamData = this.getStreamData(data_longitude_degrees_1.DataLongitudeDegrees.type, startDate, endDate);
return latitudeStreamData.reduce(function (positionArray, value, index, array) {
var currentLatitude = latitudeStreamData[index];
var currentLongitude = longitudeStreamData[index];
if (!helpers_1.isNumber(currentLatitude) || !helpers_1.isNumber(currentLongitude)) {
positionArray.push(null);
return positionArray;
}
positionArray.push({
latitudeDegrees: currentLatitude,
longitudeDegrees: currentLongitude
});
return positionArray;
}, []);
};
Activity.prototype.getSquashedPositionData = function (startDate, endDate) {
return this.getPositionData(startDate, endDate).filter(function (data) { return data !== null; });
};
Activity.prototype.getStreamDataTypesBasedOnDataType = function (streamTypeToBaseOn, streamTypes) {
return activity_utilities_1.ActivityUtilities.getStreamDataTypesBasedOnDataType(this.getStream(streamTypeToBaseOn), this.getAllStreams()
.filter(function (stream) { return stream.type !== streamTypeToBaseOn; })
.filter(function (stream) { return streamTypes.indexOf(stream.type) !== -1; }));
};
Activity.prototype.getStreamDataTypesBasedOnTime = function (streamTypes) {
return activity_utilities_1.ActivityUtilities.getStreamDataTypesBasedOnTime(this.startDate, this.endDate, !streamTypes
? this.getAllStreams()
: this.getAllStreams().filter(function (stream) { return streamTypes.indexOf(stream.type) !== -1; }));
};
Activity.prototype.getStreamDataByTime = function (streamType, filterNull, filterInfinity) {
if (filterNull === void 0) { filterNull = false; }
if (filterInfinity === void 0) { filterInfinity = false; }
return this.getStream(streamType).getStreamDataByTime(this.startDate, filterNull, filterInfinity);
};
Activity.prototype.getStreamDataByDuration = function (streamType, filterNull, filterInfinity) {
if (filterNull === void 0) { filterNull = false; }
if (filterInfinity === void 0) { filterInfinity = false; }
return this.getStream(streamType).getStreamDataByDuration(0, filterNull, filterInfinity);
};
Activity.prototype.addLap = function (lap) {
this.laps.push(lap);
return this;
};
Activity.prototype.getLaps = function (activity) {
return this.laps;
};
Activity.prototype.getAllEvents = function () {
return this.events;
};
Activity.prototype.getStartEvents = function () {
return this.events.filter(function (event) { return event instanceof data_start_event_1.DataStartEvent; });
};
Activity.prototype.getStopEvents = function () {
return this.events.filter(function (event) { return event instanceof data_stop_event_1.DataStopEvent; });
};
Activity.prototype.getStopAllEvents = function () {
return this.events.filter(function (event) { return event instanceof data_stop_all_event_1.DataStopAllEvent; });
};
Activity.prototype.addEvent = function (event) {
this.events.push(event);
return this;
};
Activity.prototype.setAllEvents = function (events) {
this.events = events;
return this;
};
Activity.prototype.generateTimeStream = function (streamTypes) {
var _this = this;
if (streamTypes === void 0) { streamTypes = []; }
var timeStream = this.createStream(data_time_1.DataTime.type);
var streams = this.getAllStreams();
if (streamTypes.length) {
streams = streams.filter(function (stream) { return streamTypes.indexOf(stream.type) !== -1; });
}
streams.forEach(function (stream) {
_this.getStreamDataByDuration(stream.type, true, false).forEach(function (data) {
timeStream.getData()[data.time / 1000] = data.time / 1000;
});
});
return timeStream;
};
Activity.prototype.getDateIndex = function (date) {
// @todo ceil vs floor (still debatable)
return Math.round((+date - +this.startDate) / 1000);
};
Activity.prototype.toJSON = function () {
var intensityZones = [];
this.intensityZones.forEach(function (value) {
intensityZones.push(value.toJSON());
});
var stats = {};
this.stats.forEach(function (value, key) {
Object.assign(stats, value.toJSON());
});
return {
startDate: this.startDate.getTime(),
endDate: this.endDate.getTime(),
type: this.type,
creator: this.creator.toJSON(),
intensityZones: intensityZones,
stats: stats,
events: this.getAllEvents().reduce(function (eventsArray, event) {
eventsArray.push(event.toJSON());
return eventsArray;
}, []),
laps: this.getLaps().reduce(function (jsonLapsArray, lap) {
jsonLapsArray.push(lap.toJSON());
return jsonLapsArray;
}, [])
};
};
Activity.TRAINER_TYPES = [
activity_types_1.ActivityTypes.VirtualRun,
activity_types_1.ActivityTypes.VirtualCycling,
activity_types_1.ActivityTypes.Treadmill,
activity_types_1.ActivityTypes.IndoorCycling,
activity_types_1.ActivityTypes.IndoorRunning,
activity_types_1.ActivityTypes.IndoorRowing,
activity_types_1.ActivityTypes.Crosstrainer,
activity_types_1.ActivityTypes.EllipticalTrainer,
activity_types_1.ActivityTypes.FitnessEquipment,
activity_types_1.ActivityTypes.StairStepper
];
return Activity;
}(duration_class_abstract_1.DurationClassAbstract));
exports.Activity = Activity;