Last active
August 8, 2018 00:21
-
-
Save mikhail/606bd724a45ad63f189db957dfeb690e to your computer and use it in GitHub Desktop.
Elo for ping pong
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ELO_DEFAULT = 1500 | |
ELO_K_FACTOR = 16 | |
def expected(Ra, Rb): | |
# https://en.wikipedia.org/wiki/Elo_rating_system | |
Ea = (1.0 / (1.0 + pow(10.0, (Rb-Ra)/400.0))) | |
return Ea, 1-Ea | |
@bot.add_command('!challenge') | |
@gen.coroutine | |
def challenge(message): | |
"""Creates an interactive prompt, and keeps track of scores. | |
This function uses the Elo method of keeping track of ranks. | |
Every participant starts with 1500 and the "k" factor of 16""" | |
Ua = bot._get_user(message.user) | |
ratings = yield bot.memory.get('pong-elo-ratings', {}) | |
Ra = ratings.get(Ua.id) | |
if Ra is None: | |
Ra = yield bot.memory.get('%s-rating' % Ua.id, ELO_DEFAULT) | |
action = yield message.button_prompt( | |
'Who <!here> would like to challenge {}? Rating: {}'.format(Ua.first_name, int(Ra)), | |
['Take on the challenge'] | |
) | |
event = action._meta['event'] | |
accepting_user_id = event.get('user', {}).get('id') | |
Ub = bot._get_user(accepting_user_id) | |
Rb = ratings.get(Ub.id) | |
if Rb is None: | |
Rb = yield bot.memory.get('%s-rating' % Ub.id, ELO_DEFAULT) | |
yield message.reply('{} ({}) takes on the challenge!'.format(Ub.first_name, int(Rb))) | |
yield message.reply('{} vs. {}'.format(Ua.first_name, Ub.first_name)) | |
winner = yield message.button_prompt( | |
'Who won?', [ | |
'{}'.format(Ua.first_name), | |
'{}'.format(Ub.first_name), | |
'Draw', | |
'Cancel'] | |
) | |
if winner == 'Cancel': | |
yield message.reply('Too bad ... :(') | |
raise gen.Return() | |
if winner == 'Draw': | |
Sa, Sb = 0.5, 0.5 | |
elif winner == Ua.first_name: | |
Sa, Sb = 1, 0 | |
elif winner == Ub.first_name: | |
Sa, Sb = 0, 1 | |
else: | |
yield message.reply(('Got some strange button value "{}"...' | |
'ignoring this game').format(winner)) | |
raise gen.Return() | |
Ea, Eb = expected(Ra, Rb) | |
Ra = Ra + ELO_K_FACTOR * (Sa - Ea) | |
Rb = Rb + ELO_K_FACTOR * (Sb - Eb) | |
ratings[Ua.id] = Ra | |
ratings[Ub.id] = Rb | |
yield bot.memory.save('pong-elo-ratings', ratings) | |
yield message.reply('New Ratings:') | |
yield message.reply('{}: {}'.format(Ua.first_name, int(Ra))) | |
yield message.reply('{}: {}'.format(Ub.first_name, int(Rb))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment