]> git.xonotic.org Git - xonotic/xonstat.git/blobdiff - xonstat/models/player.py
Change to explicit floats, add string representations of objects.
[xonotic/xonstat.git] / xonstat / models / player.py
index 2564dd3317acd666735a562607d10ff3a34c0905..89c8cdb7dc1c63bf04ed91c4d5c24bef50c63976 100644 (file)
@@ -7,8 +7,22 @@ from calendar import timegm
 from xonstat.models.mixins import FuzzyDateMixin, EpochMixin, NickColorsMixin
 from xonstat.util import strip_colors, pretty_date, qfont_decode
 
+# Glicko Constants
 
-class Player(EpochMixin, NickColorsMixin):
+# the default initial rating value
+MU = 1500.0
+
+# the default ratings deviation value
+PHI = 350.0
+
+# the default volatility value
+SIGMA = 0.06
+
+# the ratio to convert from/to glicko2
+GLICKO2_SCALE = 173.7178
+
+
+class Player(EpochMixin, NickColorsMixin, FuzzyDateMixin):
     """
     A player, which can represent either a human or a bot.
     """
@@ -19,10 +33,6 @@ class Player(EpochMixin, NickColorsMixin):
         else:
             return strip_colors(self.nick)
 
-    # TODO: use FuzzyDateMixin instead, but change the method calls
-    def joined_pretty_date(self):
-        return pretty_date(self.create_dt)
-
     def __repr__(self):
         return "<Player({}, {})>".format(self.player_id, self.nick.encode('utf-8'))
 
@@ -210,4 +220,51 @@ class PlayerMedal(object):
     """
 
     def __repr__(self):
-        return "<PlayerRank(pid={0.player_id}, place={0.place}, alt={0.alt})>".format(self)
+        return "<PlayerMedal(pid={0.player_id}, place={0.place}, alt={0.alt})>".format(self)
+
+
+class PlayerGlicko(object):
+    """
+    A player's skill for a particular game type, as determined by the Glicko2 algorithm.
+    """
+    def __init__(self, player_id, game_type_cd, category="general", mu=MU, phi=PHI, sigma=SIGMA):
+        self.player_id = player_id
+        self.game_type_cd = game_type_cd
+        self.category = category
+        self.mu = float(mu)
+        self.phi = phi
+        self.sigma = sigma
+
+    def to_glicko2(self):
+        """ Convert a rating to the Glicko2 scale. """
+        return PlayerGlicko(
+            player_id=self.player_id,
+            game_type_cd=self.game_type_cd,
+            category=self.category,
+            mu=(float(self.mu) - MU)/GLICKO2_SCALE,
+            phi=self.phi/GLICKO2_SCALE,
+            sigma=self.sigma
+        )
+
+    def from_glicko2(self):
+        """ Convert a rating to the original Glicko scale. """
+        return PlayerGlicko(
+            player_id=self.player_id,
+            game_type_cd=self.game_type_cd,
+            category=self.category,
+            mu=self.mu * GLICKO2_SCALE + MU,
+            phi=self.phi * GLICKO2_SCALE,
+            sigma=self.sigma
+        )
+
+    def __repr__(self):
+        return ("<PlayerGlicko({0.player_id}, {0.game_type_cd}, {0.category}, "
+                "{0.mu}, {0.phi}, {0.sigma})>".format(self))
+
+
+class PlayerGlickoBase(PlayerGlicko):
+    """
+    A clone of the above PlayerGlicko class, but created separately in order to avoid
+    dealing with primary and non-primary SQLAlchemy mappers.
+    """
+    pass
\ No newline at end of file