Class: ICU::Result

Inherits:
Object
  • Object
show all
Extended by:
Util::Accessor
Defined in:
lib/icu_tournament/result.rb,
lib/icu_tournament/tournament_sp.rb,
lib/icu_tournament/tournament_spx.rb,
lib/icu_tournament/tournament_krause.rb

Overview

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Util::Accessor

attr_accessor, attr_date, attr_date_or_nil, attr_integer, attr_integer_or_nil, attr_positive, attr_positive_or_nil, attr_string, attr_string_or_nil

Constructor Details

#initialize(round, player, score, opt = {}) ⇒ Result

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



91
92
93
94
95
96
97
# 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

Instance Attribute Details

#colourObject

Returns the value of attribute colour.



87
88
89
# File 'lib/icu_tournament/result.rb', line 87

def colour
  @colour
end

#opponentObject

Returns the value of attribute opponent.



87
88
89
# File 'lib/icu_tournament/result.rb', line 87

def opponent
  @opponent
end

#rateableObject

Returns the value of attribute rateable.



87
88
89
# File 'lib/icu_tournament/result.rb', line 87

def rateable
  @rateable
end

#scoreObject

Returns the value of attribute score.



87
88
89
# File 'lib/icu_tournament/result.rb', line 87

def score
  @score
end

Instance Method Details

#eql?(other, opt = {}) ⇒ Boolean

Equality. True if all attributes equal, exceptions allowed.

Returns:

  • (Boolean)


184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# 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

#inspectObject

Short descrition mainly for debugging.



179
180
181
# File 'lib/icu_tournament/result.rb', line 179

def inspect
  "R#{@round}P#{@player}O#{@opponent || '-'}#{@score}#{@colour || '-'}#{@rateable ? 'R' : 'U'}"
end

#pointsObject

Return the score as a floating point number.



110
111
112
113
114
115
116
# 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

#renumber(map) ⇒ Object

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



166
167
168
169
170
171
172
173
174
175
176
# 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

#reverseObject

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



155
156
157
158
159
160
161
162
163
# 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

#to_krauseObject

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



579
580
581
582
583
584
585
586
# File 'lib/icu_tournament/tournament_krause.rb', line 579

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_textObject

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



345
346
347
348
349
350
351
352
353
354
355
356
357
# 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