From: yoonho@dip.eecs.umich.edu (Yoonho Park)
Subject: Handicap Scripts
Organization: University of Michigan EECS Dept., Ann Arbor, MI
Date: Thu, 23 Jul 1992 17:43:07 GMT

Here's my first attempt at some scripts that will calculate your
handicap.  I collected several posts about the algorithm, and I tried
to follow them faithfully.  However, I can't guarantee correctness.

All you need is ksh and an awk that will handle floating point numbers
(like the latest gawk).  I would appreciate comments, and I'll try to
improve the scripts in my spare time (of course I would rather be on
the golf course :).

Anyone is welcome to improve them, change them, whatever!  It would be
nice to keep track of stats like fairways hit, GIRs, sand saves, putts,
etc.  It would also be nice to store course descriptions to make
entering scores easier.

----------------------------------------------------------------------------
Yoonho Park                                    Software Systems Research Lab
yoonho@eecs.umich.edu                  The University of Michigan--Ann Arbor
Summer: park@hpl.hp.com
----------------------------------------------------------------------------

============================================================================
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by Yoonho Park <yoonho@freud> on Thu Jul 23 10:14:35 1992
#
# This archive contains:
#	handicap	
#

LANG=""; export LANG
PATH=/bin:/usr/bin:$PATH; export PATH

echo mkdir - handicap
mkdir handicap

echo x - handicap/handi.awk
cat >handicap/handi.awk <<'@EOF'
# Grab the differentials, figure out how many to use, average those
# differentials and multiply by 0.96

BEGIN {
	num_scores = 0
	total = 0
	max_diff = 0
}

{
	date = $1
	dif = $24
	diff[num_scores % 20] = dif
	num_scores++
}

END {
	# Does awk (or gawk) have a case statement?!
	if ( num_scores < 5 ) {
		printf "%8s\t%s\n", date, "36.0"
		exit
	}
	if ( num_scores == 5 || num_scores == 6 ) { num_best = 1 }
	if ( num_scores == 7 || num_scores == 8 ) { num_best = 2 }
	if ( num_scores == 9 || num_scores == 10 ) { num_best = 3 }
	if ( num_scores == 11 || num_scores == 12 ) { num_best = 4 }
	if ( num_scores == 13 || num_scores == 14 ) { num_best = 5 }
	if ( num_scores == 15 || num_scores == 16 ) { num_best = 6 }
	if ( num_scores == 17 )	{ num_best = 7 }
	if ( num_scores == 18 ) { num_best = 8 }
	if ( num_scores == 19 ) { num_best = 9 }
	if ( num_scores >= 20 ) { num_best = 10 }
	# Bubble sort the diffs to make grabbing the num_best best diffs
	# easy
	for ( i = 0; i < num_scores; i++ ) {
		for ( j = i+1; j < num_scores; j++ ) {
			if ( diff[i] > diff[j] ) {
				tmp = diff[i]
				diff[i] = diff[j]
				diff[j] = tmp
			}
		}
	}
	for ( i = 0; i < num_best; i++ ) {
		total += diff[i]
	}
	handicap = total/num_best*0.96
	printf "%8s\t%0.1f\n", date, handicap
}
@EOF

chmod 644 handicap/handi.awk

echo x - handicap/README
cat >handicap/README <<'@EOF'

You should have the following files:

  README	This file
  diffs.awk	Calculates differentials (implements ESC)
  handi.awk	Calculates your handicap
  handicap*	A ksh script that runs diffs.awk and handi.awk
  history.yoon	An example history file
  scores.yoon	An example scores file

Calculating your handicap is a 2 step process.  First, you enter your
scores in the scores file.  Then you type

  ./handicap

Each line in the scores file should have the following format:

  date one_word_description par rating slope scores...

Your scores should be entered as strokes plus or minus from par (ex, a
birdie is -1, par is 0, a bogey is 1, etc).  After you run handicap, a
differential is attached to each line in the scores file.

As an example I've included my history and scores file.  The last score
in my scores file does not have a differential, so type the following
commands to calculate my ``latest handicap:''

  mv scores.yoon scores
  mv history.yoon history
  ./handicap

My ``latest handicap'' should be 18.3 on 7/22/92.  The last line in the
scores file should now have a differential of 22.3.

One more thing.  Before you run handicap, you should edit it and make
sure the AWK variable is set correctly.  The awk you use needs to handle
floating point numbers.  I use the latest gawk.  Some awks (such as
the new awk found in HP-UX Release 8.0) will also handle floating point
numbers.

@EOF

chmod 644 handicap/README

echo x - handicap/handicap
cat >handicap/handicap <<'@EOF'
#!/bin/ksh

# If your awk does not handle floating point numbers, use gawk
AWK=/usr/local/bin/gawk
if [[ ! -x $AWK ]]
then
	print "Set AWK correctly in handicap (AWK is now $AWK)"
	exit
fi

# Open the history file
if [[ ! -f ./history ]]; then touch ./history; fi
exec 3<./history

