3 # Author: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
6 # Quick & dirty script to calculate ELO rankings. See later of input format.
12 # K factor, can be either fixed, or staircased, or some other function
36 # choose the one we want here
41 # the player list is a hash player => rating that defaults to the base rating
42 @rating = Hash.new { |h, k| h[k] = BASE_RATING }
51 rating.to_a.sort { |a, b| b.last <=> a.last }.map { |a| a.join(': ') }.join("\n")
54 def update(winner, loser, draw=false)
55 diff = rating[loser] - rating[winner]
56 winner_wins = 1.0/(Math.exp(diff/174)+1)
57 loser_wins = 1.0 - winner_wins
60 rating[winner] += factor(rating[winner])*(score - winner_wins)
61 rating[loser] += factor(rating[loser])*(1.0 - score - loser_wins)
65 # read lines from standard input, skipping lines that start with a has sign (#)
66 # each match line is supposed to be in the form:
68 # where <=> is < if player2 won, > if player1 won, = if the match was a draw.
69 # 2, 1, x are also accepted instead of <, > and = respectively.
74 # The player names should have no spaces in them, and anything after the name
75 # of the second player is ignored
78 $stdin.each_line do |line|
84 player1, sign, player2, junk = line.split($;,4)
86 player1, player2, sign = line.split(/\s*,\s*/,3)
90 rating.update(player2.intern, player1.intern)
92 rating.update(player2.intern, player1.intern, true)
94 rating.update(player1.intern, player2.intern)
96 raise "wrong match sign #{sign.inspect}"
98 puts "%s,%s,%s,%f,%f" % [player1, player2, sign, rating[player1], rating[player2]]