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.
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
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
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
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
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
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
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 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 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
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
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
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
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
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
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 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
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
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 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
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
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.