-
Notifications
You must be signed in to change notification settings - Fork 2
/
elopy.py
155 lines (131 loc) · 4.48 KB
/
elopy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
"""
Created 5-18-17
All of the classes for EloPy. The users should only interact with the Implementation class.
@author - Hank Hang Kai Sheehan
"""
class Implementation:
"""
A class that represents an implementation of the Elo Rating System
"""
def __init__(self, base_rating=1000):
"""
Runs at initialization of class object.
@param base_rating - The rating a new player would have
"""
self.base_rating = base_rating
self.players = []
def __getPlayerList(self):
"""
Returns this implementation's player list.
@return - the list of all player objects in the implementation.
"""
return self.players
def getPlayer(self, name):
"""
Returns the player in the implementation with the given name.
@param name - name of the player to return.
@return - the player with the given name.
"""
for player in self.players:
if player.name == name:
return player
return None
def contains(self, name):
"""
Returns true if this object contains a player with the given name.
Otherwise returns false.
@param name - name to check for.
"""
for player in self.players:
if player.name == name:
return True
return False
def addPlayer(self, name, rating=None):
"""
Adds a new player to the implementation.
@param name - The name to identify a specific player.
@param rating - The player's rating.
"""
if rating == None:
rating = self.base_rating
#Check if duplicate with exact same name
for p in self.players:
if name == p.name:
return
self.players.append(_Player(name=name,rating=rating))
def removePlayer(self, name):
"""
Adds a new player to the implementation.
@param name - The name to identify a specific player.
"""
self.__getPlayerList().remove(self.getPlayer(name))
def recordMatch(self, name1, name2, winner=None, draw=False):
"""
Should be called after a game is played.
@param name1 - name of the first player.
@param name2 - name of the second player.
"""
player1 = self.getPlayer(name1)
player2 = self.getPlayer(name2)
expected1 = player1.compareRating(player2)
expected2 = player2.compareRating(player1)
k = len(self.__getPlayerList()) * 42
rating1 = player1.rating
rating2 = player2.rating
if draw:
score1 = 0.5
score2 = 0.5
elif winner == name1:
score1 = 1.0
score2 = 0.0
elif winner == name2:
score1 = 0.0
score2 = 1.0
else:
raise InputError('One of the names must be the winner or draw must be True')
newRating1 = rating1 + k * (score1 - expected1)
newRating2 = rating2 + k * (score2 - expected2)
if newRating1 < 0:
newRating1 = 0
newRating2 = rating2 - rating1
elif newRating2 < 0:
newRating2 = 0
newRating1 = rating1 - rating2
player1.rating = newRating1
player2.rating = newRating2
def getPlayerRating(self, name):
"""
Returns the rating of the player with the given name.
@param name - name of the player.
@return - the rating of the player with the given name.
"""
player = self.getPlayer(name)
return player.rating
def getRatingList(self):
"""
Returns a list of tuples in the form of ({name},{rating})
@return - the list of tuples
"""
lst = []
for player in self.__getPlayerList():
lst.append((player.name,player.rating))
return lst
class _Player:
"""
A class to represent a player in the Elo Rating System
"""
def __init__(self, name, rating):
"""
Runs at initialization of class object.
@param name - TODO
@param rating - TODO
"""
self.name = name
self.rating = rating
def compareRating(self, opponent):
"""
Compares the two ratings of the this player and the opponent.
@param opponent - the player to compare against.
@returns - The expected score between the two players.
"""
return ( 1+10**( ( opponent.rating-self.rating )/400.0 ) ) ** -1