# Grab the current handicap
curr_hndcp=36
while read -r -u3 date hndcp
do
	curr_hndcp=$hndcp
done

# Close the history file
exec 3<&-

# Calculate the differentials
if [[ ! -f ./scores ]]; then touch ./scores; fi
$AWK -f ./diffs.awk -v handicap=$curr_hndcp ./scores > ./scores.diffs

# Calculate the current handicap and append it to the history file
$AWK -f ./handi.awk ./scores.diffs >> history

# Update the scores file
/bin/mv ./scores.diffs ./scores

# Display the last handicaps
tail ./history
@EOF

chmod 755 handicap/handicap

echo x - handicap/history.yoon
cat >handicap/history.yoon <<'@EOF'
 5/31/92	19.8
  6/1/92	19.8
  6/3/92	20.2
  6/9/92	20.2
 6/15/92	17.9
 6/30/92	17.9
  7/6/92	18.3
 7/10/92	17.2
 7/17/92	17.8
 7/20/92	17.8
@EOF

chmod 644 handicap/history.yoon

echo x - handicap/diffs.awk
cat >handicap/diffs.awk <<'@EOF'
# Calculate the differentials (apply ESC)

BEGIN {
	# Figure out how many doubles and triples are allowed
	num_scores = 0
	num_dbl_allowed = 0
	num_trp_allowed = 0
	if ( handicap <= 18 ) {
		num_dbl_allowed = handicap
	} else {
		num_dbl_allowed = 18
		num_trp_allowed = handicap - 18
	}
}

{
	par = $3
	rating = $4
	slope = $5
	# If the differential has been calculated, don't recalculate it
	if ( NF == 24 ) {
		print $0
		num_scores++
		next
	}
	# Apply ESC
	num_dbl = 0
	num_trp = 0
	for ( i = 0; i < 18; i++ ) {
		score = $(i+6)
		if ( score > 3 ) {
			score = 3
		}
		if ( score == 3) {
			num_trp++
			if ( num_trp > num_trp_allowed ) {
				score = 2
				num_trp--
			}
		}
		if ( score == 2 ) {
			num_dbl++
			if ( num_dbl > num_dbl_allowed ) {
				score = 1
				num_dbl--
			}
		}
		round[i] = score
	}
	# Calculate the differential
	diff = 0
	for ( i = 0; i < 18; i++ ) {
		diff += round[i]
	}
	diff += (par-rating)
	diff *= 113/slope
	printf "%s %0.1f\n", $0, diff
	num_scores++
}
@EOF

chmod 644 handicap/diffs.awk

echo x - handicap/scores.yoon
cat >handicap/scores.yoon <<'@EOF'
5/21/92 PA 72 70.4 113 2 0 0 2 2 0 1 0 1 1 1 3 1 1 3 2 1 1 23.6
5/22/92 Sv 70 69.7 119 1 1 1 2 2 1 1 3 2 1 2 1 1 1 1 1 1 1 23.1
5/25/92 SC 72 70.5 118 2 2 1 2 0 1 2 3 1 2 1 1 1 0 1 1 1 0 22.5
5/29/92 PA 72 70.4 113 2 2 1 2 2 0 0 1 0 1 2 1 2 1 0 0 1 1 20.6
5/31/92 PA 72 70.4 113 2 2 2 2 1 1 1 0 1 2 1 1 1 1 1 0 1 0 21.6
6/1/92 SC 72 70.5 118 2 0 1 2 0 1 0 3 1 1 1 2 1 2 2 2 0 0 21.5
6/3/92 Shrln 72 70.1 121 4 2 1 3 4 4 3 0 2 1 0 2 0 1 1 2 1 4 26.1
6/9/92 Sv 70 69.7 119 1 0 2 1 1 2 0 4 4 0 1 1 2 2 -1 3 1 3 22.1
6/15/92 Shrln 72 70.1 121 1 2 1 1 1 1 1 0 -1 0 1 0 0 0 1 3 0 1 13.9
6/30/92 Shrln 72 70.1 121 1 2 0 2 2 1 1 3 2 1 1 0 1 1 1 1 1 1 21.4
7/6/92 Shrln 72 70.1 121 3 2 2 0 2 1 4 0 0 1 2 0 1 1 1 0 1 2 20.5
7/10/92 Stadium 72 72.0 130 2 1 1 2 1 1 2 0 1 0 2 1 1 0 0 2 0 2 16.5
7/17/92 Shrln 72 70.1 121 1 0 1 2 1 1 1 1 4 1 1 2 1 1 2 3 3 2 24.2
7/20/92 Sunol 72 67.2 112 2 1 3 2 2 0 3 2 2 1 0 0 2 4 1 3 1 1 30.1
7/22/92 Shrln 72 70.1 121 1 2 1 0 1 1 2 1 2 1 2 2 1 2 0 1 0 2
@EOF

chmod 644 handicap/scores.yoon

chmod 755 handicap

exit 0
Newsgroups: rec.sport.golf