all-up-in-your-elo 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/.document +5 -0
  2. data/Gemfile +14 -0
  3. data/Gemfile.lock +22 -0
  4. data/LICENSE.txt +20 -0
  5. data/README.rdoc +42 -0
  6. data/Rakefile +54 -0
  7. data/VERSION +1 -0
  8. data/all-up-in-your-elo.gemspec +148 -0
  9. data/ext/bayeselo/.gitignore +4 -0
  10. data/ext/bayeselo/CBradleyTerry.cpp +670 -0
  11. data/ext/bayeselo/CBradleyTerry.h +137 -0
  12. data/ext/bayeselo/CCDistribution.cpp +135 -0
  13. data/ext/bayeselo/CCDistribution.h +44 -0
  14. data/ext/bayeselo/CCDistributionCUI.cpp +104 -0
  15. data/ext/bayeselo/CCDistributionCUI.h +38 -0
  16. data/ext/bayeselo/CCondensedResults.cpp +253 -0
  17. data/ext/bayeselo/CCondensedResults.h +64 -0
  18. data/ext/bayeselo/CDiscretization.h +40 -0
  19. data/ext/bayeselo/CDistribution.cpp +123 -0
  20. data/ext/bayeselo/CDistribution.h +58 -0
  21. data/ext/bayeselo/CDistributionCollection.cpp +34 -0
  22. data/ext/bayeselo/CDistributionCollection.h +29 -0
  23. data/ext/bayeselo/CEloRatingCUI.cpp +1046 -0
  24. data/ext/bayeselo/CEloRatingCUI.h +67 -0
  25. data/ext/bayeselo/CIndirectCompare.h +28 -0
  26. data/ext/bayeselo/CJointBayesian.cpp +111 -0
  27. data/ext/bayeselo/CJointBayesian.h +38 -0
  28. data/ext/bayeselo/CLUDecomposition.cpp +154 -0
  29. data/ext/bayeselo/CLUDecomposition.h +36 -0
  30. data/ext/bayeselo/CMatrix.cpp +48 -0
  31. data/ext/bayeselo/CMatrix.h +35 -0
  32. data/ext/bayeselo/CMatrixIO.cpp +27 -0
  33. data/ext/bayeselo/CMatrixIO.h +17 -0
  34. data/ext/bayeselo/CPredictionCUI.cpp +393 -0
  35. data/ext/bayeselo/CPredictionCUI.h +50 -0
  36. data/ext/bayeselo/CResultSet.cpp +245 -0
  37. data/ext/bayeselo/CResultSet.h +50 -0
  38. data/ext/bayeselo/CResultSetCUI.cpp +355 -0
  39. data/ext/bayeselo/CResultSetCUI.h +44 -0
  40. data/ext/bayeselo/CTimeIO.cpp +58 -0
  41. data/ext/bayeselo/CTimeIO.h +19 -0
  42. data/ext/bayeselo/CVector.cpp +110 -0
  43. data/ext/bayeselo/CVector.h +42 -0
  44. data/ext/bayeselo/EloDataFromFile.cpp +120 -0
  45. data/ext/bayeselo/EloDataFromFile.h +21 -0
  46. data/ext/bayeselo/README +8 -0
  47. data/ext/bayeselo/ReadLineToString.cpp +32 -0
  48. data/ext/bayeselo/ReadLineToString.h +18 -0
  49. data/ext/bayeselo/chtime.cpp +56 -0
  50. data/ext/bayeselo/chtime.h +61 -0
  51. data/ext/bayeselo/chtimer.h +27 -0
  52. data/ext/bayeselo/clktimer.cpp +178 -0
  53. data/ext/bayeselo/clktimer.h +29 -0
  54. data/ext/bayeselo/consolui.cpp +538 -0
  55. data/ext/bayeselo/consolui.h +154 -0
  56. data/ext/bayeselo/const.cpp +79 -0
  57. data/ext/bayeselo/const.h +42 -0
  58. data/ext/bayeselo/date.cpp +96 -0
  59. data/ext/bayeselo/date.h +44 -0
  60. data/ext/bayeselo/debug.h +58 -0
  61. data/ext/bayeselo/elomain.cpp +26 -0
  62. data/ext/bayeselo/eloratings.cpp +76 -0
  63. data/ext/bayeselo/extconf.rb +6 -0
  64. data/ext/bayeselo/list.h +367 -0
  65. data/ext/bayeselo/listi.h +125 -0
  66. data/ext/bayeselo/move.cpp +249 -0
  67. data/ext/bayeselo/move.h +139 -0
  68. data/ext/bayeselo/pgn.h +62 -0
  69. data/ext/bayeselo/pgnlex.cpp +432 -0
  70. data/ext/bayeselo/pgnlex.h +105 -0
  71. data/ext/bayeselo/pgnstr.cpp +126 -0
  72. data/ext/bayeselo/piece.h +44 -0
  73. data/ext/bayeselo/player.h +31 -0
  74. data/ext/bayeselo/position.h +89 -0
  75. data/ext/bayeselo/random.cpp +114 -0
  76. data/ext/bayeselo/random.h +63 -0
  77. data/ext/bayeselo/readstr.cpp +51 -0
  78. data/ext/bayeselo/readstr.h +19 -0
  79. data/ext/bayeselo/square.h +61 -0
  80. data/ext/bayeselo/str.cpp +81 -0
  81. data/ext/bayeselo/str.h +71 -0
  82. data/ext/bayeselo/version.cpp +30 -0
  83. data/ext/bayeselo/version.h +28 -0
  84. data/ext/bayeselo/version_number.h +1 -0
  85. data/lib/elo_ratings.rb +9 -0
  86. data/lib/elo_ratings/c_bayeselo.rb +5 -0
  87. data/lib/elo_ratings/results.rb +41 -0
  88. data/test/elo_ratings/test_c_bayeselo.rb +84 -0
  89. data/test/elo_ratings/test_results.rb +41 -0
  90. data/test/helper.rb +19 -0
  91. metadata +233 -0
