Skip to content

Instantly share code, notes, and snippets.

@daveliepmann
Last active April 2, 2018 18:41
Show Gist options
  • Save daveliepmann/c7c640091a9fe157befd68891c76176a to your computer and use it in GitHub Desktop.
Save daveliepmann/c7c640091a9fe157befd68891c76176a to your computer and use it in GitHub Desktop.
;; # One-Rep-Maximum Calculator
;; People who strength train often want to predict the maximum weight they could lift for one repetition. This is because actually making a maximal attempt is tiring, slightly risky, and difficult to repeat. Let's see how to guess our "1RM" using sub-maximal attempts.
;; If you need to re-evaluate one of the code blocks below, put your cursor in it and press `Control-Shift-Enter` (`Command-Shift-Enter` on Mac).
;; ## Equations
;; There are many equations used to predict one-repetition maximum based on the greatest weight lifted for two to ten reps. All are unavoidably inexact. One popular method for determining your 1RM comes from Baechle, Earle, and Wathen (2000):
;; * Weight × ( 1 + ( 0.033 × Number of repetitions ) )
;; We can rewrite this as a Clojure function:
(defn baechle-1rm [weight reps]
(Math/round (* weight (+ 1 (* 0.033 reps)))))
;; We can do the same with [Brzycki's equation](https://www.tandfonline.com/doi/abs/10.1080/07303084.1993.10606684):
;; * Weight ÷ ( 1.0278 - ( 0.0278 × Number of repetitions ) )
(defn brzycki-1rm [weight reps]
(Math/round (/ weight (- 1.0278 (* 0.0278 reps)))))
;; ...and Landers':
;; * (100 × Weight) ÷ ( 101.3 - (2.67123 × Number of repetitions ) )
(defn landers-1rm [weight reps]
(Math/round (/ (* 100 weight)
(- 101.3 (* 2.67123 reps)))))
;; Notice two things. First, that all the papers that provide these equations are behind absurdly costly paywalls, because science is broken. Second, that the calculations are just as clear (perhaps more) in code as they are in traditional math notation. The only appreciable difference is prefix notation.
;; Let's explore those equations interactively.
;; ## See the numbers
;; We'll build an interactive one-rep-max calculator, with a little visualization to help us make sense of the numbers.
;; Since we know all the equations rely on two variables, we define a cell for those values. (Cells are used to hold values that change over time, in a way that makes it simple to flow data across elements.)
(defcell variables
{:weight-lifted 100
:repetitions-performed 1})
;; Next we create a cell for the calculated results of the equations.
(defcell calculated
{:baechle (baechle-1rm (:weight-lifted @variables) (:repetitions-performed @variables))
:brzycki (brzycki-1rm (:weight-lifted @variables) (:repetitions-performed @variables))
:landers (landers-1rm (:weight-lifted @variables) (:repetitions-performed @variables))})
;; Now we're ready to build an interaction on top of the data in our two cells.
;; We describe our HTML UI using a Hiccup syntax of vectors and keywords. The key point is `value-to-cell!` in the `on-change` property of our slider input. This function is provided by the Maria environment as a simple way to give the input value to a cell.
(cell
(html [:table
[:tr
[:td {:style {:padding-right 10}} "Weight Lifted (lbs or kg)"]
[:td [:input {:type "range" :min 20 :max 300 :step 5
:on-change (value-to-cell! variables :weight-lifted)}]]]
[:tr
[:td "Repetitions Performed"]
[:td [:input {:type "range" :min 1 :max 10
:on-change (value-to-cell! variables :repetitions-performed)}]]]]))
;; Notice that the top level of our UI is an anonymous cell that hooks our UI into the page's data flow. Go ahead and play with the sliders on the right, and see how the values for `variables` and `calculated` are updated automatically.
;; As a last step, let's add some visual sugar to our interaction, to help get an intuitive sense of the data. We'll use the Shapes library's `colorize` and `rectangle` to concisely declare shapes.
(cell
(html
[:table
[:tr [:td "Weight lifted: "]
[:td {:colspan 3 :style {:padding-right 10}} (rectangle (:weight-lifted @variables) 8)]
[:td (:weight-lifted @variables)]]
[:tr [:td "Baechle: "]
[:td {:colspan 3 :style {:padding-right 10}}
(colorize "darkslategray" (rectangle (:baechle @calculated) 8))]
[:td {:style {:color "darkslategray"}} (:baechle @calculated)]]
[:tr
[:td "Brzycki: "]
[:td {:colspan 3 :style {:padding-right 10}}
(colorize "slategray" (rectangle (:brzycki @calculated) 8))]
[:td {:style {:color "slategray"}} (:brzycki @calculated)]]
[:tr
[:td "Landers: "]
[:td {:colspan 3 :style {:padding-right 10}}
(colorize "darkslateblue" (rectangle (:landers @calculated) 8))]
[:td {:style {:color "darkslateblue"}} (:landers @calculated)]]]))
;; I hope this demonstrates how between math notation and code, the advantage goes clearly to code. Interactivity and visualization make code the method of choice for understanding numbers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment