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.