Class: Gambit::Tools::Scorecard
- Inherits:
-
Object
- Object
- Gambit::Tools::Scorecard
- Includes:
- Viewable
- Defined in:
- lib/gambit/tools/scorecard.rb
Overview
A tool for managing the score of just about any game.
Instance Method Summary collapse
-
#add_player(player) ⇒ Object
Add a new player to this Scorecard.
-
#add_players(*players) ⇒ Object
Add a group of players to this Scorecard.
-
#initialize(*players) ⇒ Scorecard
constructor
Creates a new Scorecard object, optionally initialized with some players.
-
#loser(&condition) ⇒ Object
Returns the losing player, as determined by the provided winning condition.
-
#require_categories ⇒ Object
Forces this Scorecard to score by category only.
-
#score(player, points = 0, category = nil) ⇒ Object
Can be used to add points to the score of the given player or to fetch the score for a player, by omitting the points.
-
#set_total(name, *from, &validation) ⇒ Object
This method adds a “total” field to this Scorecard, by name.
-
#set_win(name) ⇒ Object
Sets the score catrgory used to determine a winner.
-
#start_at=(minimum_score) ⇒ Object
Sets a starting score for each field.
-
#total(player, category = nil) ⇒ Object
Returns the total score for the given player or for the given player in the optional category.
-
#use_category(category, *details, &validation) ⇒ Object
Adds a category to this Scorecard.
-
#winner(&condition) ⇒ Object
Returns the winning player, as determined by the provided winning condition.
Methods included from Viewable
Constructor Details
#initialize(*players) ⇒ Scorecard
Creates a new Scorecard object, optionally initialized with some players.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/gambit/tools/scorecard.rb', line 79 def initialize( *players ) @score = Hash.new(0) @players = Array.new @use_categories = false @categories = Array.new @totals = Array.new @order = Array.new @categories_score = Hash.new do |names, cat| names[cat] = Hash.new(0) end @win_category = nil add_players(*players) end |
Instance Method Details
#add_player(player) ⇒ Object
Add a new player to this Scorecard.
Returns self
for method chaining.
100 101 102 103 104 |
# File 'lib/gambit/tools/scorecard.rb', line 100 def add_player( player ) @players << player self end |
#add_players(*players) ⇒ Object
Add a group of players to this Scorecard.
Returns self
for method chaining.
111 112 113 114 115 |
# File 'lib/gambit/tools/scorecard.rb', line 111 def add_players( *players ) players.each { |player| add_player(player) } self end |
#loser(&condition) ⇒ Object
Returns the losing player, as determined by the provided winning condition. If a condition block is not given, scores will be compared numerically, with the highest score considered to be the best.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/gambit/tools/scorecard.rb', line 123 def loser( &condition ) if @use_categories scores = @categories_score.map do |(name, scores)| if @categories.assoc(@win_category) @score[@win_category] elsif total = @totals.assoc(@win_category) figure_total(name, total[1], total[2]) end end best_score = scores.min(&condition) @categories_score.find do |(name, score)| if @categories.assoc(@win_category) @score[@win_category] == best_score elsif total = @totals.assoc(@win_category) figure_total(name, total[1], total[2]) == best_score end end.first else best_score = @score.values.min(&condition) @score.find { |(player, score)| score == best_score }.first end end |
#require_categories ⇒ Object
Forces this Scorecard to score by category only.
Returns self
for method chaining.
151 152 153 154 155 |
# File 'lib/gambit/tools/scorecard.rb', line 151 def require_categories( ) @use_categories = true self end |
#score(player, points = 0, category = nil) ⇒ Object
Can be used to add points to the score of the given player or to fetch the score for a player, by omitting the points. If given, a score will be modified or fetched for the given category.
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/gambit/tools/scorecard.rb', line 163 def score( player, points = 0, category = nil ) if @use_categories cat = @categories.assoc(category) or raise ArgumentError, "Invalid category." total = @categories_score[player][category] total += points if cat.size == 2 and cat.last.is_a? Proc unless cat.last[total] raise ArgumentError, "Invalid score for " + "#{cat.first} category." end elsif cat.size == 2 and cat.last.is_a? Array unless cat.last.include?(total) raise ArgumentError, "Invalid score for " + "#{cat.first} category." end elsif cat.size == 3 unless cat[1] <= total and total <= cat[2] raise ArgumentError, "Invalid score for " + "#{cat.first} category." end end @categories_score[player][category] = total total(player, category) else @score[player] += points @score[player] = yield(@score[player]) if block_given? total(player) end end |
#set_total(name, *from, &validation) ⇒ Object
This method adds a “total” field to this Scorecard, by name. A total can be calculated from any other fields on the card, including other totals.
A validation block can be given, if needed. The block will be called each time the total is display and passed the sum of all from fields. The return value of the block will be the total displayed.
Returns self
for method chaining.
211 212 213 214 215 216 |
# File 'lib/gambit/tools/scorecard.rb', line 211 def set_total( name, *from, &validation ) @order << name @totals << [name, from, validation] self end |
#set_win(name) ⇒ Object
Sets the score catrgory used to determine a winner.
Returns self
for method chaining.
223 224 225 226 227 |
# File 'lib/gambit/tools/scorecard.rb', line 223 def set_win( name ) @win_category = name self end |
#start_at=(minimum_score) ⇒ Object
Sets a starting score for each field. WARNING: Should be called before any calls to score(), for predictable results.
233 234 235 |
# File 'lib/gambit/tools/scorecard.rb', line 233 def start_at=( minimum_score ) @score.default = minimum_score end |
#total(player, category = nil) ⇒ Object
Returns the total score for the given player or for the given player in the optional category.
241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/gambit/tools/scorecard.rb', line 241 def total( player, category = nil ) if category.nil? @score[player] else if @categories.assoc(category) @categories_score[player][category] elsif total = @totals.assoc(category) figure_total(player, total[1], total[2]) else end end end |
#use_category(category, *details, &validation) ⇒ Object
Adds a category to this Scorecard.
Returns self
for method chaining.
:call-seq:
use_category(cat) { |score| ... } -> self
use_category(cat, ary_of_accepted_values) -> self
use_category(cat, low, high) -> self
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/gambit/tools/scorecard.rb', line 265 def use_category( category, *details, &validation ) @order << category if not validation.nil? @categories << [category, validation] elsif details.size == 1 and details[0].is_a? Array @categories << [category, details[0]] elsif details.size == 2 and details.all? { |n| n.is_a? Integer } @categories << [category, *details] else raise ArgumentError, "Invalid category definition." end self end |
#winner(&condition) ⇒ Object
Returns the winning player, as determined by the provided winning condition. If a condition block is not given, scores will be compared numerically, with the highest score considered to be the best.
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/gambit/tools/scorecard.rb', line 287 def winner( &condition ) if @use_categories scores = @categories_score.map do |(name, scores)| if @categories.assoc(@win_category) @score[@win_category] elsif total = @totals.assoc(@win_category) figure_total(name, total[1], total[2]) end end best_score = scores.max(&condition) @categories_score.find do |(name, score)| if @categories.assoc(@win_category) @score[@win_category] == best_score elsif total = @totals.assoc(@win_category) figure_total(name, total[1], total[2]) == best_score end end.first else best_score = @score.values.max(&condition) @score.find { |(player, score)| score == best_score }.first end end |