Skip to content

Commit

Permalink
Merge pull request #32 from syargeau/develop
Browse files Browse the repository at this point in the history
Update master with v0.5.1
  • Loading branch information
syargeau authored Jul 3, 2018
2 parents 1ebf765 + 8f692fe commit 89ffd39
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 8 deletions.
7 changes: 7 additions & 0 deletions functional_tests/test_all_matches.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,10 @@ def test_all_matches(self):
self.browser.find_element_by_id('previous-page-link').click()
current_page = self.browser.find_element_by_id('current-page')
self.assertEqual(current_page.text, 'Page 2 of 3')

# Lastly he see a link to go back to the home page, and clicks this
home_page_link = self.browser.find_element_by_id('home-page-link')
self.assertEqual(home_page_link.text, 'Back to leaderboard')
home_page_link.click()
home_url = self.live_server_url + '/'
self.assertEqual(home_url, self.browser.current_url)
26 changes: 19 additions & 7 deletions leaderboard/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,31 +57,43 @@ def date(self):

@property
def description(self):
"""Description of who defeated who and what the score was."""
description = (
f'{self.date}: {self.winner} defeated {self.loser} {self.score}'
)
return description

def save(self, *args, **kwargs):
super().save(*args, **kwargs)
PlayerRating.generate_ratings()
if self.id: # occurs when the match already exists and is being updated
super().save(*args, **kwargs)
PlayerRating.generate_ratings()
else: # occurs when it's a new match being added
super().save(*args, **kwargs)
elo_rating = EloRating(use_current_ratings=True)
elo_rating.update_ratings(self.winner, self.loser)
PlayerRating.add_ratings(elo_rating)


class PlayerRating(models.Model):
"""Table for keeping track of a player's rating."""
player = models.OneToOneField(Player, default=None, primary_key=True)
rating = models.IntegerField(default=None, blank=False)

@staticmethod
def add_ratings(elo_rating: EloRating):
"""Add ratings to database given EloRating object."""
PlayerRating.objects.all().delete()
for player, rating in elo_rating.ratings.items():
PlayerRating.objects.create(player=player, rating=rating)

@staticmethod
def generate_ratings():
"""Generate ratings from all previous matches."""
PlayerRating.objects.all().delete()
matches = Match.objects.all().order_by('datetime')
"""Generate ratings from scratch based on all previous matches."""
elo_rating = EloRating()
matches = Match.objects.all().order_by('datetime')
for match in matches:
elo_rating.update_ratings(match.winner, match.loser)
for player, rating in elo_rating.ratings.items():
PlayerRating.objects.create(player=player, rating=rating)
PlayerRating.add_ratings(elo_rating)

@property
def games_played(self):
Expand Down
8 changes: 7 additions & 1 deletion leaderboard/rankings.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import leaderboard.models

DEFAULT_ELO_RATING = 1000
DEFAULT_K_FACTOR = 30


class EloRating(object):
"""Uses Elo rating system to rate players."""

def __init__(self):
def __init__(self, use_current_ratings=False):
self.ratings = {}
if use_current_ratings:
rated_players = leaderboard.models.PlayerRating.objects.all()
for rated_player in rated_players:
self.ratings[rated_player.player] = rated_player.rating

def get_rating(self, player):
"""Return the rating of the specified player."""
Expand Down
2 changes: 2 additions & 0 deletions leaderboard/templates/all_matches.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
<body>
<h1>All Matches</h1>

<a id="home-page-link" href="{% url 'home' %}">Back to leaderboard</a>

<table id="matches">
<tr>
<th>Date</th>
Expand Down
1 change: 1 addition & 0 deletions leaderboard/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ def test_generate_ratings_in_order(self):
losing_score=19,
datetime=pytz.utc.localize(datetime(2000, 1, 1))
)
PlayerRating.generate_ratings()
ranking1 = PlayerRating.objects.get(pk=self.player1.id)
ranking2 = PlayerRating.objects.get(pk=self.player2.id)
self.assertGreater(ranking2.rating, ranking1.rating)
Expand Down
9 changes: 9 additions & 0 deletions leaderboard/tests/test_rankings.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.test import TestCase

from leaderboard.rankings import EloRating, DEFAULT_ELO_RATING, DEFAULT_K_FACTOR
from leaderboard.models import PlayerRating, Player


class EloRatingTest(TestCase):
Expand Down Expand Up @@ -69,3 +70,11 @@ def test_rating_updates(self):
expected_loser_rating = DEFAULT_ELO_RATING - DEFAULT_K_FACTOR * 0.5
self.assertEqual(winner_rating, expected_winner_rating)
self.assertEqual(loser_rating, expected_loser_rating)

def test_use_current_rating(self):
"""Test that the EloRating class can use current ratings."""
player = Player.objects.create(first_name='Bob', last_name='Hope')
test_rating = 1013
rated_player = PlayerRating.objects.create(player=player, rating=test_rating)
rating = EloRating(use_current_ratings=True)
self.assertEqual(test_rating, rating.get_rating(player))

0 comments on commit 89ffd39

Please sign in to comment.