Skip to content

ding.league.metric

ding.league.metric

EloCalculator

Bases: object

Overview

A class that calculates Elo ratings for players based on game results.

Attributes:

Name Type Description
- score

obj:dict): A dictionary that maps game results to scores.

Interfaces

__init__, get_new_rating, get_new_rating_array.

get_new_rating(rating_a, rating_b, result, k_factor=32, beta=200) classmethod

Overview

Calculates the new ratings for two players based on their current ratings and game result.

Parameters:

Name Type Description Default
- rating_a (

obj:int): The current rating of player A.

required
- rating_b (

obj:int): The current rating of player B.

required
- result (

obj:int): The result of the game: 1 for player A win, 0 for draw, -1 for player B win.

required
- k_factor (

obj:int): The K-factor used in the Elo rating system. Defaults to 32.

required
- beta (

obj:int): The beta value used in the Elo rating system. Defaults to 200.

required

Returns:

Type Description
Tuple[int, int]

-ret (:obj:Tuple[int, int]): The new ratings for player A and player B, respectively.

get_new_rating_array(rating, result, game_count, k_factor=32, beta=200) classmethod

Overview

Calculates the new ratings for multiple players based on their current ratings, game results, and game counts.

Parameters:

Name Type Description Default
- rating (obj

np.ndarray): An array of current ratings for each player.

required
- result (obj

np.ndarray): An array of game results, where 1 represents a win, 0 represents a draw, and -1 represents a loss.

required
- game_count (obj

np.ndarray): An array of game counts for each player.

required
- k_factor (obj

int): The K-factor used in the Elo rating system. Defaults to 32.

required
- beta (obj

int): The beta value used in the Elo rating system. Defaults to 200.

required

Returns:

Type Description
ndarray

-ret(obj:np.ndarray): An array of new ratings for each player.

Shapes
  • rating (obj:np.ndarray): :math:(N, ), N is the number of player
  • result (obj:np.ndarray): :math:(N, N)
  • game_count (obj:np.ndarray): :math:(N, N)

PlayerRating

Bases: Rating

Overview

Represents the rating of a player.

Interfaces

__init__, __repr__.

LeagueMetricEnv

Bases: TrueSkill

Overview

A class that represents a TrueSkill rating system for game players. Inherits from the TrueSkill class. For more details, please refer to https://trueskill.org/.

Interfaces

__init__, create_rating, rate_1vs1, rate_1vsC.

create_rating(mu=None, sigma=None, elo_init=None)

Overview

Creates a new player rating object with the specified mean, standard deviation, and Elo rating.

Parameters:

Name Type Description Default
- mu (

obj:float): The mean value of the player's skill rating. If not provided, the default TrueSkill mean is used.

required
- sigma (

obj:float): The standard deviation of the player's skill rating. If not provided, the default TrueSkill sigma is used.

required
- elo_init (

obj:int`): The initial Elo rating value for the player. If not provided, the default elo_init value of the LeagueMetricEnv class is used.

required

Returns:

Type Description
PlayerRating
  • PlayerRating: A player rating object with the specified mean, standard deviation, and Elo rating.

rate_1vs1(team1, team2, result=None, **kwargs)

Overview

Rates two teams of players against each other in a 1 vs 1 match and returns the updated ratings for both teams.

Parameters:

Name Type Description Default
- team1 (

obj:PlayerRating): The rating object representing the first team of players.

required
- team2 (

obj:PlayerRating): The rating object representing the second team of players.

required
- result (

obj:List[str]): The result of the match. Can be 'wins', 'draws', or 'losses'. If not provided, the default behavior is to rate the match as a win for team1.

required

Returns:

Type Description
Tuple[PlayerRating, PlayerRating]
  • ret (:obj:Tuple[PlayerRating, PlayerRating]): A tuple containing the updated ratings for team1 and team2.

rate_1vsC(team1, team2, result)

Overview

Rates a team of players against a single player in a 1 vs C match and returns the updated rating for the team.

Parameters:

Name Type Description Default
- team1 (

obj:PlayerRating): The rating object representing the team of players.

required
- team2 (

obj:PlayerRating): The rating object representing the single player.

required
- result (

obj:List[str]): The result of the match. Can be 'wins', 'draws', or 'losses'.

required

Returns:

Type Description
PlayerRating
  • PlayerRating: The updated rating for the team of players.

Full Source Code

../ding/league/metric.py

1from typing import Tuple, Union, List 2import math 3import numpy as np 4from trueskill import TrueSkill, Rating, rate_1vs1 5 6 7class EloCalculator(object): 8 """ 9 Overview: 10 A class that calculates Elo ratings for players based on game results. 11 12 Attributes: 13 - score (:obj:`dict`): A dictionary that maps game results to scores. 14 15 Interfaces: 16 ``__init__``, ``get_new_rating``, ``get_new_rating_array``. 17 """ 18 19 score = { 20 1: 1.0, # win 21 0: 0.5, # draw 22 -1: 0.0, # lose 23 } 24 25 @classmethod 26 def get_new_rating(cls, 27 rating_a: int, 28 rating_b: int, 29 result: int, 30 k_factor: int = 32, 31 beta: int = 200) -> Tuple[int, int]: 32 """ 33 Overview: 34 Calculates the new ratings for two players based on their current ratings and game result. 35 36 Arguments: 37 - rating_a (:obj:`int`): The current rating of player A. 38 - rating_b (:obj:`int`): The current rating of player B. 39 - result (:obj:`int`): The result of the game: 1 for player A win, 0 for draw, -1 for player B win. 40 - k_factor (:obj:`int`): The K-factor used in the Elo rating system. Defaults to 32. 41 - beta (:obj:`int`): The beta value used in the Elo rating system. Defaults to 200. 42 43 Returns: 44 -ret (:obj:`Tuple[int, int]`): The new ratings for player A and player B, respectively. 45 """ 46 assert result in [1, 0, -1] 47 expect_a = 1. / (1. + math.pow(10, (rating_b - rating_a) / (2. * beta))) 48 expect_b = 1. / (1. + math.pow(10, (rating_a - rating_b) / (2. * beta))) 49 new_rating_a = rating_a + k_factor * (EloCalculator.score[result] - expect_a) 50 new_rating_b = rating_b + k_factor * (1 - EloCalculator.score[result] - expect_b) 51 return round(new_rating_a), round(new_rating_b) 52 53 @classmethod 54 def get_new_rating_array( 55 cls, 56 rating: np.ndarray, 57 result: np.ndarray, 58 game_count: np.ndarray, 59 k_factor: int = 32, 60 beta: int = 200 61 ) -> np.ndarray: 62 """ 63 Overview: 64 Calculates the new ratings for multiple players based on their current ratings, game results, \ 65 and game counts. 66 67 Arguments: 68 - rating (obj:`np.ndarray`): An array of current ratings for each player. 69 - result (obj:`np.ndarray`): An array of game results, where 1 represents a win, 0 represents a draw, \ 70 and -1 represents a loss. 71 - game_count (obj:`np.ndarray`): An array of game counts for each player. 72 - k_factor (obj:`int`): The K-factor used in the Elo rating system. Defaults to 32. 73 - beta (obj:`int`): The beta value used in the Elo rating system. Defaults to 200. 74 75 Returns: 76 -ret(obj:`np.ndarray`): An array of new ratings for each player. 77 78 Shapes: 79 - rating (obj:`np.ndarray`): :math:`(N, )`, N is the number of player 80 - result (obj:`np.ndarray`): :math:`(N, N)` 81 - game_count (obj:`np.ndarray`): :math:`(N, N)` 82 """ 83 rating_diff = np.expand_dims(rating, 0) - np.expand_dims(rating, 1) 84 expect = 1. / (1. + np.power(10, rating_diff / (2. * beta))) * game_count 85 delta = ((result + 1.) / 2 - expect) * (game_count > 0) 86 delta = delta.sum(axis=1) 87 return np.round(rating + k_factor * delta).astype(np.int64) 88 89 90class PlayerRating(Rating): 91 """ 92 Overview: 93 Represents the rating of a player. 94 95 Interfaces: 96 ``__init__``, ``__repr__``. 97 """ 98 99 def __init__(self, mu: float = None, sigma: float = None, elo_init: int = None) -> None: 100 super(PlayerRating, self).__init__(mu, sigma) 101 self.elo = elo_init 102 103 def __repr__(self) -> str: 104 c = type(self) 105 args = ('.'.join([c.__module__, c.__name__]), self.mu, self.sigma, self.exposure, self.elo) 106 return '%s(mu=%.3f, sigma=%.3f, exposure=%.3f, elo=%d)' % args 107 108 109class LeagueMetricEnv(TrueSkill): 110 """ 111 Overview: 112 A class that represents a TrueSkill rating system for game players. Inherits from the TrueSkill class. \ 113 For more details, please refer to https://trueskill.org/. 114 115 Interfaces: 116 ``__init__``, ``create_rating``, ``rate_1vs1``, ``rate_1vsC``. 117 """ 118 119 def __init__(self, *args, elo_init: int = 1200, **kwargs) -> None: 120 super(LeagueMetricEnv, self).__init__(*args, **kwargs) 121 self.elo_init = elo_init 122 123 def create_rating(self, mu: float = None, sigma: float = None, elo_init: int = None) -> PlayerRating: 124 """ 125 Overview: 126 Creates a new player rating object with the specified mean, standard deviation, and Elo rating. 127 128 Arguments: 129 - mu (:obj:`float`): The mean value of the player's skill rating. If not provided, the default \ 130 TrueSkill mean is used. 131 - sigma (:obj:`float`): The standard deviation of the player's skill rating. If not provided, \ 132 the default TrueSkill sigma is used. 133 - elo_init (:obj:int`): The initial Elo rating value for the player. If not provided, the default \ 134 elo_init value of the LeagueMetricEnv class is used. 135 136 Returns: 137 - PlayerRating: A player rating object with the specified mean, standard deviation, and Elo rating. 138 """ 139 if mu is None: 140 mu = self.mu 141 if sigma is None: 142 sigma = self.sigma 143 if elo_init is None: 144 elo_init = self.elo_init 145 return PlayerRating(mu, sigma, elo_init) 146 147 @staticmethod 148 def _rate_1vs1(t1, t2, **kwargs): 149 t1_elo, t2_elo = t1.elo, t2.elo 150 t1, t2 = rate_1vs1(t1, t2, **kwargs) 151 if 'drawn' in kwargs: 152 result = 0 153 else: 154 result = 1 155 t1_elo, t2_elo = EloCalculator.get_new_rating(t1_elo, t2_elo, result) 156 t1 = PlayerRating(t1.mu, t1.sigma, t1_elo) 157 t2 = PlayerRating(t2.mu, t2.sigma, t2_elo) 158 return t1, t2 159 160 def rate_1vs1(self, team1: PlayerRating, team2: PlayerRating, result: List[str] = None, **kwargs) \ 161 -> Tuple[PlayerRating, PlayerRating]: 162 """ 163 Overview: 164 Rates two teams of players against each other in a 1 vs 1 match and returns the updated ratings \ 165 for both teams. 166 167 Arguments: 168 - team1 (:obj:`PlayerRating`): The rating object representing the first team of players. 169 - team2 (:obj:`PlayerRating`): The rating object representing the second team of players. 170 - result (:obj:`List[str]`): The result of the match. Can be 'wins', 'draws', or 'losses'. If \ 171 not provided, the default behavior is to rate the match as a win for team1. 172 173 Returns: 174 - ret (:obj:`Tuple[PlayerRating, PlayerRating]`): A tuple containing the updated ratings for team1 \ 175 and team2. 176 """ 177 if result is None: 178 return self._rate_1vs1(team1, team2, **kwargs) 179 else: 180 for r in result: 181 if r == 'wins': 182 team1, team2 = self._rate_1vs1(team1, team2) 183 elif r == 'draws': 184 team1, team2 = self._rate_1vs1(team1, team2, drawn=True) 185 elif r == 'losses': 186 team2, team1 = self._rate_1vs1(team2, team1) 187 else: 188 raise RuntimeError("invalid result: {}".format(r)) 189 return team1, team2 190 191 def rate_1vsC(self, team1: PlayerRating, team2: PlayerRating, result: List[str]) -> PlayerRating: 192 """ 193 Overview: 194 Rates a team of players against a single player in a 1 vs C match and returns the updated rating \ 195 for the team. 196 197 Arguments: 198 - team1 (:obj:`PlayerRating`): The rating object representing the team of players. 199 - team2 (:obj:`PlayerRating`): The rating object representing the single player. 200 - result (:obj:`List[str]`): The result of the match. Can be 'wins', 'draws', or 'losses'. 201 202 Returns: 203 - PlayerRating: The updated rating for the team of players. 204 """ 205 for r in result: 206 if r == 'wins': 207 team1, _ = self._rate_1vs1(team1, team2) 208 elif r == 'draws': 209 team1, _ = self._rate_1vs1(team1, team2, drawn=True) 210 elif r == 'losses': 211 _, team1 = self._rate_1vs1(team2, team1) 212 else: 213 raise RuntimeError("invalid result: {}".format(r)) 214 return team1 215 216 217get_elo = EloCalculator.get_new_rating 218get_elo_array = EloCalculator.get_new_rating_array