UNPKG

@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

199 lines (198 loc) 6.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.standardDeviation = exports.medianFilter = exports.meanWindowSmoothing = exports.mean = void 0; exports.isNumberOrString = isNumberOrString; exports.isNumber = isNumber; exports.convertSpeedToPace = convertSpeedToPace; exports.convertSpeedToSwimPace = convertSpeedToSwimPace; exports.convertSwimPaceToSpeed = convertSwimPaceToSpeed; exports.convertSpeedToSpeedInKilometersPerHour = convertSpeedToSpeedInKilometersPerHour; exports.convertSpeedToSpeedInMilesPerHour = convertSpeedToSpeedInMilesPerHour; exports.convertSpeedToSpeedInFeetPerSecond = convertSpeedToSpeedInFeetPerSecond; exports.convertSpeedToSpeedInMetersPerMinute = convertSpeedToSpeedInMetersPerMinute; exports.convertSpeedToSpeedInFeetPerMinute = convertSpeedToSpeedInFeetPerMinute; exports.convertSpeedToSpeedInFeetPerHour = convertSpeedToSpeedInFeetPerHour; exports.convertSpeedToSpeedInMetersPerHour = convertSpeedToSpeedInMetersPerHour; exports.convertSpeedToSpeedInKnots = convertSpeedToSpeedInKnots; exports.convertPaceToPaceInMinutesPerMile = convertPaceToPaceInMinutesPerMile; exports.convertMetersToMiles = convertMetersToMiles; exports.convertMetersToFeet = convertMetersToFeet; exports.convertSwimPaceToSwimPacePer100Yard = convertSwimPaceToSwimPacePer100Yard; exports.getSize = getSize; exports.getSizeFormated = getSizeFormated; exports.fillMissingValuesLinear = fillMissingValuesLinear; function isNumberOrString(property) { return typeof property === 'number' || typeof property === 'string'; } function isNumber(property) { return typeof property === 'number' && !isNaN(property); } /** * Converts speed from m/s to pace as of seconds per km * @param {number} number * @return {number} */ function convertSpeedToPace(number) { return number === 0 ? Infinity : 1000 / number; } /** * Converts m/s to seconds per 100m * @param number */ function convertSpeedToSwimPace(number) { return number === 0 ? Infinity : 100 / number; } /** * Converts swim pace from seconds per 100m to m/s * @param number */ function convertSwimPaceToSpeed(number) { return number === 0 ? Infinity : 100 / number; } function convertSpeedToSpeedInKilometersPerHour(number) { return number * 3.6; } function convertSpeedToSpeedInMilesPerHour(number) { return number * 2.237; } function convertSpeedToSpeedInFeetPerSecond(number) { return number * 3.28084; } function convertSpeedToSpeedInMetersPerMinute(number) { return number * 60; } function convertSpeedToSpeedInFeetPerMinute(number) { return number * 196.85; } function convertSpeedToSpeedInFeetPerHour(number) { return number * 11811.024; } function convertSpeedToSpeedInMetersPerHour(number) { return number * 3600; } function convertSpeedToSpeedInKnots(number) { return number * 1.943844; } function convertPaceToPaceInMinutesPerMile(number) { return number * 1.60934; } function convertMetersToMiles(number) { return number === 0 ? 0 : number / 1609; } function convertMetersToFeet(number) { return number * 3.28084; } /** * Converts swim pace from seconds per 100m to seconds per 100yd. * @param number */ function convertSwimPaceToSwimPacePer100Yard(number) { return number * 0.9144; } function getSize(obj) { return getSizeWithOptionalFormat(obj, false); } function getSizeFormated(obj) { return getSizeWithOptionalFormat(obj, true); } function getSizeWithOptionalFormat(obj, format = true) { let size; try { size = new Blob([obj]).size; } catch (_a) { size = Buffer.from(obj).length; } function formatByteSize(bytes) { if (bytes < 1024) { return bytes + ' bytes'; } else if (bytes < 1048576) { return (bytes / 1024).toFixed(4) + ' KiB'; } else if (bytes < 1073741824) { return (bytes / 1048576).toFixed(4) + ' MiB'; } else { return (bytes / 1073741824).toFixed(4) + ' GiB'; } } return format ? formatByteSize(size) : size; } /** * from https://stackoverflow.com/questions/48340403/fill-missing-numeric-values-in-an-array * Very badly written * @param array */ function fillMissingValuesLinear(array) { let i = 0, j, delta; while (i < array.length) { if (array[i] !== null) { i++; continue; } j = i; while (array[++j] === null) { } // @ts-ignore delta = (array[j] - array[i - 1]) / (j - i + 1); do { // @ts-ignore array[i] = delta + array[i - 1]; i++; } while (i < j); } return array; } const mean = (array) => { return array.reduce((a, b) => a + b, 0) / array.length; }; exports.mean = mean; const meanWindowSmoothing = (array, windowSize = 7, roundDecimals = 3) => { const roundDecimalsFactor = Math.pow(10, roundDecimals); return array.map((value, index) => { const window = array.slice(index, index + windowSize); // Get window return Math.round((0, exports.mean)(window) * roundDecimalsFactor) / roundDecimalsFactor; // Round and return }); }; exports.meanWindowSmoothing = meanWindowSmoothing; const median = (inputArray) => { const s = inputArray.slice().sort((a, b) => { return a - b; }); return s[Math.floor((s.length - 1) / 2)]; }; /** * Remove spikes into a vector (http://fourier.eng.hmc.edu/e161/lectures/smooth_sharpen/node2.html) * @param array to be filtered * @param window Window size (should be odd number) */ const medianFilter = (array, window = 11) => { if (window % 2 === 0) { throw new Error('Window size should be an odd number'); } if (array.length < window) { return array; } const f = []; const w = []; let i; w.push(array[0]); for (i = 0; i < array.length; i++) { const midWindowIndex = Math.floor(window / 2); if (array.length - 1 >= i + midWindowIndex) { w.push(array[i + midWindowIndex]); } f.push(median(w)); if (i >= midWindowIndex) { w.shift(); } } return f; }; exports.medianFilter = medianFilter; const standardDeviation = (stream) => { const avg = (0, exports.mean)(stream); const variance = (0, exports.mean)(stream.map(value => Math.pow(value, 2))) - Math.pow(avg, 2); return variance > 0 ? Math.sqrt(variance) : 0; }; exports.standardDeviation = standardDeviation;