class ICU::Result

A result is the outcome of a game from the perspective of one of the players. If the game was not a bye or a walkover and involved a second player, then that second player will also have a result for the same game, and the two results will be mirror images of each other.

A result always involves a round number, a player number and a score, so these three attributes must be supplied in the constructor.

result = ICU::Result.new(2, 10, 'W')

The above example represents player 10 winning in round 2. As it stands, it represends a bye or walkover since there is no opponent. Without an opponent, it is unrateable.

result.rateable     # => false

The player’s colour and the number of their opponent can be set as follows:

result.colour = 'B'
result.opponent = 13

Specifying an opponent always makes a result rateable.

result.rateable     # => true

This example now represents a win by player 10 with the black pieces over player number 13 in round 2. Alternatively, all this can been specified in the constructor.

result = ICU::Result.new(2, 10, 'W', :opponent => 13, :colour => 'B')

To make a game unratable, even if it involves an opponent, set the rateable atribute explicity:

result.rateable = false

or include it in the constructor:

result = ICU::Result.new(2, 10, 'W', :opponent => 13, :colour => 'B', :rateable => false)

The result of the same game from the perspective of the opponent is:

tluser = result.reverse

which, with the above example, would be:

tluser.player       # => 13
tluser.opponent     # => 10
tluser.score        # => 'L'
tluser.colour       # => 'B'
tluser.round        # => 2

The rateable attribute is the same in a result and it’s reverse. A result which has no opponent is not reversible (the reverse method returns nil).

The return value from the score method is always one of W, L or D. However, when setting the score, a certain amount of variation is permitted as long as it is clear what is meant. For eample, the following would all be converted to D:

result.score = ' D '
result.score = 'd'
result.score = '='
result.score = '0.5'
result.score = '½'

The points read-only accessor always returns a floating point number: either 0.0, 0.5 or 1.0.

Two results are eql? if all there attributes are the same, unless exceptions are specified.

r  = ICU::Result.new(1, 1, 'W', :opponent => 2)
r1 = ICU::Result.new(1, 1, 'W', :opponent => 2)
r2 = ICU::Result.new(1, 1, 'W', :opponent => 2, :rateable => false)
r3 = ICU::Result.new(1, 1, 'L', :opponent => 2, :rateable => false)

r.eql?(r1)                                   # => true
r.eql?(r2)                                   # => false
r.eql?(r3)                                   # => false
r.eql?(r2, :except => :rateable)             # => true
r.eql?(r3, :except => [:rateable, :score])   # => true

Attributes

colour[R]
opponent[R]
rateable[R]
score[R]

Public Class Methods

new(round, player, score, opt={}) click to toggle source

Constructor. Round number, player number and score must be supplied. Optional hash attribute are opponent, colour and rateable.

# File lib/icu_tournament/result.rb, line 91
def initialize(round, player, score, opt={})
  self.round  = round
  self.player = player
  self.score  = score
  [:colour, :opponent].each { |a| self.send("#{a}=", opt[a]) unless opt[a].nil? }
  self.rateable = opt[:rateable]  # always attempt to set this, and do it last, to get the right default
end

Public Instance Methods

colour=(colour) click to toggle source

Colour. Either ‘W’ (white) or ‘B’ (black).

# File lib/icu_tournament/result.rb, line 119
def colour=(colour)
  @colour = case colour.to_s
    when ''   then nil
    when /W/i then 'W'
    when /B/i then 'B'
    else raise "invalid colour (#{colour})"
  end
end
eql?(other, opt={}) click to toggle source

Equality. True if all attributes equal, exceptions allowed.

# File lib/icu_tournament/result.rb, line 184
def eql?(other, opt={})
  return true if equal?(other)
  return unless other.is_a? Result
  except = Hash.new
  if opt[:except]
    if opt[:except].is_a?(Array)
      opt[:except].each { |x| except[x.to_sym] = true }
    else
      except[opt[:except].to_sym] = true
    end
  end
  [:round, :player, :opponent, :colour, :score, :rateable].each do |m|
    return false unless except[m] || self.send(m) == other.send(m)
  end
  true
