Parent

Tournament::Pool

Represents a NCAA tournament pool. Contains 4 regions of 16 teams each. Champions of Region 1 and Region 2 and champions of Region 3 and Region 4 play each other in the final four.

Attributes

regions[R]

The regions in the pool.

entries[R]

Tournament::Entry objects for the participants

payouts[R]

Hash of payouts by rank

entry_fee[RW]

The entry fee

scoring_strategy[R]

The scoring strategy for the pool

Public Class Methods

ncaa_2008() click to toggle source

Creates a Pool object for the 2008 NCAA tournament

     # File lib/tournament/pool.rb, line 102
102:   def self.ncaa_2008
103:     pool = Tournament::Pool.new
104:     pool.add_region("East",
105:       [
106:         Tournament::Team.new('North Carolina', 'UNC', 1),
107:         Tournament::Team.new('Mt. St. Mary\'s', 'MSM', 16),
108:         Tournament::Team.new('Indiana', 'Ind', 8),
109:         Tournament::Team.new('Arkansas', 'Ark', 9),
110:         Tournament::Team.new('Notre Dame', 'ND', 5),
111:         Tournament::Team.new('George Mason', 'GM', 12),
112:         Tournament::Team.new('Washington St.', 'WSt', 4),
113:         Tournament::Team.new('Winthrop', 'Win', 13),
114:         Tournament::Team.new('Oklahoma', 'Okl', 6),
115:         Tournament::Team.new('St. Joseph\'s', 'StJ', 11),
116:         Tournament::Team.new('Louisville', 'Lou', 3),
117:         Tournament::Team.new('Boise St.', 'BSt', 14),
118:         Tournament::Team.new('Butler', 'But', 7),
119:         Tournament::Team.new('South Alabama', 'SAl', 10),
120:         Tournament::Team.new('Tennessee', 'Ten', 2),
121:         Tournament::Team.new('American', 'Am', 15)
122:       ],
123:       0
124:     )
125:     pool.add_region("Midwest",
126:       [
127:         Tournament::Team.new('Kansas', 'Kan', 1),
128:         Tournament::Team.new('Portland St.', 'PSt', 16),
129:         Tournament::Team.new('UNLV', 'ULV', 8),
130:         Tournament::Team.new('Kent St.', 'KSt', 9),
131:         Tournament::Team.new('Clemson', 'Clm', 5),
132:         Tournament::Team.new('Villanova', 'Vil', 12),
133:         Tournament::Team.new('Vanderbilt', 'Van', 4),
134:         Tournament::Team.new('Siena', 'Sie', 13),
135:         Tournament::Team.new('USC', 'USC', 6),
136:         Tournament::Team.new('Kansas St.', 'KSU', 11),
137:         Tournament::Team.new('Wisconsin', 'Wis', 3),
138:         Tournament::Team.new('CSU Fullerton', 'CSF', 14),
139:         Tournament::Team.new('Gonzaga', 'Gon', 7),
140:         Tournament::Team.new('Davidson', 'Dav', 10),
141:         Tournament::Team.new('Georgetown', 'GT', 2),
142:         Tournament::Team.new('UMBC', 'UBC', 15)
143:       ],
144:       1
145:     )
146:     pool.add_region("South",
147:       [
148:         Tournament::Team.new('Memphis', 'Mem', 1),
149:         Tournament::Team.new('TX Arlington', 'TxA', 16),
150:         Tournament::Team.new('Mississippi St.', 'MiS', 8),
151:         Tournament::Team.new('Oregon', 'Ore', 9),
152:         Tournament::Team.new('Michigan St.', 'MSU', 5),
153:         Tournament::Team.new('Temple', 'Tem', 12),
154:         Tournament::Team.new('Pittsburgh', 'Pit', 4),
155:         Tournament::Team.new('Oral Roberts', 'ORo', 13),
156:         Tournament::Team.new('Marquette', 'Mar', 6),
157:         Tournament::Team.new('Kentucky', 'Ken', 11),
158:         Tournament::Team.new('Stanford', 'Sta', 3),
159:         Tournament::Team.new('Cornell', 'Cor', 14),
160:         Tournament::Team.new('Miami (FL)', 'Mia', 7),
161:         Tournament::Team.new('St. Mary\'s', 'StM', 10),
162:         Tournament::Team.new('Texas', 'Tex', 2),
163:         Tournament::Team.new('Austin Peay', 'APe', 15)
164:       ],
165:       2
166:     )
167:     pool.add_region("West",
168:       [
169:         Tournament::Team.new('UCLA', 'ULA', 1),
170:         Tournament::Team.new('Mis. Valley St', 'MVS', 16),
171:         Tournament::Team.new('BYU', 'BYU', 8),
172:         Tournament::Team.new('Texas A&M', 'A&M', 9),
173:         Tournament::Team.new('Drake', 'Dra', 5),
174:         Tournament::Team.new('W. Kentucky', 'WKy', 12),
175:         Tournament::Team.new('Connecticut', 'Con', 4),
176:         Tournament::Team.new('San Diego', 'SD', 13),
177:         Tournament::Team.new('Purdue', 'Pur', 6),
178:         Tournament::Team.new('Baylor', 'Bay', 11),
179:         Tournament::Team.new('Xavier', 'Xav', 3),
180:         Tournament::Team.new('Georgia', 'UG', 14),
181:         Tournament::Team.new('West Virginia', 'WVa', 7),
182:         Tournament::Team.new('Arizona', 'UA', 10),
183:         Tournament::Team.new('Duke', 'Duk', 2),
184:         Tournament::Team.new('Belmont', 'Bel', 15)
185:       ],
186:       3
187:     )
188:     return pool
189:   end
ncaa_2009() click to toggle source

