Skip to content

Commit dfa7e41

Browse files
committed
Ref: Factor out get_scores
1 parent 1de9335 commit dfa7e41

1 file changed

Lines changed: 39 additions & 29 deletions

File tree

  • codeclash/analysis/metrics

codeclash/analysis/metrics/elo.py

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,35 @@ def calculate_round_weight_exponential(round_num: int, total_rounds: int, alpha:
6363
return raw_weight * norm_factor
6464

6565

66+
def get_scores(stats: dict) -> dict[str, float]:
67+
valid_submits = sum(
68+
[x["valid_submit"] for x in stats["player_stats"].values() if x.get("valid_submit") is not None]
69+
)
70+
71+
ties = stats["scores"].get(RESULT_TIE, 0)
72+
sims = sum(stats["scores"].values())
73+
assert sims >= ties
74+
75+
player2score = {}
76+
for k, v in stats["player_stats"].items():
77+
if k != RESULT_TIE:
78+
if v["score"] is None:
79+
# Not sure why this happens, but just skip it
80+
# Kilian: This is probably when we skip a round (might have fixed this, but probably in old logs)
81+
continue
82+
if valid_submits == 1:
83+
# FOR BACKWARDS COMPATIBILITY: If only one player submitted, give them full point
84+
if v["valid_submit"]:
85+
_score = 1.0
86+
else:
87+
_score = 0.0
88+
else:
89+
assert sims > 0, (stats["scores"], valid_submits)
90+
_score = (v["score"] + 0.5 * ties) * 1.0 / sims
91+
player2score[k] = _score
92+
return player2score
93+
94+
6695
def update_profiles(prof_and_score: list[tuple[ModelEloProfile, float]], k_factor: float) -> None:
6796
"""Update ELO profiles for two players based on their scores
6897
@@ -101,9 +130,12 @@ def __init__(self, *, k_factor: float, starting_elo: float, weighting_function:
101130
self._alpha = alpha
102131
self._player_profiles = {}
103132

133+
@property
134+
def player_profiles(self) -> dict[str, ModelEloProfile]:
135+
return self._player_profiles
136+
104137
def _analyze_round(self, stats: dict, player2profile: dict, *, total_rounds: int) -> None:
105138
"""Update all profiles based on the results of one round"""
106-
# Calculate round weight
107139
current_round = stats["round_num"]
108140
if self._weighting_function == "linear":
109141
round_weight = calculate_round_weight_linear(current_round, total_rounds)
@@ -112,36 +144,14 @@ def _analyze_round(self, stats: dict, player2profile: dict, *, total_rounds: int
112144
else: # none
113145
round_weight = 1.0
114146

115-
prof_and_score: list[tuple[ModelEloProfile, float]] = []
116-
valid_submits = sum(
117-
[x["valid_submit"] for x in stats["player_stats"].values() if x.get("valid_submit") is not None]
118-
)
147+
player2score = get_scores(stats)
119148

120-
# game repetitions
121-
ties = stats["scores"].get(RESULT_TIE, 0)
122-
# total games
123-
sims = sum(stats["scores"].values())
124-
assert sims >= ties
125-
for k, v in stats["player_stats"].items():
126-
if k != RESULT_TIE:
127-
if v["score"] is None:
128-
# Not sure why this happens, but just skip it
129-
# Kilian: This is probably when we skip a round (might have fixed this, but probably in old logs)
130-
continue
131-
if valid_submits == 1:
132-
# FOR BACKWARDS COMPATIBILITY: If only one player submitted, give them full point
133-
if v["valid_submit"]:
134-
_score = 1.0
135-
else:
136-
_score = 0.0
137-
else:
138-
assert sims > 0, (stats["scores"], valid_submits)
139-
_score = (v["score"] + 0.5 * ties) * 1.0 / sims
140-
prof = player2profile[k]
141-
prof.rounds_played += 1
142-
prof_and_score.append((prof, _score))
149+
prof_and_score = []
150+
for player, score in player2score.items():
151+
prof = player2profile[player]
152+
prof.rounds_played += 1
153+
prof_and_score.append((prof, score))
143154

144-
# Update ELO ratings - should only happen once per match
145155
if len(prof_and_score) != 2:
146156
print(f"Skipping round {current_round} (wrong number of players)")
147157
raise SkipTournamentException

0 commit comments

Comments
 (0)