USGA Handicap Calculator
This example shows off a method of displaying live, editable Clojure code that is evaluated within the page itself. It uses Klipse and Reagent. Experiment with making changes to the code and see how it changes the output.
Let’s start with player and course data.
You can edit this data for your personal handicap calculation. You can also experiment with code changes. Scroll to the bottom of the page to see the output.
(def course-data
{:course-pars [5 4 3 4 3 4 5 3 5 4 3 5 4 3 4 5 4 4]
:tees {:black {:rating 72.5 :slope 133}
:blue {:rating 70.4 :slope 128}
:white-m {:rating 68.6 :slope 120}
:white-f {:rating 72.1 :slope 127}
:red {:rating 69.4 :slope 120}}})
(def player-course-tee
{:course-handicap 12
:gender :male
:tee :white-m
:rounds [[5 5 3 4 4 5 6 4 5 5 7 5 4 4 6 6 5 5]
[5 5 3 4 4 5 6 4 5 5 8 5 4 4 6 7 5 5]
[4 4 4 5 3 5 5 3 6 4 5 5 5 3 5 6 4 4]
[5 4 5 3 3 5 4 4 5 5 5 4 6 5 4 5 6 5]
[6 5 2 4 4 4 5 5 4 5 8 5 4 3 5 4 4 5]
[4 3 5 4 4 5 4 3 6 6 5 6 6 3 5 6 4 6]
[5 3 3 5 3 6 5 3 4 5 5 6 5 5 5 5 6 4]
[6 6 3 3 4 5 5 4 6 4 8 5 4 4 4 6 4 6]
[7 5 4 4 5 4 6 5 6 5 7 6 7 4 6 5 5 5]]})
This code calculates a USGA handicap:
(defn esc-max
"Return the maximum score given the PAR for the hole
and the players current course handicap"
[chcp holepar]
(cond
(<= chcp 9) (+ holepar 2)
(<= 10 chcp 19) 7
(<= 20 chcp 29) 8
(<= 30 chcp 39) 9
:else 10))
;;Handicap Differential = (AGS - Course Rating) X 113 ÷ Slope Rating
(defn hdiff
"Return a Handicap Differential for a give Adjusted Gross Score (AGS)"
[rating slope ags]
(let [roundoff #(/ (int (* 10 (+ 0.05 %))) 10.0)]
(roundoff (* (- ags rating) (/ 113 slope)))))
(defn hdiff4Player
[{:keys [course-handicap rounds]} {:keys [course-pars]} rating slope]
"Return all Handicap Differentials for a given player, course, and tee"
(let [maximums (map (partial esc-max course-handicap) course-pars)
ags4player (map #(apply + (map min % maximums)) rounds) ; adj gross
hdif (partial hdiff rating slope)]
(map hdif ags4player)))
(defn LowestHandicapDifferentials [hdiffs]
"Return the lowest handicap differentials for a given player, course, tee"
(let [n (get [nil nil nil nil nil ; no handicap until five scores recorded.
1 1 2 2 3 3 4 4 5 5 6 6 7 8 9 10] (count hdiffs) 10)]
(take n (sort hdiffs)))) ; lowest N
(defn usga-handicap [{:keys [gender tee] :as player} {:keys [tees] :as course}]
(let [avg (fn [s] (/ (apply + s) (count s)))
hcpmax (if (= :male gender) 36.4 40.4)
thetee (tee tees)
hdiffs (hdiff4Player player course (:rating thetee) (:slope thetee))
player-avg (avg (LowestHandicapDifferentials hdiffs))
trunk (fn [dd] (/ (int (* 10 dd)) 10.0)) ;truncate to tenths
hcp-index (min hcpmax (trunk (* 0.96 player-avg)))]
(int (* hcp-index (/ (:slope thetee) 113)))))
Calculate handicap and format the output:
(defn handicap-out
[pct cd]
(str "USGA Handicap: " (usga-handicap pct cd) " strokes"))
Call it. If you've made any changes above, update this field to force a re-eval. (e.g. add a space at the end)
(handicap-out player-course-tee course-data)
Code evaluation powered by Klipse