Skip to content

Instantly share code, notes, and snippets.

@nicktimko
Last active January 20, 2018 01:56
Show Gist options
  • Save nicktimko/e36aa2a57fd0058543886902ec95c152 to your computer and use it in GitHub Desktop.
Save nicktimko/e36aa2a57fd0058543886902ec95c152 to your computer and use it in GitHub Desktop.
This or That?
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import itertools\n",
"import math\n",
"import random\n",
"\n",
"import trueskill as ts # http://trueskill.org/"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"things = [\n",
" 'Half-life 2',\n",
" 'Portal',\n",
" 'Portal 2',\n",
" 'HL2: Episode One',\n",
" 'HL2: Episode Two',\n",
" 'Inside',\n",
" 'Limbo',\n",
" 'Furi',\n",
" 'Overwatch',\n",
" 'Dead Cells',\n",
" 'GTA V',\n",
" 'Team Fortress 2',\n",
" 'Runner2',\n",
" 'Civilization VI',\n",
" 'Civilization V',\n",
"]\n",
"\n",
"tse = ts.TrueSkill()\n",
"ratings = {\n",
" name: tse.create_rating()\n",
" for name\n",
" in things\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"already_compared = set()"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\"q\" to quit. \"x\" for draws.\n",
"\n",
" Which game is better? \n",
"--------------------------------------------------\n",
" A B \n",
"abandoning GTA V v Furi (low quality, 0.14607010133179865)\n",
" Runner2 Limbo > b\n",
" Civilization VI Furi > b\n",
"abandoning Portal v GTA V (low quality, 0.06135526166854186)\n",
"abandoning GTA V v Inside (low quality, 0.01650739079838616)\n",
" Portal Runner2 > a\n",
"abandoning GTA V v Inside (low quality, 0.01650739079838616)\n",
" Overwatch Team Fortress 2 > b\n",
" Civilization V Runner2 > a\n",
" HL2: Episode Two Furi > a\n",
" Civilization V Dead Cells > b\n",
" Portal Team Fortress 2 > a\n",
" HL2: Episode One GTA V > a\n",
" Portal 2 Overwatch > a\n",
" Civilization VI Portal > a\n",
" Half-life 2 Civilization VI > a\n",
" Half-life 2 Overwatch > a\n",
" Portal 2 HL2: Episode One > a\n",
" Inside Civilization VI > a\n",
" Half-life 2 Portal > b\n",
" Team Fortress 2 Portal 2 > b\n",
" Dead Cells Team Fortress 2 > b\n",
"abandoning GTA V v Team Fortress 2 (low quality, 0.07598480839640576)\n",
" Team Fortress 2 Civilization V > a\n",
"abandoning GTA V v Portal (low quality, 0.02038641592390918)\n",
" Inside HL2: Episode Two > a\n",
" HL2: Episode One Civilization VI > b\n",
" Portal HL2: Episode Two > a\n",
" Overwatch HL2: Episode Two > b\n",
" Overwatch Civilization VI > a\n",
" Portal Overwatch > a\n",
" Half-life 2 Limbo > b\n",
" Furi Inside > b\n",
" Dead Cells Runner2 > a\n",
"abandoning Half-life 2 v GTA V (low quality, 0.03691856590881096)\n",
"abandoning Civilization V v Portal (low quality, 0.0627472588791589)\n",
" Runner2 Civilization VI > b\n",
" Furi Runner2 > a\n",
" Portal 2 HL2: Episode Two > a\n",
"abandoning Portal v GTA V (low quality, 0.01163142820286043)\n",
" Inside Half-life 2 > a\n",
"abandoning Runner2 v Half-life 2 (low quality, 0.07800893333120992)\n",
" Portal 2 Civilization VI > a\n",
" Dead Cells Half-life 2 > b\n",
"abandoning GTA V v Half-life 2 (low quality, 0.03657380456512426)\n",
" HL2: Episode Two Team Fortress 2 > b\n",
"abandoning Runner2 v Team Fortress 2 (low quality, 0.07634956312685778)\n",
"abandoning GTA V v Inside (low quality, 0.0023413686447429616)\n",
" Furi Limbo > a\n",
" HL2: Episode One Civilization V > q\n"
]
}
],
"source": [
"title = 'Which game is better?'\n",
"\n",
"print('\"q\" to quit. \"x\" for draws.\\n\\n'\n",
" '{:^50s}\\n{:^50s}\\n{:^25s}{:^25s}'.format(\n",
" title, '-' * 50,\n",
" 'A', 'B',\n",
"))\n",
"\n",
"while True:\n",
" games = list(ratings)\n",
" for attempt in range(10):\n",
" fight = random.sample(games, 2)\n",
" key = tuple(sorted(fight))\n",
" if key in already_compared:\n",
" continue\n",
" \n",
" quality = tse.quality_1vs1(ratings[fight[0]], ratings[fight[1]])\n",
" if attempt < 8 and quality < 0.15:\n",
" print('abandoning {} v {} (low quality, {})'.format(*fight, quality))\n",
" continue\n",
" already_compared.add(key)\n",
" break\n",
"\n",
" g1, g2 = fight\n",
" result = input('{:^25s}{:^25s} > '.format(g1, g2))\n",
"\n",
" char = result.lower().strip()\n",
" if char == 'q':\n",
" break\n",
" elif char == 'x':\n",
" ratings[g1], ratings[g2] = ts.rate_1vs1(ratings[g1], ratings[g2], drawn=True) \n",
" elif char == 'a':\n",
" ratings[g1], ratings[g2] = ts.rate_1vs1(ratings[g1], ratings[g2])\n",
" elif char == 'b':\n",
" ratings[g2], ratings[g1] = ts.rate_1vs1(ratings[g2], ratings[g1])\n"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"79"
]
},
"execution_count": 67,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(already_compared)"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"[('Inside', trueskill.Rating(mu=38.706, sigma=4.084)),\n",
" ('Portal 2', trueskill.Rating(mu=37.698, sigma=4.305)),\n",
" ('Portal', trueskill.Rating(mu=33.797, sigma=3.599)),\n",
" ('Limbo', trueskill.Rating(mu=30.331, sigma=4.167)),\n",
" ('Half-life 2', trueskill.Rating(mu=29.989, sigma=3.299)),\n",
" ('Team Fortress 2', trueskill.Rating(mu=29.957, sigma=3.720)),\n",
" ('Furi', trueskill.Rating(mu=28.261, sigma=3.281)),\n",
" ('HL2: Episode Two', trueskill.Rating(mu=25.507, sigma=2.935)),\n",
" ('Civilization VI', trueskill.Rating(mu=24.818, sigma=3.152)),\n",
" ('Overwatch', trueskill.Rating(mu=23.002, sigma=3.703)),\n",
" ('HL2: Episode One', trueskill.Rating(mu=19.766, sigma=3.827)),\n",
" ('Dead Cells', trueskill.Rating(mu=19.679, sigma=3.116)),\n",
" ('Civilization V', trueskill.Rating(mu=16.525, sigma=3.472)),\n",
" ('Runner2', trueskill.Rating(mu=13.179, sigma=3.607)),\n",
" ('GTA V', trueskill.Rating(mu=10.175, sigma=4.477))]"
]
},
"execution_count": 66,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ordered_ratings = list(ratings.items())\n",
"ordered_ratings.sort(key=lambda item: item[1].mu, reverse=True)\n",
"ordered_ratings"
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def win_probability(team1, team2, ts_env=None):\n",
" # adapted from https://github.com/sublee/trueskill/issues/1#issuecomment-149762508\n",
" if ts_env is None:\n",
" ts_env = ts.global_env()\n",
" delta_mu = sum(r.mu for r in team1) - sum(r.mu for r in team2)\n",
" sum_sigma = sum(r.sigma ** 2 for r in itertools.chain(team1, team2))\n",
" size = len(team1) + len(team2)\n",
" denom = math.sqrt(size * (tse.beta * tse.beta) + sum_sigma)\n",
" return ts_env.cdf(delta_mu / denom)"
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.9956040458083428"
]
},
"execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"win_probability([ratings['Portal 2']], [ratings['Civilization V']], ts_env=tse)"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.6841821391626337"
]
},
"execution_count": 76,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"win_probability([ratings['Portal 2']], [ratings['Portal']], ts_env=tse)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6",
"language": "python",
"name": "py36"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment