Class: ICU::RatedTournament
- Inherits:
-
Object
- Object
- ICU::RatedTournament
- Defined in:
- lib/icu_ratings/tournament.rb
Overview
Creating Tournaments
ICU::RatedTournament objects are created directly.
t = ICU::RatedTournament.new
They have some optional parameters which can be set via the constructor or by calling the same-named setter methods. One is called desc (short for description) the value of which can be any object but will, if utilized, typically be the name of the tournament as a string.
t = ICU::RatedTournament.new(:desc => "Irish Championships 2010")
puts t.desc # "Irish Championships 2010"
Another optional parameter is start for the start date. A Date object or a string that can be parsed as a string can be used to set it. The European convention is preferred for dates like “03/06/2013” (3rd of June, not 6th of March). Attempting to set an invalid date will raise an exception.
t = ICU::RatedTournament.new(:start => "01/07/2010")
puts t.start.class # Date
puts t.start.to_s # "2010-07-01"
Also, there is the option no_bonuses. Bonuses are a feature of the ICU rating system. If you are rating a non-ICU tournament (such as a FIDE tournament) where bonues are not awarded use this option.
t = ICU::RatedTournament.new(:desc => 'Linares', :start => "07/02/2009", :no_bonuses => true)
Note, however, that the ICU system also has its own unique way of treating provisional, unrated and foreign players, so the only FIDE tournaments that can be rated using this software are those that consist solely of rated players.
Rating Tournaments
To rate a tournament, first add the players (see ICU::RatedPlayer for details):
t.add_player(1, :rating => 2534, :kfactor => 16)
# ...
Then add the results (see ICU::RatedResult for details):
t.add_result(1, 1, 2, 'W')
# ...
Then rate the tournament by calling the rate! method:
t.rate!
Now the results of the rating calculations can be retrieved from the players in the tournement or their results. For example, player 1’s new rating would be:
t.player(1).
See ICU::RatedPlayer and ICU::RatedResult for more details.
The rate! method takes an optional version argument to control the precise algorithm, for example:
t.rate!(version: 2)
Without a version number or with version 0, the original pre-2012 algorithm is used. However, some improvements have since been found (see ratings.icu.ie/articles/18 for more details) and currently the recommended version to use is 2.
Error Handling
Some of the above methods have the potential to raise RuntimeError exceptions. In the case of add_player and add_result, the use of invalid arguments would cause such an error. Theoretically, the rate! method could also throw an exception if the iterative algorithm it uses to estimate performance ratings of unrated players failed to converge. However an instance of non-convergence has yet to be observed in practice.
Since exception throwing is how errors are signalled, you should arrange for them to be caught and handled in some suitable place in your code.
Instance Attribute Summary collapse
-
#desc ⇒ Object
Returns the value of attribute desc.
-
#iterations1 ⇒ Object
readonly
Returns the value of attribute iterations1.
-
#iterations2 ⇒ Object
readonly
Returns the value of attribute iterations2.
-
#no_bonuses ⇒ Object
Returns the value of attribute no_bonuses.
-
#start ⇒ Object
Returns the value of attribute start.
Instance Method Summary collapse
-
#add_player(num, args = {}) ⇒ Object
Add a new player to the tournament.
-
#add_result(round, player, opponent, score) ⇒ Object
Add a new result to the tournament.
-
#player(num) ⇒ Object
Return a player (ICU::RatedPlayer) given a player number (returns nil if the number is invalid).
-
#players ⇒ Object
Return an array of all players, in order of player number.
-
#rate!(opt = {}) ⇒ Object
Rate the tournament.
Instance Attribute Details
#desc ⇒ Object
Returns the value of attribute desc.
81 82 83 |
# File 'lib/icu_ratings/tournament.rb', line 81 def desc @desc end |
#iterations1 ⇒ Object (readonly)
Returns the value of attribute iterations1.
82 83 84 |
# File 'lib/icu_ratings/tournament.rb', line 82 def iterations1 @iterations1 end |
#iterations2 ⇒ Object (readonly)
Returns the value of attribute iterations2.
82 83 84 |
# File 'lib/icu_ratings/tournament.rb', line 82 def iterations2 @iterations2 end |
#no_bonuses ⇒ Object
Returns the value of attribute no_bonuses.
82 83 84 |
# File 'lib/icu_ratings/tournament.rb', line 82 def no_bonuses @no_bonuses end |
#start ⇒ Object
Returns the value of attribute start.
82 83 84 |
# File 'lib/icu_ratings/tournament.rb', line 82 def start @start end |
Instance Method Details
#add_player(num, args = {}) ⇒ Object
Add a new player to the tournament. Returns the instance of ICU::RatedPlayer created. See ICU::RatedPlayer for details.
86 87 88 89 90 |
# File 'lib/icu_ratings/tournament.rb', line 86 def add_player(num, args={}) raise "player with number #{num} already exists" if @player[num] args[:kfactor] = ICU::RatedPlayer.kfactor(args[:kfactor].merge({ :start => start, :rating => args[:rating] })) if args[:kfactor].is_a?(Hash) @player[num] = ICU::RatedPlayer.factory(num, args) end |
#add_result(round, player, opponent, score) ⇒ Object
Add a new result to the tournament. Two instances of ICU::RatedResult are created. One is added to the first player and the other to the second player. The method returns nil. See ICU::RatedResult for details.
95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/icu_ratings/tournament.rb', line 95 def add_result(round, player, opponent, score) n1 = player.is_a?(ICU::RatedPlayer) ? player.num : player.to_i n2 = opponent.is_a?(ICU::RatedPlayer) ? opponent.num : opponent.to_i p1 = @player[n1] || raise("no such player number (#{n1})") p2 = @player[n2] || raise("no such player number (#{n2})") r1 = ICU::RatedResult.new(round, p2, score) r2 = ICU::RatedResult.new(round, p1, r1.opponents_score) p1.add_result(r1) p2.add_result(r2) nil end |
#player(num) ⇒ Object
Return a player (ICU::RatedPlayer) given a player number (returns nil if the number is invalid).
149 150 151 |
# File 'lib/icu_ratings/tournament.rb', line 149 def player(num) @player[num] end |
#players ⇒ Object
Return an array of all players, in order of player number.
144 145 146 |
# File 'lib/icu_ratings/tournament.rb', line 144 def players @player.keys.sort.map{ |num| @player[num] } end |
#rate!(opt = {}) ⇒ Object
Rate the tournament. Called after all players and results have been added.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/icu_ratings/tournament.rb', line 108 def rate!(opt={}) # The original algorithm (version 0). max_iterations = [30, 1] phase_2_bonuses = true update_bonuses = false threshold = 0.5 # New versions of the algorithm. version = opt[:version].to_i if version >= 1 # See http://ratings.icu.ie/articles/18 (Part 1) max_iterations[1] = 30 end if version >= 2 # See http://ratings.icu.ie/articles/18 (Part 2) phase_2_bonuses = false update_bonuses = true threshold = 0.1 end # Phase 1. players.each { |p| p.reset } @iterations1 = (max_iterations[0], threshold) players.each { |p| p.rate! } # Phase 2. if !no_bonuses && calculate_bonuses > 0 players.each { |p| p.rate!(update_bonuses) } @iterations2 = (max_iterations[1], threshold) calculate_bonuses if phase_2_bonuses else @iterations2 = 0 end end |