Creates a Pool object for the 2009 NCAA tournament

     # File lib/tournament/pool.rb, line 192
192:   def self.ncaa_2009
193:     pool = Tournament::Pool.new
194:     pool.add_region("Midwest",
195:       [
196:         Tournament::Team.new('Louisville', 'UNC', 1),
197:         Tournament::Team.new('Morehead State', 'MrS', 16),
198:         Tournament::Team.new('Ohio State', 'OSU', 8),
199:         Tournament::Team.new('Siena', 'Sie', 9),
200:         Tournament::Team.new('Utah', 'Uta', 5),
201:         Tournament::Team.new('Arizona', 'UA', 12),
202:         Tournament::Team.new('Wake Forest', 'WkF', 4),
203:         Tournament::Team.new('Cleveland State', 'ClS', 13),
204:         Tournament::Team.new('West Virginia', 'WVa', 6),
205:         Tournament::Team.new('Dayton', 'Day', 11),
206:         Tournament::Team.new('Kansas', 'Kan', 3),
207:         Tournament::Team.new('North Dakota State', 'NDS', 14),
208:         Tournament::Team.new('Boston College', 'BC', 7),
209:         Tournament::Team.new('USC', 'USC', 10),
210:         Tournament::Team.new('Michigan State', 'MSU', 2),
211:         Tournament::Team.new('Robert Morris', 'RbM', 15)
212:       ],
213:       0
214:     )
215:     pool.add_region("West",
216:       [
217:         Tournament::Team.new('Connecticut', 'Con', 1),
218:         Tournament::Team.new('Chattanooga', 'Cht', 16),
219:         Tournament::Team.new('BYU', 'BYU', 8),
220:         Tournament::Team.new('Texas A&M', 'A&M', 9),
221:         Tournament::Team.new('Purdue', 'Pur', 5),
222:         Tournament::Team.new('Northern Iowa', 'NIo', 12),
223:         Tournament::Team.new('Washington', 'Was', 4),
224:         Tournament::Team.new('Mississippi State', 'MiS', 13),
225:         Tournament::Team.new('Marquette', 'Mar', 6),
226:         Tournament::Team.new('Utah State', 'USt', 11),
227:         Tournament::Team.new('Missouri', 'Msr', 3),
228:         Tournament::Team.new('Cornell', 'Cor', 14),
229:         Tournament::Team.new('California', 'Cal', 7),
230:         Tournament::Team.new('Maryland', 'Mry', 10),
231:         Tournament::Team.new('Memphis', 'Mem', 2),
232:         Tournament::Team.new('Cal State Northridge', 'CSN', 15)
233:       ],
234:       1
235:     )
236:     pool.add_region("East",
237:       [
238:         Tournament::Team.new('Pittsburgh', 'Pit', 1),
239:         Tournament::Team.new('East Tennessee State', 'ETS', 16),
240:         Tournament::Team.new('Oklahoma State', 'OkS', 8),
241:         Tournament::Team.new('Tennessee', 'Ten', 9),
242:         Tournament::Team.new('Florida State', 'FSU', 5),
243:         Tournament::Team.new('Wisconsin', 'Wis', 12),
244:         Tournament::Team.new('Xavier', 'Xav', 4),
245:         Tournament::Team.new('Portland St', 'PSt', 13),
246:         Tournament::Team.new('UCLA', 'ULA', 6),
247:         Tournament::Team.new('Virginia Commonwealth', 'VAC', 11),
248:         Tournament::Team.new('Villanova', 'Vil', 3),
249:         Tournament::Team.new('Cornell', 'Cor', 14),
250:         Tournament::Team.new('Texas', 'Tex', 7),
251:         Tournament::Team.new('Minnesota', 'Min', 10),
252:         Tournament::Team.new('Duke', 'Duk', 2),
253:         Tournament::Team.new('Binghamton', 'Bin', 15)
254:       ],
255:       2
256:     )
257:     pool.add_region("South",
258:       [
259:         Tournament::Team.new('North Carolina', 'UNC', 1),
260:         Tournament::Team.new('Radford', 'Rad', 16),
261:         Tournament::Team.new('LSU', 'LSU', 8),
262:         Tournament::Team.new('Butler', 'But', 9),
263:         Tournament::Team.new('Illinois', 'Ill', 5),
264:         Tournament::Team.new('W. Kentucky', 'WKy', 12),
265:         Tournament::Team.new('Gonzaga', 'Gon', 4),
266:         Tournament::Team.new('Akron', 'Akr', 13),
267:         Tournament::Team.new('Arizona State', 'ASU', 6),
268:         Tournament::Team.new('Temple', 'Tem', 11),
269:         Tournament::Team.new('Syracuse', 'Syr', 3),
270:         Tournament::Team.new('Stephen F. Austin', 'SFA', 14),
271:         Tournament::Team.new('Clemson', 'Cle', 7),
272:         Tournament::Team.new('Michigan', 'UM', 10),
273:         Tournament::Team.new('Oklahoma', 'Okl', 2),
274:         Tournament::Team.new('Morgan State', 'MgS', 15)
275:       ],
276:       3
277:     )
278:     return pool
279:   end
ncaa_2010() click to toggle source

