diff --git a/app/engine/MovingAverager.js b/app/engine/MovingAverager.js index 5ca1e8f..3020cb4 100644 --- a/app/engine/MovingAverager.js +++ b/app/engine/MovingAverager.js @@ -2,20 +2,20 @@ /* Open Rowing Monitor, https://github.com/laberning/openrowingmonitor - This keeps an array, which we can ask for an moving average + This Averager can calculate the moving average of a continuous flow of data points Please note: The array contains flankLength + 1 measured currentDt's, thus flankLength number of flanks between them - They are arranged that dataPoints[0] is the youngest, and dataPoints[flankLength] the youngest + They are arranged that dataPoints[0] is the youngest, and dataPoints[flankLength] the oldest */ function createMovingAverager (length, initValue) { let dataPoints reset() function pushValue (dataPoint) { - // add the new dataPoint to the array, we have to move datapoints starting at the oldst ones + // add the new dataPoint to the array, we have to move data points starting at the oldest ones let i = length - 1 while (i > 0) { - // older datapoints are moved toward the higher numbers + // older data points are moved towards the higher numbers dataPoints[i] = dataPoints[i - 1] i = i - 1 } @@ -31,7 +31,7 @@ function createMovingAverager (length, initValue) { let i = length - 1 let arrayTotal = 0.0 while (i >= 0) { - // summarise the value of the moving average + // summarize the value of the moving average arrayTotal = arrayTotal + dataPoints[i] i = i - 1 } diff --git a/app/engine/MovingFlankDetector.js b/app/engine/MovingFlankDetector.js index 72182fa..4564d3d 100644 --- a/app/engine/MovingFlankDetector.js +++ b/app/engine/MovingFlankDetector.js @@ -2,7 +2,7 @@ /* Open Rowing Monitor, https://github.com/laberning/openrowingmonitor - This keeps an array, which we can test for an upgoing or downgoing flank + A Detector used to test for up-going and down-going flanks Please note: The array contains flankLength + 1 measured currentDt's, thus flankLength number of flanks between them They are arranged that dataPoints[0] is the youngest, and dataPoints[flankLength] the oldest @@ -24,10 +24,10 @@ function createMovingFlankDetector (rowerSettings) { const movingAverage = createMovingAverager(rowerSettings.smoothing, rowerSettings.maximumTimeBetweenImpulses) function pushValue (dataPoint) { - // add the new dataPoint to the array, we have to move datapoints starting at the oldst ones + // add the new dataPoint to the array, we have to move data points starting at the oldest ones let i = rowerSettings.flankLength while (i > 0) { - // older datapoints are moved toward the higher numbers + // older data points are moved toward the higher numbers dirtyDataPoints[i] = dirtyDataPoints[i - 1] cleanDataPoints[i] = cleanDataPoints[i - 1] angularVelocity[i] = angularVelocity[i - 1] @@ -70,12 +70,14 @@ function createMovingFlankDetector (rowerSettings) { function isFlywheelUnpowered () { let numberOfErrors = 0 if (rowerSettings.naturalDeceleration < 0) { - // A valid natural deceleration of the flywheel has been provided, this has to be maintained for a flanklength to count as an indication for an unpowered flywheel - // Please note that angularAcceleration[] contains flank-information already, so we need to check from rowerSettings.flankLength -1 until 0 flanks + // A valid natural deceleration of the flywheel has been provided, this has to be maintained for a flank length + // to count as an indication for an unpowered flywheel + // Please note that angularAcceleration[] contains flank-information already, so we need to check from + // rowerSettings.flankLength -1 until 0 flanks let i = rowerSettings.flankLength - 1 while (i >= 0) { if (angularAcceleration[i] > rowerSettings.naturalDeceleration) { - // There seems to be some power present, so we detecten an error + // There seems to be some power present, so we detected an error numberOfErrors = numberOfErrors + 1 } i = i - 1 @@ -85,7 +87,8 @@ function createMovingFlankDetector (rowerSettings) { let i = rowerSettings.flankLength while (i > 0) { if (cleanDataPoints[i] >= cleanDataPoints[i - 1]) { - // Oldest interval (dataPoints[i]) is larger than the younger one (datapoint[i-1], as the distance is fixed, we are accelerating + // Oldest interval (dataPoints[i]) is larger than the younger one (datapoint[i-1], as the distance is + // fixed, we are accelerating numberOfErrors = numberOfErrors + 1 } i = i - 1 @@ -101,8 +104,10 @@ function createMovingFlankDetector (rowerSettings) { function isFlywheelPowered () { let numberOfErrors = 0 if (rowerSettings.naturalDeceleration < 0) { - // A valid natural deceleration of the flywheel has been provided, this has to be consistently be encountered for a flanklength to count as an indication of a powered flywheel - // Please note that angularAcceleration[] contains flank-information already, so we need to check from rowerSettings.flankLength -1 until 0 flanks + // A valid natural deceleration of the flywheel has been provided, this has to be consistently encountered + // for a flank length to count as an indication of a powered flywheel + // Please note that angularAcceleration[] contains flank-information already, so we need to check from + // rowerSettings.flankLength -1 until 0 flanks let i = rowerSettings.flankLength - 1 while (i >= 0) { if (angularAcceleration[i] < rowerSettings.naturalDeceleration) { @@ -116,7 +121,8 @@ function createMovingFlankDetector (rowerSettings) { let i = rowerSettings.flankLength while (i > 1) { if (cleanDataPoints[i] < cleanDataPoints[i - 1]) { - // Oldest interval (dataPoints[i]) is shorter than the younger one (datapoint[i-1], as the distance is fixed, we discovered a deceleration + // Oldest interval (dataPoints[i]) is shorter than the younger one (datapoint[i-1], as the distance is fixed, we + // discovered a deceleration numberOfErrors = numberOfErrors + 1 } i = i - 1 @@ -135,7 +141,7 @@ function createMovingFlankDetector (rowerSettings) { } function timeToBeginOfFlank () { - // You expect the curve to bend between dirtyDataPoints[rowerSettings.flankLength] and dirtyDataPoints[rowerSettings.flankLength+1], + // We expect the curve to bend between dirtyDataPoints[rowerSettings.flankLength] and dirtyDataPoints[rowerSettings.flankLength+1], // as acceleration FOLLOWS the start of the pulling the handle, we assume it must have started before that let i = rowerSettings.flankLength let total = 0.0 @@ -151,9 +157,10 @@ function createMovingFlankDetector (rowerSettings) { } function impulseLengthAtBeginFlank () { - // As this is fed into the speed calculation where small changes have big effects, and we typically use it when the curve is in a plateau, - // we return the cleaned data and not the dirty data - // Regardless of the way to determine the acceleration, cleanDataPoints[rowerSettings.flankLength] is always the impuls at the beginning of the flank being investigated + // As this is fed into the speed calculation where small changes have big effects, and we typically use it when + // the curve is in a plateau, we return the cleaned data and not the dirty data + // Regardless of the way to determine the acceleration, cleanDataPoints[rowerSettings.flankLength] is always the + // impulse at the beginning of the flank being investigated return cleanDataPoints[rowerSettings.flankLength] } diff --git a/app/engine/MovingIntervalAverager.js b/app/engine/MovingIntervalAverager.js index af1b52d..c306f63 100644 --- a/app/engine/MovingIntervalAverager.js +++ b/app/engine/MovingIntervalAverager.js @@ -2,7 +2,7 @@ /* Open Rowing Monitor, https://github.com/laberning/openrowingmonitor - This averager calculates the average forcast for a moving inteval of a continuous flow + This Averager calculates the average forecast for a moving interval of a continuous flow of data points for a certain (time) interval */ function createMovingIntervalAverager (movingDuration) { diff --git a/app/engine/RowingEngine.js b/app/engine/RowingEngine.js index 3e3f10f..ea8fe03 100644 --- a/app/engine/RowingEngine.js +++ b/app/engine/RowingEngine.js @@ -19,7 +19,6 @@ const log = loglevel.getLogger('RowingEngine') function createRowingEngine (rowerSettings) { let workoutHandler const flankDetector = createMovingFlankDetector(rowerSettings) - let movementAllowed = true let cyclePhase = 'Drive' let totalTime = 0.0 let totalNumberOfImpulses = 0.0 @@ -43,8 +42,8 @@ function createRowingEngine (rowerSettings) { let currentDragFactor = rowerSettings.dragFactor / 1000000 const movingDragAverage = createMovingAverager(5, currentDragFactor) let dragFactor = movingDragAverage.getMovingAverage() - const minimumCycleLenght = rowerSettings.minimumDriveTime + rowerSettings.minimumRecoveryTime - let cycleLenght = minimumCycleLenght + const minimumCycleLength = rowerSettings.minimumDriveTime + rowerSettings.minimumRecoveryTime + let cycleLength = minimumCycleLength let linearCycleVelocity = 0.0 let totalLinearDistance = 0.0 let averagedCyclePower = 0.0 @@ -54,12 +53,6 @@ function createRowingEngine (rowerSettings) { // called if the sensor detected an impulse, currentDt is an interval in seconds function handleRotationImpulse (currentDt) { - // First we check if the rower is allowed to move - if (movementAllowed !== true) { - // The rower isn't allowed to move - return - } - // impulses that take longer than maximumImpulseTimeBeforePause seconds are considered a pause if (currentDt > rowerSettings.maximumImpulseTimeBeforePause) { workoutHandler.handlePause(currentDt) @@ -69,18 +62,19 @@ function createRowingEngine (rowerSettings) { totalTime += currentDt totalNumberOfImpulses++ - // STEP 2: detect where we are in the rowing phase (drive or recovery) + // detect where we are in the rowing phase (drive or recovery) flankDetector.pushValue(currentDt) - // Here we implement the finite state machine that goes between "Drive" and "Recovery" phases, - // It will allow a phase-change provinding sufficient time has passed and there is a credible flank + // we implement a finite state machine that goes between "Drive" and "Recovery" phases, + // which allows a phase-change if sufficient time has passed and there is a plausible flank if (cyclePhase === 'Drive') { // We currently are in the "Drive" phase, lets determine what the next phase is if (flankDetector.isFlywheelUnpowered()) { - // The flankdetector detects that the flywheel has no power excerted on it + // The flank detector detects that the flywheel has no power exerted on it drivePhaseLength = (totalTime - flankDetector.timeToBeginOfFlank()) - drivePhaseStartTime if (drivePhaseLength >= rowerSettings.minimumDriveTime) { - // We change into the Revocevery phase since we have been long enough in the Drive phase, and we see a clear lack of power excerted on the flywheel + // We change into the "Recovery" phase since we have been long enough in the Drive phase, and we see a clear lack of power + // exerted on the flywheel startRecoveryPhase(currentDt) cyclePhase = 'Recovery' } else { @@ -95,32 +89,33 @@ function createRowingEngine (rowerSettings) { } else { // We currently are in the "Recovery" phase, lets determine what the next phase is if (flankDetector.isFlywheelPowered()) { - // The flankdetector consistently detects some force on the flywheel + // The flank detector consistently detects some force on the flywheel recoveryPhaseLength = (totalTime - flankDetector.timeToBeginOfFlank()) - recoveryPhaseStartTime if (recoveryPhaseLength >= rowerSettings.minimumRecoveryTime) { - // We change into the Drive phase if we have been long enough in the Recovery phase, and we see a conistent force being excerted on the flywheel + // We change into the "Drive" phase if we have been long enough in the "Recovery" phase, and we see a consistent force being + // exerted on the flywheel startDrivePhase(currentDt) cyclePhase = 'Drive' } else { - // We see a force, but the recovery phase has been too short, we stay in the recovery phase + // We see a force, but the "Recovery" phase has been too short, we stay in the "Recovery" phase log.debug(`Time: ${totalTime.toFixed(4)} sec, impuls ${totalNumberOfImpulses}: flank suggests power (${flankDetector.accelerationAtBeginOfFlank().toFixed(1)} rad/s2), but waiting for recoveryPhaseLength (${recoveryPhaseLength.toFixed(4)} sec) to exceed minimumRecoveryTime (${rowerSettings.minimumRecoveryTime} sec)`) updateRecoveryPhase(currentDt) } } else { - // No force on the flywheel, let's continue the drive phase + // No force on the flywheel, let's continue the "Drive" phase updateRecoveryPhase(currentDt) } } } function startDrivePhase (currentDt) { - // First, we conclude the recovery phase + // First, we conclude the "Recovery" phase log.debug('*** recovery phase completed') if (rowerSettings.minimumRecoveryTime <= recoveryPhaseLength && rowerSettings.minimumDriveTime <= drivePhaseLength) { - // We have a credible cycletime - cycleLenght = recoveryPhaseLength + drivePhaseLength + // We have a plausible cycle time + cycleLength = recoveryPhaseLength + drivePhaseLength } else { - log.debug(`Cyclelenght isn't credible: recoveryPhaseLength ${recoveryPhaseLength.toFixed(4)} sec, drivePhaseLength = ${drivePhaseLength.toFixed(4)} s, maximumImpulseTimeBeforePause ${rowerSettings.maximumImpulseTimeBeforePause} s`) + log.debug(`CycleLength isn't plausible: recoveryPhaseLength ${recoveryPhaseLength.toFixed(4)} sec, drivePhaseLength = ${drivePhaseLength.toFixed(4)} s, maximumImpulseTimeBeforePause ${rowerSettings.maximumImpulseTimeBeforePause} s`) } recoveryPhaseAngularDisplacement = (totalNumberOfImpulses - recoveryPhaseStartAngularDisplacement) * angularDisplacementPerImpulse @@ -132,12 +127,12 @@ function createRowingEngine (rowerSettings) { currentDragFactor = -1 * rowerSettings.flywheelInertia * ((1 / recoveryStartAngularVelocity) - (1 / recoveryEndAngularVelocity)) / recoveryPhaseLength if (rowerSettings.autoAdjustDragFactor) { if (currentDragFactor > (movingDragAverage.getMovingAverage() * 0.75) && currentDragFactor < (movingDragAverage.getMovingAverage() * 1.40)) { - // If the calculated dragfactor is close to that we expect + // If the calculated drag factor is close to what we expect movingDragAverage.pushValue(currentDragFactor) dragFactor = movingDragAverage.getMovingAverage() log.info(`*** Calculated drag factor: ${(currentDragFactor * 1000000).toFixed(2)}`) } else { - // The calculated drag factor is outside the credible ranges + // The calculated drag factor is outside the plausible range log.info(`Calculated drag factor: ${(currentDragFactor * 1000000).toFixed(2)}, which is too far off the currently used dragfactor of ${movingDragAverage.getMovingAverage() * 1000000}`) log.debug(`Time: ${totalTime.toFixed(4)} sec, impuls ${totalNumberOfImpulses}: recoveryStartAngularVelocity = ${recoveryStartAngularVelocity.toFixed(2)} rad/sec, recoveryEndAngularVelocity = ${recoveryEndAngularVelocity.toFixed(2)} rad/sec, recoveryPhaseLength = ${recoveryPhaseLength.toFixed(4)} sec`) } @@ -159,15 +154,15 @@ function createRowingEngine (rowerSettings) { currentAngularVelocity = angularDisplacementPerImpulse / currentDt currentTorque = rowerSettings.flywheelInertia * ((currentAngularVelocity - previousAngularVelocity) / currentDt) + dragFactor * Math.pow(currentAngularVelocity, 2) } - if (cycleLenght >= minimumCycleLenght) { - // There is no division by zero and the data data is credible - linearCycleVelocity = Math.pow((dragFactor / rowerSettings.magicConstant), 1.0 / 3.0) * ((recoveryPhaseAngularDisplacement + drivePhaseAngularDisplacement) / cycleLenght) - averagedCyclePower = dragFactor * Math.pow((recoveryPhaseAngularDisplacement + drivePhaseAngularDisplacement) / cycleLenght, 3.0) + if (cycleLength >= minimumCycleLength) { + // There is no division by zero and the data data is plausible + linearCycleVelocity = Math.pow((dragFactor / rowerSettings.magicConstant), 1.0 / 3.0) * ((recoveryPhaseAngularDisplacement + drivePhaseAngularDisplacement) / cycleLength) + averagedCyclePower = dragFactor * Math.pow((recoveryPhaseAngularDisplacement + drivePhaseAngularDisplacement) / cycleLength, 3.0) } else { - log.error(`Time: ${totalTime.toFixed(4)} sec, impuls ${totalNumberOfImpulses}: cycle length was not credible, cycleLenght = ${cycleLenght} sec`) + log.error(`Time: ${totalTime.toFixed(4)} sec, impuls ${totalNumberOfImpulses}: cycle length was not plausible, CycleLength = ${cycleLength} sec`) } - // Next, we start the Drive Phase + // Next, we start the "Drive" Phase log.debug(`*** DRIVE phase started at time: ${totalTime.toFixed(4)} sec, impuls number ${totalNumberOfImpulses}`) strokeNumber++ drivePhaseStartTime = totalTime - flankDetector.timeToBeginOfFlank() @@ -180,7 +175,7 @@ function createRowingEngine (rowerSettings) { timeSinceStart: totalTime, // currDragFactor : currentDragFactor, power: averagedCyclePower, - duration: cycleLenght, + duration: cycleLength, strokeDistance: driveLinearDistance + recoveryLinearDistance, durationDrivePhase: drivePhaseLength, speed: linearCycleVelocity, @@ -211,13 +206,13 @@ function createRowingEngine (rowerSettings) { } function startRecoveryPhase (currentDt) { - // First, we conclude the Drive Phase + // First, we conclude the "Drive" Phase log.debug('*** drive phase completed') if (rowerSettings.minimumRecoveryTime <= recoveryPhaseLength && rowerSettings.minimumDriveTime <= drivePhaseLength) { - // We have a credible cycletime - cycleLenght = recoveryPhaseLength + drivePhaseLength + // We have a plausible cycle time + cycleLength = recoveryPhaseLength + drivePhaseLength } else { - log.debug(`Cycleleght wasn't credible: recoveryPhaseLength ${recoveryPhaseLength.toFixed(4)} sec, drivePhaseLength = ${drivePhaseLength.toFixed(4)} s`) + log.debug(`CycleLength wasn't plausible: recoveryPhaseLength ${recoveryPhaseLength.toFixed(4)} sec, drivePhaseLength = ${drivePhaseLength.toFixed(4)} s`) } drivePhaseAngularDisplacement = ((totalNumberOfImpulses - flankDetector.noImpulsesToBeginFlank()) - drivePhaseStartAngularDisplacement) * angularDisplacementPerImpulse // driveEndAngularVelocity = angularDisplacementPerImpulse / flankDetector.impulseLengthAtBeginFlank() @@ -228,17 +223,17 @@ function createRowingEngine (rowerSettings) { currentAngularVelocity = angularDisplacementPerImpulse / currentDt currentTorque = rowerSettings.flywheelInertia * ((currentAngularVelocity - previousAngularVelocity) / currentDt) + dragFactor * Math.pow(currentAngularVelocity, 2) } - // We display the AVERAGE speed in the display, NOT the topspeed of the stroke - if (drivePhaseLength > rowerSettings.minimumDriveTime && cycleLenght > minimumCycleLenght) { - // let's prevent division's by zero and make sure data is credible - linearCycleVelocity = Math.pow((dragFactor / rowerSettings.magicConstant), 1.0 / 3.0) * ((drivePhaseAngularDisplacement + recoveryPhaseAngularDisplacement) / cycleLenght) + // We display the AVERAGE speed in the display, NOT the top speed of the stroke + if (drivePhaseLength > rowerSettings.minimumDriveTime && cycleLength > minimumCycleLength) { + // let's prevent division's by zero and make sure data is plausible + linearCycleVelocity = Math.pow((dragFactor / rowerSettings.magicConstant), 1.0 / 3.0) * ((drivePhaseAngularDisplacement + recoveryPhaseAngularDisplacement) / cycleLength) // drivePhaseEnergyProduced = rowerSettings.flywheelInertia * ((driveEndAngularVelocity - driveStartAngularVelocity) / drivePhaseLength) * drivePhaseAngularDisplacement + dragFactor * Math.pow(driveEndAngularVelocity, 2) * drivePh$ - averagedCyclePower = dragFactor * Math.pow((recoveryPhaseAngularDisplacement + drivePhaseAngularDisplacement) / cycleLenght, 3.0) + averagedCyclePower = dragFactor * Math.pow((recoveryPhaseAngularDisplacement + drivePhaseAngularDisplacement) / cycleLength, 3.0) } else { - log.error(`Time: ${totalTime.toFixed(4)} sec, impuls ${totalNumberOfImpulses}: cycle length was not credible, drivePhaseLength = ${drivePhaseLength.toFixed(4)} sec, cycleLenght = ${cycleLenght.toFixed(4)} sec`) + log.error(`Time: ${totalTime.toFixed(4)} sec, impuls ${totalNumberOfImpulses}: cycle length was not plausible, drivePhaseLength = ${drivePhaseLength.toFixed(4)} sec, cycleLength = ${cycleLength.toFixed(4)} sec`) } - // Next, we start the Recovery Phase + // Next, we start the "Recovery" Phase log.debug(`*** RECOVERY phase started at time: ${totalTime.toFixed(4)} sec, impuls number ${totalNumberOfImpulses}`) recoveryPhaseStartTime = totalTime - flankDetector.timeToBeginOfFlank() recoveryPhaseStartAngularDisplacement = totalNumberOfImpulses - flankDetector.noImpulsesToBeginFlank() @@ -253,7 +248,7 @@ function createRowingEngine (rowerSettings) { workoutHandler.handleStrokeEnd({ timeSinceStart: totalTime, power: averagedCyclePower, - duration: cycleLenght, + duration: cycleLength, strokeDistance: driveLinearDistance + recoveryLinearDistance, durationDrivePhase: drivePhaseLength, speed: linearCycleVelocity, @@ -282,14 +277,6 @@ function createRowingEngine (rowerSettings) { } } - function allowMovement () { - movementAllowed = true - } - - function stopMoving () { - movementAllowed = false - } - function reset () { cyclePhase = 'Drive' totalTime = 0.0 @@ -313,7 +300,7 @@ function createRowingEngine (rowerSettings) { currentDragFactor = rowerSettings.dragFactor / 1000000 movingDragAverage.reset() dragFactor = movingDragAverage.getMovingAverage() - cycleLenght = 0.0 + cycleLength = 0.0 linearCycleVelocity = 0.0 totalLinearDistance = 0.0 averagedCyclePower = 0.0 @@ -325,8 +312,6 @@ function createRowingEngine (rowerSettings) { return { handleRotationImpulse, - allowMovement, - stopMoving, reset, notify } diff --git a/app/engine/RowingStatistics.js b/app/engine/RowingStatistics.js index de5d3e7..92bceee 100644 --- a/app/engine/RowingStatistics.js +++ b/app/engine/RowingStatistics.js @@ -53,7 +53,7 @@ function createRowingStatistics (config) { function handleStrokeEnd (stroke) { if (!trainingRunning) startTraining() - // if we do not get a stroke for timeBetweenStrokesBeforePause miliseconds we treat this as a rowing pause + // if we do not get a stroke for timeBetweenStrokesBeforePause milliseconds we treat this as a rowing pause if (rowingPausedTimer)clearInterval(rowingPausedTimer) rowingPausedTimer = setTimeout(() => pauseRowing(), timeBetweenStrokesBeforePause) @@ -63,7 +63,7 @@ function createRowingStatistics (config) { powerAverager.pushValue(stroke.power) speedAverager.pushValue(stroke.speed) if (stroke.duration < timeBetweenStrokesBeforePause && stroke.duration > minimumStrokeTime) { - // stroke duration has to be credible to be accepted + // stroke duration has to be plausible to be accepted powerRatioAverager.pushValue(stroke.durationDrivePhase / stroke.duration) strokeAverager.pushValue(stroke.duration) caloriesAveragerMinute.pushValue(calories, stroke.duration) @@ -92,13 +92,13 @@ function createRowingStatistics (config) { // initiated when the stroke state changes function handleRecoveryEnd (stroke) { - // todo: wee need a better mechanism to communicate strokeState updates + // todo: we need a better mechanism to communicate strokeState updates // this is an initial hacky attempt to see if we can use it for the C2-pm5 protocol durationTotal = stroke.timeSinceStart powerAverager.pushValue(stroke.power) speedAverager.pushValue(stroke.speed) if (stroke.duration < timeBetweenStrokesBeforePause && stroke.duration > minimumStrokeTime) { - // stroke duration has to be credible to be accepted + // stroke duration has to be plausible to be accepted powerRatioAverager.pushValue(stroke.durationDrivePhase / stroke.duration) strokeAverager.pushValue(stroke.duration) } else { @@ -120,9 +120,9 @@ function createRowingStatistics (config) { instantaneousTorque = stroke.instantaneousTorque } - // initiated when new heart rate value is received from heart rate sensor + // initiated when a new heart rate value is received from heart rate sensor function handleHeartrateMeasurement (value) { - // set the heart rate to zero, if we did not receive a value for some time + // set the heart rate to zero if we did not receive a value for some time if (heartrateResetTimer)clearInterval(heartrateResetTimer) heartrateResetTimer = setTimeout(() => { heartrate = 0 @@ -194,7 +194,7 @@ function createRowingStatistics (config) { emitter.emit('rowingPaused') } - // converts a timeStamp in seconds to a human readable hh:mm:ss format + // converts a timestamp in seconds to a human readable hh:mm:ss format function secondsToTimeString (secondsTimeStamp) { if (secondsTimeStamp === Infinity) return '∞' const hours = Math.floor(secondsTimeStamp / 60 / 60) diff --git a/app/engine/WeightedAverager.js b/app/engine/WeightedAverager.js index ee6b8ee..32da5d0 100644 --- a/app/engine/WeightedAverager.js +++ b/app/engine/WeightedAverager.js @@ -2,7 +2,7 @@ /* Open Rowing Monitor, https://github.com/laberning/openrowingmonitor - The Averager calculates the weighted average of a continuous flow of data points + This Averager can calculate the weighted average of a continuous flow of data points */ function createWeightedAverager (maxNumOfDataPoints) { let dataPoints = [] diff --git a/config/rowerProfiles.js b/config/rowerProfiles.js index 2a35f0e..72ab5dc 100644 --- a/config/rowerProfiles.js +++ b/config/rowerProfiles.js @@ -73,7 +73,7 @@ export default { // A constant that is commonly used to convert flywheel revolutions to a rowed distance // see here: http://eodg.atm.ox.ac.uk/user/dudhia/rowing/physics/ergometer.html#section9 // Concept2 seems to use 2.8, which they admit is an arbitrary number which came close - // to their expectations. So for your rower, you have to find a credible distance for your effort. + // to their expectations. So for your rower, you have to find a plausible distance for your effort. // Also note that the rowed distance also depends on flywheelInertia, so please calibrate that before changing this constant. // PLEASE NOTE: Increasing this number decreases your rowed meters magicConstant: 2.8