Exemple #1
0
async def test_compute_rating_raises_game_error(game: Game, players):
    game.state = GameState.LOBBY
    add_connected_players(game, [players.hosting, players.joining])
    # add_connected_players sets this, so we need to unset it again
    del game._player_options[players.hosting.id]["Team"]
    game.set_player_option(players.joining.id, "Team", 1)
    await game.launch()

    with pytest.raises(GameError):
        game.compute_rating(rating=RatingType.LADDER_1V1)
Exemple #2
0
async def test_compute_rating_balanced_teamgame(game: Game, create_player):
    await game.clear_data()

    game.state = GameState.LOBBY
    players = [(
        create_player(**info), result, team
    ) for info, result, team in [
        (dict(login='******', id=1, global_rating=Rating(1500, 250.7)), 0,
         1),
        (dict(login='******', id=2, global_rating=Rating(1700, 120.1)), 0,
         1),
        (dict(login='******', id=3, global_rating=Rating(1200, 72.02)),
         0, 2),
        (dict(login='******', id=4, global_rating=Rating(1200, 72.02)), 0,
         2),
    ]]
    add_connected_players(game, [player for player, _, _ in players])
    for player, _, team in players:
        game.set_player_option(player.id, 'Team', team)
        game.set_player_option(player.id, 'Army', player.id - 1)
    await game.launch()
    for player, result, _ in players:
        await game.add_result(player, player.id - 1, 'score', result)
    result = game.compute_rating()
    for team in result:
        for player, new_rating in team.items():
            assert player in game.players
            assert new_rating != Rating(*player.global_rating)
Exemple #3
0
async def test_compute_rating_balanced_teamgame(game: Game, player_factory):
    game.state = GameState.LOBBY
    players = [(player_factory(login=f"{i}",
                               player_id=i,
                               global_rating=rating,
                               with_lobby_connection=False), result, team)
               for i, (rating, result, team) in enumerate([
                   (Rating(1500, 250), 0, 2),
                   (Rating(1700, 120), 0, 2),
                   (Rating(1200, 72), 0, 3),
                   (Rating(1200, 72), 0, 3),
               ], 1)]
    add_connected_players(game, [player for player, _, _ in players])
    for player, _, team in players:
        game.set_player_option(player.id, 'Team', team)
        game.set_player_option(player.id, 'Army', player.id - 1)
    await game.launch()
    for player, result, team in players:
        await game.add_result(player, player.id - 1,
                              'victory' if team == 2 else 'defeat', result)
    result = game.compute_rating()
    for team in result:
        for player, new_rating in team.items():
            assert player in game.players
            assert new_rating != Rating(*player.ratings[RatingType.GLOBAL])
Exemple #4
0
async def test_compute_rating_does_not_rate_double_win(game: Game,
                                                       player_factory):
    game.state = GameState.LOBBY
    players = [(player_factory(f"{i}", player_id=i,
                               global_rating=rating), result, team)
               for i, (rating, result, team) in enumerate([
                   (Rating(1500, 250), 10, 2),
                   (Rating(1700, 120), 0, 3),
               ], 1)]
    add_connected_players(game, [player for player, _, _ in players])
    for player, _, team in players:
        game.set_player_option(player.id, 'Team', team)
        game.set_player_option(player.id, 'Army', player.id - 1)
    await game.launch()

    for player, result, _ in players:
        await game.add_result(player, player.id - 1, 'victory', result)
    with pytest.raises(GameRatingError):
        game.compute_rating()
Exemple #5
0
async def test_compute_rating_computes_ladder_ratings(game: Game, players):
    game.state = GameState.LOBBY
    players.hosting.ratings[RatingType.LADDER_1V1] = Rating(1500, 250)
    players.joining.ratings[RatingType.LADDER_1V1] = Rating(1500, 250)
    add_connected_players(game, [players.hosting, players.joining])
    await game.launch()
    await game.add_result(players.hosting.id, 0, 'victory', 1)
    await game.add_result(players.joining.id, 1, 'defeat', 0)
    game.set_player_option(players.hosting.id, 'Team', 1)
    game.set_player_option(players.joining.id, 'Team', 1)
    groups = game.compute_rating(rating=RatingType.LADDER_1V1)
    assert players.hosting in groups[0]
    assert players.joining in groups[1]
Exemple #6
0
async def test_compute_rating_computes_global_ratings(game: Game, players):
    await game.clear_data()

    game.state = GameState.LOBBY
    players.hosting.global_rating = Rating(1500, 250)
    players.joining.global_rating = Rating(1500, 250)
    add_connected_players(game, [players.hosting, players.joining])
    await game.launch()
    await game.add_result(players.hosting, 0, 'victory', 1)
    await game.add_result(players.joining, 1, 'defeat', 0)
    game.set_player_option(players.hosting.id, 'Team', 2)
    game.set_player_option(players.joining.id, 'Team', 3)
    groups = game.compute_rating()
    assert players.hosting in groups[0]
    assert players.joining in groups[1]
Exemple #7
0
async def test_compute_rating_computes_ladder_ratings(game: Game, players):
    await game.clear_data()

    game.state = GameState.LOBBY
    players.hosting.ladder_rating = Rating(1500, 250)
    players.joining.ladder_rating = Rating(1500, 250)
    add_connected_players(game, [players.hosting, players.joining])
    await game.launch()
    await game.add_result(players.hosting, 0, 'victory', 1)
    await game.add_result(players.joining, 1, 'defeat', 0)
    game.set_player_option(players.hosting.id, 'Team', 1)
    game.set_player_option(players.joining.id, 'Team', 1)
    groups = game.compute_rating(rating='ladder')
    assert players.hosting in groups[0]
    assert players.joining in groups[1]
Exemple #8
0
async def test_single_wrong_report_still_rated_correctly(
        game: Game, player_factory):
    # based on replay with UID 11255492

    # Mocking out database calls, since not all player IDs exist.
    game.update_game_player_stats = CoroutineMock()

    game.state = GameState.LOBBY

    # Loading log data
    with open("tests/data/uid11255492.log.json", "r") as f:
        log_dict = json.load(f)

    old_rating = 1500
    players = {
        player_id: player_factory(
            login=f"{player_id}",
            player_id=player_id,
            global_rating=Rating(old_rating, 250),
            with_lobby_connection=False,
        )
        for team in log_dict["teams"].values() for player_id in team
    }

    add_connected_players(game, list(players.values()))
    for team_id, team_list in log_dict["teams"].items():
        for player_id in team_list:
            game.set_player_option(player_id, "Team", team_id)
            game.set_player_option(player_id, "Army", player_id - 1)
    await game.launch()

    for reporter, reportee, outcome, score in log_dict["results"]:
        await game.add_result(players[reporter], reportee, outcome, score)

    result = game.compute_rating()
    winning_ids = log_dict["teams"][str(log_dict["winning_team"])]
    for team in result:
        for player, new_rating in team.items():
            assert player in game.players
            player_is_on_winning_team = player.id in winning_ids
            rating_improved = new_rating.mu > old_rating
            assert rating_improved is player_is_on_winning_team
Exemple #9
0
async def test_compute_rating_only_one_surviver(game: Game, player_factory):
    """
    When a player dies their score is reported as "defeat", but this does not
    necessarily mean they lost the game, if their team mates went on and later
    reported a "victory".
    """
    game.state = GameState.LOBBY
    win_team = 2
    lose_team = 3
    players = [(player_factory(login=f"{i}",
                               player_id=i,
                               global_rating=Rating(1500, 200),
                               with_lobby_connection=False), outcome, result,
                team) for i, (outcome, result, team) in enumerate([
                    ("defeat", -10, lose_team),
                    ("defeat", -10, lose_team),
                    ("defeat", -10, lose_team),
                    ("defeat", -10, lose_team),
                    ("defeat", -10, win_team),
                    ("defeat", -10, win_team),
                    ("defeat", -10, win_team),
                    ("victory", 10, win_team),
                ], 1)]
    add_connected_players(game, [player for player, _, _, _ in players])
    for player, _, _, team in players:
        game.set_player_option(player.id, 'Team', team)
        game.set_player_option(player.id, 'Army', player.id - 1)
    await game.launch()

    for player, outcome, result, team in players:
        await game.add_result(player, player.id - 1, outcome, result)

    result = game.compute_rating()
    for team in result:
        for player, new_rating in team.items():
            old_rating = Rating(*player.ratings[RatingType.GLOBAL])
            # `team` index in result might not coincide with `team` index in players
            if player.id > 4:
                assert new_rating > old_rating
            else:
                assert new_rating < old_rating
Exemple #10
0
async def test_compute_rating_sum_of_scores_edge_case(game: Game,
                                                      player_factory):
    """
    For certain scores, compute_rating was determining the winner incorrectly,
    see issue <https://github.com/FAForever/server/issues/485>.
    """
    game.state = GameState.LOBBY
    win_team = 2
    lose_team = 3
    players = [(player_factory(login=f"{i}",
                               player_id=i,
                               global_rating=rating,
                               with_lobby_connection=False), result, team)
               for i, (rating, result, team) in enumerate([
                   (Rating(1500, 200), 1, lose_team),
                   (Rating(1500, 200), 1, lose_team),
                   (Rating(1500, 200), 1, lose_team),
                   (Rating(1500, 200), -10, lose_team),
                   (Rating(1500, 200), 10, win_team),
                   (Rating(1500, 200), -10, win_team),
                   (Rating(1500, 200), -10, win_team),
                   (Rating(1500, 200), 2, win_team),
               ], 1)]
    add_connected_players(game, [player for player, _, _ in players])
    for player, _, team in players:
        game.set_player_option(player.id, 'Team', team)
        game.set_player_option(player.id, 'Army', player.id - 1)
    await game.launch()

    for player, result, team in players:
        outcome = 'victory' if team is win_team else 'defeat'
        await game.add_result(player, player.id - 1, outcome, result)

    result = game.compute_rating()
    for team in result:
        for player, new_rating in team.items():
            old_rating = Rating(*player.ratings[RatingType.GLOBAL])
            if player.id > 4:  # `team` index in result might not coincide with `team` index in players
                assert new_rating > old_rating
            else:
                assert new_rating < old_rating