Creates a Pool object for the 2010 NCAA tournament

     # File lib/tournament/pool.rb, line 282
282:   def self.ncaa_2010
283:     pool = Tournament::Pool.new
284:     pool.add_region("Midwest",
285:       [
286:         Tournament::Team.new('Kansas', 'Kan', 1),
287:         Tournament::Team.new('Lehigh', 'Leh', 16),
288:         Tournament::Team.new('UNLV', 'ULV', 8),
289:         Tournament::Team.new('Northern Iowa', 'NIo', 9),
290:         Tournament::Team.new('Michigan St.', 'MSU', 5),
291:         Tournament::Team.new('New Mexico State', 'NMS', 12),
292:         Tournament::Team.new('Maryland', 'Mry', 4),
293:         Tournament::Team.new('Houston', 'Hou', 13),
294:         Tournament::Team.new('Tennessee', 'Ten', 6),
295:         Tournament::Team.new('San Diego State', 'SDS', 11),
296:         Tournament::Team.new('Georgetown', 'GT', 3),
297:         Tournament::Team.new('Ohio', 'Ohi', 14),
298:         Tournament::Team.new('Oklahoma State', 'OkS', 7),
299:         Tournament::Team.new('Georgia Tech', 'GTc', 10),
300:         Tournament::Team.new('Ohio State', 'OSU', 2),
301:         Tournament::Team.new('UC Santa Barbara', 'SB', 15)
302:       ],
303:       0
304:     )
305:     pool.add_region("West",
306:       [
307:         Tournament::Team.new('Syracuse', 'Syr', 1),
308:         Tournament::Team.new('Vermont', 'Ver', 16),
309:         Tournament::Team.new('Gonzaga', 'Gon', 8),
310:         Tournament::Team.new('Florida State', 'FSU', 9),
311:         Tournament::Team.new('Butler', 'But', 5),
312:         Tournament::Team.new('UTEP', 'UTP', 12),
313:         Tournament::Team.new('Vanderbilt', 'Van', 4),
314:         Tournament::Team.new('Murray State', 'Mur', 13),
315:         Tournament::Team.new('Xavier', 'Xav', 6),
316:         Tournament::Team.new('Minnesota', 'Min', 11),
317:         Tournament::Team.new('Pittsburgh', 'Pit', 3),
318:         Tournament::Team.new('Oakland', 'Oak', 14),
319:         Tournament::Team.new('BYU', 'BYU', 7),
320:         Tournament::Team.new('Florida', 'Fla', 10),
321:         Tournament::Team.new('Kansas St.', 'KSU', 2),
322:         Tournament::Team.new('Nort Texas', 'NTx', 15)
323:       ],
324:       1
325:     )
326:     pool.add_region("East",
327:       [
328:         Tournament::Team.new('Kentucky', 'Ken', 1),
329:         Tournament::Team.new('East Tennessee State', 'ETS', 16),
330:         Tournament::Team.new('Texas', 'Tex', 8),
331:         Tournament::Team.new('Wake Forest', 'WkF', 9),
332:         Tournament::Team.new('Temple', 'Tem', 5),
333:         Tournament::Team.new('Cornell', 'Cor', 12),
334:         Tournament::Team.new('Wisconsin', 'Wis', 4),
335:         Tournament::Team.new('Wofford', 'Wof', 13),
336:         Tournament::Team.new('Marquette', 'Mar', 6),
337:         Tournament::Team.new('Washington', 'Was', 11),
338:         Tournament::Team.new('New Mexico', 'NMx', 3),
339:         Tournament::Team.new('Montana', 'Mon', 14),
340:         Tournament::Team.new('Clemson', 'Clm', 7),
341:         Tournament::Team.new('Missouri', 'Msr', 10),
342:         Tournament::Team.new('West Virginia', 'WVa', 2),
343:         Tournament::Team.new('Morgan State', 'MgS', 15)
344:       ],
345:       2
346:     )
347:     pool.add_region("South",
348:       [
349:         Tournament::Team.new('Duke', 'Duk', 1),
350:         Tournament::Team.new('Arkansa-Pine Bluff', 'APB', 16),
351:         Tournament::Team.new('California', 'Cal', 8),
352:         Tournament::Team.new('Louisville', 'Lou', 9),
353:         Tournament::Team.new('Texas A&M', 'A&M', 5),
354:         Tournament::Team.new('Utah State', 'USt', 12),
355:         Tournament::Team.new('Purdue', 'Pur', 4),
356:         Tournament::Team.new('Siena', 'Sie', 13),
357:         Tournament::Team.new('Notre Dame', 'ND', 6),
358:         Tournament::Team.new('Old Dominion', 'OD', 11),
359:         Tournament::Team.new('Baylor', 'Bay', 3),
360:         Tournament::Team.new('Sam Houston State', 'SHS', 14),
361:         Tournament::Team.new('Richmond', 'Rch', 7),
362:         Tournament::Team.new("St. Mary's", 'StM', 10),
363:         Tournament::Team.new('Villanova', 'Vil', 2),
364:         Tournament::Team.new('Robert Morris', 'RbM', 15)
365:       ],
366:       3
367:     )
368:     return pool
369:   end
new() click to toggle source

