module AgbHandicap
Constants
- SCORING_SCHEMES
Public Class Methods
calculate(score, distances, rounded = true)
click to toggle source
Calculate AGB score handicap as per David Lane's original algorithm
Example:
>> distances = [ {'range_in_meters' => 91.44, 'total_shots' => 72, 'target_diameter_cm' => 122, 'scoring_scheme' => 'IMPERIAL'}, {'range_in_meters' => 73.152, 'total_shots' => 48, 'target_diameter_cm' => 122, 'scoring_scheme' => 'IMPERIAL'}, {'range_in_meters' => 54.864, 'total_shots' => 24, 'target_diameter_cm' => 122, 'scoring_scheme' => 'IMPERIAL'} ] >> score = 1105 >> result = AgbHandicap.calculate(score, distances)
# File lib/agb_handicap.rb, line 27 def calculate(score, distances, rounded = true) result = agbhandicap(score, distances) rounded ? result.ceil.to_i : result end
Private Class Methods
agbhandicap(score, distances)
click to toggle source
# File lib/agb_handicap.rb, line 34 def agbhandicap(score, distances) rtrange = 32.0 hc = 50.0 while (rtrange > 0.01) nextscore = agbscore(hc, distances) if (score < nextscore) hc = hc + rtrange end if (score > nextscore) hc = hc - rtrange end rtrange = rtrange / 2 end hc = 0 if (hc < 0) hc = 100 if (hc > 100) return hc.to_f.round(1) end
agbscore(h, distances)
click to toggle source
# File lib/agb_handicap.rb, line 58 def agbscore(h, distances) score = 0.0 distances.each do | d | score = score + calculate_distance_score(d, h) end score end
calculate_distance_score(distance, h)
click to toggle source
# File lib/agb_handicap.rb, line 66 def calculate_distance_score(distance, h) range = distance['range_in_meters'].to_f shots = distance['total_shots'].to_f diameter = distance['target_diameter_cm'].to_f scoring = distance['scoring_scheme'] score = 0 sr = score_range(h.to_f, range).to_f case scoring when 'METRIC' score = 10 (1..10).each do | n | score = score - solution((n.to_f * diameter / 20.0 + 0.357), sr) end when 'IMPERIAL' score = 9 (1..4).each do | n | score = score - (2.0 * solution((n.to_f * diameter / 10.0 + 0.357), sr)) end score = score - solution((diameter / 2 + 0.357), sr) when 'ONE_TO_FIVE' # could be worcester or NFAA round etc score = 5 (1..5).each do | n | score = score - solution((n.to_f * diameter / 10.0 + 0.357), sr) end when 'INNER_TEN' score = 10 score = score - solution((diameter / 40 + 0.357), sr) (2..10).each do | n | score = score - solution((n.to_f * diameter / 20 + 0.357), sr) end when 'TRIPLE' score = 10 (1..4).each do | n | score = score - solution((n.to_f * diameter / 20 + 0.357), sr) end score = score - (6 * solution((5 * diameter / 20 + 0.357), sr)) when 'TRIPLE_INNER_TEN' score = 10 score = score - solution((diameter / 40 + 0.357), sr) (2..4).each do | n | score = score - solution((n.to_f * diameter / 20 + 0.357), sr) end score = score - (6 * solution((5 * diameter / 20 + 0.357), sr)) when 'SIX_ZONE' score = 10 (1..5).each do | n | score = score - solution((n.to_f * diameter / 20 + 0.357), sr) end score = score - (5 * solution((6 * diameter / 20 + 0.357), sr)) end (score.to_f * shots).to_f end
score_range(h, range)
click to toggle source
# File lib/agb_handicap.rb, line 122 def score_range(h, range) 100 * range * (1.036 ** (h + 12.9)) * 5e-4 * (1 + 1.429e-6 * (1.07 ** (h + 4.3)) * (range * range)) end
solution(operator, score_range)
click to toggle source
# File lib/agb_handicap.rb, line 126 def solution(operator, score_range) return Math.exp( -(operator / score_range) ** 2 ) end