Skip to content

Commit ec9bb76

Browse files
committed
add examples/elo_tourney.rb
1 parent cd98d87 commit ec9bb76

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed

examples/elo_tourney.rb

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
require 'compsci/elo'
2+
3+
include CompSci
4+
5+
# return two different integers 0..(pool.count -1)
6+
def pool_matchup(pool)
7+
a = rand(pool.count)
8+
[a, (a + rand(pool.count - 1) + 1) % pool.count]
9+
end
10+
11+
# sum / divide / round
12+
def avg_rating(pool)
13+
(pool.map(&:rating).sum.to_f / pool.count).round
14+
end
15+
16+
class Array
17+
# reverse sort
18+
def rank
19+
sort { |a, b| b <=> a }
20+
end
21+
end
22+
23+
pool_size = 999
24+
pool_matchups = 99_999
25+
tourney_size = 64
26+
iters = 5
27+
28+
# randomize skill levels
29+
pool = Elo::Player.init_pool(pool_size).each { |player|
30+
player.skill = rand.round(3)
31+
}
32+
33+
# LETS GO
34+
35+
iters.times { |i|
36+
puts
37+
puts
38+
puts "=" * 40
39+
puts " Season #{i + 1}"
40+
puts "=" * 40
41+
42+
# pool matchups
43+
pool_matchups.times {
44+
a, b = pool_matchup(pool)
45+
pool[a].simulate(pool[b]) # win / lose / draw
46+
}
47+
pool = pool.rank
48+
puts "Ran #{pool_matchups} matchups; average rating: #{avg_rating(pool)}"
49+
50+
# bottom 5% of pool retires
51+
rc = pool_size / 20
52+
(pool.count - rc).upto(pool.count - 1) { |i|
53+
pool[i] = Elo::Player.new(skill: rand.round(3))
54+
}
55+
puts "Retired the bottom 10%; average rating: #{avg_rating(pool)}"
56+
57+
# take top 64 for the tournament
58+
puts
59+
puts "Top 64:"
60+
puts '---'
61+
tpool = pool.take(tourney_size).each { |p| puts p }.shuffle
62+
puts
63+
64+
# run the tournament
65+
while tpool.size > 1
66+
puts "Players: #{tpool.size}"
67+
puts '---'
68+
next_round = []
69+
70+
# evens play odds
71+
(tpool.size / 2).times { |i|
72+
a = i * 2
73+
b = a + 1
74+
puts format("%s vs %s", tpool[a], tpool[b])
75+
76+
# best 4 out of 7
77+
wins, losses = 0, 0
78+
while (wins < 4 and losses < 4) or (wins == losses)
79+
outcome = tpool[a].simulate(tpool[b])
80+
if outcome == 0.5
81+
wins += 0.5
82+
losses += 0.5
83+
elsif outcome < 0.5
84+
losses += 1
85+
else
86+
wins += 1
87+
end
88+
end
89+
if wins > losses
90+
outcome, winner = 1, tpool[a]
91+
else
92+
outcome, winner = 0, tpool[b]
93+
end
94+
next_round << winner
95+
puts "Outcome: #{outcome}\tWinner: #{winner}"
96+
puts
97+
}
98+
puts
99+
tpool = next_round
100+
end
101+
102+
# a few pros retire
103+
retired = Set.new
104+
3.times { retired.add(rand(tourney_size)) }
105+
puts "Retired: #{retired.sort.join(', ')}"
106+
retired.each { |i|
107+
print pool[i]
108+
pool[i] = Elo::Player.new(skill: rand.round(3))
109+
puts " -> #{pool[i]}"
110+
}
111+
puts
112+
113+
# 5% non-pros retire
114+
retired = Set.new
115+
(pool_size / 20).times {
116+
retired.add(rand(pool_size - tourney_size) + tourney_size)
117+
}
118+
puts "Retired: #{retired.sort.join(', ')}"
119+
retired.each { |i|
120+
pool[i] = Elo::Player.new(skill: rand.round(3))
121+
}
122+
123+
pool = pool.rank
124+
puts "Average rating: #{avg_rating(pool)}"
125+
puts
126+
}
127+
128+
# pool matchups
129+
pool_matchups.times {
130+
a, b = pool_matchup(pool)
131+
pool[a].simulate(pool[b]) # win / lose / draw
132+
}
133+
pool = pool.rank
134+
puts "Ran #{pool_matchups} matchups; average rating: #{avg_rating(pool)}"
135+
136+
puts pool

0 commit comments

Comments
 (0)