Create a new empty pool with no Regions or Entries

    # File lib/tournament/pool.rb, line 18
18:   def initialize
19:     @regions = Array.new(4)
20:     @entries = []
21:     @payouts = {}
22:     @scoring_strategy = Tournament::ScoringStrategy::Basic.new
23:   end
split_line(str, len) click to toggle source

Splits str on space chars in chunks of around len size

     # File lib/tournament/pool.rb, line 488
488:   def self.split_line(str, len)
489:     new_str = []
490:     beg_idx = 0
491:     end_idx = len - 1
492:     while end_idx < str.length
493:       end_idx += 1 while end_idx < (str.length - 1) && str[end_idx].chr != ' '
494:       new_str << str[beg_idx,(end_idx-beg_idx+1)].strip
495:       beg_idx = end_idx + 1
496:       end_idx += len
497:     end
498:     new_str << str[beg_idx,str.length-1]
499:     return new_str.reject {|s| s.nil? || s.length == 0}  
500:   end
test(num_picks = 20) click to toggle source

Run a test pool with random entries and a random outcome.

     # File lib/tournament/pool.rb, line 372
372:   def self.test(num_picks = 20)
373:     pool = ncaa_2008
374:     pool.entry_fee = 10
375:     pool.set_payout(1, 70)
376:     pool.set_payout(2, 20)
377:     pool.set_payout(3, 10)
378:     pool.set_payout(:last, -10)
379:     pool.scoring_strategy = Tournament::ScoringStrategy::Upset.new
380:     b = pool.tournament_entry.picks
381:     picks = (1..num_picks).map {|n| Tournament::Bracket.random_bracket(b.teams)}
382:     # Play out the bracket
383:     32.times { |n| b.set_winner(1,n+1, b.matchup(1, n+1)[rand(2)])}
384:     10.times { |n| b.set_winner(2,n+1, b.matchup(2, n+1)[rand(2)])}
385: #    8.times { |n| b.set_winner(3,n+1, b.matchup(3, n+1)[rand(2)])}
386: #4.times { |n| b.set_winner(4,n+1, b.matchup(4, n+1)[rand(2)])}
387:     #2.times { |n| b.set_winner(5,n+1, b.matchup(5, n+1)[rand(2)])}
388:     #1.times { |n| b.set_winner(6,n+1, b.matchup(6, n+1)[rand(2)])}
389:     picks.each_with_index {|p, idx| pool.add_entry Tournament::Entry.new("picker_#{idx}", p) }
390:     picks.each_with_index do |p, idx|
391:       puts "Score #{idx+1}: #{p.score_against(b, pool.scoring_strategy)}"
392:     end
393:     pool.region_report
394:     pool.leader_report
395:     pool.final_four_report
396:     pool.possibility_report
397:     pool.entry_report
398:     pool.score_report
399:   end

Public Instance Methods

add_entry(entry) click to toggle source

Add an Tournament::Entry object to the pool

    # File lib/tournament/pool.rb, line 35
35:   def add_entry(entry)
36:     @entries << entry
37:   end
add_entry_yaml(yaml) click to toggle source

Add an Tournament::Entry object to the pool after reading the Tournament::Entry from the provided YAML file.

    # File lib/tournament/pool.rb, line 46
46:   def add_entry_yaml(yaml)
47:     @entries << YAML::load_file(yaml)
48:   end
add_region(name, teams, index) click to toggle source

add regions to the pool. Champ of region with index = 0 plays region with index = 1 and index == 2 plays index == 3.

    # File lib/tournament/pool.rb, line 27
27:   def add_region(name, teams, index)
28:     @regions[index] = {
29:       :name => name,
30:       :teams => teams
31:     }
32:   end
entry_report(out = $stdout) click to toggle source

Shows a report of each entry’s picks by round.

     # File lib/tournament/pool.rb, line 503
