Untitled

 avatar
unknown
python
a year ago
3.3 kB
4
Indexable
import math
import random

import matplotlib.pyplot as plt
from tqdm import tqdm


class Team:
    id: int
    pos: float
    elo: float
    win_count: int
    placement: int

    def __init__(self, id, pos, elo=2000):
        self.id = id
        self.pos = pos
        self.elo = elo
        self.placement = 0
        self.win_count = 0

    def __repr__(self) -> str:
        return f"Team {self.id}, pos {self.pos:.2f}, placement {self.placement}"


def simulate(p=0.5) -> tuple[int, int]:
    teams = [Team(i, random.random() * 2 - 1) for i in range(20)]
    teams[0].elo += 400 * math.log(p / (1 - p), 10)
    res = []
    while len(teams) != 1:
        teams.sort(key=lambda x: x.pos)
        min_diff = 2
        min_diff_idx = 0
        for i in range(len(teams) - 1):
            diff = teams[i + 1].pos - teams[i].pos
            if diff < min_diff:
                min_diff = diff
                min_diff_idx = i
        elo_diff = teams[min_diff_idx + 1].elo - teams[min_diff_idx].elo
        win_rate = 1 / (1 + 10 ** (-elo_diff / 400))
        win = random.random() < win_rate
        new_pos = (teams[min_diff_idx + 1].pos + teams[min_diff_idx].pos) / 2
        winner_idx = min_diff_idx + 1 if win else min_diff_idx
        loser_idx = min_diff_idx if win else min_diff_idx + 1
        teams[winner_idx].pos = new_pos
        teams[winner_idx].win_count += 1
        teams[loser_idx].placement = len(teams)
        res.append(teams[loser_idx])
        teams.pop(loser_idx)
    teams[0].placement = 1
    res.append(teams[0])
    t: Team = next((x for x in res if x.id == 0))
    return t.placement, t.win_count


def main():
    for P in [0.4, 0.45, 0.5, 0.55, 0.6]:
        COUNT = 100000
        y = [0.0] * 20
        PLACEMENT_SCORE = [
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            5,
            5,
            5,
            10,
            10,
            20,
            20,
            30,
            45,
            55,
            70,
            95,
            125,
        ]
        KILL_SCORE = [
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            5,
            5,
            5,
            10,
            10,
            12,
            12,
            14,
            16,
            18,
            20,
            23,
            25,
        ]
        total_placement_score = 0
        total_kill_score = 0
        for _ in tqdm(range(COUNT)):
            placement, win_count = simulate(P)
            y[placement - 1] += 1
            total_placement_score += PLACEMENT_SCORE[20 - placement]
            total_kill_score += KILL_SCORE[20 - placement] * win_count * 2.5
        x = range(1, 21)
        y = [i / COUNT for i in y]
        plt.xticks(x)
        plt.bar(x, y)
        plt.title(
            f"win rate: {P:.2f}, "
            f"avg placement score: {(total_placement_score / COUNT):.2f}, "
            f"avg kill score: {(total_kill_score / COUNT):.2f}"
        )
        plt.savefig(f"img/{P:.2f}.png")
        plt.clf()


if __name__ == "__main__":
    main()
Editor is loading...
Leave a Comment