Class: ICU::RatedResult

Inherits:
Object
  • Object
show all
Defined in:
lib/icu_ratings/result.rb

Overview

Adding Results to Tournaments

You don’t create results directly with a constructor, instead, you add them to a tournament using the add_result method, giving the round number, the player numbers and the score of the first player relative to the second:

t = ICU::RatedTournament.new
t.add_player(10)
t.add_player(20)
t.add_result(1, 10, 20, 'W')

The above example expresses the result that in round 1 player 10 won against player 20. An exception is raised if either of the two players does not already exist in the tournament, if either player already has a game with another opponent in that round or if the two players already have a different result against each other in that round. Note that the result is added to both players: in the above example a win in round 1 against player 20 is added to player 10’s results and a loss against player 10 in round 1 is added to player 20’s results. It’s OK (but unnecessary) to add the same result again from the other player’s prespective as long as the score is consistent.

t.add_result(1, 20, 10, 'L')   # unnecessary (nothing would change) but would not cause an exception
t.add_result(1, 20, 10, 'D')   # inconsistent result - would raise an exception

Specifying the Score

The method score will always return a Float value (either 0.0, 0.5 or 1.0). When specifying a score using the add_result of ICU::Tourmanent the same values can be used as can other, equally valid alternatives:

win

“1”, “1.0”, “W”, “w” (String), 1 (Fixnum), 1.0 (Float)

loss

“0”, “0.0”, “L”, “l” (String), 0 (Fixnum), 0.0 (Float)

draw

“½”, “D”, “d” (String), 0.5 (Float)

Strings padded with whitespace also work (e.g. “ 1.0 ” and “ W ”).

Specifying the Players

As described above, one way to specify the two players is via player numbers. Equally possible is player objects:

t = ICU::RatedTournament.new
p = t.add_player(10)
q = t.add_plater(20)
t.add_result(1, p, q, 'W')

Or indeed (although this is unnecessary):

t = ICU::RatedTournament.new
t.add_player(10)
t.add_plater(20)
t.add_result(1, t.player(10), t.player(20), 'W')

A players cannot have a results against themselves:

t.add_player(2, 10, 10, 'D')   # exception!

Retrieving Results

Results belong to players (ICU::RatedPlayer objects) and are stored in an array accessed by the method results. Each result has a round number, an opponent object (also an ICU::RatedPlayer object) and a score (1.0, 0.5 or 0.0):

p = t.player(10)
p.results.size      # 1
r = p.results[0]
r.round             # 1
r.opponent.num      # 20
r.score             # 1.0 (Float)

The results method returns results in round order, irrespective of what order they were added in:

t = ICU::RatedTournament.new
[0,1,2,3,4].each { |num| t.add_player(num) }
[3,1].each { |rnd| t.add_result(rnd, 0, rnd, 'W') }
[4,2].each { |rnd| t.add_result(rnd, 0, rnd, 'L') }
t.player(0).results.map{ |r| r.round }.join(',')      # "1,2,3,4"

Unrated Results

Results that are not for rating, such as byes, walkovers and defaults, should not be added to the tournament. Instead, players can simply have no results for certain rounds. Indeed, it’s even valid for players not to have any results at all (although, in that case, for those players, no new rating can be calculated from the tournament).

After the Tournament is Rated

The main rating calculations are available from player methods (see ICU::RatedPlayer) but additional details are available via methods of each player’s individual results: expected_score, rating_change (rated players only).

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#expected_scoreObject (readonly)

Returns the value of attribute expected_score.



93
94
95
# File 'lib/icu_ratings/result.rb', line 93

def expected_score
  @expected_score
end

#opponentObject

Returns the value of attribute opponent.



93
94
95
# File 'lib/icu_ratings/result.rb', line 93

def opponent
  @opponent
end

#rating_changeObject (readonly)

Returns the value of attribute rating_change.



93
94
95
# File 'lib/icu_ratings/result.rb', line 93

def rating_change
  @rating_change
end

#roundObject

Returns the value of attribute round.



93
94
95
# File 'lib/icu_ratings/result.rb', line 93

def round
  @round
end

#scoreObject

Returns the value of attribute score.



93
94
95
# File 'lib/icu_ratings/result.rb', line 93

def score
  @score
end

Instance Method Details

#==(other) ⇒ Object

:nodoc:



104
105
106
107
108
109
# File 'lib/icu_ratings/result.rb', line 104

def ==(other) # :nodoc:
  return false unless other.round    == round
  return false unless other.opponent == opponent
  return false unless other.score    == score
  true
end

#opponents_scoreObject

:nodoc:



111
112
113
# File 'lib/icu_ratings/result.rb', line 111

def opponents_score # :nodoc:
  1.0 - score
end

#rate!(player) ⇒ Object

:nodoc:



95
96
97
98
99
100
101
102
# File 'lib/icu_ratings/result.rb', line 95

def rate!(player) # :nodoc:
  player_rating   = player.new_rating(:start)
  opponent_rating = opponent.new_rating(:opponent)
  if player_rating && opponent_rating
    @expected_score = 1 / (1 + 10 ** ((opponent_rating - player_rating) / 400.0))
    @rating_change  = (score - expected_score) * player.kfactor if player.type == :rated
  end
end