I don't know anything about running; I haven't gone on a run in 5+ years. However, when inspecting the Calculate
button from Runner's World, the site runs a function called runConversion()
. A quick Ctrl+F for that in the source gives us script:
<script language="JavaScript">
<!--
var metric;
var VO2max;
function initGlobals() {
metric = false;
VO2Max = -1;
}
function runConversion() {
var frm = document.forms.input1;
// race time in min, length in m and speed in m/min.
var time = document.forms.input1.hours.value * 60 + document.forms.input1.minutes.value * 1 + document.forms.input1.seconds.value / 60;
var rlength = document.forms.input1.length.value;
var speed;
if (time <= 0 || isNaN(time)) {
alert('Please input a valid time');
return;
}
if (rlength <= 0 || isNaN(rlength)) {
alert('Please input a valid race length.');
return;
}
if (frm.units.options[0].selected) {
rlength *= 1000;
} else {
rlength *= 1609;
}
speed = rlength / time;
VO2Max = velToVO2(speed) / timeToPercentVO2Max(time);
makeCalculations();
}
function makeCalculations() {
if (VO2Max <= 0) {
return;
}
var velEasy = VO2ToVel(VO2Max * .7);
var velTempo = VO2ToVel(VO2Max * .88);
var velMaximum = VO2ToVel(VO2Max);
var velSpeed = VO2ToVel(VO2Max * 1.1);
var velxlong = VO2ToVel(VO2Max * .6);
var velYasso = velMaximum * 1.95;
var toAppend;
if (metric) {
toAppend = ' min/km';
} else {
toAppend = ' min/mile';
}
var frm = document.forms.input1;
frm.easy.value = '' + timeConvert(velEasy) + toAppend;
frm.tempo.value = '' + timeConvert(velTempo) + toAppend;
frm.maximum.value = '' + timeConvert(velMaximum) + toAppend;
frm.speed.value = '' + timeConvert(velSpeed) + toAppend;
frm.xlong.value = '' + timeConvert(velEasy) + ' - ' + timeConvert(velxlong) + toAppend;
var oldMetric = metric;
metric = false;
frm.yasso.value = '' + timeConvert(velYasso) + ' min/800';
metric = oldMetric;
}
// Toggle output type of paces.
function toggleMetric() {
if (document.forms.input1.paceType.options[0].selected) {
metric = false;
} else {
metric = true;
}
makeCalculations();
}
// Takes a velocity and converts it to a VO2 level.
function velToVO2(vel) {
return (-4.60 + 0.182258 * vel + 0.000104 * vel * vel);
}
// Takes a VO2 measurement and converts it to a velocity.
function VO2ToVel(VO2) {
return (29.54 + 5.000663 * VO2 - 0.007546 * VO2 * VO2);
}
// Takes a time in minutes and uses EQ 2 to convert it to a percent of VO2 maximum.
function timeToPercentVO2Max(minutes) {
return (.8 + 0.1894393 * Math.exp(-.012778 * minutes) + 0.2989558 * Math.exp(-.1932695 * minutes));
}
// Takes a speed in metres / minute a converts it to a string representing a pace in
// minutes per mile or km.
function timeConvert(speed) {
var ans;
if (!metric) {
ans = (1 / speed) * 1609;
} else {
ans = (1 / speed) * 1000;
}
minutes = Math.floor(ans);
seconds = Math.floor((ans - minutes) * 60);
if (seconds > 9) {
return '' + minutes + ':' + seconds;
} else {
return '' + minutes + ':0' + seconds;
}
}
// -->
</script>
When dissecting this a bit, it looks like every estimate is your calculated V02Max multiplied by varying coefficients. This is then calculated back into a velocity to give you a pace. The calculator found at Helpful Runner gives the same results because it's the identical code pushed into a file.
The V02Max coefficients are:
- Easy = 70% * VO2Max
- Tempo = 88% * V02Max
- Maximum = 100% * VO2Max
- Speed = 110% * VO2Max
- xlong = 60% * VO2Max
- Yasso = Maximum Velocity * 1.95
I'm having a bit more trouble dissecting Omni Calculator but they calculate velocity_to_V02
using the exact same formula so I'd take a guesstimation that the rest is the same formulae just re-packaged:
from: training-pace.js
'use strict';
omni.onResult(['x'], function(ctx, x) {
ctx.hideVariables('base1', 'base2', 'percent_max',
'vo2max', 'vo2', 'easy_vo2','x','y','velocity', 'velocity_easy',
'velocity_vo2max','velocity_tempo', 'velocity_speed', 'velocity_long',
'speed_vo2','tempo_vo2', 'long_vo2' );
});
/*
omni.onInit(function(ctx) {
var countryCode = ctx.getCountryCode();
if (countryCode === 'US') {
ctx.setDefault('result_units_type', '1');
} else {
ctx.setDefault('result_units_type', '0');
}
});
omni.define('velocity_to_vo2', function(_velocity) {
var velocity = _velocity.toNumber();
return (-4.60 + 0.182258 * velocity + 0.000104 * velocity * velocity);
});
omni.define('time_convert', function(_trainingVelocity, _useImperial) {
var trainingVelocity = _trainingVelocity.toNumber();
var useImperial = _useImperial.toNumber();
var trainingPace;
if (useImperial) {
trainingPace = (1 / trainingVelocity) * 1609;
} else {
trainingPace = (1 / trainingVelocity) * 1000;
}
return trainingPace;
});
*/
Unfortunately, I can't find anywhere that specifies that these are the coefficients to be used. No one has really set in stone that an easy run should be 70% of your V02Max. I find a lot of websites that list ranges (i.e. 65-75%). My guess is that this code is simply being passed from one site to the next.