31 May 2009

VBA code to calculate par for zero-sum butler

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

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).