icu_ratings 1.4.0 → 1.5.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.
- data/README.rdoc +6 -6
- data/lib/icu_ratings/player.rb +3 -4
- data/lib/icu_ratings/result.rb +2 -15
- data/lib/icu_ratings/tournament.rb +37 -26
- data/lib/icu_ratings/version.rb +1 -1
- data/spec/tournament_spec.rb +205 -33
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -4,11 +4,11 @@ For calculating the Elo ratings of players in a chess tournament. The software i
|
|
4
4
|
the Irish Chess Union's existing rating software written in Microsoft Visual Basic and
|
5
5
|
intended to replace it in the near future.
|
6
6
|
|
7
|
-
The rating calculations are
|
8
|
-
of established players
|
7
|
+
The rating calculations are the same as FIDE's for tournaments that consist entirely
|
8
|
+
of established players with the exception of player bonuses (which can be turned off)
|
9
|
+
and different rules for assigning K-factors.
|
9
10
|
However, the ICU has it's own peculiar way of dealing with unrated players (players
|
10
|
-
with only a provisional rating or without any prior rating) which is
|
11
|
-
FIDE's.
|
11
|
+
with only a provisional rating or without any prior rating) which is different to FIDE's.
|
12
12
|
|
13
13
|
== Install
|
14
14
|
|
@@ -35,9 +35,9 @@ Then add results (see ICU::RatedResult for details):
|
|
35
35
|
t.add_result(4, 2, 1, 'D') # players 1 and 2 drew in round 4
|
36
36
|
# ...
|
37
37
|
|
38
|
-
Then call the <em>rate!</em> method.
|
38
|
+
Then call the <em>rate!</em> method using the recommended version of the algorithm (see ICU::RatedTournament).
|
39
39
|
|
40
|
-
t.rate!
|
40
|
+
t.rate!(version: 2)
|
41
41
|
|
42
42
|
If no exceptions have been raised yet, the tournament is now rated and the
|
43
43
|
main results of the rating calculations can be extracted by querying the
|
data/lib/icu_ratings/player.rb
CHANGED
@@ -241,8 +241,9 @@ module ICU
|
|
241
241
|
@bonus = 0
|
242
242
|
end
|
243
243
|
|
244
|
-
def rate! # :nodoc:
|
244
|
+
def rate!(update_bonus=false) # :nodoc:
|
245
245
|
@results.each { |r| r.rate!(self) }
|
246
|
+
@bonus_rating = @rating + @bonus + rating_change if update_bonus && @bonus_rating
|
246
247
|
end
|
247
248
|
|
248
249
|
def estimate_performance # :nodoc:
|
@@ -273,9 +274,7 @@ module ICU
|
|
273
274
|
stable
|
274
275
|
end
|
275
276
|
|
276
|
-
def calculate_bonus
|
277
|
-
# New in December 2012 - see http://ratings.icu.ie/articles/18 (Part 2).
|
278
|
-
return if !allow_new_bonus && @bonus == 0
|
277
|
+
def calculate_bonus # :nodoc:
|
279
278
|
# Rounding is performed in places to emulate the older MSAccess implementation.
|
280
279
|
return if @type != :rated || @kfactor <= 24 || @results.size <= 4 || @rating >= 2100
|
281
280
|
change = rating_change
|
data/lib/icu_ratings/result.rb
CHANGED
@@ -85,25 +85,12 @@ module ICU
|
|
85
85
|
#
|
86
86
|
# == After the Tournament is Rated
|
87
87
|
#
|
88
|
-
# The main rating calculations are
|
88
|
+
# The main rating calculations are available from player methods (see ICU::RatedPlayer)
|
89
89
|
# but additional details are available via methods of each player's individual results:
|
90
90
|
# _expected_score_, _rating_change_.
|
91
91
|
#
|
92
92
|
class RatedResult
|
93
|
-
|
94
|
-
def round
|
95
|
-
@round
|
96
|
-
end
|
97
|
-
|
98
|
-
# The player's opponent (an instance of ICU::RatedPlayer).
|
99
|
-
def opponent
|
100
|
-
@opponent
|
101
|
-
end
|
102
|
-
|
103
|
-
# The player's score in this game (1.0, 0.5 or 0.0).
|
104
|
-
def score
|
105
|
-
@score
|
106
|
-
end
|
93
|
+
attr_reader :round, :opponent, :score
|
107
94
|
|
108
95
|
# After the tournament has been rated, this returns the expected score (between 0 and 1)
|
109
96
|
# for the player based on the rating difference with the opponent scaled by 400.
|
@@ -57,27 +57,20 @@ module ICU
|
|
57
57
|
#
|
58
58
|
# See ICU::RatedPlayer and ICU::RatedResult for more details.
|
59
59
|
#
|
60
|
-
# The <em>rate!</em> method takes
|
60
|
+
# The <em>rate!</em> method takes an optional <em>version</em> argument to control the precise algorithm, for example:
|
61
61
|
#
|
62
|
-
# t.rate!(
|
62
|
+
# t.rate!(version: 2)
|
63
63
|
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
# * <em>max_iterations2</em>: the maximum number of re-estimation iterations after the bonus calculation (default <b>1</b>)
|
68
|
-
# * <em>threshold</em>: the maximum difference allowed between re-estimated ratings in a stabe solution (default <b>0.5</b>)
|
69
|
-
# * <em>phase_2_bonuses</em>: allow new bonuses in the second phase of calculation (default <b>true</b>)
|
70
|
-
#
|
71
|
-
# The defaults correspond to the original algorithm. However, it is recommended not to use the defaults for
|
72
|
-
# <em>max_iterations2</em> and <em>phase_2_bonuses</em> but to use <em>30</em> and <em>false</em> instead.
|
73
|
-
# See <a href="http://ratings.icu.ie/articles/18">this article</a> for more details.
|
64
|
+
# Without a version number or with version <em>0</em>, the original pre-2012 algorithm is used. However, some improvements
|
65
|
+
# have since been found (see http://ratings.icu.ie/articles/18 for more details) and currently
|
66
|
+
# the recommended version to use is <b>2</b>.
|
74
67
|
#
|
75
68
|
# == Error Handling
|
76
69
|
#
|
77
70
|
# Some of the above methods have the potential to raise RuntimeError exceptions.
|
78
|
-
# In the case of _add_player_ and _add_result_, the use of invalid arguments
|
79
|
-
#
|
80
|
-
# exception if the iterative algorithm it uses to estimate performance ratings
|
71
|
+
# In the case of _add_player_ and _add_result_, the use of invalid arguments would
|
72
|
+
# cause such an error. Theoretically, the <em>rate!</em> method could also throw
|
73
|
+
# an exception if the iterative algorithm it uses to estimate performance ratings
|
81
74
|
# of unrated players failed to converge. However an instance of non-convergence
|
82
75
|
# has yet to be observed in practice.
|
83
76
|
#
|
@@ -113,17 +106,35 @@ module ICU
|
|
113
106
|
|
114
107
|
# Rate the tournament. Called after all players and results have been added.
|
115
108
|
def rate!(opt={})
|
116
|
-
|
117
|
-
|
118
|
-
phase_2_bonuses =
|
119
|
-
|
109
|
+
# The original algorithm (version 0).
|
110
|
+
max_iterations = [30, 1]
|
111
|
+
phase_2_bonuses = true
|
112
|
+
update_bonuses = false
|
113
|
+
threshold = 0.5
|
114
|
+
|
115
|
+
# New versions of the algorithm.
|
116
|
+
version = opt[:version].to_i
|
117
|
+
if version >= 1
|
118
|
+
# See http://ratings.icu.ie/articles/18 (Part 1)
|
119
|
+
max_iterations[1] = 30
|
120
|
+
end
|
121
|
+
if version >= 2
|
122
|
+
# See http://ratings.icu.ie/articles/18 (Part 2)
|
123
|
+
phase_2_bonuses = false
|
124
|
+
update_bonuses = true
|
125
|
+
threshold = 0.1
|
126
|
+
end
|
127
|
+
|
128
|
+
# Phase 1.
|
120
129
|
players.each { |p| p.init }
|
121
|
-
@iterations1 = performance_ratings(
|
130
|
+
@iterations1 = performance_ratings(max_iterations[0], threshold)
|
122
131
|
players.each { |p| p.rate! }
|
132
|
+
|
133
|
+
# Phase 2.
|
123
134
|
if !no_bonuses && calculate_bonuses > 0
|
124
|
-
players.each { |p| p.rate! }
|
125
|
-
@iterations2 = performance_ratings(
|
126
|
-
calculate_bonuses
|
135
|
+
players.each { |p| p.rate!(update_bonuses) }
|
136
|
+
@iterations2 = performance_ratings(max_iterations[1], threshold)
|
137
|
+
calculate_bonuses if phase_2_bonuses
|
127
138
|
else
|
128
139
|
@iterations2 = 0
|
129
140
|
end
|
@@ -157,7 +168,7 @@ module ICU
|
|
157
168
|
@player = Hash.new
|
158
169
|
end
|
159
170
|
|
160
|
-
# Calculate performance ratings either iteratively
|
171
|
+
# Calculate performance ratings either iteratively up to a maximum number.
|
161
172
|
def performance_ratings(max, thresh)
|
162
173
|
stable, count = false, 0
|
163
174
|
while !stable && count < max
|
@@ -170,8 +181,8 @@ module ICU
|
|
170
181
|
end
|
171
182
|
|
172
183
|
# Calculate bonuses for all players and return the number who got one.
|
173
|
-
def calculate_bonuses
|
174
|
-
@player.values.inject(0) { |t,p| t + (p.calculate_bonus
|
184
|
+
def calculate_bonuses
|
185
|
+
@player.values.inject(0) { |t,p| t + (p.calculate_bonus ? 1 : 0) }
|
175
186
|
end
|
176
187
|
end
|
177
188
|
end
|
data/lib/icu_ratings/version.rb
CHANGED
data/spec/tournament_spec.rb
CHANGED
@@ -1218,7 +1218,7 @@ module ICU
|
|
1218
1218
|
@t.iterations2.should be_nil
|
1219
1219
|
end
|
1220
1220
|
|
1221
|
-
it "should produce inconsistent results with
|
1221
|
+
it "should produce inconsistent results with original algorithm" do
|
1222
1222
|
@t.rate!
|
1223
1223
|
|
1224
1224
|
@p.new_rating.should be_within(0.5).of(763) # the original calculation
|
@@ -1239,8 +1239,8 @@ module ICU
|
|
1239
1239
|
@t.iterations2.should == 1
|
1240
1240
|
end
|
1241
1241
|
|
1242
|
-
it "should produce consistent results with
|
1243
|
-
@t.rate!(
|
1242
|
+
it "should produce consistent results with version 1 algorithm" do
|
1243
|
+
@t.rate!(version: 1)
|
1244
1244
|
|
1245
1245
|
@p.new_rating.should_not be_within(0.5).of(763) # the new calculation is different
|
1246
1246
|
|
@@ -1265,7 +1265,7 @@ module ICU
|
|
1265
1265
|
before(:each) do
|
1266
1266
|
@t = ICU::RatedTournament.new(desc: "Bunratty Minor 2012")
|
1267
1267
|
|
1268
|
-
# Add the
|
1268
|
+
# Add the players of most interest (Sasha-Ettore Faleschini and his opponents).
|
1269
1269
|
@p = @t.add_player(1752, desc: "Sasha-Ettore Faleschini")
|
1270
1270
|
@o1 = @t.add_player(1748, desc: "John P. Dunne", rating: 946, kfactor: 40)
|
1271
1271
|
@o2 = @t.add_player(1755, desc: "Jack Fitzgerald", rating: 913, kfactor: 40)
|
@@ -1276,57 +1276,57 @@ module ICU
|
|
1276
1276
|
|
1277
1277
|
# Add all the other players.
|
1278
1278
|
@t.add_player(1730, desc: "Jeffrey Alfred", rating: 1058, kfactor: 40)
|
1279
|
-
@t.add_player(1731, desc: "Suliman Ali", rating: 1166,
|
1279
|
+
@t.add_player(1731, desc: "Suliman Ali", rating: 1166, games: 17)
|
1280
1280
|
@t.add_player(1733, desc: "Dylan Boland")
|
1281
1281
|
@t.add_player(1734, desc: "Shane Briggs", rating: 1079, kfactor: 24)
|
1282
1282
|
@t.add_player(1735, desc: "Joe Browne", rating: 919, kfactor: 24)
|
1283
|
-
@t.add_player(1736, desc: "Kieran Burke", rating: 765,
|
1283
|
+
@t.add_player(1736, desc: "Kieran Burke", rating: 765, games: 10)
|
1284
1284
|
@t.add_player(1737, desc: "Liam Cadogan", rating: 1002, kfactor: 24)
|
1285
|
-
@t.add_player(1738, desc: "Evan Cahill", rating: 494,
|
1285
|
+
@t.add_player(1738, desc: "Evan Cahill", rating: 494, games: 4)
|
1286
1286
|
@t.add_player(1739, desc: "Joseph Cesar", rating: 751, kfactor: 40)
|
1287
|
-
@t.add_player(1740, desc: "Joshua Cesar", rating: 403,
|
1287
|
+
@t.add_player(1740, desc: "Joshua Cesar", rating: 403, games: 10)
|
1288
1288
|
@t.add_player(1741, desc: "John G. Connolly", rating: 952, kfactor: 32)
|
1289
1289
|
@t.add_player(1742, desc: "Fiona Cormican", rating: 483, kfactor: 32)
|
1290
|
-
@t.add_player(1743, desc: "Joe Cronin", rating: 601,
|
1291
|
-
@t.add_player(1744, desc: "Aaron Daly", rating: 699,
|
1290
|
+
@t.add_player(1743, desc: "Joe Cronin", rating: 601, games: 6)
|
1291
|
+
@t.add_player(1744, desc: "Aaron Daly", rating: 699, games: 12)
|
1292
1292
|
@t.add_player(1745, desc: "Conor Devilly", rating: 676, kfactor: 40)
|
1293
1293
|
@t.add_player(1746, desc: "Charles Dillon")
|
1294
1294
|
@t.add_player(1747, desc: "Jack Donovan")
|
1295
1295
|
@t.add_player(1749, desc: "Thomas Dunne", rating: 887, kfactor: 32)
|
1296
1296
|
@t.add_player(1750, desc: "Michael Eyers", rating: 857, kfactor: 32)
|
1297
|
-
@t.add_player(1751, desc: "Sean Fagan", rating: 243,
|
1298
|
-
@t.add_player(1753, desc: "Victoria Fennell", rating: 166,
|
1297
|
+
@t.add_player(1751, desc: "Sean Fagan", rating: 243, games: 10)
|
1298
|
+
@t.add_player(1753, desc: "Victoria Fennell", rating: 166, games: 11)
|
1299
1299
|
@t.add_player(1754, desc: "Mark Finn-Lynch")
|
1300
|
-
@t.add_player(1756, desc: "Peter Fletcher", rating: 680,
|
1300
|
+
@t.add_player(1756, desc: "Peter Fletcher", rating: 680, games: 18)
|
1301
1301
|
@t.add_player(1757, desc: "Darragh Flynn", rating: 296, kfactor: 40)
|
1302
|
-
@t.add_player(1758, desc: "Geordan Freeman", rating: 413,
|
1302
|
+
@t.add_player(1758, desc: "Geordan Freeman", rating: 413, games: 4)
|
1303
1303
|
@t.add_player(1759, desc: "Ruairi Freeman", rating: 582, kfactor: 40)
|
1304
1304
|
@t.add_player(1760, desc: "Aoife Gallagher")
|
1305
1305
|
@t.add_player(1761, desc: "Hannah Gallagher")
|
1306
1306
|
@t.add_player(1762, desc: "Tommy Gallagher")
|
1307
1307
|
@t.add_player(1763, desc: "Leslie Garabedian")
|
1308
|
-
@t.add_player(1764, desc: "Alexander Gillett", rating: 850,
|
1309
|
-
@t.add_player(1765, desc: "Jan Glegolski", rating: 525,
|
1308
|
+
@t.add_player(1764, desc: "Alexander Gillett", rating: 850, games: 19)
|
1309
|
+
@t.add_player(1765, desc: "Jan Glegolski", rating: 525, games: 16)
|
1310
1310
|
@t.add_player(1767, desc: "Mark Halley", rating: 1280, kfactor: 40)
|
1311
|
-
@t.add_player(1768, desc: "Siobhan Halley", rating: 434,
|
1312
|
-
@t.add_player(1769, desc: "Luke Hayden", rating: 781,
|
1313
|
-
@t.add_player(1770, desc: "Colm Hehir", rating: 564,
|
1314
|
-
@t.add_player(1771, desc: "Donal Hehir", rating: 424,
|
1311
|
+
@t.add_player(1768, desc: "Siobhan Halley", rating: 434, games: 18)
|
1312
|
+
@t.add_player(1769, desc: "Luke Hayden", rating: 781, games: 6)
|
1313
|
+
@t.add_player(1770, desc: "Colm Hehir", rating: 564, games: 16)
|
1314
|
+
@t.add_player(1771, desc: "Donal Hehir", rating: 424, games: 6)
|
1315
1315
|
@t.add_player(1772, desc: "Andrew Ingram", rating: 859, kfactor: 32)
|
1316
1316
|
@t.add_player(1773, desc: "Rory Jackson")
|
1317
1317
|
@t.add_player(1774, desc: "Tom Kearney", rating: 924, kfactor: 40)
|
1318
|
-
@t.add_player(1775, desc: "Jamie Kearns", rating: 753,
|
1318
|
+
@t.add_player(1775, desc: "Jamie Kearns", rating: 753, games: 11)
|
1319
1319
|
@t.add_player(1777, desc: "Thomas Keating", rating: 864, kfactor: 40)
|
1320
1320
|
@t.add_player(1778, desc: "Darragh Kennedy", rating: 1052, kfactor: 40)
|
1321
1321
|
@t.add_player(1779, desc: "Stephen Kennedy", rating: 490, kfactor: 40)
|
1322
1322
|
@t.add_player(1780, desc: "Jonathan Kiely", rating: 1117, kfactor: 24)
|
1323
1323
|
@t.add_player(1781, desc: "Kevin Kilduff", rating: 1116, kfactor: 40)
|
1324
|
-
@t.add_player(1782, desc: "Conor Kirby MacGuill", rating: 410,
|
1324
|
+
@t.add_player(1782, desc: "Conor Kirby MacGuill", rating: 410, games: 9)
|
1325
1325
|
@t.add_player(1783, desc: "Wiktor Kwapinski")
|
1326
1326
|
@t.add_player(1784, desc: "Andrew Kyne-Delaney", rating: 869, kfactor: 40)
|
1327
1327
|
@t.add_player(1785, desc: "Samuel Lenihan", rating: 683, kfactor: 40)
|
1328
1328
|
@t.add_player(1786, desc: "Haoang Li", rating: 667, kfactor: 40)
|
1329
|
-
@t.add_player(1787, desc: "Stephen Li", rating: 880,
|
1329
|
+
@t.add_player(1787, desc: "Stephen Li", rating: 880, games: 17)
|
1330
1330
|
@t.add_player(1788, desc: "Desmond Martin", rating: 1018, kfactor: 24)
|
1331
1331
|
@t.add_player(1789, desc: "Clare McCarrick", rating: 805, kfactor: 40)
|
1332
1332
|
@t.add_player(1790, desc: "Padraig McCullough", rating: 676, kfactor: 24)
|
@@ -1339,7 +1339,7 @@ module ICU
|
|
1339
1339
|
@t.add_player(1797, desc: "Jacob Miller")
|
1340
1340
|
@t.add_player(1799, desc: "Diarmuid Minnock", rating: 760, kfactor: 40)
|
1341
1341
|
@t.add_player(1800, desc: "Michael Morgan", rating: 889, kfactor: 32)
|
1342
|
-
@t.add_player(1801, desc: "Alex Mulligan", rating: 603,
|
1342
|
+
@t.add_player(1801, desc: "Alex Mulligan", rating: 603, games: 17)
|
1343
1343
|
@t.add_player(1802, desc: "Scott Mulligan", rating: 1100, kfactor: 40)
|
1344
1344
|
@t.add_player(1803, desc: "Jessica Mulqueen-Danaher", rating: 286, kfactor: 40)
|
1345
1345
|
@t.add_player(1804, desc: "Christopher Murphy", rating: 990, kfactor: 40)
|
@@ -1348,10 +1348,10 @@ module ICU
|
|
1348
1348
|
@t.add_player(1807, desc: "Dan O'Brien", rating: 789, kfactor: 40)
|
1349
1349
|
@t.add_player(1808, desc: "Pat O'Brien", rating: 970, kfactor: 24)
|
1350
1350
|
@t.add_player(1809, desc: "Michael Joseph O'Connell", rating: 1010, kfactor: 32)
|
1351
|
-
@t.add_player(1810, desc: "John P. O'Connor", rating: 242,
|
1351
|
+
@t.add_player(1810, desc: "John P. O'Connor", rating: 242, games: 6)
|
1352
1352
|
@t.add_player(1811, desc: "Ross O'Connor", rating: 812, kfactor: 40)
|
1353
1353
|
@t.add_player(1812, desc: "Colm O'Muireagain", rating: 950, kfactor: 32)
|
1354
|
-
@t.add_player(1813, desc: "Barry O'Reilly", rating: 736,
|
1354
|
+
@t.add_player(1813, desc: "Barry O'Reilly", rating: 736, games: 6)
|
1355
1355
|
@t.add_player(1814, desc: "Jim O'Reilly", rating: 784, kfactor: 40)
|
1356
1356
|
@t.add_player(1815, desc: "David Piercy", rating: 970, kfactor: 32)
|
1357
1357
|
@t.add_player(1816, desc: "Agnieszka Pozniak", rating: 906, kfactor: 40)
|
@@ -1362,8 +1362,8 @@ module ICU
|
|
1362
1362
|
@t.add_player(1821, desc: "Stephen Sheehan")
|
1363
1363
|
@t.add_player(1822, desc: "Kevin Singpurwala", rating: 790, kfactor: 40)
|
1364
1364
|
@t.add_player(1823, desc: "Kaj Skubiszak")
|
1365
|
-
@t.add_player(1824, desc: "Jack Staed", rating: 133,
|
1366
|
-
@t.add_player(1825, desc: "Devin Tarleton", rating: 852,
|
1365
|
+
@t.add_player(1824, desc: "Jack Staed", rating: 133, games: 10)
|
1366
|
+
@t.add_player(1825, desc: "Devin Tarleton", rating: 852, games: 11)
|
1367
1367
|
@t.add_player(1826, desc: "M. Thangaramanujam", rating: 813, kfactor: 24)
|
1368
1368
|
@t.add_player(1827, desc: "Haley Tomlinson")
|
1369
1369
|
@t.add_player(1828, desc: "Peter Urwin", rating: 848, kfactor: 40)
|
@@ -1998,7 +1998,7 @@ module ICU
|
|
1998
1998
|
@t.iterations2.should be_nil
|
1999
1999
|
end
|
2000
2000
|
|
2001
|
-
it "should produce inconsistent results with
|
2001
|
+
it "should produce inconsistent results with original algorithm" do
|
2002
2002
|
@t.rate!
|
2003
2003
|
|
2004
2004
|
@p.new_rating.should == @p.performance
|
@@ -2019,8 +2019,8 @@ module ICU
|
|
2019
2019
|
@t.iterations2.should == 1
|
2020
2020
|
end
|
2021
2021
|
|
2022
|
-
it "should produce inconsistent results
|
2023
|
-
@t.rate!(
|
2022
|
+
it "should produce inconsistent results with version 1 algorithm" do
|
2023
|
+
@t.rate!(version: 1)
|
2024
2024
|
|
2025
2025
|
@p.new_rating.should == @p.performance
|
2026
2026
|
|
@@ -2040,8 +2040,8 @@ module ICU
|
|
2040
2040
|
@t.iterations2.should be > 1
|
2041
2041
|
end
|
2042
2042
|
|
2043
|
-
it "should produce consistent results
|
2044
|
-
@t.rate!(
|
2043
|
+
it "should produce consistent results with version 2 algorithm" do
|
2044
|
+
@t.rate!(version: 2)
|
2045
2045
|
|
2046
2046
|
@o1.bonus.should == 0 # no bonus this time because it comes from 2nd phase
|
2047
2047
|
@o2.bonus.should == 0
|
@@ -2058,6 +2058,178 @@ module ICU
|
|
2058
2058
|
@t.iterations1.should be > 1
|
2059
2059
|
@t.iterations2.should be > 1
|
2060
2060
|
end
|
2061
|
+
|
2062
|
+
it "should produce consistent results with version 3 algorithm" do
|
2063
|
+
@t.rate!(version: 3)
|
2064
|
+
|
2065
|
+
@o1.bonus.should == 0 # no bonus this time because it comes from 2nd phase
|
2066
|
+
@o2.bonus.should == 0
|
2067
|
+
@o3.bonus.should == 0
|
2068
|
+
@o4.bonus.should == 0
|
2069
|
+
@o5.bonus.should == 0
|
2070
|
+
@o6.bonus.should == 0
|
2071
|
+
|
2072
|
+
ratings = [@o1, @o2, @o3, @o4, @o5, @o6].map { |o| o.bonus == 0 ? o.rating : o.new_rating }
|
2073
|
+
|
2074
|
+
performance = ratings.inject(0.0){ |m,r| m = m + r } / 6.0 - 400.0 / 3.0
|
2075
|
+
performance.should be_within(0.5).of(@p.new_rating)
|
2076
|
+
|
2077
|
+
@t.iterations1.should be > 1
|
2078
|
+
@t.iterations2.should be > 1
|
2079
|
+
end
|
2080
|
+
end
|
2081
|
+
|
2082
|
+
context "#rate - Dierdre Turner in the Limerick U1400 2012" do
|
2083
|
+
before(:each) do
|
2084
|
+
@t = ICU::RatedTournament.new(desc: "Limerick U1400 2012")
|
2085
|
+
|
2086
|
+
# Add the players of most interest (Dierdre Turner and her opponents).
|
2087
|
+
@p = @t.add_player(6697, desc: "Dierdre Turner")
|
2088
|
+
@o1 = @t.add_player(6678, desc: "John P. Dunne", rating: 980, kfactor: 40)
|
2089
|
+
@o2 = @t.add_player(6694, desc: "Jordan O'Sullivan")
|
2090
|
+
@o3 = @t.add_player(6681, desc: "Ruairi Freeman", rating: 537, kfactor: 40)
|
2091
|
+
@o4 = @t.add_player(6676, desc: "Joe Cronin", rating: 682, kfactor: 32)
|
2092
|
+
@o5 = @t.add_player(6675, desc: "Jeffrey Alfred", rating: 1320, kfactor: 40)
|
2093
|
+
@o6 = @t.add_player(6687, desc: "Roisin MacNamee", rating: 460, games: 7)
|
2094
|
+
|
2095
|
+
# Add all the other players.
|
2096
|
+
@t.add_player(6679, desc: "Thomas Senior Dunne", rating: 876, kfactor: 32)
|
2097
|
+
@t.add_player(6682, desc: "John Hensey", rating: 1347, kfactor: 24)
|
2098
|
+
@t.add_player(6683, desc: "Noel Keating", rating: 622, kfactor: 32)
|
2099
|
+
@t.add_player(6684, desc: "Thomas Keating", rating: 886, kfactor: 40)
|
2100
|
+
@t.add_player(6686, desc: "Nora MacNamee", rating: 508, kfactor: 40)
|
2101
|
+
@t.add_player(6690, desc: "Robbie Meaney", rating: 1020, kfactor: 40)
|
2102
|
+
@t.add_player(6691, desc: "Stephen Meaney", rating: 979, kfactor: 40)
|
2103
|
+
@t.add_player(6692, desc: "Jessica Mulqueen-Danaher", rating: 435, kfactor: 40)
|
2104
|
+
@t.add_player(6693, desc: "Michael Joseph O'Connell", rating: 965, kfactor: 32)
|
2105
|
+
@t.add_player(6677, desc: "Adam Dean", rating: 652, games: 6)
|
2106
|
+
@t.add_player(6680, desc: "Geordan Freeman", rating: 344, games: 10)
|
2107
|
+
@t.add_player(6685, desc: "Eamon MacNamee")
|
2108
|
+
@t.add_player(6688, desc: "Pippa Madigan")
|
2109
|
+
@t.add_player(6689, desc: "John McNamara")
|
2110
|
+
@t.add_player(6695, desc: "Grigory Ramendik")
|
2111
|
+
@t.add_player(6696, desc: "Mark David Tonita")
|
2112
|
+
@t.add_player(6698, desc: "Eoghan Turner")
|
2113
|
+
|
2114
|
+
# Dierdre's results.
|
2115
|
+
@t.add_result(1, 6697, 6678, "L")
|
2116
|
+
@t.add_result(2, 6697, 6694, "W")
|
2117
|
+
@t.add_result(3, 6697, 6681, "W")
|
2118
|
+
@t.add_result(4, 6697, 6676, "L")
|
2119
|
+
@t.add_result(5, 6697, 6675, "L")
|
2120
|
+
@t.add_result(6, 6697, 6687, "W")
|
2121
|
+
|
2122
|
+
# Other results.
|
2123
|
+
@t.add_result(1, 6689, 6676, "L")
|
2124
|
+
@t.add_result(1, 6693, 6677, "L")
|
2125
|
+
@t.add_result(1, 6695, 6679, "L")
|
2126
|
+
@t.add_result(1, 6694, 6681, "L")
|
2127
|
+
@t.add_result(1, 6692, 6682, "L")
|
2128
|
+
@t.add_result(1, 6688, 6683, "L")
|
2129
|
+
@t.add_result(1, 6698, 6684, "D")
|
2130
|
+
@t.add_result(1, 6691, 6685, "W")
|
2131
|
+
@t.add_result(1, 6696, 6686, "L")
|
2132
|
+
@t.add_result(1, 6690, 6687, "W")
|
2133
|
+
@t.add_result(2, 6684, 6675, "D")
|
2134
|
+
@t.add_result(2, 6682, 6676, "W")
|
2135
|
+
@t.add_result(2, 6698, 6677, "L")
|
2136
|
+
@t.add_result(2, 6683, 6678, "L")
|
2137
|
+
@t.add_result(2, 6686, 6679, "L")
|
2138
|
+
@t.add_result(2, 6690, 6680, "W")
|
2139
|
+
@t.add_result(2, 6691, 6681, "W")
|
2140
|
+
@t.add_result(2, 6693, 6685, "W")
|
2141
|
+
@t.add_result(2, 6695, 6687, "L")
|
2142
|
+
@t.add_result(2, 6692, 6689, "W")
|
2143
|
+
@t.add_result(3, 6678, 6675, "W")
|
2144
|
+
@t.add_result(3, 6687, 6676, "L")
|
2145
|
+
@t.add_result(3, 6682, 6677, "W")
|
2146
|
+
@t.add_result(3, 6696, 6680, "D")
|
2147
|
+
@t.add_result(3, 6686, 6683, "L")
|
2148
|
+
@t.add_result(3, 6693, 6684, "D")
|
2149
|
+
@t.add_result(3, 6698, 6685, "W")
|
2150
|
+
@t.add_result(3, 6692, 6688, "W")
|
2151
|
+
@t.add_result(3, 6695, 6689, "L")
|
2152
|
+
@t.add_result(3, 6691, 6690, "W")
|
2153
|
+
@t.add_result(4, 6687, 6675, "L")
|
2154
|
+
@t.add_result(4, 6683, 6677, "W")
|
2155
|
+
@t.add_result(4, 6682, 6678, "D")
|
2156
|
+
@t.add_result(4, 6691, 6679, "W")
|
2157
|
+
@t.add_result(4, 6684, 6680, "W")
|
2158
|
+
@t.add_result(4, 6693, 6681, "L")
|
2159
|
+
@t.add_result(4, 6695, 6685, "W")
|
2160
|
+
@t.add_result(4, 6694, 6686, "L")
|
2161
|
+
@t.add_result(4, 6692, 6690, "L")
|
2162
|
+
@t.add_result(4, 6698, 6696, "W")
|
2163
|
+
@t.add_result(5, 6683, 6676, "W")
|
2164
|
+
@t.add_result(5, 6692, 6677, "L")
|
2165
|
+
@t.add_result(5, 6691, 6678, "W")
|
2166
|
+
@t.add_result(5, 6698, 6679, "D")
|
2167
|
+
@t.add_result(5, 6687, 6680, "W")
|
2168
|
+
@t.add_result(5, 6689, 6681, "L")
|
2169
|
+
@t.add_result(5, 6690, 6682, "L")
|
2170
|
+
@t.add_result(5, 6686, 6684, "L")
|
2171
|
+
@t.add_result(5, 6696, 6693, "L")
|
2172
|
+
@t.add_result(5, 6695, 6694, "D")
|
2173
|
+
@t.add_result(6, 6677, 6675, "D")
|
2174
|
+
@t.add_result(6, 6698, 6676, "W")
|
2175
|
+
@t.add_result(6, 6679, 6678, "L")
|
2176
|
+
@t.add_result(6, 6694, 6680, "L")
|
2177
|
+
@t.add_result(6, 6690, 6681, "W")
|
2178
|
+
@t.add_result(6, 6691, 6682, "L")
|
2179
|
+
@t.add_result(6, 6684, 6683, "L")
|
2180
|
+
@t.add_result(6, 6696, 6685, "W")
|
2181
|
+
@t.add_result(6, 6689, 6686, "L")
|
2182
|
+
@t.add_result(6, 6693, 6692, "W")
|
2183
|
+
end
|
2184
|
+
|
2185
|
+
it "should be setup properly" do
|
2186
|
+
@p.desc.should == "Dierdre Turner"
|
2187
|
+
@o1.desc.should == "John P. Dunne"
|
2188
|
+
@o2.desc.should == "Jordan O'Sullivan"
|
2189
|
+
@o3.desc.should == "Ruairi Freeman"
|
2190
|
+
@o4.desc.should == "Joe Cronin"
|
2191
|
+
@o5.desc.should == "Jeffrey Alfred"
|
2192
|
+
@o6.desc.should == "Roisin MacNamee"
|
2193
|
+
|
2194
|
+
@p.type.should == :unrated
|
2195
|
+
@o1.type.should == :rated
|
2196
|
+
@o2.type.should == :unrated
|
2197
|
+
@o3.type.should == :rated
|
2198
|
+
@o4.type.should == :rated
|
2199
|
+
@o5.type.should == :rated
|
2200
|
+
@o6.type.should == :provisional
|
2201
|
+
|
2202
|
+
@o1.rating.should == 980
|
2203
|
+
@o2.rating.should be_nil
|
2204
|
+
@o3.rating.should == 537
|
2205
|
+
@o4.rating.should == 682
|
2206
|
+
@o5.rating.should == 1320
|
2207
|
+
@o6.rating.should == 460
|
2208
|
+
|
2209
|
+
@t.iterations1.should be_nil
|
2210
|
+
@t.iterations2.should be_nil
|
2211
|
+
end
|
2212
|
+
|
2213
|
+
it "should produce consistent results with version 2 algorithm" do
|
2214
|
+
@t.rate!(version: 2)
|
2215
|
+
|
2216
|
+
@p.new_rating.should == @p.performance
|
2217
|
+
|
2218
|
+
@o1.bonus.should == 23
|
2219
|
+
@o2.bonus.should == 0
|
2220
|
+
@o3.bonus.should == 0
|
2221
|
+
@o4.bonus.should == 0
|
2222
|
+
@o5.bonus.should == 0
|
2223
|
+
@o6.bonus.should == 0
|
2224
|
+
|
2225
|
+
ratings = [@o1, @o2, @o3, @o4, @o5, @o6].map { |o| o.bonus > 0 || o.type != :rated ? o.new_rating : o.rating }
|
2226
|
+
|
2227
|
+
performance = ratings.inject(0.0){ |m,r| m = m + r } / 6.0
|
2228
|
+
performance.should be_within(0.5).of(@p.new_rating)
|
2229
|
+
|
2230
|
+
@t.iterations1.should be > 1
|
2231
|
+
@t.iterations2.should be > 1
|
2232
|
+
end
|
2061
2233
|
end
|
2062
2234
|
end
|
2063
2235
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: icu_ratings
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -111,7 +111,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
111
111
|
version: '0'
|
112
112
|
segments:
|
113
113
|
- 0
|
114
|
-
hash:
|
114
|
+
hash: -4449600080095585228
|
115
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
@@ -120,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
120
120
|
version: '0'
|
121
121
|
segments:
|
122
122
|
- 0
|
123
|
-
hash:
|
123
|
+
hash: -4449600080095585228
|
124
124
|
requirements: []
|
125
125
|
rubyforge_project: icu_ratings
|
126
126
|
rubygems_version: 1.8.23
|