From 1b8f84941c3ca28fc6590ccc907228b8afded8c6 Mon Sep 17 00:00:00 2001 From: emkael Date: Wed, 30 Nov 2016 14:26:35 +0100 Subject: * coding standards and formatting --- elo.py | 20 +++++++------ f1elo/db.py | 4 ++- f1elo/elo.py | 85 +++++++++++++++++++++++++++++++++++------------------- f1elo/interface.py | 34 ++++++++++++++-------- f1elo/model.py | 57 ++++++++++++++++++++++-------------- 5 files changed, 127 insertions(+), 73 deletions(-) diff --git a/elo.py b/elo.py index 743ee4e..ed0a2f8 100755 --- a/elo.py +++ b/elo.py @@ -10,12 +10,14 @@ parser = argparse.ArgumentParser( formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('command', metavar='COMMAND', nargs='?', help="Action to execute against the database:\n" - "print - prints the rankings for all drivers ranked in 12 months,\n" + "print - prints the rankings for all drivers ranked " + "in 12 months,\n" "reset - resets the rankings,\n" "rate - calculates the rankings\n" "init - init clean database for the application\n" "Default value is 'print'.", - default='print', choices=['print', 'rate', 'reset', 'init']) + default='print', + choices=['print', 'rate', 'reset', 'init']) parser.add_argument('--date', help='Date for which the action should be executed.\n' 'Print ratings for DATE,\n' @@ -23,17 +25,17 @@ parser.add_argument('--date', 'or rank the races all the way up to DATE.') parser.add_argument( '--limit', - help='Ranking list (display) cut-off point.', - type=int) + help='Ranking list (display) cut-off point.', + type=int) parser.add_argument( '-v', - help='Display verbose info on rating progress to STDERR.', - action='store_true') + help='Display verbose info on rating progress to STDERR.', + action='store_true') parser.add_argument( '--force', - '-f', - help='Force database initialization (for "init" command).', - action='store_true') + '-f', + help='Force database initialization (for "init" command).', + action='store_true') arguments = parser.parse_args() diff --git a/f1elo/db.py b/f1elo/db.py index 58e7a8a..1991e77 100644 --- a/f1elo/db.py +++ b/f1elo/db.py @@ -9,12 +9,14 @@ config = json.load( open(path.join(path.dirname(__main__.__file__), 'config', 'db.json'))) if config['engine'] == 'mysql': engine = create_engine( - "mysql://{0[user]}:{0[pass]}@{0[host]}/{0[db]}?charset=utf8".format(config)) + "mysql://{0[user]}:{0[pass]}@{0[host]}/{0[db]}?charset=utf8".format( + config)) elif config['engine'] == 'sqlite': engine = create_engine("sqlite:///{0[file]}".format(config)) def fk_pragma(conn, record): conn.execute('PRAGMA FOREIGN_KEYS=ON') + event.listen(engine, 'connect', fk_pragma) Session = sessionmaker(bind=engine) diff --git a/f1elo/elo.py b/f1elo/elo.py index d864e6b..588cc9d 100644 --- a/f1elo/elo.py +++ b/f1elo/elo.py @@ -1,18 +1,26 @@ -import json, dateutil -from sqlalchemy import func +import json from itertools import combinations from os import path import __main__ +import dateutil +from sqlalchemy import func from f1elo.model import * -class Elo: +class Elo(object): def __init__(self, session): self.session = session self.config = json.load( - open(path.join(path.dirname(__main__.__file__), 'config', 'elo.json'))) + open( + path.join( + path.dirname(__main__.__file__), + 'config', + 'elo.json' + ) + ) + ) def get_ranking(self, driver, rank_date=None): rank = driver.get_ranking(rank_date) @@ -21,12 +29,15 @@ class Elo: return self.config['initial_ranking'] def get_entry_ranking(self, entry, date=None): - return sum([self.get_ranking(d, date) for d in entry.drivers]) / len(entry.drivers) + return sum( + [self.get_ranking(d, date) for d in entry.drivers] + ) / len(entry.drivers) def get_race_disparity(self, race): race_disparity = self.config['disparity']['base_disparity'] if self.config['disparity']['adjust']: - recent_date = race.date - dateutil.relativedelta.relativedelta(months=3) + recent_date = race.date - dateutil.relativedelta.relativedelta( + months=3) recent_ratings = self.session.query( func.min(Ranking.ranking).label('min'), func.max(Ranking.ranking).label('max') @@ -37,14 +48,26 @@ class Elo: ) changes_query = self.session.query( func.avg( - recent_ratings.subquery().columns.max - recent_ratings.subquery().columns.min + recent_ratings.subquery().columns.max + - recent_ratings.subquery().columns.min ) ) recent_rank_change = changes_query.scalar() if not recent_rank_change: recent_rank_change = 0 - recent_rank_change = min(self.config['disparity']['base_rating_change'], recent_rank_change) - race_disparity *= (2.5 + (self.config['disparity']['base_rating_change']/(recent_rank_change - 2.0 * self.config['disparity']['base_rating_change']))) * 0.5 + recent_rank_change = min( + self.config['disparity']['base_rating_change'], + recent_rank_change) + race_disparity *= ( + 2.5 + + ( + self.config['disparity']['base_rating_change'] + / ( + recent_rank_change + - 2.0 * self.config['disparity']['base_rating_change'] + ) + ) + ) * 0.5 return race_disparity def rank_race(self, race): @@ -53,22 +76,22 @@ class Elo: entries_to_compare = [] rankings = {} new_rankings = {} - for e in entries: - rankings[e] = self.get_entry_ranking(e, race.date) - new_rankings[e] = 0.0 - if e.result_group: - entries_to_compare.append(e) - for c in combinations(entries_to_compare, 2): - score = self.get_score( - rankings[c[0]] - rankings[c[1]], - self.get_outcome(c), + for entry in entries: + rankings[entry] = self.get_entry_ranking(entry, race.date) + new_rankings[entry] = 0.0 + if entry.result_group: + entries_to_compare.append(entry) + for combo in combinations(entries_to_compare, 2): + score = get_score( + rankings[combo[0]] - rankings[combo[1]], + get_outcome(combo), self.get_importance(race, - [rankings[c[0]], - rankings[c[1]]]), + [rankings[combo[0]], + rankings[combo[1]]]), race_disparity ) - new_rankings[c[0]] += score - new_rankings[c[1]] -= score + new_rankings[combo[0]] += score + new_rankings[combo[1]] -= score return new_rankings def get_importance(self, race, rankings): @@ -80,12 +103,14 @@ class Elo: return base_importance * 0.75 return base_importance / 2 - def get_outcome(self, entries): - if entries[0].result_group < entries[1].result_group: - return 1 - elif entries[0].result_group > entries[1].result_group: - return 0 - return 0.5 - def get_score(self, difference, outcome, importance, disparity): - return importance * (outcome - 1 / (1 + (10 ** (-difference / disparity)))) +def get_outcome(entries): + if entries[0].result_group < entries[1].result_group: + return 1 + elif entries[0].result_group > entries[1].result_group: + return 0 + return 0.5 + + +def get_score(difference, outcome, importance, disparity): + return importance * (outcome - 1 / (1 + (10 ** (-difference / disparity)))) diff --git a/f1elo/interface.py b/f1elo/interface.py index da1b77f..3ba1cb8 100644 --- a/f1elo/interface.py +++ b/f1elo/interface.py @@ -9,10 +9,9 @@ import dateutil.relativedelta from f1elo.db import Session from f1elo.elo import Elo from f1elo.model import * -from sqlalchemy import MetaData -class Interface: +class Interface(object): def __init__(self, date=None): self.session = Session() @@ -23,7 +22,8 @@ class Interface: if force: Base.metadata.drop_all(self.session.get_bind()) Base.metadata.create_all(self.session.get_bind()) - with open(path.join(path.dirname(__main__.__file__), 'sql', 'results.sql')) as result_dump: + with open(path.join(path.dirname(__main__.__file__), + 'sql', 'results.sql')) as result_dump: for line in result_dump.readlines(): line = line.strip() if line and line[0:2] != '--': @@ -62,7 +62,7 @@ class Interface: date = datetime.date.today() elo = Elo(self.session) - race_query = self.session.query(Race).filter(Race.ranked == False) + race_query = self.session.query(Race).filter(Race.ranked.is_(False)) if date is not None: race_query = race_query.filter(Race.date <= date) races = race_query.order_by(Race.date, Race.id).all() @@ -84,7 +84,9 @@ class Interface: for driver, rank in driver_ranks.iteritems(): ranking = Ranking() ranking.rank_date = race.date - ranking.ranking = round(elo.get_ranking(driver, race.date) + rank, 2) + ranking.ranking = round( + elo.get_ranking(driver, race.date) + rank, + 2) self.session.add(ranking) driver.rankings.append(ranking) @@ -95,8 +97,10 @@ class Interface: rating_change_sum = 0 changed_ratings = 0 for entry in sorted(race.entries): - old_rating = elo.get_entry_ranking(entry, - race.date - dateutil.relativedelta.relativedelta(days=1)) + old_rating = elo.get_entry_ranking( + entry, + race.date + - dateutil.relativedelta.relativedelta(days=1)) new_rating = elo.get_entry_ranking(entry) rating_sum += old_rating if entry.result_group != 0: @@ -107,13 +111,17 @@ class Interface: old_rating, new_rating, file=sys.stderr) - if entry.result in ['1','2','3']: + if entry.result in ['1', '2', '3']: podium_rating += old_rating podium_rating_after += new_rating print('', file=sys.stderr) - print('Podium rating: ', podium_rating, podium_rating_after, file=sys.stderr) - print('Average rating: ', rating_sum / len(race.entries), file=sys.stderr) - print('Average rating change: ', rating_change_sum / changed_ratings, file=sys.stderr) + print('Podium rating: ', podium_rating, podium_rating_after, + file=sys.stderr) + print('Average rating: ', rating_sum / len(race.entries), + file=sys.stderr) + print('Average rating change: ', + rating_change_sum / changed_ratings, + file=sys.stderr) print('', file=sys.stderr) race.ranked = True @@ -151,4 +159,6 @@ class Interface: self.date = date - return sorted(drivers.values(), key=lambda rank: rank.ranking, reverse=True) + return sorted(drivers.values(), + key=lambda rank: rank.ranking, + reverse=True) diff --git a/f1elo/model.py b/f1elo/model.py index c450353..b42cc08 100644 --- a/f1elo/model.py +++ b/f1elo/model.py @@ -1,13 +1,14 @@ +import sys +from functools import total_ordering + from sqlalchemy import Column, ForeignKey, Table from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import backref, relationship, sessionmaker +from sqlalchemy.orm import relationship from sqlalchemy.types import Boolean, Date, Float, Integer, String -from functools import total_ordering -import sys - Base = declarative_base() + class Country(Base): __tablename__ = 'countries' @@ -29,6 +30,7 @@ class Country(Base): session.add(country) return country + class Driver(Base): __tablename__ = 'drivers' @@ -74,21 +76,22 @@ class Driver(Base): session.add(driver) return driver + driver_entry = Table('driver_entries', Base.metadata, Column( - '_driver', - Integer, - ForeignKey( - 'drivers.id', - onupdate="CASCADE", - ondelete="CASCADE")), + '_driver', + Integer, + ForeignKey( + 'drivers.id', + onupdate="CASCADE", + ondelete="CASCADE")), Column( - '_entry', - Integer, - ForeignKey( - 'entries.id', - onupdate="CASCADE", - ondelete="CASCADE")), + '_entry', + Integer, + ForeignKey( + 'entries.id', + onupdate="CASCADE", + ondelete="CASCADE")), Column('id', Integer, primary_key=True)) @@ -119,7 +122,12 @@ class Entry(Base): passive_deletes=True) def __repr__(self): - return ('#%s (%s) %s[%d]' % (self.car_no, ', '.join([driver.__repr__().decode('utf8') for driver in self.drivers]), self.result, self.result_group)).encode('utf8') + return ('#%s (%s) %s[%d]' % ( + self.car_no, + ', '.join([driver.__repr__().decode('utf8') + for driver in self.drivers]), + self.result, + self.result_group)).encode('utf8') def __eq__(self, other): return self.id == other.id @@ -141,13 +149,17 @@ class Entry(Base): else: return self_result < other_result + class Race(Base): __tablename__ = 'races' id = Column(Integer, primary_key=True) race = Column(String(1024)) date = Column(Date, index=True) - ranked = Column(Boolean, nullable=False, server_default='0', default=False, index=True) + ranked = Column(Boolean, + nullable=False, + server_default='0', default=False, + index=True) _type = Column( Integer, @@ -204,9 +216,12 @@ class Ranking(Base): driver = relationship( 'Driver', back_populates='rankings', - order_by=rank_date) + order_by=rank_date) def __repr__(self): - return ("%s: %0.2f (%s)" % (self.driver.__repr__().decode('utf8'), self.ranking, self. rank_date)).encode('utf8') + return ("%s: %0.2f (%s)" % ( + self.driver.__repr__().decode('utf8'), + self.ranking, self. rank_date)).encode('utf8') + -__all__ = ['Country', 'Driver', 'Entry', 'Ranking', 'Race', 'RaceType'] +__all__ = ('Country', 'Driver', 'Entry', 'Ranking', 'Race', 'RaceType') -- cgit v1.2.3