|
# -*- coding: utf-8 -*- |
|
""" |
|
<`Comedy Big League`_ Season 4> TrueSkill rating calculator |
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
|
|
This small code collects match results and calculate `TrueSkill`_ ratings |
|
of the teams. The match results are provided from `Enhawiki mobile |
|
mirror`_. |
|
|
|
It depends on :mod:`trueskill`, :mod:`ranking`, :mod:`lxml` and |
|
:mod:`requests`. |
|
|
|
.. _Comedy Big League: http://cobig.interest.me/ |
|
.. _TrueSkill: http://pythonhosted.org/trueskill |
|
.. _Enhawiki mobile mirror: http://m.enha.kr/wiki/ |
|
|
|
:copyright: (c) 2013 by Heungsub Lee |
|
:license: Public domain. |
|
""" |
|
from __future__ import unicode_literals |
|
from collections import defaultdict |
|
|
|
from lxml import etree |
|
from ranking import Ranking |
|
import requests |
|
|
|
from trueskill import Rating, rate_1vs1 |
|
from trueskill.mathematics import Gaussian |
|
|
|
|
|
res = requests.get('http://m.enha.kr/wiki/' |
|
'코미디%20빅%20리그%202012-2013/세부결과') |
|
html = etree.fromstring(res.text, etree.HTMLParser(encoding='utf-8')) |
|
|
|
|
|
# collect match results |
|
ratings = defaultdict(Rating) |
|
prev_ranking = {} |
|
for round_, table in enumerate(html.xpath('//table'), start=1): |
|
trs = table.xpath('.//tr') |
|
if len(trs) != 12: |
|
continue |
|
match_results = [] |
|
for tr in [tr for x, tr in enumerate(trs) if x % 2 == 1]: |
|
tds = tr.xpath('.//td') |
|
try: |
|
left_wins = '#87cefa' in tds[0].get('style') |
|
except TypeError: |
|
continue |
|
winner = tds[2 if left_wins else 3].text.strip() |
|
loser = tds[3 if left_wins else 2].text.strip() |
|
# fix a writing error |
|
if loser == '129': |
|
loser = '코벤져스' |
|
match_results.append((winner, loser)) |
|
if not match_results: |
|
continue |
|
# rate collected matches |
|
for winner, loser in match_results: |
|
rated = rate_1vs1(ratings[winner], ratings[loser]) |
|
ratings[winner], ratings[loser] = rated |
|
# print ratings |
|
print |
|
print '== Until round %d ==' % round_ |
|
print |
|
key = lambda x: x[1].exposure |
|
ranking = sorted(ratings.iteritems(), key=key, reverse=True) |
|
for rank, (team, rating) in Ranking(ranking, key=key, start=1): |
|
try: |
|
prev_rank = prev_ranking[team] |
|
except KeyError: |
|
delta = 0 |
|
else: |
|
delta = prev_rank - rank |
|
delta = ' {:+2}'.format(delta) if delta else ' ' |
|
print '{0:2}{1}'.format(rank, delta), |
|
print '{0.mu:.3f} {0.sigma:.3f}'.format(rating), team |
|
prev_ranking[team] = rank |