I don't have the USBF COC scales. Are they different from what the WBF published? I had some trouble understanding the way the WBF Scoring Panel dealt with the Concavity Rule (see the January 2013 report), but I think I get it now. I didn't follow their idea of using a vector of boolean and handled the problem by defining different array sizes for the scores array, the differences array and the second differences array. I'm not much of a programmer (not even "Intermediate", I think), and I didn't bother with classes or even functions. The total code is way smaller than a hundred lines. I would politely ask to concentrate on correctness (does the code produce correct results?) rather than my odd programming style. :-) The C++ code will compile with recent versions of g++, and probably with most C++ compilers. I checked the output against the 10, 14, 16, 20 and 32 tables on the WBF Continuous VP Scale that can be found on the Web (and which doesn't contain tables for 24, 28, 40, 48, 60, 64 boards).
/*
Reference: The New WBF IMP to VP Scales
Technical Report of WBF Scoring Panel (January 2013)
*/
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
const double R = 0.2360679775; /* == Tau^3 == sqrt(5) - 2 */
const double V0 = 10.0; /* VP score in drawn match */
double N, /* number of boards played */
X, /* maximum win IMP margin, 15*sqrt(N) */
VP,
VPraw;
cout << "number of boards played: ";
cin >> N;
// CALCULATION OF RAW VP SCORES
X = 15 * sqrt(N);
int blitz = ceil(X); // IMP margin for 20-0 score
double * scores; // array of VP scores
scores = new double[blitz+1]; // including zero margin
for (int i=0; i!=blitz+1; ++i) // i is the IMP margin
{
// calculate VP scores
VPraw = V0 + V0 * ((1 - pow(R, i/X)) / (1 - R));
VP = min((round(100 * VPraw) /100), 2*V0); // rounding
// add score to array
scores[i] = VP;
}
// CORRECTION OF CONCAVITY RULE VIOLATIONS
int * diff; // array of differences
diff = new int[blitz];
for (int i=0; i!=blitz; ++i)
diff[i] = round(100*(scores[i+1] - scores[i]));
int * diff2; // array of second differences
diff2 = new int[blitz-1];
for (int i=0; i!=blitz-1; ++i)
diff2[i] = diff[i+1] - diff[i];
bool violation = true;
while (violation)
{
violation = false;
for (int i=0; i!=blitz-1; ++i)
{
if (diff2[i] > 0)
{
scores[i+1] += 0.01;
--diff2[i];
violation = true;
}
}
if (violation)
{ /* recalculate arrays diff and diff2 */
for (int i=0; i!=blitz; ++i)
diff[i] = round(100*(scores[i+1] - scores[i]));
for (int i=0; i!=blitz-1; ++i)
diff2[i] = diff[i+1] - diff[i];
}
}
// SEND SCALE TO SCREEN
cout << endl << endl;
cout << "WBF CONTINUOUS VP SCALE for " << N << " boards" << endl
<< "(trailing zeros not shown)"
<< endl << endl << endl << "IMP margin and score" << endl;
for (int i=0; i!=blitz+1; ++i)
cout << i << " " << scores[i] << " - " << 20 - scores[i] << endl;
cout << endl << endl;
delete [] scores; delete [] diff; delete [] diff2;
char ch; cin >> ch;
return 0;
}