Skip to content

Instantly share code, notes, and snippets.

@mikhail
Last active August 8, 2018 00:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikhail/606bd724a45ad63f189db957dfeb690e to your computer and use it in GitHub Desktop.
Save mikhail/606bd724a45ad63f189db957dfeb690e to your computer and use it in GitHub Desktop.
Elo for ping pong
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