503:   def entry_report(out = $stdout)
504:     out << "There are #{@entries.size} entries." << "\n"
505:     if @entries.size > 0
506:       out << "".center(15) + "|" + "First Round".center(128) << "\n"
507:       out << "Name".center(15) + "|" + "Sweet 16".center(64) + "|" + "Elite 8".center(32) +
508:         "|" + "Final 4".center(16) + "|" + "Final 2".center(8) + "|" + "Champion".center(15) +
509:         "|" + "Tie Break" << "\n"
510:       out << ("-" * 15) + "+" + ("-" * 64) + "+" + ("-" * 32) +
511:         "+" + ("-" * 16) + "+" + ("-" * 8) + "+" + ("-" * 15) +
512:         "+" + ("-" * 10) << "\n"
513:       output = Proc.new do |name, bracket, tie_breaker|
514:         first_round = bracket.winners[1].map {|t| "%s" % (t.short_name rescue 'Unk')}.join('-')
515:         sweet_16 = bracket.winners[2].map {|t| "%s" % (t.short_name rescue 'Unk')}.join('-')
516:         elite_8 = bracket.winners[3].map {|t| "%s" % (t.short_name rescue 'Unk')}.join('-')
517:         final_4 = bracket.winners[4].map {|t| "%s" % (t.short_name rescue 'Unk')}.join('-')
518:         final_2 = bracket.winners[5].map {|t| "%s" % (t.short_name rescue 'Unk')}.join('-')
519:         champ = bracket.champion.name rescue 'Unk'
520:         out << "               |%128s" % first_round << "\n"
521:         out << "%15s|%64s|%32s|%16s|%8s|%15s|%s" %
522:           [name, sweet_16, elite_8, final_4, final_2, champ, tie_breaker.to_s]  << "\n"
523:         out << ("-" * 15) + "+" + ("-" * 64) + "+" + ("-" * 32) +
524:           "+" + ("-" * 16) + "+" + ("-" * 8) + "+" + ("-" * 15) +
525:           "+" + ("-" * 10) << "\n"
526:       end
527: 
528:       output.call('Tournament', tournament_entry.picks, tournament_entry.tie_breaker || '-')
529: 
530:       @entries.sort_by{|e| e.name}.each do |entry|
531:         output.call(entry.name, entry.picks, entry.tie_breaker)
532:       end
533:     end
534:   end
final_four_report(out = $stdout) click to toggle source

When there are four teams left, for each of the 16 possible outcomes shows who will win according to the configured payouts.

     # File lib/tournament/pool.rb, line 556
