Skip to content

Instantly share code, notes, and snippets.

@jogo3000
Last active July 12, 2024 10:07
Show Gist options
  • Save jogo3000/901d74eb73b020e1a8f08009bbe3d3a7 to your computer and use it in GitHub Desktop.
Save jogo3000/901d74eb73b020e1a8f08009bbe3d3a7 to your computer and use it in GitHub Desktop.
Some formulas for finding equivalent performances based on a reference
;; Adaptations of equations found in Jack Daniels - Daniels' Running Formula in clojure
(import (java.lang Math))
(defn %VOmax
"Returns the percentage of VOmax a runner can sustain for the given duration"
[seconds]
(let [mins (/ seconds 60)]
(+ 0.8
(* 0.1894393
(Math/exp (* -0.012778 mins)))
(* 0.2989558
(Math/exp (* -0.1932605 mins))))))
(defn VO2
"Returns the oxygen consumption of a runner when running in a given speed"
[v]
(+ -4.60
(* 0.182258 v)
(* 0.000104 (Math/pow v 2))))
(defn m-min
"Gilbert's formulas use meters / minutes as units. Calculates the speed required to cover a distance in the given time
using these units"
[s t]
(/ s (/ t 60)))
(defn pace->velocity
"Pace is seconds / 1000 m so..."
[pace]
(int (/ 1000 (/ pace 60))))
(defn velocity->pace
"velocity is m / min so...
v = m / min and we want the pace per 1000 m
v = 1000 m / min -> min = 1000 m / v"
[velocity]
(int (* 60 (/ 1000 velocity))))
(defn VO2->velocity
"Calculates theoretical velocity when runner consumes given amount of oxygen"
[vo2]
(+ 29.54
(* 5.000663 vo2)
(* -0.007546 (Math/pow vo2 2))))
(defn VDot
"Calculates the pseudo VO2max, VDot based on a race distance and duration"
[race-distance race-duration]
(/ (VO2 (m-min race-distance race-duration))
(%VOmax race-duration)))
(defn equivalent
"Finds the theoretical best time for a race distance given vdot is known. Doesn't support efforts that take more than three hours."
[vdot race-distance]
(->> (range 1 (* 3 60 60))
(map (juxt identity #(VDot race-distance %)))
(drop-while (fn [[t v]] (< vdot v)))
(ffirst)))
(defn min-s [s]
((juxt quot rem) s 60))
(defn race-predictions
"Predicts performance in some common racing distances given an earlier race performance"
[race-distance race-duration]
(let [vdot (VDot race-distance race-duration)
common-race-distances [800 1500 3000 5000 10000 21095]]
(for [d common-race-distances]
[d (min-s (equivalent vdot d))])))
(defn effort [multiplier vdot]
(-> (* multiplier vdot)
(VO2->velocity)
(velocity->pace)
(min-s)))
(defn training-paces
"Prescribes suitable training paces given an earlier race performance"
[race-distance race-duration]
(let [vdot (VDot race-distance race-duration)
effort-levels [[:easy [0.60 0.75]]
[:threshold [0.80 0.85]]
[:maximal [0.90 0.95]]]]
(for [[level [low high]] effort-levels]
[level (mapv #(effort % vdot) [low high])])))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment