Module server.rating_service.game_rater

Classes

class AdjustmentGameRater (rater: GameRater,
base_ratings: dict[int, Rating])
Expand source code
@with_logger
class AdjustmentGameRater(GameRater):
    """GameRater for performing adjustments using another GameRater"""

    def __init__(self, rater: GameRater, base_ratings: RatingDict):
        self.rater = rater
        self.base_ratings = base_ratings

    def compute_rating(
        self,
        ratings: RatingDict
    ) -> RatingDict:
        """
        Adjust one rating to bring it closer to a different base rating. For
        each player, this will rate the game with trueskill as if they
        played this game with the rating we are adjusting instead of the
        base rating. Adjustments are only returned under certain conditions to
        prevent rating manipulation.
        """
        new_adjusted_ratings = {}
        for player_id, base_rating in self.base_ratings.items():
            old_adjusted_rating = ratings[player_id]
            # Since we only adjust upwards, we should not adjust ratings that
            # are already higher than the base.
            if base_rating.displayed() < old_adjusted_rating.displayed():
                continue
            # Make a copy of the base ratings, but substitute this player's
            # rating with the rating we are adjusting.
            old_ratings = dict(self.base_ratings)
            old_ratings[player_id] = old_adjusted_rating

            new_ratings = self.rater.compute_rating(old_ratings)
            new_adjusted_rating = new_ratings[player_id]
            self._logger.debug(
                "Got new adjusted rating for player %d: %s",
                player_id,
                new_adjusted_rating
            )
            if (
                old_adjusted_rating.displayed() <
                new_adjusted_rating.displayed() <=
                config.RATING_ADJUSTMENT_MAX_RATING
            ):
                new_adjusted_ratings[player_id] = new_adjusted_rating

        return new_adjusted_ratings

    def get_outcome_map(self) -> dict[PlayerID, GameOutcome]:
        return self.rater.outcome_map

GameRater for performing adjustments using another GameRater

Ancestors

Methods

def compute_rating(self,
ratings: dict[int, Rating]) ‑> dict[int, Rating]
Expand source code
def compute_rating(
    self,
    ratings: RatingDict
) -> RatingDict:
    """
    Adjust one rating to bring it closer to a different base rating. For
    each player, this will rate the game with trueskill as if they
    played this game with the rating we are adjusting instead of the
    base rating. Adjustments are only returned under certain conditions to
    prevent rating manipulation.
    """
    new_adjusted_ratings = {}
    for player_id, base_rating in self.base_ratings.items():
        old_adjusted_rating = ratings[player_id]
        # Since we only adjust upwards, we should not adjust ratings that
        # are already higher than the base.
        if base_rating.displayed() < old_adjusted_rating.displayed():
            continue
        # Make a copy of the base ratings, but substitute this player's
        # rating with the rating we are adjusting.
        old_ratings = dict(self.base_ratings)
        old_ratings[player_id] = old_adjusted_rating

        new_ratings = self.rater.compute_rating(old_ratings)
        new_adjusted_rating = new_ratings[player_id]
        self._logger.debug(
            "Got new adjusted rating for player %d: %s",
            player_id,
            new_adjusted_rating
        )
        if (
            old_adjusted_rating.displayed() <
            new_adjusted_rating.displayed() <=
            config.RATING_ADJUSTMENT_MAX_RATING
        ):
            new_adjusted_ratings[player_id] = new_adjusted_rating

    return new_adjusted_ratings

Adjust one rating to bring it closer to a different base rating. For each player, this will rate the game with trueskill as if they played this game with the rating we are adjusting instead of the base rating. Adjustments are only returned under certain conditions to prevent rating manipulation.

def get_outcome_map(self) ‑> dict[int, GameOutcome]
Expand source code
def get_outcome_map(self) -> dict[PlayerID, GameOutcome]:
    return self.rater.outcome_map
class GameRater (summary: GameRatingSummary)
Expand source code
@with_logger
class GameRater:
    def __init__(self, summary: GameRatingSummary):
        self.summary = summary
        self.outcome_map = {
            player_id: team.outcome
            for team in summary.teams
            for player_id in team.player_ids
        }
        self.player_ids = list(self.outcome_map.keys())
        self.team_outcomes = [team.outcome for team in summary.teams]
        self.ranks = _ranks_from_team_outcomes(self.team_outcomes)

    def compute_rating(
        self,
        ratings: RatingDict
    ) -> RatingDict:
        rating_groups = [
            {
                player_id: trueskill.Rating(*ratings[player_id])
                for player_id in team.player_ids
            }
            for team in self.summary.teams
        ]

        self._logger.debug("Rating groups: %s", rating_groups)
        self._logger.debug("Ranks: %s", self.ranks)

        new_rating_groups = trueskill.rate(rating_groups, self.ranks)

        player_rating_map = {
            player_id: Rating(*new_rating)
            for team in new_rating_groups
            for player_id, new_rating in team.items()
        }

        return player_rating_map

    def get_outcome_map(self) -> dict[PlayerID, GameOutcome]:
        return self.outcome_map

Subclasses

Methods

def compute_rating(self,
ratings: dict[int, Rating]) ‑> dict[int, Rating]
Expand source code
def compute_rating(
    self,
    ratings: RatingDict
) -> RatingDict:
    rating_groups = [
        {
            player_id: trueskill.Rating(*ratings[player_id])
            for player_id in team.player_ids
        }
        for team in self.summary.teams
    ]

    self._logger.debug("Rating groups: %s", rating_groups)
    self._logger.debug("Ranks: %s", self.ranks)

    new_rating_groups = trueskill.rate(rating_groups, self.ranks)

    player_rating_map = {
        player_id: Rating(*new_rating)
        for team in new_rating_groups
        for player_id, new_rating in team.items()
    }

    return player_rating_map
def get_outcome_map(self) ‑> dict[int, GameOutcome]
Expand source code
def get_outcome_map(self) -> dict[PlayerID, GameOutcome]:
    return self.outcome_map
class GameRatingError (*args, **kwargs)
Expand source code
class GameRatingError(Exception):
    pass

Common base class for all non-exit exceptions.

Ancestors

  • builtins.Exception
  • builtins.BaseException