icu_ratings 1.3.1 → 1.4.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/lib/icu_ratings/player.rb +3 -1
- data/lib/icu_ratings/tournament.rb +13 -7
- data/lib/icu_ratings/version.rb +1 -1
- data/spec/tournament_spec.rb +22 -6
- metadata +4 -4
data/lib/icu_ratings/player.rb
CHANGED
@@ -273,7 +273,9 @@ module ICU
|
|
273
273
|
stable
|
274
274
|
end
|
275
275
|
|
276
|
-
def calculate_bonus # :nodoc:
|
276
|
+
def calculate_bonus(allow_new_bonus) # :nodoc:
|
277
|
+
# New in December 2012 - see http://ratings.icu.ie/articles/18 (Part 2).
|
278
|
+
return if !allow_new_bonus && @bonus == 0
|
277
279
|
# Rounding is performed in places to emulate the older MSAccess implementation.
|
278
280
|
return if @type != :rated || @kfactor <= 24 || @results.size <= 4 || @rating >= 2100
|
279
281
|
change = rating_change
|
@@ -57,15 +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 some optional arguments to control the
|
60
|
+
# The <em>rate!</em> method takes some optional arguments to control the algorithm, for example:
|
61
61
|
#
|
62
|
-
# t.rate!(max_iterations2: 30)
|
62
|
+
# t.rate!(max_iterations2: 30, phase_2_bonuses: false) # these are the recommended options
|
63
63
|
#
|
64
|
-
# The complete set of current options is:
|
64
|
+
# The complete set of current options, with their defaults, is:
|
65
65
|
#
|
66
66
|
# * <em>max_iterations1</em>: the maximum number of re-estimation iterations before the bonus calculation (default <b>30</b>)
|
67
67
|
# * <em>max_iterations2</em>: the maximum number of re-estimation iterations after the bonus calculation (default <b>1</b>)
|
68
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.
|
69
74
|
#
|
70
75
|
# == Error Handling
|
71
76
|
#
|
@@ -109,7 +114,8 @@ module ICU
|
|
109
114
|
# Rate the tournament. Called after all players and results have been added.
|
110
115
|
def rate!(opt={})
|
111
116
|
max_iterations1 = opt[:max_iterations1] || 30
|
112
|
-
max_iterations2 = opt[:max_iterations2] || 1
|
117
|
+
max_iterations2 = opt[:max_iterations2] || 1 # legacy default - see http://ratings.icu.ie/articles/18 (Part 1)
|
118
|
+
phase_2_bonuses = opt.has_key?(:phase_2_bonuses) ? opt[:phase_2_bonuses] : true # legacy default - see http://ratings.icu.ie/articles/18 (Part 2)
|
113
119
|
threshold = opt[:threshold] || 0.5
|
114
120
|
players.each { |p| p.init }
|
115
121
|
@iterations1 = performance_ratings(max_iterations1, threshold)
|
@@ -117,7 +123,7 @@ module ICU
|
|
117
123
|
if !no_bonuses && calculate_bonuses > 0
|
118
124
|
players.each { |p| p.rate! }
|
119
125
|
@iterations2 = performance_ratings(max_iterations2, threshold)
|
120
|
-
calculate_bonuses
|
126
|
+
calculate_bonuses(phase_2_bonuses)
|
121
127
|
else
|
122
128
|
@iterations2 = 0
|
123
129
|
end
|
@@ -164,8 +170,8 @@ module ICU
|
|
164
170
|
end
|
165
171
|
|
166
172
|
# Calculate bonuses for all players and return the number who got one.
|
167
|
-
def calculate_bonuses
|
168
|
-
@player.values.inject(0) { |t,p| t + (p.calculate_bonus ? 1 : 0) }
|
173
|
+
def calculate_bonuses(allow_new_bonus=true)
|
174
|
+
@player.values.inject(0) { |t,p| t + (p.calculate_bonus(allow_new_bonus) ? 1 : 0) }
|
169
175
|
end
|
170
176
|
end
|
171
177
|
end
|
data/lib/icu_ratings/version.rb
CHANGED
data/spec/tournament_spec.rb
CHANGED
@@ -2001,11 +2001,9 @@ module ICU
|
|
2001
2001
|
it "should produce inconsistent results with default settings" do
|
2002
2002
|
@t.rate!
|
2003
2003
|
|
2004
|
-
@p.new_rating.should be_within(0.5).of(713) # the original inconsistent calculation
|
2005
2004
|
@p.new_rating.should == @p.performance
|
2006
2005
|
|
2007
2006
|
@o1.bonus.should == 16
|
2008
|
-
@o1.new_rating.should be_within(0.5).of(1013)
|
2009
2007
|
@o2.bonus.should == 0
|
2010
2008
|
@o3.bonus.should == 0
|
2011
2009
|
@o4.bonus.should == 0
|
@@ -2021,13 +2019,31 @@ module ICU
|
|
2021
2019
|
@t.iterations2.should == 1
|
2022
2020
|
end
|
2023
2021
|
|
2024
|
-
it "should produce
|
2025
|
-
pending "a fix to the algorithm (the number of iterations does not help)"
|
2026
|
-
|
2022
|
+
it "should produce inconsistent results even with more 2nd phase iterations" do
|
2027
2023
|
@t.rate!(max_iterations2: 30)
|
2028
2024
|
|
2025
|
+
@p.new_rating.should == @p.performance
|
2026
|
+
|
2029
2027
|
@o1.bonus.should == 16
|
2030
|
-
@
|
2028
|
+
@o2.bonus.should == 0
|
2029
|
+
@o3.bonus.should == 0
|
2030
|
+
@o4.bonus.should == 0
|
2031
|
+
@o5.bonus.should == 0
|
2032
|
+
@o6.bonus.should == 0
|
2033
|
+
|
2034
|
+
ratings = [@o1, @o2, @o3, @o4, @o5, @o6].map { |o| o.bonus == 0 ? o.rating : o.new_rating }
|
2035
|
+
|
2036
|
+
performance = ratings.inject(0.0){ |m,r| m = m + r } / 6.0 - 400.0 / 3.0
|
2037
|
+
performance.should_not be_within(0.5).of(@p.new_rating)
|
2038
|
+
|
2039
|
+
@t.iterations1.should be > 1
|
2040
|
+
@t.iterations2.should be > 1
|
2041
|
+
end
|
2042
|
+
|
2043
|
+
it "should produce consistent results only when new bonuses in phase 2 are disallowed" do
|
2044
|
+
@t.rate!(max_iterations2: 30, phase_2_bonuses: false)
|
2045
|
+
|
2046
|
+
@o1.bonus.should == 0 # no bonus this time because it comes from 2nd phase
|
2031
2047
|
@o2.bonus.should == 0
|
2032
2048
|
@o3.bonus.should == 0
|
2033
2049
|
@o4.bonus.should == 0
|
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.4.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-25 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: 4520836644444600714
|
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: 4520836644444600714
|
124
124
|
requirements: []
|
125
125
|
rubyforge_project: icu_ratings
|
126
126
|
rubygems_version: 1.8.23
|