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

383 lines (382 loc) 16.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FITSampleMapper = void 0; const data_latitude_degrees_1 = require("../../../../data/data.latitude-degrees"); const data_altitude_1 = require("../../../../data/data.altitude"); const data_heart_rate_1 = require("../../../../data/data.heart-rate"); const data_cadence_1 = require("../../../../data/data.cadence"); const data_temperature_1 = require("../../../../data/data.temperature"); const data_distance_1 = require("../../../../data/data.distance"); const data_speed_1 = require("../../../../data/data.speed"); const data_vertical_speed_1 = require("../../../../data/data.vertical-speed"); const data_power_1 = require("../../../../data/data.power"); const data_longitude_degrees_1 = require("../../../../data/data.longitude-degrees"); const data_form_power_1 = require("../../../../data/data.form-power"); const data_leg_stiffness_1 = require("../../../../data/data.leg-stiffness"); const data_vertical_oscillation_1 = require("../../../../data/data.vertical-oscillation"); const helpers_1 = require("../../../utilities/helpers"); const data_accumulated_power_1 = require("../../../../data/data.accumulated-power"); const data_stryd_altitude_1 = require("../../../../data/data.stryd-altitude"); const data_stryd_distance_1 = require("../../../../data/data.stryd-distance"); const data_stryd_speed_1 = require("../../../../data/data.stryd-speed"); const data_power_balance_left_1 = require("../../../../data/data.power-balance-left"); const data_power_balance_right_1 = require("../../../../data/data.power-balance-right"); const data_ground_contact_time_1 = require("../../../../data/data.ground-contact-time"); const data_ground_contact_time_balance_left_1 = require("../../../../data/data-ground-contact-time-balance-left"); const data_ground_contact_time_balance_right_1 = require("../../../../data/data-ground-contact-time-balance-right"); const data_stance_time_1 = require("../../../../data/data.stance-time"); const data_stance_time_balance_left_1 = require("../../../../data/data-stance-time-balance-left"); const data_step_length_1 = require("../../../../data/data.step-length"); const data_effort_pace_1 = require("../../../../data/data.effort-pace"); const data_vertical_ratio_1 = require("../../../../data/data.vertical-ratio"); const data_ground_time_1 = require("../../../../data/data.ground-time"); const data_air_power_1 = require("../../../../data/data.air-power"); const data_grit_1 = require("../../../../data/data.grit"); const data_flow_1 = require("../../../../data/data.flow"); const data_stamina_1 = require("../../../../data/data.stamina"); const data_running_dynamics_balance_1 = require("../../../../data/data.running-dynamics-balance"); const data_left_torque_effectiveness_1 = require("../../../../data/data.left-torque-effectiveness"); const data_right_torque_effectiveness_1 = require("../../../../data/data.right-torque-effectiveness"); const data_left_pedal_smoothness_1 = require("../../../../data/data.left-pedal-smoothness"); const data_right_pedal_smoothness_1 = require("../../../../data/data.right-pedal-smoothness"); const constants_1 = require("../../../../constants/constants"); const getPositiveBalanceValue = (sample, fieldName) => { const value = sample[fieldName]; return (0, helpers_1.isNumber)(value) && value > 0 ? value : null; }; const getPositiveBalanceComplementValue = (sample, fieldName) => { const value = getPositiveBalanceValue(sample, fieldName); return value === null ? null : 100 - value; }; exports.FITSampleMapper = [ { dataType: data_latitude_degrees_1.DataLatitudeDegrees.type, getSampleValue: (sample) => { return (0, helpers_1.isNumber)(sample.position_lat) ? Math.round(sample.position_lat * Math.pow(10, constants_1.GNSS_DEGREES_PRECISION_NUMBER_OF_DECIMAL_PLACES)) / Math.pow(10, constants_1.GNSS_DEGREES_PRECISION_NUMBER_OF_DECIMAL_PLACES) : sample.position_lat; } }, { dataType: data_longitude_degrees_1.DataLongitudeDegrees.type, getSampleValue: (sample) => { return (0, helpers_1.isNumber)(sample.position_long) ? Math.round(sample.position_long * Math.pow(10, constants_1.GNSS_DEGREES_PRECISION_NUMBER_OF_DECIMAL_PLACES)) / Math.pow(10, constants_1.GNSS_DEGREES_PRECISION_NUMBER_OF_DECIMAL_PLACES) : sample.position_long; } }, { dataType: data_distance_1.DataDistance.type, getSampleValue: (sample) => { // TODO(sports-lib): fix duplicate distance-family outputs at the source by reading FIT field units/metadata // instead of blindly preferring `distance`/`Distance`. Some vendor exports can mix differently-scaled fields. return (0, helpers_1.isNumber)(sample.distance) ? sample.distance : sample.Distance; } }, { dataType: data_heart_rate_1.DataHeartRate.type, getSampleValue: (sample) => { return sample.heart_rate; } }, { dataType: data_altitude_1.DataAltitude.type, getSampleValue: (sample) => { const altitude = (0, helpers_1.isNumber)(sample.enhanced_altitude) ? sample.enhanced_altitude : (0, helpers_1.isNumber)(sample.EnhancedAltitude) ? sample.EnhancedAltitude : (0, helpers_1.isNumber)(sample.altitude) ? sample.altitude : (0, helpers_1.isNumber)(sample.Altitude) ? sample.Altitude : null; return (0, helpers_1.isNumber)(altitude) ? Math.round(altitude * Math.pow(10, constants_1.ALTITUDE_PRECISION_NUMBER_OF_DECIMAL_PLACES)) / Math.pow(10, constants_1.ALTITUDE_PRECISION_NUMBER_OF_DECIMAL_PLACES) : altitude; } }, { dataType: data_stryd_altitude_1.DataStrydAltitude.type, getSampleValue: (sample) => { return (0, helpers_1.isNumber)(sample.Elevation) ? Math.round(sample.Elevation * Math.pow(10, constants_1.ALTITUDE_PRECISION_NUMBER_OF_DECIMAL_PLACES)) / Math.pow(10, constants_1.ALTITUDE_PRECISION_NUMBER_OF_DECIMAL_PLACES) : sample.Elevation; } }, { dataType: data_stryd_distance_1.DataStrydDistance.type, getSampleValue: (sample) => { return sample.Distance; } }, { dataType: data_stryd_speed_1.DataStrydSpeed.type, getSampleValue: (sample) => { return sample.Speed; } }, { dataType: data_cadence_1.DataCadence.type, getSampleValue: (sample) => { let cadenceValue = sample.cadence; if ((0, helpers_1.isNumber)(sample.fractional_cadence)) { cadenceValue += sample.fractional_cadence; } return cadenceValue; } }, { dataType: data_speed_1.DataSpeed.type, getSampleValue: (sample) => { // TODO(sports-lib): fix duplicate speed-family outputs at the source by normalizing vendor-specific speed keys // (`enhanced_speed`, `speed`, `Speed`) with explicit unit handling. This should guarantee one canonical base stream. if ((0, helpers_1.isNumber)(sample.enhanced_speed)) { return sample.enhanced_speed; } if ((0, helpers_1.isNumber)(sample.EnhancedSpeed)) { return sample.EnhancedSpeed; } if ((0, helpers_1.isNumber)(sample.speed)) { return sample.speed; } if ((0, helpers_1.isNumber)(sample.Speed)) { return sample.Speed; } return null; } }, { dataType: data_vertical_speed_1.DataVerticalSpeed.type, getSampleValue: (sample) => { return sample.vertical_speed; } }, { dataType: data_power_1.DataPower.type, getSampleValue: (sample, sampleInfo) => { // Ensure power stream compliance when in some cases power sample field could be missing even if others samples have it // Just set watts to 0 when this happen // Case example: ride file "7432332116.fit" from integration tests const watts = (0, helpers_1.isNumber)(sample.power) ? sample.power : (0, helpers_1.isNumber)(sample.Power) ? sample.Power : sample.RP_Power; return (sampleInfo === null || sampleInfo === void 0 ? void 0 : sampleInfo.hasPowerMeter) ? watts || 0 : null; } }, { dataType: data_accumulated_power_1.DataAccumulatedPower.type, getSampleValue: (sample) => { return sample.accumulated_power; } }, { dataType: data_temperature_1.DataTemperature.type, getSampleValue: (sample) => { return sample.temperature; } }, { dataType: data_form_power_1.DataFormPower.type, getSampleValue: (sample) => { return sample['Form Power']; } }, { dataType: data_air_power_1.DataAirPower.type, getSampleValue: (sample) => { return sample['Air Power']; } }, { dataType: data_ground_time_1.DataGroundTime.type, getSampleValue: (sample) => { return sample['Ground Time']; } }, { dataType: data_leg_stiffness_1.DataLegStiffness.type, getSampleValue: (sample) => { return sample['Leg Spring Stiffness']; } }, { dataType: data_vertical_oscillation_1.DataVerticalOscillation.type, getSampleValue: (sample) => { return sample.vertical_oscillation; } }, { dataType: data_power_balance_right_1.DataPowerBalanceRight.type, getSampleValue: (sample) => { if (!sample.left_right_balance) { return null; } return sample.left_right_balance.right === true ? sample.left_right_balance.value : 100 - sample.left_right_balance.value; } }, // @todo if conservation of data is needed this can be taken of and generated on the fly { dataType: data_power_balance_left_1.DataPowerBalanceLeft.type, getSampleValue: (sample) => { if (!sample.left_right_balance) { return null; } return sample.left_right_balance.right === false ? sample.left_right_balance.value : 100 - sample.left_right_balance.value; } }, { dataType: data_ground_contact_time_1.DataGroundContactTime.type, getSampleValue: (sample) => { return (0, helpers_1.isNumber)(sample.stance_time) ? sample.stance_time : (0, helpers_1.isNumber)(sample['Ground Time']) ? sample['Ground Time'] : null; } }, // Keep DataStanceTime for backward compatibility { dataType: data_stance_time_1.DataStanceTime.type, getSampleValue: (sample) => { return (0, helpers_1.isNumber)(sample.stance_time) ? sample.stance_time : (0, helpers_1.isNumber)(sample['Ground Time']) ? sample['Ground Time'] : null; } }, { dataType: data_ground_contact_time_balance_left_1.DataGroundContactTimeBalanceLeft.type, getSampleValue: (sample) => { // The FIT stance_time_balance field refers to the balance on the left leg. return getPositiveBalanceValue(sample, 'stance_time_balance'); } }, { dataType: data_ground_contact_time_balance_right_1.DataGroundContactTimeBalanceRight.type, getSampleValue: (sample) => { return getPositiveBalanceComplementValue(sample, 'stance_time_balance'); } }, { dataType: data_running_dynamics_balance_1.DataVerticalOscillationBalanceLeft.type, getSampleValue: (sample) => { return getPositiveBalanceValue(sample, 'Vertical Oscillation Balance'); } }, { dataType: data_running_dynamics_balance_1.DataVerticalOscillationBalanceRight.type, getSampleValue: (sample) => { return getPositiveBalanceComplementValue(sample, 'Vertical Oscillation Balance'); } }, { dataType: data_running_dynamics_balance_1.DataLegSpringStiffnessBalanceLeft.type, getSampleValue: (sample) => { return getPositiveBalanceValue(sample, 'Leg Spring Stiffness Balance'); } }, { dataType: data_running_dynamics_balance_1.DataLegSpringStiffnessBalanceRight.type, getSampleValue: (sample) => { return getPositiveBalanceComplementValue(sample, 'Leg Spring Stiffness Balance'); } }, { dataType: data_running_dynamics_balance_1.DataImpactLoadingRateBalanceLeft.type, getSampleValue: (sample) => { return getPositiveBalanceValue(sample, 'Impact Loading Rate Balance'); } }, { dataType: data_running_dynamics_balance_1.DataImpactLoadingRateBalanceRight.type, getSampleValue: (sample) => { return getPositiveBalanceComplementValue(sample, 'Impact Loading Rate Balance'); } }, // Keep DataStanceTimeBalanceLeft for backward compatibility { dataType: data_stance_time_balance_left_1.DataStanceTimeBalanceLeft.type, getSampleValue: (sample) => { // The FIT stance_time_balance field refers to the balance on the left leg. return getPositiveBalanceValue(sample, 'stance_time_balance'); } }, { dataType: data_step_length_1.DataStepLength.type, getSampleValue: (sample) => { return sample.step_length / 1000; } }, { dataType: data_effort_pace_1.DataEffortPace.type, getSampleValue: (sample) => { if (!(0, helpers_1.isNumber)(sample['Effort Pace']) || sample['Effort Pace'] <= 0) { return null; } const effortPace = (0, helpers_1.convertSpeedToPace)(sample['Effort Pace']); return Number.isFinite(effortPace) ? effortPace : null; } }, { dataType: data_vertical_ratio_1.DataVerticalRatio.type, getSampleValue: (sample) => { return sample.vertical_ratio; } }, { dataType: data_stamina_1.DataStamina.type, getSampleValue: (sample) => { return (0, helpers_1.isNumber)(sample.stamina) ? sample.stamina : null; } }, { dataType: data_stamina_1.DataPotentialStamina.type, getSampleValue: (sample) => { return (0, helpers_1.isNumber)(sample.potential_stamina) ? sample.potential_stamina : null; } }, { dataType: data_grit_1.DataGrit.type, getSampleValue: (sample) => { return sample.grit; } }, { dataType: data_flow_1.DataFlow.type, getSampleValue: (sample) => { return sample.flow; } }, { dataType: data_left_torque_effectiveness_1.DataLeftTorqueEffectiveness.type, getSampleValue: (sample) => { return sample.left_torque_effectiveness; } }, { dataType: data_right_torque_effectiveness_1.DataRightTorqueEffectiveness.type, getSampleValue: (sample) => { return sample.right_torque_effectiveness; } }, { dataType: data_left_pedal_smoothness_1.DataLeftPedalSmoothness.type, getSampleValue: (sample) => { return sample.left_pedal_smoothness; } }, { dataType: data_right_pedal_smoothness_1.DataRightPedalSmoothness.type, getSampleValue: (sample) => { return sample.right_pedal_smoothness; } } ];