@@ -0,0 +1,58 @@
1
+ /////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // R�mi Coulom
4
+ //
5
+ // December, 2004
6
+ //
7
+ /////////////////////////////////////////////////////////////////////////////
8
+ #ifndef CDistribution_Declared
9
+ #define CDistribution_Declared
10
+
11
+ #include <vector>
12
+
13
+ class CDistribution // dist
14
+ {
15
+ protected: ////////////////////////////////////////////////////////////////
16
+ std::vector<double> vDistribution;
17
+
18
+ int GetBoundIndex(double Confidence,
19
+ int Begin,
20
+ int End,
21
+ int Direction) const;
22
+
23
+ public: ///////////////////////////////////////////////////////////////////
24
+ CDistribution() : vDistribution(1) {vDistribution[0] = 1.0;}
25
+ CDistribution(int Size) : vDistribution(Size) {}
26
+
27
+ //
28
+ // Basic functions
29
+ //
30
+ int GetSize() const {return vDistribution.size();}
31
+ double GetProbability(int i) const {return vDistribution[i];}
32
+ void SetProbability(int i, double p) {vDistribution[i] = p;}
33
+ void Add(int i, double p) {vDistribution[i] += p;}
34
+
35
+ void Reset();
36
+ void SetUniform();
37
+ void Normalize();
38
+ void LogNormalize();
39
+
40
+ //
41
+ // Discrete bounds
42
+ //
43
+ int GetLowerIndex(double Confidence) const;
44
+ int GetUpperIndex(double Confidence) const;
45
+
46
+ //
47
+ // Functions to deal with result distributions
48
+ //
49
+ friend CDistribution BinomialDistribution(double p);
50
+ friend CDistribution SumDistribution(const CDistribution &dist1,
51
+ const CDistribution &dist2);
52
+ };
53
+
54
+ CDistribution BinomialDistribution(double p);
55
+ CDistribution SumDistribution(const CDistribution &dist1,
56
+ const CDistribution &dist2);
57
+
58
+ #endif
@@ -0,0 +1,34 @@
1
+ /////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // R�mi Coulom
4
+ //
5
+ // December, 2004
6
+ //
7
+ /////////////////////////////////////////////////////////////////////////////
8
+ #include "CDistributionCollection.h"
9
+ #include "CCDistribution.h"
10
+
11
+ /////////////////////////////////////////////////////////////////////////////
12
+ // Constructor
13
+ /////////////////////////////////////////////////////////////////////////////
14
+ CDistributionCollection::CDistributionCollection(int PlayersInit,
15
+ int Size,
16
+ double Min,
17
+ double Max):
18
+ CDiscretization(Size, Min, Max),
19
+ Players(PlayersInit)
20
+ {
21
+ ppDistribution = new CCDistribution*[Players];
22
+ for (int i = Players; --i >= 0;)
23
+ ppDistribution[i] = new CCDistribution(Size, Min, Max);
24
+ }
25
+
26
+ /////////////////////////////////////////////////////////////////////////////
27
+ // Destructor
28
+ /////////////////////////////////////////////////////////////////////////////
29
+ CDistributionCollection::~CDistributionCollection()
30
+ {
31
+ for (int i = Players; --i >= 0;)
32
+ delete ppDistribution[i];
33
+ delete[] ppDistribution;
34
+ }
@@ -0,0 +1,29 @@
1
+ /////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // R�mi Coulom
4
+ //
5
+ // December, 2004
6
+ //
7
+ /////////////////////////////////////////////////////////////////////////////
8
+ #ifndef CDistributionCollection_Declared
9
+ #define CDistributionCollection_Declared
10
+
11
+ #include "CDiscretization.h"
12
+
13
+ class CCDistribution;
14
+
15
+ class CDistributionCollection: public CDiscretization // dc
16
+ {
17
+ private: //////////////////////////////////////////////////////////////////
18
+ CCDistribution **ppDistribution;
19
+ int Players;
20
+
21
+ public: ///////////////////////////////////////////////////////////////////
22
+ CDistributionCollection(int PlayersInit, int Size, double Min, double Max);
23
+
24
+ CCDistribution &GetDistribution(int i) {return *ppDistribution[i];}
25
+
26
+ ~CDistributionCollection();
27
+ };
28
+
29
+ #endif
@@ -0,0 +1,1046 @@
1
+ ////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // Remi Coulom
4
+ //
5
+ // December, 2004
6
+ //
7
+ ////////////////////////////////////////////////////////////////////////////
8
+ #include "CEloRatingCUI.h"
9
+ #include "CResultSet.h"
10
+ #include "CCDistribution.h"
11
+ #include "CCDistributionCUI.h"
12
+ #include "CDistributionCollection.h"
13
+ #include "CJointBayesian.h"
14
+ #include "clktimer.h"
15
+ #include "chtime.h"
16
+ #include "CTimeIO.h"
17
+ #include "CMatrix.h"
18
+ #include "CPredictionCUI.h"
19
+ #include "CIndirectCompare.h"
20
+ #include "ReadLineToString.h"
21
+
22
+ #include <iostream>
23
+ #include <iomanip>
24
+ #include <algorithm>
25
+ #include <sstream>
26
+ #include <fstream>
27
+ #include <set>
28
+
29
+ ////////////////////////////////////////////////////////////////////////////
30
+ // Command strings
31
+ ////////////////////////////////////////////////////////////////////////////
32
+ const char * const CEloRatingCUI::tszCommands[] =
33
+ {
34
+ "?",
35
+ "ratings",
36
+ "details",
37
+ "offset",
38
+ "scale",
39
+ "minelo",
40
+ "maxelo",
41
+ "advantage",
42
+ "drawelo",
43
+ "prior",
44
+ "resolution",
45
+ "confidence",
46
+ "p",
47
+ "likelihood",
48
+ "prediction",
49
+ "plotres",
50
+ "plotdraw",
51
+ "mm",
52
+ "elostat",
53
+ "elo",
54
+ "jointdist",
55
+ "exactdist",
56
+ "variance",
57
+ "covariance",
58
+ "los",
59
+ "advdist",
60
+ "drawdist",
61
+ "pairstats",
62
+ 0
63
+ };
64
+
65
+ ////////////////////////////////////////////////////////////////////////////
66
+ // Convert to closes int
67
+ ////////////////////////////////////////////////////////////////////////////
68
+ static int RoundDouble(double x)
69
+ {
70
+ if (x > 0)
71
+ return int(x+0.5);
72
+ else
73
+ return int(x-0.5);
74
+ }
75
+
76
+ ////////////////////////////////////////////////////////////////////////////
77
+ // Constructor
78
+ ////////////////////////////////////////////////////////////////////////////
79
+ CEloRatingCUI::CEloRatingCUI(const CResultSet &rsInit,
80
+ const std::vector<std::string> &vecNameInit,
81
+ CConsoleUI *pcui,
82
+ int openmode) :
83
+ CConsoleUI(pcui, openmode),
84
+ rs(rsInit),
85
+ crs(rsInit),
86
+ vecName(vecNameInit),
87
+ vPermutation(crs.GetPlayers()),
88
+ veloLower(crs.GetPlayers()),
89
+ veloUpper(crs.GetPlayers()),
90
+ Confidence(0.95),
91
+ eloMin(-1500),
92
+ eloMax(1500),
93
+ Resolution(1001),
94
+ eloOffset(0),
95
+ EloScale(1.0),
96
+ Prior(2.0),
97
+ bt(crs),
98
+ fLOSComputed(0)
99
+ {
100
+ for (int i = crs.GetPlayers(); --i >= 0;)
101
+ {
102
+ bt.SetElo(i, 0);
103
+ veloLower[i] = 0;
104
+ veloUpper[i] = 0;
105
+ vPermutation[i] = i;
106
+ }
107
+
108
+ MaxNameLength = 0;
109
+ for (int i = crs.GetPlayers(); --i >= 0;)
110
+ if (vecName[i].length() > MaxNameLength)
111
+ MaxNameLength = vecName[i].length();
112
+
113
+ crs.AddPrior(Prior);
114
+ }
115
+
116
+ ////////////////////////////////////////////////////////////////////////////
117
+ // Local prompt
118
+ ////////////////////////////////////////////////////////////////////////////
119
+ void CEloRatingCUI::PrintLocalPrompt(std::ostream &out)
120
+ {
121
+ out << "EloRating";
122
+ }
123
+
124
+ ////////////////////////////////////////////////////////////////////////////
125
+ // Inverse of normal distribution function
126
+ ////////////////////////////////////////////////////////////////////////////
127
+ static double NormInv(double Confidence)
128
+ {
129
+ CCDistribution cdist(1000, -10, 10);
130
+ cdist.SetNormal(0, 1);
131
+ return cdist.GetUpperValue(Confidence);
132
+ }
133
+
134
+ ////////////////////////////////////////////////////////////////////////////
135
+ // Compute variance
136
+ ////////////////////////////////////////////////////////////////////////////
137
+ void CEloRatingCUI::ComputeVariance()
138
+ {
139
+ std::vector<double> vVariance(crs.GetPlayers());
140
+ bt.GetVariance(&vVariance[0]);
141
+
142
+ double x = NormInv(Confidence);
143
+
144
+ for (int i = crs.GetPlayers(); --i >= 0;)
145
+ if (crs.GetOpponents(i) > 0)
146
+ veloLower[i] = veloUpper[i] = x * std::sqrt(vVariance[i]);
147
+ }
148
+
149
+ ////////////////////////////////////////////////////////////////////////////
150
+ // Process commands
151
+ ////////////////////////////////////////////////////////////////////////////
152
+ int CEloRatingCUI::ProcessCommand(const char *pszCommand,
153
+ const char *pszParameters,
154
+ std::istream &in,
155
+ std::ostream &out)
156
+ {
157
+ enum
158
+ {
159
+ IDC_Help,
160
+ IDC_Ratings,
161
+ IDC_Details,
162
+ IDC_Offset,
163
+ IDC_Scale,
164
+ IDC_MinElo,
165
+ IDC_MaxElo,
166
+ IDC_Advantage,
167
+ IDC_DrawElo,
168
+ IDC_Prior,
169
+ IDC_Resolution,
170
+ IDC_Confidence,
171
+ IDC_P,
172
+ IDC_Likelihood,
173
+ IDC_Prediction,
174
+ IDC_PlotRes,
175
+ IDC_PlotDraw,
176
+ IDC_MM,
177
+ IDC_ELOstat,
178
+ IDC_Elo,
179
+ IDC_JointDist,
180
+ IDC_ExactDist,
181
+ IDC_Variance,
182
+ IDC_Covariance,
183
+ IDC_LOS,
184
+ IDC_AdvDist,
185
+ IDC_DrawDist,
186
+ IDC_PairStats
187
+ };
188
+
189
+ switch (ArrayLookup(pszCommand, tszCommands))
190
+ {
191
+ case IDC_Help: ///////////////////////////////////////////////////////////
192
+ CConsoleUI::ProcessCommand(pszCommand, pszParameters, in, out);
193
+ out << "EloRating commands\n";
194
+ out << "~~~~~~~~~~~~~~~~~~\n";
195
+ out << "advantage [x] ... get[set] advantage of playing first\n";
196
+ out << "drawelo [x] ..... get[set] draw Elo\n";
197
+ out << "prior [x] ....... get[set] prior (= number of virtual draws)\n";
198
+ out << "elo [p] [elo] ... get[set] Elo of player number p\n";
199
+ out << "mm [a] [d] ...... compute maximum-likelihood Elos:\n";
200
+ out << " a: flag to compute advantage (default = 0)\n";
201
+ out << " d: flag to compute elodraw (default = 0)\n";
202
+ out << "elostat ......... compute ratings with ELOstat algorithm\n";
203
+ out << '\n';
204
+ out << "ratings [min [f [F]]] list players and their ratings:\n";
205
+ out << " min: minimum number of games\n";
206
+ out << " f: file name that contains the list of names\n";
207
+ out << " F: Full-rank flag (0 or 1, default 0)\n";
208
+ out << "details ......... detailed list\n";
209
+ out << "offset [elo [pl]] get[set] Elo offset, or player (pl) elo\n";
210
+ out << "scale ........... get[set] Elo scale\n";
211
+ out << '\n';
212
+ out << "p <w> <b> <r> ... probability of result <r> with Elos <w> and <b>\n";
213
+ out << "likelihood ...... log-likelihood of the current Elo list\n";
214
+ out << "prediction ...... open prediction interface\n";
215
+ out << '\n';
216
+ out << "plotres [i] [M] . plot result likelihoods as a function of rating diff:\n";
217
+ out << " i: number of intervals (default = 21)\n";
218
+ out << " M: maximum rating difference (default = 500)\n";
219
+ out << "plotdraw [n] [d] plot draw frequency as a function of average rating\n";
220
+ out << " n: number of games per group (default = 100)\n";
221
+ out << " d: maximum rating difference (default = 100)\n";
222
+ out << '\n';
223
+ out << "confidence ...... get[set] level of confidence intervals\n";
224
+ out << "variance ........ compute intervals with the diagonal of the Hessian\n";
225
+ out << "covariance ...... compute intervals with the full Hessian\n";
226
+ out << "los [f] [p] [w] . likelihood of superiority (f=first,p=players,w=width)\n";
227
+ out << '\n';
228
+ out << "minelo [x] ...... get[set] minimum Elo\n";
229
+ out << "maxelo [x] ...... get[set] maximum Elo\n";
230
+ out << "resolution [n] .. get[set] resolution\n";
231
+ out << "jointdist [p] ... compute intervals from joint distribution\n";
232
+ out << "exactdist [p] ... compute intervals assuming exact opponent Elos\n";
233
+ out << "advdist ......... likelihood distribution of advantage\n";
234
+ out << "drawdist ........ likelihood distribution of drawelo\n";
235
+ out << '\n';
236
+ out << "pairstats i j ... get stats between players i and j\n";
237
+ out << '\n';
238
+ break;
239
+
240
+ case IDC_MinElo: /////////////////////////////////////////////////////////
241
+ GetSet<double>(eloMin, pszParameters, out);
242
+ break;
243
+
244
+ case IDC_MaxElo: /////////////////////////////////////////////////////////
245
+ GetSet<double>(eloMax, pszParameters, out);
246
+ break;
247
+
248
+ case IDC_Advantage: //////////////////////////////////////////////////////
249
+ {
250
+ double eloAdvantage = bt.GetAdvantage();
251
+ GetSet<double>(eloAdvantage, pszParameters, out);
252
+ bt.SetAdvantage(eloAdvantage);
253
+ }
254
+ break;
255
+
256
+ case IDC_DrawElo: ////////////////////////////////////////////////////////
257
+ {
258
+ double eloDraw = bt.GetDrawElo();
259
+ GetSet<double>(eloDraw, pszParameters, out);
260
+ bt.SetDrawElo(eloDraw);
261
+ }
262
+ break;
263
+
264
+ case IDC_Prior: //////////////////////////////////////////////////////////
265
+ {
266
+ float NewPrior = Prior;
267
+ std::istringstream(pszParameters) >> NewPrior;
268
+ crs.AddPrior(NewPrior - Prior);
269
+ Prior = NewPrior;
270
+ out << Prior << '\n';
271
+ out << "With this prior, you will get the following Elo differences:\n";
272
+ CResultSet rs;
273
+ for (int i = 1; i < 6; i++)
274
+ {
275
+ rs.Append(0, 1, 2);
276
+ CCondensedResults crs(rs);
277
+ crs.AddPrior(Prior);
278
+
279
+ CBradleyTerry btLocal(crs);
280
+ btLocal.SetAdvantage(bt.GetAdvantage());
281
+ btLocal.SetDrawElo(bt.GetDrawElo());
282
+
283
+ btLocal.MinorizationMaximization(0, 0);
284
+ double Delta = btLocal.GetElo(0) - btLocal.GetElo(1);
285
+ out << i << "-0 : +" << Delta << '\n';
286
+ }
287
+ }
288
+ break;
289
+
290
+ case IDC_Resolution: /////////////////////////////////////////////////////
291
+ GetSet<int>(Resolution, pszParameters, out);
292
+ break;
293
+
294
+ case IDC_Confidence: /////////////////////////////////////////////////////
295
+ GetSet<double>(Confidence, pszParameters, out);
296
+ break;
297
+
298
+ case IDC_P: //////////////////////////////////////////////////////////////
299
+ {
300
+ double eloWhite = 0;
301
+ double eloBlack = 0;
302
+ int Result = 0;
303
+
304
+ std::istringstream is(pszParameters);
305
+ is >> eloWhite >> eloBlack >> Result;
306
+
307
+ out << "White Elo: " << eloWhite << '\n';
308
+ out << "Black Elo: " << eloBlack << '\n';
309
+ out << "Result: " << Result << '\n';
310
+
311
+ out << bt.ResultProbability(eloWhite - eloBlack, Result) << '\n';
312
+ }
313
+ break;
314
+
315
+ case IDC_Likelihood: /////////////////////////////////////////////////////
316
+ out << bt.LogLikelihood() << '\n';
317
+ break;
318
+
319
+ case IDC_Prediction: /////////////////////////////////////////////////////
320
+ {
321
+ CPredictionCUI predcui(*this);
322
+ predcui.MainLoop(in, out);
323
+ }
324
+ break;
325
+
326
+ case IDC_PlotRes: ////////////////////////////////////////////////////////
327
+ {
328
+ //
329
+ // Parse parameters
330
+ //
331
+ int Intervals = 21;
332
+ double eloMaxDiff = 500;
333
+ {
334
+ std::istringstream is(pszParameters);
335
+ is >> Intervals;
336
+ is >> eloMaxDiff;
337
+ }
338
+
339
+ #if 0 // Compute ratings with a half the games, and mesure predictions on the other half
340
+ unsigned Seed = 1;
341
+ CResultSet rsBT;
342
+ CResultSet rsRes;
343
+ rs.Extract(rsBT, rsRes, Seed);
344
+
345
+ CCondensedResults crsBT(rsBT);
346
+ CBradleyTerry btRes(crsBT);
347
+ for (int i = crsBT.GetPlayers(); --i >= 0;)
348
+ btRes.SetElo(i, 0);
349
+ crsBT.AddPrior(Prior);
350
+ // btRes.MinorizationMaximization(0, 0);
351
+ btRes.ELOstat();
352
+ #if 0 // compute log-likelihood for 100 priors
353
+ {
354
+ std::ofstream ofsCV("cv.dat");
355
+ for (int i = 0; i < 200; i++)
356
+ {
357
+ double Prior = 0.0000001 + i * 0.1;
358
+ CCondensedResults crsBT(rsBT);
359
+ crsBT.AddPrior(Prior);
360
+ CBradleyTerry btRes(crsBT);
361
+ for (int i = crsBT.GetPlayers(); --i >= 0;)
362
+ btRes.SetElo(i, 0);
363
+ btRes.MinorizationMaximization(0, 0);
364
+ double LL = btRes.LogLikelihood(rsRes);
365
+ ofsCV << Prior << ' ' << LL << '\n';
366
+ ofsCV.flush();
367
+ std::cerr << "Prior = " << Prior;
368
+ std::cerr << "; Loglikelihood = " << LL;
369
+ std::cerr << "\n\n";
370
+ }
371
+ }
372
+ #endif
373
+ #else
374
+ const CResultSet& rsRes = rs;
375
+ const CBradleyTerry& btRes = bt;
376
+ #endif
377
+
378
+ //
379
+ // Vector to store data for each interval
380
+ //
381
+ std::vector<int> vGames(Intervals);
382
+ std::vector<double> vEloDiff(Intervals);
383
+ std::vector<int> vWins(Intervals);
384
+ std::vector<int> vDraws(Intervals);
385
+ std::vector<int> vLosses(Intervals);
386
+ std::vector<double> vExpectedWins(Intervals);
387
+ std::vector<double> vExpectedDraws(Intervals);
388
+ std::vector<double> vExpectedLosses(Intervals);
389
+ std::vector<double> vExpectedElostat(Intervals);
390
+
391
+ //
392
+ // Initialization of data
393
+ //
394
+ for (int i = Intervals; --i >= 0;)
395
+ {
396
+ vGames[i] = 0;
397
+ vEloDiff[i] = 0.0;
398
+ vWins[i] = 0;
399
+ vDraws[i] = 0;
400
+ vLosses[i] = 0;
401
+ vExpectedWins[i] = 0.0;
402
+ vExpectedDraws[i] = 0.0;
403
+ vExpectedLosses[i] = 0.0;
404
+ vExpectedElostat[i] = 0.0;
405
+ }
406
+
407
+ //
408
+ // Loop over games
409
+ //
410
+ for (int i = rsRes.GetGames(); --i >= 0;)
411
+ {
412
+ double eloDiff = btRes.GetElo(rsRes.GetWhite(i)) -
413
+ btRes.GetElo(rsRes.GetBlack(i));
414
+ double x = eloDiff + eloMaxDiff;
415
+ if (x > 0)
416
+ {
417
+ int Index = int(Intervals * x / (2 * eloMaxDiff));
418
+ if (Index < Intervals)
419
+ {
420
+ vGames[Index]++;
421
+ vEloDiff[Index] += eloDiff;
422
+
423
+ int res = rsRes.GetResult(i);
424
+ switch(res)
425
+ {
426
+ case 0: vLosses[Index]++; break;
427
+ case 1: vDraws[Index]++; break;
428
+ case 2: vWins[Index]++; break;
429
+ }
430
+
431
+ double PLoss = btRes.ResultProbability(eloDiff, 0);
432
+ double PDraw = btRes.ResultProbability(eloDiff, 1);
433
+ double PWin = btRes.ResultProbability(eloDiff, 2);
434
+ double PElostat = btRes.ElostatProbability(eloDiff);
435
+
436
+ vExpectedLosses[Index] += PLoss;
437
+ vExpectedDraws[Index] += PDraw;
438
+ vExpectedWins[Index] += PWin;
439
+ vExpectedElostat[Index] += PElostat;
440
+ }
441
+ }
442
+ }
443
+
444
+ //
445
+ // Integrals
446
+ //
447
+ double TotalLW = 0.0;
448
+ double TotalDD = 0.0;
449
+ double TotalD = 0.0;
450
+
451
+ for (int i = 0; i < Intervals; i++)
452
+ {
453
+ double g = vGames[i];
454
+
455
+ TotalLW += vLosses[i] * vWins[i] / (g * g);
456
+ TotalDD += vDraws[i] * vDraws[i] / (g * g);
457
+ TotalD += vDraws[i] / g;
458
+ }
459
+
460
+ //
461
+ // Print histogram data
462
+ //
463
+ for (int i = 0; i < Intervals; i++)
464
+ if (vGames[i])
465
+ {
466
+ double g = vGames[i];
467
+ double L = vLosses[i] / g;
468
+ double D = vDraws[i] / g;
469
+ double W = vWins[i] / g;
470
+
471
+ out << vEloDiff[i] / g << ' ';
472
+ out << vGames[i] << ' ';
473
+ out << L << ' ';
474
+ out << D << ' ';
475
+ out << W << ' ';
476
+ out << W + 0.5 * D << ' ';
477
+ out << vExpectedLosses[i] / g << ' ';
478
+ out << vExpectedDraws[i] / g << ' ';
479
+ out << vExpectedWins[i] / g << ' ';
480
+ out << (vExpectedWins[i] + 0.5 * vExpectedDraws[i]) / g << ' ';
481
+ out << vExpectedElostat[i] / g << ' ';
482
+
483
+ double x = NormInv(Confidence);
484
+ double LDev = x * std::sqrt(L * (1 - L) / g);
485
+ double DDev = x * std::sqrt(D * (1 - D) / g);
486
+ double WDev = x * std::sqrt(D * (1 - D) / g);
487
+
488
+ out << L - LDev << ' ';
489
+ out << D - DDev << ' ';
490
+ out << W - WDev << ' ';
491
+ out << L + LDev << ' ';
492
+ out << D + DDev << ' ';
493
+ out << W + WDev << ' ';
494
+
495
+ out << L * W / TotalLW << ' ';
496
+ out << D * D / TotalDD << ' ';
497
+ out << D / TotalD << ' ';
498
+
499
+ out << '\n';
500
+ }
501
+ }
502
+ break;
503
+
504
+ case IDC_PlotDraw: ///////////////////////////////////////////////////////
505
+ {
506
+ int GroupSize = 100;
507
+ double MaxDiff = 100;
508
+ std::istringstream(pszParameters) >> GroupSize >> MaxDiff;
509
+
510
+ //
511
+ // Filter out games with a big rating difference
512
+ //
513
+ CResultSet rsFiltered;
514
+ for (int i = rs.GetGames(); --i >= 0;)
515
+ {
516
+ double Diff = bt.GetElo(rs.GetWhite(i)) - bt.GetElo(rs.GetBlack(i));
517
+ if (std::fabs(Diff) < MaxDiff)
518
+ rsFiltered.Append(rs.GetWhite(i), rs.GetBlack(i), rs.GetResult(i));
519
+ }
520
+ std::cerr << rsFiltered.GetGames() << " games left after filtering\n";
521
+
522
+ //
523
+ // Sort games according to average rating
524
+ //
525
+ std::vector<int> vOrder(rsFiltered.GetGames());
526
+ std::vector<double> vAverage(rsFiltered.GetGames());
527
+ {
528
+ for (int i = rsFiltered.GetGames(); --i >= 0;)
529
+ {
530
+ vOrder[i] = i;
531
+ vAverage[i] = bt.GetElo(rs.GetWhite(i)) + bt.GetElo(rs.GetBlack(i));
532
+ }
533
+ std::sort(vOrder.begin(), vOrder.end(), CIndirectCompare<double>(&vAverage[0]));
534
+ }
535
+
536
+ //
537
+ // Number of draws for each group of GroupSize players, starting
538
+ // from the top players
539
+ //
540
+ int Index = 0;
541
+ for (int Group = rsFiltered.GetGames() / GroupSize; --Group >= 0;)
542
+ {
543
+ int Draws = 0;
544
+ double TotalRating = 0;
545
+ for (int i = GroupSize; --i >= 0;)
546
+ {
547
+ int g = vOrder[Index++];
548
+ if (rsFiltered.GetResult(g) == 1)
549
+ Draws++;
550
+ TotalRating += vAverage[g];
551
+ }
552
+ CCDistribution cdist(Resolution, 0.0, 1.0);
553
+ cdist.SetBinomialPosterior(GroupSize, Draws);
554
+ out << TotalRating / (2 * GroupSize) << ' ';
555
+ out << double(Draws) / double(GroupSize) << ' ';
556
+ out << cdist.GetLowerValue(Confidence) << ' ';
557
+ out << cdist.GetUpperValue(Confidence) << '\n';
558
+ }
559
+ }
560
+ break;
561
+
562
+ case IDC_Ratings: ////////////////////////////////////////////////////////
563
+ {
564
+ int MinGames = 1;
565
+ std::string sFileName;
566
+ int fFullRank = 0;
567
+
568
+ std::istringstream(pszParameters) >> MinGames >> sFileName >> fFullRank;
569
+ if (MinGames < 1)
570
+ MinGames = 1;
571
+
572
+ //
573
+ // Read a list of player names
574
+ //
575
+ std::ifstream ifsNames(sFileName.c_str());
576
+ std::set<std::string> setNames;
577
+ while (1)
578
+ {
579
+ std::string s;
580
+ ReadLineToString(s, ifsNames);
581
+ if (ifsNames)
582
+ setNames.insert(s);
583
+ else
584
+ break;
585
+ }
586
+
587
+ std::sort(vPermutation.begin(),
588
+ vPermutation.end(),
589
+ CIndirectCompare<double>(bt.GetElo()));
590
+
591
+ int Width = MaxNameLength;
592
+ if (Width < 4)
593
+ Width = 4;
594
+
595
+ CCondensedResults crsNoPrior(rs);
596
+
597
+ std::ios::fmtflags f = out.flags();
598
+ out.setf(std::ios::right, std::ios::adjustfield);
599
+ out << std::setw(3) << "Rank" << ' ';
600
+ out.setf(std::ios::left, std::ios::adjustfield);
601
+ out << std::setw(Width) << "Name" << ' ';
602
+ out.setf(std::ios::right, std::ios::adjustfield);
603
+ out << std::setw(5) << "Elo" << ' ';
604
+ out << std::setw(4) << " +" << ' ';
605
+ out << std::setw(4) << " -" << ' ';
606
+ out << std::setw(5) << "games" << ' ';
607
+ out << std::setw(5) << "score" << ' ';
608
+ out << std::setw(5) << "oppo." << ' ';
609
+ out << std::setw(5) << "draws" << ' ';
610
+ out << '\n';
611
+
612
+ const double *pElo = bt.GetElo();
613
+ for (int i = 0, Counter = 0; i < crs.GetPlayers(); i++)
614
+ {
615
+ int j = vPermutation[i];
616
+ float Games = crsNoPrior.CountGames(j);
617
+ if (Games >= MinGames &&
618
+ (setNames.size() == 0 || setNames.find(vecName[j]) != setNames.end()))
619
+ {
620
+ Counter++;
621
+ double Score = double(crsNoPrior.Score(j)) / 2;
622
+ out.setf(std::ios::right, std::ios::adjustfield);
623
+ if (fFullRank)
624
+ out << std::setw(4) << i + 1 << ' ';
625
+ else
626
+ out << std::setw(4) << Counter << ' ';
627
+ out.setf(std::ios::left, std::ios::adjustfield);
628
+ out << std::setw(Width) << vecName[j] << ' ';
629
+ out.setf(std::ios::right, std::ios::adjustfield);
630
+ out << std::setw(5) << RoundDouble(EloScale * bt.GetElo(j) + eloOffset) << ' ';
631
+ out << std::setw(4) << RoundDouble(EloScale * veloUpper[j]) << ' ';
632
+ out << std::setw(4) << RoundDouble(EloScale * veloLower[j]) << ' ';
633
+ out << std::setw(5) << Games << ' ';
634
+ out << std::setw(4) << RoundDouble(100 * Score / Games) << "% ";
635
+ out << std::setw(5) <<
636
+ RoundDouble(EloScale * crs.AverageOpponent(j, pElo) + eloOffset) << ' ';
637
+ out << std::setw(4) << RoundDouble(100 * crsNoPrior.CountDraws(j) /
638
+ double(Games)) << "% ";
639
+ out << '\n';
640
+ }
641
+ }
642
+
643
+ out.flags(f);
644
+ }
645
+ break;
646
+
647
+ case IDC_Details: ////////////////////////////////////////////////////////
648
+ {
649
+ std::sort(vPermutation.begin(),
650
+ vPermutation.end(),
651
+ CIndirectCompare<double>(bt.GetElo()));
652
+
653
+ std::ios::fmtflags f = out.flags();
654
+ int precision = out.precision();
655
+
656
+ out.setf(std::ios::fixed, std::ios::floatfield);
657
+ out.precision(1);
658
+
659
+ int Width = MaxNameLength;
660
+ if (Width < 4)
661
+ Width = 4;
662
+
663
+ CCondensedResults crsNoPrior(rs);
664
+
665
+ for (int i = 0, Counter = 0; i < crs.GetPlayers(); i++)
666
+ {
667
+ int j = vPermutation[i];
668
+ float Games = crsNoPrior.CountGames(j);
669
+ Counter++;
670
+ double Score = double(crsNoPrior.Score(j)) / 2;
671
+ out.setf(std::ios::right, std::ios::adjustfield);
672
+ out << std::setw(4) << Counter << ' ';
673
+ out.setf(std::ios::left, std::ios::adjustfield);
674
+ out << std::setw(Width) << vecName[j] << ' ';
675
+ out.setf(std::ios::right, std::ios::adjustfield);
676
+ out << std::setw(5) << RoundDouble(EloScale * bt.GetElo(j) + eloOffset) << ' ';
677
+ out << std::setw(5) << Games << " (";
678
+ out << std::setw(5) << Score << " : ";
679
+ out << std::setw(5) << Games-Score << ")\n";
680
+
681
+ //
682
+ // Sort opponents
683
+ //
684
+ std::vector<int> vOpponentIndex(crsNoPrior.GetOpponents(j));
685
+ std::vector<double> vOpponentElo(crsNoPrior.GetOpponents(j));
686
+ for (int k = crsNoPrior.GetOpponents(j); --k >= 0;)
687
+ {
688
+ const CCondensedResult &cr = crsNoPrior.GetCondensedResult(j, k);
689
+ vOpponentIndex[k] = k;
690
+ vOpponentElo[k] = bt.GetElo(cr.Opponent);
691
+ }
692
+ std::sort(vOpponentIndex.begin(),
693
+ vOpponentIndex.end(),
694
+ CIndirectCompare<double>(&vOpponentElo[0]));
695
+
696
+ //
697
+ // Print opponent data
698
+ //
699
+ for (int k = 0; k < crsNoPrior.GetOpponents(j); k++)
700
+ {
701
+ int l = vOpponentIndex[k];
702
+ const CCondensedResult &cr = crsNoPrior.GetCondensedResult(j, l);
703
+ out.setf(std::ios::right, std::ios::adjustfield);
704
+ out << std::setw(4) << ' ' << ' ';
705
+ out.setf(std::ios::left, std::ios::adjustfield);
706
+ out << std::setw(Width) << ' ' << ' ';
707
+ out.setf(std::ios::right, std::ios::adjustfield);
708
+ out << std::setw(5) << ' ' << ' ';
709
+ out << std::setw(5) << cr.Games() << " (";
710
+ out << std::setw(5) << cr.Score() << " : ";
711
+ out << std::setw(5) << cr.Games()-cr.Score() << ") ";
712
+ out.setf(std::ios::left, std::ios::adjustfield);
713
+ out << std::setw(Width) << vecName[cr.Opponent] << ' ';
714
+ out.setf(std::ios::right, std::ios::adjustfield);
715
+ out << std::setw(5) << RoundDouble(EloScale * bt.GetElo(cr.Opponent) + eloOffset) << '\n';
716
+ }
717
+ }
718
+ out.flags(f);
719
+ out.precision(precision);
720
+ }
721
+ break;
722
+
723
+ case IDC_Offset: /////////////////////////////////////////////////////////
724
+ {
725
+ std::istringstream iss(pszParameters);
726
+ float elo = eloOffset;
727
+ iss >> elo;
728
+
729
+ std::string sName;
730
+ iss >> sName; // ??? there must be a better way
731
+ if (sName != "")
732
+ {
733
+ char c = 0;
734
+ while (iss.get(c))
735
+ sName += c;
736
+
737
+ int fFound = 0;
738
+ for (int i = 0; i < crs.GetPlayers(); i++)
739
+ if (sName == vecName[i])
740
+ {
741
+ fFound = 1;
742
+ eloOffset = elo - EloScale * bt.GetElo(i);
743
+ break;
744
+ }
745
+
746
+ if (!fFound)
747
+ out << "Error: unknow player " << sName << '\n';
748
+ }
749
+ else
750
+ GetSet<double>(eloOffset, pszParameters, out);
751
+ }
752
+ break;
753
+
754
+ case IDC_Scale: //////////////////////////////////////////////////////////
755
+ GetSet<double>(EloScale, pszParameters, out);
756
+ break;
757
+
758
+ case IDC_MM: /////////////////////////////////////////////////////////////
759
+ {
760
+ int fThetaW = 0;
761
+ int fThetaD = 0;
762
+ std::istringstream(pszParameters) >> fThetaW >> fThetaD;
763
+ CClockTimer timer;
764
+ bt.MinorizationMaximization(fThetaW, fThetaD);
765
+ out << timer.GetInterval() << '\n';
766
+ ComputeVariance();
767
+ {
768
+ double x = std::pow(10.0, -bt.GetDrawElo() / 400);
769
+ EloScale = x * 4.0 / ((1 + x) * (1 + x));
770
+ }
771
+ fLOSComputed = 0;
772
+ }
773
+ break;
774
+
775
+ case IDC_ELOstat: ////////////////////////////////////////////////////////
776
+ {
777
+ crs.AddPrior(-Prior);
778
+ CClockTimer timer;
779
+ bt.ELOstat();
780
+ bt.ELOstatIntervals(&veloLower[0], &veloUpper[0]);
781
+ out << timer.GetInterval() << '\n';
782
+ crs.AddPrior(Prior);
783
+ EloScale = 1.0;
784
+ fLOSComputed = 0;
785
+ }
786
+ break;
787
+
788
+ case IDC_Elo: ////////////////////////////////////////////////////////////
789
+ {
790
+ std::istringstream is(pszParameters);
791
+ unsigned Player = 0;
792
+ is >> Player;
793
+ if (Player < unsigned(crs.GetPlayers()))
794
+ {
795
+ double elo = EloScale * bt.GetElo(Player) + eloOffset;
796
+ is >> elo;
797
+ bt.SetElo(Player, elo);
798
+ out << "Rating of player " << Player << " (" << vecName[Player];
799
+ out << ") is " << elo << ".\n";
800
+ }
801
+ else
802
+ out << "Player out of range (should be in 0-" <<
803
+ crs.GetPlayers() - 1 << ")\n";
804
+ }
805
+ break;
806
+
807
+ case IDC_JointDist: //////////////////////////////////////////////////////
808
+ {
809
+ int Player = -1;
810
+ std::istringstream(pszParameters) >> Player;
811
+
812
+ CClockTimer timer;
813
+ CDistributionCollection dc(crs.GetPlayers(),
814
+ Resolution,
815
+ eloMin,
816
+ eloMax);
817
+ CJointBayesian jb(rs, dc, bt);
818
+ jb.RunComputation();
819
+ out << timer.GetInterval() << '\n';
820
+ for (int i = crs.GetPlayers(); --i >= 0;)
821
+ {
822
+ veloLower[i] = bt.GetElo(i) - dc.GetDistribution(i).
823
+ GetLowerValue(Confidence);
824
+ veloUpper[i] = dc.GetDistribution(i).
825
+ GetUpperValue(Confidence) - bt.GetElo(i);
826
+ if (i == Player)
827
+ {
828
+ CCDistributionCUI cdcui(dc.GetDistribution(i), this);
829
+ cdcui.MainLoop(in, out);
830
+ }
831
+ }
832
+ }
833
+ break;
834
+
835
+ case IDC_ExactDist: //////////////////////////////////////////////////////
836
+ {
837
+ int Player = -1;
838
+ std::istringstream(pszParameters) >> Player;
839
+
840
+ CClockTimer timer;
841
+ CCDistribution cdist(Resolution, eloMin, eloMax);
842
+
843
+ for (int i = crs.GetPlayers(); --i >= 0;)
844
+ {
845
+ if (i % 10 == 0)
846
+ {
847
+ out << i << " left \r";
848
+ out.flush();
849
+ }
850
+ bt.GetPlayerDist(i, cdist);
851
+ veloLower[i] = bt.GetElo(i) - cdist.GetLowerValue(Confidence);
852
+ veloUpper[i] = cdist.GetUpperValue(Confidence) - bt.GetElo(i);
853
+ if (i == Player)
854
+ {
855
+ CCDistributionCUI cdcui(cdist, this);
856
+ cdcui.MainLoop(in, out);
857
+ }
858
+ }
859
+
860
+ out << timer.GetInterval() << " \n";
861
+ }
862
+ break;
863
+
864
+ case IDC_Variance: ///////////////////////////////////////////////////////
865
+ ComputeVariance();
866
+ break;
867
+
868
+ case IDC_Covariance: /////////////////////////////////////////////////////
869
+ {
870
+ bt.ComputeCovariance();
871
+ bt.ComputeLikelihoodOfSuperiority();
872
+
873
+ const CMatrix &mCovariance = bt.GetCovariance();
874
+ CCDistribution cdist(1000, -10, 10);
875
+ cdist.SetNormal(0, 1);
876
+ double x = cdist.GetUpperValue(Confidence);
877
+ for (int i = crs.GetPlayers(); --i >= 0;)
878
+ veloLower[i] = veloUpper[i] = x * std::sqrt(mCovariance.GetElement(i, i));
879
+
880
+ fLOSComputed = 1;
881
+ }
882
+ break;
883
+
884
+ case IDC_LOS: ////////////////////////////////////////////////////////////
885
+ {
886
+ if (!fLOSComputed)
887
+ {
888
+ bt.ComputeCovariance();
889
+ bt.ComputeLikelihoodOfSuperiority();
890
+ }
891
+ const CMatrix &mLOS = bt.GetLikelihoodOfSuperiority();
892
+
893
+ //
894
+ // Parse command parameters
895
+ //
896
+ int First = 0;
897
+ int Players = mLOS.GetRows();
898
+ int Width = 3;
899
+ std::istringstream(pszParameters) >> First >> Players >> Width;
900
+ if (Width < 2)
901
+ Width = 2;
902
+ if (First < 0)
903
+ First = 0;
904
+ if (First + Players > mLOS.GetRows())
905
+ Players = mLOS.GetRows() - First;
906
+ if (Players <= 0)
907
+ {
908
+ First = 0;
909
+ Players = mLOS.GetRows();
910
+ }
911
+ const double Mult = std::pow(10.0, (Width > 8 ? 8 : Width) - 1);
912
+
913
+ //
914
+ // Sort players according to rating
915
+ //
916
+ std::sort(vPermutation.begin(),
917
+ vPermutation.end(),
918
+ CIndirectCompare<double>(bt.GetElo()));
919
+
920
+ //
921
+ // Column headers with Width-1 letters of each player
922
+ //
923
+ out << std::setw(MaxNameLength) << ' ' << ' ';
924
+ for (int p = First; p < First + Players; p++)
925
+ {
926
+ int i = vPermutation[p];
927
+ std::string s = vecName[i].substr(0, Width - 1);
928
+ out << std::setw(Width) << s;
929
+ }
930
+ out << '\n';
931
+ out.flush();
932
+
933
+ //
934
+ // Two nested loops to print the matrix
935
+ //
936
+ for (int p = First; p < First + Players; p++)
937
+ {
938
+ int i = vPermutation[p];
939
+ out.setf(std::ios::left, std::ios::adjustfield);
940
+ out << std::setw(MaxNameLength) << vecName[i] << ' ';
941
+ out.setf(std::ios::right, std::ios::adjustfield);
942
+
943
+ for (int q = First; q < First + Players; q++)
944
+ {
945
+ if (p != q)
946
+ {
947
+ int j = vPermutation[q];
948
+ out << std::setw(Width) << int(mLOS.GetElement(i, j) * Mult);
949
+ }
950
+ else
951
+ out << std::setw(Width) << ' ';
952
+ }
953
+ out << '\n';
954
+ }
955
+ }
956
+ break;
957
+
958
+ case IDC_AdvDist: ////////////////////////////////////////////////////////
959
+ {
960
+ CCDistribution cdist(Resolution, eloMin, eloMax);
961
+ bt.GetAdvantageDist(cdist);
962
+ out << cdist.GetLowerValue(Confidence);
963
+ out << " <= " << cdist.GetMostLikelyValue();
964
+ out << " <= " << cdist.GetUpperValue(Confidence) << '\n';
965
+ CCDistributionCUI cdcui(cdist, this);
966
+ cdcui.MainLoop(in, out);
967
+ }
968
+ break;
969
+
970
+ case IDC_DrawDist: ///////////////////////////////////////////////////////
971
+ {
972
+ CCDistribution cdist(Resolution, eloMin < 0 ? 0 : eloMin, eloMax);
973
+ bt.GetDrawEloDist(cdist);
974
+ out << cdist.GetLowerValue(Confidence);
975
+ out << " <= " << cdist.GetMostLikelyValue();
976
+ out << " <= " << cdist.GetUpperValue(Confidence) << '\n';
977
+ CCDistributionCUI cdcui(cdist, this);
978
+ cdcui.MainLoop(in, out);
979
+ }
980
+ break;
981
+
982
+ case IDC_PairStats: //////////////////////////////////////////////////////
983
+ {
984
+ //
985
+ // Read command parameters and print player names
986
+ //
987
+ int i = 0;
988
+ int j = 0;
989
+ std::istringstream(pszParameters) >> i >> j;
990
+ if (i < 0 || i >= crs.GetPlayers() ||
991
+ j < 0 || j >= crs.GetPlayers() ||
992
+ i == j)
993
+ out << "error: bad player numbers\n";
994
+ else
995
+ {
996
+ out << "-- pairstats between i = " << i << ", and j = " << j << '\n';
997
+ out << "Name[i] = " << vecName[i] << '\n';
998
+ out << "Name[j] = " << vecName[j] << '\n';
999
+ out << "elo[i] - elo[j] = ";
1000
+ out << EloScale * (bt.GetElo(i) - bt.GetElo(j)) << '\n';
1001
+ }
1002
+
1003
+ //
1004
+ // Build the set of results between these two players
1005
+ //
1006
+ CResultSet rsLocal(rs, i, j);
1007
+ out << "Games = " << rsLocal.GetGames() << '\n';
1008
+ if (rsLocal.GetGames())
1009
+ {
1010
+ CCondensedResults crsLocal(rsLocal);
1011
+ {
1012
+ CCondensedResult &cr = crsLocal.GetCondensedResult(0, 0);
1013
+ out << "w_ij = " << cr.w_ij << '\n';
1014
+ out << "d_ij = " << cr.d_ij << '\n';
1015
+ out << "l_ij = " << cr.l_ij << '\n';
1016
+ out << "w_ji = " << cr.w_ji << '\n';
1017
+ out << "d_ji = " << cr.d_ji << '\n';
1018
+ out << "l_ji = " << cr.l_ji << '\n';
1019
+ cr = crs.FindOpponent(i, j);
1020
+ cr.Opponent = 1;
1021
+ }
1022
+ {
1023
+ CCondensedResult &cr = crsLocal.GetCondensedResult(1, 0);
1024
+ cr = crs.FindOpponent(j, i);
1025
+ cr.Opponent = 0;
1026
+ }
1027
+
1028
+ //
1029
+ // Compute and print elo ratings
1030
+ //
1031
+ CBradleyTerry btLocal(crsLocal);
1032
+ btLocal.SetAdvantage(bt.GetAdvantage());
1033
+ btLocal.SetDrawElo(bt.GetDrawElo());
1034
+ btLocal.MinorizationMaximization(0, 0);
1035
+ out << "elo[i] - elo[j] = ";
1036
+ out << EloScale * (btLocal.GetElo(0) - btLocal.GetElo(1)) << '\n';
1037
+ }
1038
+ }
1039
+ break;
1040
+
1041
+ default: /////////////////////////////////////////////////////////////////
1042
+ return CConsoleUI::ProcessCommand(pszCommand, pszParameters, in, out);
1043
+ }
1044
+
1045
+ return PC_Continue;
1046
+ }