end
inspect() click to toggle source

Short descrition mainly for debugging.

# File lib/icu_tournament/result.rb, line 179
def inspect
  "R#{@round}P#{@player}O#{@opponent || '-'}#{@score}#{@colour || '-'}#{@rateable ? 'R' : 'U'}"
end
opponent=(opponent) click to toggle source

Opponent player number. Either absent (nil) or any integer except the player number.

# File lib/icu_tournament/result.rb, line 129
def opponent=(opponent)
  @opponent = case opponent
    when nil     then nil
    when Integer then opponent
    when /^\s*$/ then nil
    else opponent.to_i
  end
  raise "invalid opponent number (#{opponent})" if @opponent == 0 && !opponent.to_s.match(/\d/)
  raise "opponent number and player number (#{@opponent}) must be different" if @opponent == player
  self.rateable = true if @opponent
end
points() click to toggle source

Return the score as a floating point number.

# File lib/icu_tournament/result.rb, line 110
def points
  case @score
    when 'W' then 1.0
    when 'L' then 0.0
    else 0.5
  end
end
rateable=(rateable) click to toggle source

Rateable flag. If false, result is not rateable. Can only be true if there is an opponent.

# File lib/icu_tournament/result.rb, line 142
def rateable=(rateable)
  if opponent.nil?
    @rateable = false
    return
  end
  @rateable = case rateable
    when nil   then true   # default is true
    when false then false  # this is the only way to turn it off
    else true
  end
end
renumber(map) click to toggle source

Renumber the player and opponent (if there is one) according to the supplied hash. Return self.

# File lib/icu_tournament/result.rb, line 166
def renumber(map)
  raise "result player number #{@player} not found in renumbering hash" unless map[@player]
  self.player = map[@player]
  if @opponent
    raise "result opponent number #{@opponent} not found in renumbering hash" unless map[@opponent]
    old_rateable = @rateable
    self.opponent = map[@opponent]
    self.rateable = old_rateable  # because setting the opponent has a side-effect which is undesirable in this context
  end
  self
end
reverse() click to toggle source

Return a reversed version (from the opponent’s perspective) of a result.

# File lib/icu_tournament/result.rb, line 155
def reverse
  return unless @opponent
  r = Result.new(@round, @opponent, @score == 'W' ? 'L' : (@score == 'L' ? 'W' : 'D'))
  r.opponent = @player
  r.colour = 'W' if @colour == 'B'
  r.colour = 'B' if @colour == 'W'
  r.rateable = @rateable
  r
end
score=(score) click to toggle source

Score for the game, even if a default. One of ‘W’, ‘L’ or ‘D’. Reasonable inputs like 1, 0, =, ½, etc will be converted.

# File lib/icu_tournament/result.rb, line 100
def score=(score)
  @score = case score.to_s.strip
    when /^(1\.0|1|\+|W|w)$/ then 'W'
    when /^(0\.5|½|\=|D|d)$/ then 'D'
    when /^(0\.0|0|\-|L|l)$/ then 'L'
    else raise "invalid score (#{score})"
  end
end
to_krause() click to toggle source

Format a player’s result as it would appear in a Krause formatted file (exactly 8 characters long, including leading whitespace).

# File lib/icu_tournament/tournament_krause.rb, line 596
def to_krause
  return ' ' * 8 if !@opponent && !@colour && @score == 'L'
  krause = sprintf('%4s ', @opponent || '0000')
  krause << sprintf('%1s ', @colour ? @colour.downcase : '-')
  krause << case @score; when 'W' then '1'; when 'L' then '0'; else '='; end if  @rateable
  krause << case @score; when 'W' then '+'; when 'L' then '-'; else '='; end if !@rateable
  krause
end
to_sp_text() click to toggle source

Format a player’s result as it would appear in an SP text export file.

# File lib/icu_tournament/tournament_sp.rb, line 345
def to_sp_text
  sp = opponent ? opponent.to_s : '0'
  sp << ':'
  if rateable
    sp << score
  else
    sp << case score
    when 'W' then '+'
    when 'L' then '-'
    else '='
    end
  end
end