elo-ratings 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +23 -0
  6. data/Rakefile +54 -0
  7. data/VERSION +1 -0
  8. data/elo-ratings.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/extconf.rb +6 -0
  63. data/ext/bayeselo/list.h +367 -0
  64. data/ext/bayeselo/listi.h +125 -0
  65. data/ext/bayeselo/move.cpp +249 -0
  66. data/ext/bayeselo/move.h +139 -0
  67. data/ext/bayeselo/pgn.h +62 -0
  68. data/ext/bayeselo/pgnlex.cpp +432 -0
  69. data/ext/bayeselo/pgnlex.h +105 -0
  70. data/ext/bayeselo/pgnstr.cpp +126 -0
  71. data/ext/bayeselo/piece.h +44 -0
  72. data/ext/bayeselo/player.h +31 -0
  73. data/ext/bayeselo/position.h +89 -0
  74. data/ext/bayeselo/random.cpp +114 -0
  75. data/ext/bayeselo/random.h +63 -0
  76. data/ext/bayeselo/rb_bayeselo.cpp +76 -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/bayeselo.rb +6 -0
  86. data/lib/bayeselo/bayeselo.rb +11 -0
  87. data/lib/bayeselo/c_bayeselo.rb +7 -0
  88. data/test/bayeselo/test_bayeselo.rb +33 -0
  89. data/test/bayeselo/test_c_bayeselo.rb +84 -0
  90. data/test/helper.rb +18 -0
  91. metadata +226 -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
+ }