commit d3917d0ae528d5deeeaf188bce6ca90f8fe50c69
parent 76f513a5d4ee7351051f06209ec192c414d0c62e
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date: Thu, 5 Sep 2024 20:02:26 -0700
Update VO2 Max model constants
Diffstat:
6 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/src/utils/races.js b/src/utils/races.js
@@ -5,19 +5,18 @@
* @param {Function} method The function
* @param {Function} derivative The function derivative
* @param {Number} precision The acceptable precision
- * @param {Number} iterations The maximum number of iterations
* @returns {Number} The refined estimate
*/
-function NewtonsMethod(initialEstimate, target, method, derivative, precision, iterations = 500) {
+function NewtonsMethod(initialEstimate, target, method, derivative, precision) {
// Initialize estimate
let estimate = initialEstimate;
let estimateValue;
- for (let i = 0; i < iterations; i += 1) {
+ for (let i = 0; i < 500; i += 1) {
// Evaluate function at estimate
estimateValue = method(estimate);
- // Check if estimate is close enough
+ // Check if estimate is close enough (usually occurs way before i = 500)
if (Math.abs(target - estimateValue) < precision) {
break;
}
@@ -174,6 +173,7 @@ const PurdyPointsModel = {
/*
* Methods that implement the VO2 Max race prediction model
* http://run-down.com/statistics/calcs_explained.php
+ * https://vdoto2.com/Calculator
*/
const VO2MaxModel = {
/**
@@ -185,7 +185,7 @@ const VO2MaxModel = {
getVO2(d, t) {
const minutes = t / 60;
const v = d / minutes;
- const result = -4.6 + (0.182 * v) + (0.000104 * (v ** 2));
+ const result = -4.6 + (0.182258 * v) + (0.000104 * (v ** 2));
return result;
},
@@ -196,7 +196,7 @@ const VO2MaxModel = {
*/
getVO2Percentage(t) {
const minutes = t / 60;
- const result = 0.8 + (0.189 * Math.exp(-0.0128 * minutes)) + (0.299 * Math.exp(-0.193
+ const result = 0.8 + (0.189439 * Math.exp(-0.012778 * minutes)) + (0.298956 * Math.exp(-0.193261
* minutes));
return result;
},
@@ -237,7 +237,7 @@ const VO2MaxModel = {
*/
predictTime(d1, t1, d2) {
// Calculate input VO2 max
- const inputVO2 = VO2MaxModel.getVO2Max(d1, t1);
+ const inputVO2Max = VO2MaxModel.getVO2Max(d1, t1);
// Initialize estimate
let estimate = (t1 * d2) / d1;
@@ -245,7 +245,7 @@ const VO2MaxModel = {
// Refine estimate
const method = (x) => VO2MaxModel.getVO2Max(d2, x);
const derivative = (x) => VO2MaxModel.VO2MaxTimeDerivative(d2, x);
- estimate = NewtonsMethod(estimate, inputVO2, method, derivative, 0.0001);
+ estimate = NewtonsMethod(estimate, inputVO2Max, method, derivative, 0.0001);
// Return estimate
return estimate;
diff --git a/tests/e2e/batch-calculator.spec.js b/tests/e2e/batch-calculator.spec.js
@@ -36,7 +36,7 @@ test('Batch calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:41.21');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:16.91');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:16.90');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row')).toHaveCount(16);
@@ -107,7 +107,7 @@ test('Batch calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:14.60');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('2:43.61');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('2:43.62');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(17);
await expect(page.getByRole('row')).toHaveCount(16);
diff --git a/tests/e2e/cross-calculator.spec.js b/tests/e2e/cross-calculator.spec.js
@@ -149,10 +149,10 @@ test('Cross-calculator', async ({ page }) => {
await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m @ 5 km');
await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30');
- await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:41.93');
+ await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:41.92');
await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50');
- await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:16.98');
+ await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:16.97');
await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(5);
await expect(page.getByRole('row')).toHaveCount(16);
@@ -201,6 +201,6 @@ test('Cross-calculator', async ({ page }) => {
// Assert workout splits are correct (input race and prediction model not reset)
await expect(page.getByRole('row').nth(1)).toHaveText('400 m @ 1 mi' + '1:14.81');
- await expect(page.getByRole('row').nth(3)).toHaveText('1600 m @ 1:00:00' + '5:53.58');
+ await expect(page.getByRole('row').nth(3)).toHaveText('1600 m @ 1:00:00' + '5:53.56');
await expect(page.getByRole('row')).toHaveCount(5);
});
diff --git a/tests/e2e/race-calculator.spec.js b/tests/e2e/race-calculator.spec.js
@@ -25,7 +25,7 @@ test('Race Calculator', async ({ page }) => {
// Assert race predictions are correct
await expect(page.getByRole('row').nth(5)).toHaveText('1 mi' + '4:55.53' + '4:56 / mi');
- await expect(page.getByRole('row').nth(10)).toHaveText('5 km' + '16:47.58' + '5:24 / mi');
+ await expect(page.getByRole('row').nth(10)).toHaveText('5 km' + '16:47.57' + '5:24 / mi');
await expect(page.getByRole('row')).toHaveCount(17);
// Assert race statistics are correct
@@ -40,7 +40,7 @@ test('Race Calculator', async ({ page }) => {
// Assert race predictions are correct
await expect(page.getByRole('row').nth(5)).toHaveText('1 mi' + '4:55.53' + '3:04 / km');
- await expect(page.getByRole('row').nth(10)).toHaveText('5 km' + '16:47.58' + '3:22 / km');
+ await expect(page.getByRole('row').nth(10)).toHaveText('5 km' + '16:47.57' + '3:22 / km');
await expect(page.getByRole('row')).toHaveCount(17);
// Change prediction model
diff --git a/tests/e2e/workout-calculator.spec.js b/tests/e2e/workout-calculator.spec.js
@@ -24,7 +24,7 @@ test('Workout Calculator', async ({ page }) => {
// Assert workout splits are correct
await expect(page.getByRole('row').nth(1)).toHaveText('400 m @ 1 mi' + '1:13.45');
- await expect(page.getByRole('row').nth(3)).toHaveText('1600 m @ 1:00:00' + '5:45.44');
+ await expect(page.getByRole('row').nth(3)).toHaveText('1600 m @ 1:00:00' + '5:45.43');
await expect(page.getByRole('row')).toHaveCount(5);
// Change prediction model
diff --git a/tests/unit/views/RaceCalculator.spec.js b/tests/unit/views/RaceCalculator.spec.js
@@ -119,7 +119,7 @@ test('should correctly calculate race statistics', async () => {
// Assert race statistics are correct
expect(purdyPoints).to.equal('Purdy Points: 454.5');
- expect(vo2).to.equal('V̇O₂: 47.4 ml/kg/min (95.3% of max)')
+ expect(vo2).to.equal('V̇O₂: 47.5 ml/kg/min (95.3% of max)')
expect(vo2Max).to.equal('V̇O₂ Max: 49.8 ml/kg/min')
});