556:   def final_four_report(out = $stdout)
557:     if @entries.size == 0
558:       out << "There are no entries in the pool." << "\n"
559:       return
560:     end
561:     if self.tournament_entry.picks.teams_left > 4
562:       out << "The final four report should only be run when there" << "\n"
563:       out << "are four or fewer teams left in the tournament." << "\n"
564:       return
565:     end
566:     total_payout = @entries.size * @entry_fee.to_i
567:     # Subtract out constant payments
568:     total_payout = @payouts.values.inject(total_payout) {|t, amount| t += amount if amount < 0; t}
569: 
570:     use_payouts = @payouts.inject({}) {|h,arr| k = arr[0] != :last ? arr[0].to_i : arr[0]; h[k] = arr[1]; h}
571:     payout_keys = use_payouts.keys.sort do |a,b|
572:       if Symbol === a
573:         1
574:       elsif Symbol === b
575:         -1
576:       else
577:         a <=> b
578:       end
579:     end
580: 
581:     out << "Final Four: #{self.tournament_entry.picks.winners[4][0,2].map{|t| "(#{t.seed}) #{t.name}"}.join(" vs. ")}"
582:     out << "    #{self.tournament_entry.picks.winners[4][2,2].map{|t| "(#{t.seed}) #{t.name}"}.join(" vs. ")}" << "\n"
583:     if self.tournament_entry.picks.teams_left <= 2
584:       out << "Championship: #{self.tournament_entry.picks.winners[5][0,2].map{|t| "(#{t.seed}) #{t.name}"}.join(" vs. ")}" << "\n"
585:     end
586:     out << "Payouts" << "\n"
587:     payout_keys.each do |key|
588:       amount = if use_payouts[key] > 0
589:         use_payouts[key].to_f / 100.0 * total_payout
590:       else
591:         -use_payouts[key]
592:       end
593:       out << "%4s: $%5.2f" % [key, amount] << "\n"
594:     end
595:     sep= "--------------+----------------+-----------------------------------------"
596:     out << "              |                | Winners      Tie    " << "\n"
597:     out << " Championship |    Champion    | Rank Score Break Name" << "\n"
598:     out << sep << "\n"
599:     self.tournament_entry.picks.each_possible_bracket do |poss|
600:       rankings = @entries.map{|p| [p, p.picks.score_against(poss, self.scoring_strategy)] }.sort do |a1, a2|
601:          if a1[1] == a2[1]
602:            # Use tiebreak
603:            if self.tournament_entry.tie_breaker
604:              tb1 = (a1[0].tie_breaker - self.tournament_entry.tie_breaker).abs
605:              tb2 = (a2[0].tie_breaker - self.tournament_entry.tie_breaker).abs
606:              tb1 <=> tb2
607:            else
608:              0
609:            end 
610:          else
611:            a2[1] <=> a1[1]
612:          end
613:       end
614:       finishers = {}
615:       use_payouts.each do |rank, payout|
616:         finishers[rank] = {}
617:         finishers[rank][:payout] = payout
618:         finishers[rank][:entries] = []
619:         finishers[rank][:score] = 0
620:       end
621:       index = 0
622:       rank = 1
623:       while index < @entries.size
624:         rank_score = rankings[index][1]
625:         finishers_key = index < (@entries.size - 1) ? rank : :last
626:         finish_hash = finishers[finishers_key]
627:         #puts "For rank_score = #{rank_score} finishers key = #{finishers_key.inspect}, hash = #{finish_hash}, index = #{index}"
628:         if finish_hash
629:           while index < @entries.size && rankings[index][1] == rank_score
630:             finish_hash[:entries] << rankings[index][0]
631:             finish_hash[:score] = rank_score
632:             index += 1
633:           end
634:           rank += 1
635:           next
636:         end
637:         index += 1
638:         rank += 1
639:       end
640: 
641:       num_payouts = payout_keys.size
642: 
643:       first_line = true
644:       showed_last = false
645:       payout_count = 0
646:       while payout_count < num_payouts
647:         rank = payout_keys[payout_count]
648:         finish_hash = finishers[rank]
649:         label = finish_hash[:entries].size == 1 ? "#{rank}".upcase : "TIE"
650:         finish_hash[:entries].each do |winner| 
651:           line = if first_line
652:             "%14s|%16s| %4s %5d %5d %s" % [
653:               poss.winners[5].map{|t| t.short_name}.join("-"),
654:               poss.champion.name,
655:               label,
656:               finish_hash[:score],
657:               winner.tie_breaker,
658:               winner.name
659:             ]
660:           else
661:             "%14s|%16s| %4s %5d %5d %s" % [
662:               '',
663:               '',
664:               label,
665:               finish_hash[:score],
666:               winner.tie_breaker,
667:               winner.name
668:             ]
669:           end
670:           out << line << "\n"
671:           first_line = false
672:         end
673:         payout_count += finish_hash[:entries].size
674:         showed_last = (rank == :last)
675:         if payout_count >= num_payouts && !showed_last
676:           if payout_keys[num_payouts-1] == :last
677:             payout_count -= 1
678:             showed_last = true
679:           end
680:         end
681:       end
682:       out << sep << "\n"
683:     end
684:     nil
685:   end
leader_report(out = $stdout) click to toggle source

Generate the leader board report. Shows each entry sorted by current score and gives a breakdown of score by round.

     # File lib/tournament/pool.rb, line 403
403:   def leader_report(out = $stdout)
404:     out << "Total games played: #{tournament_entry.picks.games_played}" << "\n"
405:     if tournament_entry.picks.complete?
406:       out << "Champion: #{tournament_entry.picks.champion.name}" << "\n"
407:     end
408:     out << "Pool Tie Break: #{tournament_entry.tie_breaker || '-'}" << "\n"
409:     out << "Number of entries: #{@entries.size}" << "\n"
410:     current_rank = 1
411:     if @entries.size > 0
412:       out << "    | Curr| Max |               |Champ| Tie | Round Scores" << "\n"
413:       out << "Rank|Score|Score|      Name     |Live?|Break|" + (1..tournament_entry.picks.rounds).to_a.map{|r| "%3d" % r}.join(" ") << "\n"
414:       sep ="----+-----+-----+---------------+-----+-----+" + ("-" * 4 * tournament_entry.picks.rounds)
415:       out << sep << "\n"
416:       @entries.sort do |e1, e2|
417:         s1 = e1.picks.score_against(tournament_entry.picks, self.scoring_strategy)
418:         s2 = e2.picks.score_against(tournament_entry.picks, self.scoring_strategy)
419:         if s1 == s2 && tournament_entry.tie_breaker
420:           s1 = 0 - (e1.tie_breaker - tournament_entry.tie_breaker).abs
421:           s2 = 0 - (e2.tie_breaker - tournament_entry.tie_breaker).abs
422:         end
423:         s2 <=> s1
424:       end.inject(nil) do |last_entry, entry|
425:         total = entry.picks.score_against(tournament_entry.picks, self.scoring_strategy)
426:         max = entry.picks.maximum_score(tournament_entry.picks, self.scoring_strategy)
427:         champ = entry.picks.champion
428:         round_scores = []
429:         1.upto(tournament_entry.picks.rounds) do |round|
430:           scores = entry.picks.scores_for_round(round, tournament_entry.picks, self.scoring_strategy)
431:           round_scores << scores.inject(0) {|sum, arr| sum += (arr[0] ? arr[0] : 0)}
432:         end
433:         rank_display = nil
434:         if last_entry && !tournament_entry.tie_breaker && total == last_entry.bracket.score_against(tournament_entry.picks, self.scoring_strategy)
435:           rank_display = 'TIE'
436:         else
437:           rank_display = "%4d" % current_rank
438:         end
439:         out << "%4s|%5d|%5d|%15s|%3s %1s|%5d|%s" % [rank_display, total, max, entry.name,
440:           champ.short_name,(tournament_entry.picks.still_alive?(champ) ? 'Y' : 'N'), entry.tie_breaker || '-', round_scores.map {|s| "%3d" % s}.join(" ")] << "\n"
441:         current_rank += 1
442:         entry
443:       end
444:       out << sep << "\n"
445:     end
446:   end
possibility_report(out = $stdout) click to toggle source

Runs through every possible outcome of the tournament and calculates each entry’s chance to win as a percentage of the possible outcomes the entry would win if the tournament came out that way. Generates an ASCII report of the results.

     # File lib/tournament/pool.rb, line 746
746:   def possibility_report(out = $stdout)
747:     $stdout.sync = true
748:     if @entries.size == 0
749:       out << "There are no entries in the pool." << "\n"
750:       return
751:     end
752:     out << "Checking #{self.tournament_entry.picks.number_of_outcomes} possible outcomes" << "\n"
753:     stats = possibility_stats do |percentage, remaining|
754:       hashes = '#' * (percentage.to_i/5) + '>'
755:       out << "\rCalculating: %3d%% +#{hashes.ljust(20, '-')}+ %5d seconds remaining" % [percentage.to_i, remaining]
756:     end
757:     out << "\n"
758:     #puts "SORT: #{stats.inspect}"
759:     out << "    Entry           | Win Chance | Highest Place | Curr Score | Max Score | Tie Break  " << "\n"
760:     out << "--------------------+------------+---------------+------------+-----------+------------" << "\n"
761:     stats.each do |stat|
762:       chance = stat.times_champ.to_f * 100.0 / self.tournament_entry.picks.number_of_outcomes
763:       out << "%19s | %10.2f | %13d | %10d | %9d | %7d " %
764:         [stat.entry.name, chance, stat.min_rank, stat.entry.picks.score_against(self.tournament_entry.picks, self.scoring_strategy), stat.max_score, stat.entry.tie_breaker] << "\n"
765:     end
766:     out << "Possible Champions For Win" << "\n"
767:     out << "    Entry           |    Champion     |  Ocurrences   |  Chance " << "\n"
768:     out << "--------------------+-----------------+---------------+---------" << "\n"
769:     stats.each do |stat|
770:       next if stat.champs.size == 0
771:       stat.champs.sort_by{|k,v| -v}.each_with_index do |harr, idx| 
772:         team = harr[0]
773:         occurences = harr[1]
774:         if idx == 0
775:           out << "%19s | %15s | %13d | %8.2f " % [stat.entry.name, team, occurences, occurences.to_f * 100.0 / stat.times_champ] << "\n"
776:         else
777:           out << "%19s | %15s | %13d | %8.2f " % ['', team, occurences, occurences.to_f * 100.0 / stat.times_champ] << "\n"
778:         end
779:       end
780:       out << "--------------------+-----------------+---------------+---------" << "\n"
781:     end
782:     nil
783:   end
possibility_stats() click to toggle source

Runs through every possible outcome of the tournament and calculates each entry’s chance to win as a percentage of the possible outcomes the entry would win if the tournment came out that way. If a block is provided, periodically reports progress by calling the block and passing it the percent complete and time remaining in seconds as arguments. Returns array of structs responding to times_champ, max_score, min_rank, entry and champs methods. The entry method returns the Tournament::Entry object and the champs method returns a hash keyed on team name and whose values are the number of times that team could win that would make the entry come in on top.

     # File lib/tournament/pool.rb, line 698
698:   def possibility_stats
699:     stats = @entries.map do |e|
700:       Tournament::Possibility.new(e)
701:     end
702:     max_possible_score = @entries.map{|p| 0}
703:     min_ranking = @entries.map{|p| @entries.size + 1}
704:     times_winner = @entries.map{|p| 0 }
705:     player_champions = @entries.map{|p| Hash.new {|h,k| h[k] = 0} }
706:     count = 0
707:     old_percentage = -1 
708:     old_remaining = 1_000_000_000_000
709:     start = Time.now.to_f
710:     self.tournament_entry.picks.each_possible_bracket do |poss|
711:       poss_scores = @entries.map{|p| p.picks.score_against(poss, self.scoring_strategy)}
712:       sort_scores = poss_scores.sort.reverse
713:       @entries.each_with_index do |entry, i|
714:         score = poss_scores[i]
715:         stat = stats[i]
716:         stat.max_score = score if score > stat.max_score
717:         rank = sort_scores.index(score) + 1
718:         stat.min_rank = rank if rank < stat.min_rank
719:         stat.times_champ += 1 if rank == 1
720:         if rank == 1
721:           stat.champs[poss.champion.name] ||= 0
722:           stat.champs[poss.champion.name] += 1
723:         end
724:       end
725:       count += 1
726:       percentage = (count * 100.0 / self.tournament_entry.picks.number_of_outcomes)
727:       elapsed = Time.now.to_f - start
728:       spp = elapsed / count
729:       remaining = ((self.tournament_entry.picks.number_of_outcomes - count) * spp).to_i
730:       if (percentage.to_i != old_percentage) || (remaining < old_remaining)
731:         old_remaining = remaining
732:         old_percentage = percentage.to_i
733:         if block_given?
734:           yield(percentage.to_i, remaining)
735:         end
736:       end
737:     end
738:     stats.sort!
739:     return stats
740:   end
region_report(out = $stdout) click to toggle source

Displays the regions and teams in the region.

     # File lib/tournament/pool.rb, line 537
537:   def region_report(out = $stdout)
538:     out << " Region | Seed | Team               " << "\n"
539:     current_idx = -1
540:     @regions.each_with_index do |region, idx|
541:       next unless region
542:       (region[:teams] || []).each do |team|
543:         region_name = ''
544:         if idx != current_idx
545:           region_name =  region[:name]
546:           current_idx = idx
547:           out << "--------+------+-------------------------" << "\n"
548:         end
549:         out << "%8s|%6d|%25s" % [region_name, team.seed, "#{team.name} (#{team.short_name})"] << "\n"
550:       end
551:     end
552:   end
remove_by_name(name) click to toggle source

Remove an entry by name from the pool

    # File lib/tournament/pool.rb, line 51
51:   def remove_by_name(name)
52:     entry = @entries.find {|e| e.name == name}
53:     if !entry.nil?
54:       @entries.delete(entry)
55:     end
56:   end
score_report(out = $stdout) click to toggle source

Shows detailed scores per entry. For each pick in each game, shows either a positive amount if the pick was correct, 0 if the pick was incorrect, or a ’?’ if the game has not yet been played.

     # File lib/tournament/pool.rb, line 451
451:   def score_report(out = $stdout)
452:     # Compute scores
453:     out << "Total games played: #{tournament_entry.picks.games_played}" << "\n"
454:     out << "Number of entries: #{@entries.size}" << "\n"
455:     sep = "-----+---------------+----------------------------------------------------------------------------------"
456:     if @entries.size > 0
457:       out << "Total|      Name     | Round Scores" << "\n"
458:       out << sep << "\n"
459:       fmt1 = "%5d|%15s|%d: %3d %s" 
460:       fmt2 = "     |               |%d: %3d %s" 
461:       fmt3 = "     |               |       %s" 
462:       @entries.sort_by {|e| -e.picks.score_against(tournament_entry.picks, self.scoring_strategy)}.each do |entry|
463:         total = entry.picks.score_against(tournament_entry.picks, self.scoring_strategy)
464:         1.upto(tournament_entry.picks.rounds) do |round|
465:           scores = entry.picks.scores_for_round(round, tournament_entry.picks, self.scoring_strategy)
466:           round_total = scores.inject(0) {|sum, arr| sum += (arr[0] ? arr[0] : 0)}
467:           scores_str = scores.map{|arr| "#{arr[1].short_name}=#{arr[0] ? arr[0] : '?'}"}.join(" ")
468:           if [1,2].include?(round)
469:             scores_str_arr = Tournament::Pool.split_line(scores_str, 70)
470:             if round == 1
471:               out << fmt1 % [total, entry.name, round, round_total, scores_str_arr[0]] << "\n"
472:             else
473:               out << fmt2 % [round, round_total, scores_str_arr[0]] << "\n"
474:             end
475:             scores_str_arr[1..-1].each do |ss2|
476:               out << fmt3 % ss2 << "\n"
477:             end
478:           else
479:             out << fmt2 % [round, round_total, scores_str] << "\n"
480:           end
481:         end
482:         out << sep << "\n"
483:       end
484:     end
485:   end
scoring_strategy=(new_strat) click to toggle source

Set new scoring strategy. This should not be allowed.

    # File lib/tournament/pool.rb, line 40
40:   def scoring_strategy=(new_strat)
41:     @scoring_strategy = new_strat
42:   end
set_payout(rank, payout) click to toggle source

Set a payout. Takes a rank (or the symbol :last for last place), along with the payout. The payout may be a positive integer, in which case, it represents a percentage of the the total entry fees that particular rank would receive. The payout may also be a negative integer, in which case, it represents a constant payout amount.

    # File lib/tournament/pool.rb, line 71
71:   def set_payout(rank, payout)
72:     # FIXME: Add error checking
73:     @payouts ||= {}
74:     @payouts[rank] = payout
75:   end
tournament_entry() click to toggle source

Creates a entry for the pool by combining all the regions into one bracket of 64 teams. By default the entry bracket uses the basic scoring strategy.

    # File lib/tournament/pool.rb, line 80
80:   def tournament_entry
81:     unless @tournament_entry
82:       if @regions.compact.size != 4
83:         raise "Not all regions have been set."
84:       end
85:       all_teams = @regions.map do |region|
86:         region[:teams]
87:       end
88:       all_teams = all_teams.flatten
89:       bracket = Tournament::Bracket.new(all_teams)
90:       @tournament_entry = Tournament::Entry.new('Tournament Entry', bracket, nil)
91:     end
92:     return @tournament_entry
93:   end
tournament_entry=(new_entry) click to toggle source

Replaces the pool’s bracket (as in after updating the bracket for game results)

    # File lib/tournament/pool.rb, line 97
97:   def tournament_entry=(new_entry)
98:     @tournament_entry = new_entry
99:   end
update_entry(entry) click to toggle source

Replace existing matching entry with the provided entry

    # File lib/tournament/pool.rb, line 59
59:   def update_entry(entry)
60:     remove_by_name(entry.name)
61:     @entries << entry
62:   end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.