Function par(ByVal scores As Range, Optional ByVal delta As Integer = 10) ' scores is the range of cells containing the scores ' delta is the smallest difference between scores On Error GoTo par_error If scores.Count = 1 Then ' dispose of trivial case par = scores.Value Exit Function End If Dim data data = scores ' read range into array, for efficiency Debug.Assert IsArray(data) Dim par1 As Integer, par2 As Integer Dim sum1 As Integer, sum2 As Integer ' set initial values to bracket the par value par2 = 8000 par1 = -par2 sum2 = scores.Count sum1 = -sum2 While par2 - par1 > delta par = delta * Fix((par1 + par2) / (2 * delta)) Dim sum As Integer, i As Integer, j As Integer sum = 0 ' calculate the net sum of imp scores against par ' imp_() is a function to calculate the IMP scale For i = LBound(data, 1) To UBound(data, 1) For j = LBound(data, 2) To UBound(data, 2) sum = sum + imp_(par - data(i, j)) Next j Next i If sum = 0 Then Exit Function ' if we haven't found par, adjust the bracket If sum < 0 Then par1 = par sum1 = sum Else par2 = par sum2 = sum End If ' check we haven't lost the plot! Debug.Assert par1 < par2 And sum1 < 0 And 0 < sum2 Wend ' if we can't find a par value giving sum = 0 ' take the par will the smallest sum ... If (-sum1) < sum2 Then par = par1 ElseIf sum2 < (-sum1) Then par = par2 ' ... splitting ties choosing par nearer zero ElseIf par2 > 0 Then par = par1 Else par = par2 End If Exit Function par_error: MsgBox "Error in par: " & Err.Description par = CVErr(xlErrValue) End Function
31 May 2009
VBA code to calculate par for zero-sum butler
21 May 2009
Butler scoring and other abuses of the IMP scale
I posted some random thoughts on butler scoring on a thread IBLF and earlier I promised something here on butlering so here it is.
IMP scale
I think that when you compare a pairs score with par, the difference should be doubled before converting to IMPs. The par score should not be thought of as the result in the other room but as the average of the two results at the two tables of a match. To recover the "teams result", the diffence between one real score and the average/par score needs to be multiplied by two before converting to IMPs. If you like, the IMP score can then be divided by two to represent the actual contribution of each of the pairs in a team. (Obviously this won't affect the relative scores of different pairs.)
Calculating par
Someone else on IBLF said it was obvious that the scores for all the NS pairs should sum to zero, since this determines the par score it should be used to calculate par. Other ways of calculating par approximate to this but you might was well use this desired property as the definition. Implementation is easy, some sort of binary chop will work. You need some rule for deciding what to do when there is no zero-sum par. I suggest minimizing the absolute value of the sum of the NS scores, splitting any tie by picking closest par to zero.
Barking alternative to butler for teams of eight
Another abuse of the IMP scale is to score teams-of-eight by aggregating the four scores and converting to IMPs. This is done in the Eastern Counties League and the Berks and Bucks league. You can use forms of butlering to compare the performance of the pairs in such teams-of-eight matches, or you could use cross IMPs. I think the right form of cross IMPs is
IMP(A+B+C+D) + IMP(A-B+C-D) + IMP(A-B-C+D)
to calculate the score for pair A, with pair B sat the same way, and other pairs of the team (C, D) sat the other way. This formula can be extended if there are multiple matches (in different divisions) played at the same time with the same boards. A pair is compared with all other pairs sat the same way against all possible pairs of pairs sat the other way; with all scores from four different tables. If there are two matches (8 tables) then the three terms above become 105, and if there are three matches (12 tables) there are 495 terms. When I implemented this, I described the scoring option as "barking" (a pun on my name and anticipation of other people's reaction).