Exemple #11
0
async def test_compute_rating_two_player_FFA(game: Game, player_factory):
    game.state = GameState.LOBBY
    players = [(player_factory(f"{i}", player_id=i,
                               global_rating=rating), result, team)
               for i, (rating, result, team) in enumerate([
                   (Rating(1500, 250), 0, 1),
                   (Rating(1700, 120), 0, 1),
               ], 1)]
    add_connected_players(game, [player for player, _, _ in players])
    for player, _, team in players:
        game.set_player_option(player.id, 'Team', team)
        game.set_player_option(player.id, 'Army', player.id - 1)
    await game.launch()

    for player, result, _ in players:
        outcome = 'victory' if player.id == 1 else 'defeat'
        await game.add_result(player, player.id - 1, outcome, result)
    result = game.compute_rating()
    for team in result:
        for player, new_rating in team.items():
            old_rating = Rating(*player.ratings[RatingType.GLOBAL])
            assert (new_rating > old_rating) is (player.id == 1)
Exemple #12
0
async def test_compute_rating_treats_double_defeat_as_draw(
        game: Game, player_factory):
    game.state = GameState.LOBBY
    players = [(player_factory(f"{i}", player_id=i,
                               global_rating=rating), result, team)
               for i, (rating, result, team) in enumerate([
                   (Rating(1500, 250), 10, 2),
                   (Rating(1500, 250), 0, 3),
               ], 1)]
    add_connected_players(game, [player for player, _, _ in players])
    for player, _, team in players:
        game.set_player_option(player.id, 'Team', team)
        game.set_player_option(player.id, 'Army', player.id - 1)
    await game.launch()

    for player, result, _ in players:
        await game.add_result(player, player.id - 1, 'defeat', result)
    result = game.compute_rating()
    for team in result:
        for _, new_rating in team.items():
            old_rating = Rating(*player.ratings[RatingType.GLOBAL])
            assert new_rating.mu == old_rating.mu
            assert new_rating.sigma < old_rating.sigma
Exemple #13
0
async def test_compute_rating_balanced_teamgame(game: Game, create_player):
    await game.clear_data()

    game.state = GameState.LOBBY
    players = [
        (create_player(**info), result, team) for info, result, team in [
            (dict(login='******', id=1, global_rating=Rating(1500, 250.7)), 0, 1),
            (dict(login='******', id=2, global_rating=Rating(1700, 120.1)), 0, 1),
            (dict(login='******', id=3, global_rating=Rating(1200, 72.02)), 0, 2),
            (dict(login='******', id=4, global_rating=Rating(1200, 72.02)), 0, 2),
        ]
    ]
    add_connected_players(game, [player for player, _, _ in players])
    for player, _, team in players:
        game.set_player_option(player.id, 'Team', team)
        game.set_player_option(player.id, 'Army', player.id - 1)
    await game.launch()
    for player, result, _ in players:
        await game.add_result(player, player.id - 1, 'score', result)
    result = game.compute_rating()
    for team in result:
        for player, new_rating in team.items():
            assert player in game.players
            assert new_rating != Rating(*player.global_rating)
Exemple #14
0
async def test_compute_rating_works_with_partially_unknown_results(
        game: Game, player_factory):
    game.state = GameState.LOBBY
    players = [(player_factory(f"{i}", player_id=i,
                               global_rating=rating), result, team)
               for i, (rating, result, team) in enumerate([
                   (Rating(1500, 250), 10, 2),
                   (Rating(1700, 120), 0, 2),
                   (Rating(1200, 72), -10, 3),
                   (Rating(1200, 72), 0, 3),
               ], 1)]
    add_connected_players(game, [player for player, _, _ in players])
    for player, _, team in players:
        game.set_player_option(player.id, 'Team', team)
        game.set_player_option(player.id, 'Army', player.id - 1)
    await game.launch()

    for player, result, _ in players:
        outcome = 'victory' if result == 10 else 'unknown'
        await game.add_result(player, player.id - 1, outcome, result)
    result = game.compute_rating()
    for team in result:
        for player, new_rating in team.items():
            assert new_rating != Rating(*player.ratings[RatingType.GLOBAL])