From f0dddbe8da0a42f36b245e51a55e0460e43a5041 Mon Sep 17 00:00:00 2001 From: maeries <8ij4neqiu@mozmail.com> Date: Mon, 24 Mar 2025 18:49:12 +0100 Subject: [PATCH] added comp results as bar chart --- competition_page.py | 8 ++- k-factor evaluation.ods | Bin 0 -> 25634 bytes main.py | 112 +++++++++++++++++++++++++++++++++++----- team_page.py | 10 ++-- world_ranking_list.py | 10 ++-- 5 files changed, 112 insertions(+), 28 deletions(-) create mode 100644 k-factor evaluation.ods diff --git a/competition_page.py b/competition_page.py index c394d92..ca08380 100644 --- a/competition_page.py +++ b/competition_page.py @@ -98,7 +98,7 @@ def get_competition_page_html(self, competition_id): height: auto; }} - a {{ + a {{< color: black; transition: color 0.3s ease; }} @@ -163,14 +163,12 @@ def get_competition_page_html(self, competition_id): <p><a href="../index.html">← Back to World Ranking</a></p> """ - html_content += """ + html_content += f""" </div> - <!-- <div class="chart-container"> - fancy diagram here + <img src="../images/{competition_id}_results.{self.IMAGE_FORMAT}" alt="{self.get_full_competition_name(competition_id)} Results"> </div> - --> <h2>Results</h2> <table> diff --git a/k-factor evaluation.ods b/k-factor evaluation.ods new file mode 100644 index 0000000000000000000000000000000000000000..0065d6f6b71788db06479e0fda953c1a98db0a67 GIT binary patch literal 25634 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 UD;r3eD1#_N0V@N;oH!5<0H8f7l>h($ literal 0 HcmV?d00001 diff --git a/main.py b/main.py index e1e0abb..573293a 100644 --- a/main.py +++ b/main.py @@ -18,6 +18,7 @@ from world_ranking_list import get_world_ranking_html # Constants for Elo calculation K_FACTOR = 15 INITIAL_ELO = 1500 # Starting Elo for all teams +IMAGE_FORMAT = "webp" def expected_score(rating_a, rating_b): @@ -50,6 +51,7 @@ class EloSystem: raise with open("header-snippet.html") as header_snippet: self.header_snippet = header_snippet.read() + self.IMAGE_FORMAT = IMAGE_FORMAT def load_competition_meta_data(self): if self.competition_type == "combustion": @@ -246,8 +248,10 @@ class EloSystem: self.create_world_ranking() - for competition in self.competition_history: - self.create_competition_page(competition) + #for competition in self.competition_history: + # self.create_competition_page(competition) + + pool.map(self.create_competition_page, self.competition_history) pool.map(self.create_team_page, self.teams) @@ -288,6 +292,9 @@ class EloSystem: """Create a dedicated page for a specific team""" print(f"Generating Competition site for {competition_id}") + # Competition results as bar chart + self.create_competition_result_chart(competition_id) + html_content = get_competition_page_html(self, competition_id) # Write the HTML file @@ -367,7 +374,7 @@ class EloSystem: # plt.tight_layout() # Save the chart - plt.savefig(os.path.join(self.output_directory, 'images', 'top_teams_elo.png'), dpi=100) + plt.savefig(os.path.join(self.output_directory, 'images', 'top_teams_elo.' + self.IMAGE_FORMAT), dpi=100) plt.close() def create_elo_distribution_chart(self): @@ -443,12 +450,11 @@ class EloSystem: plt.tight_layout() # Save the chart - plt.savefig(os.path.join(self.output_directory, 'images', 'elo_distribution.png'), dpi=100) + plt.savefig(os.path.join(self.output_directory, 'images', 'elo_distribution.' + self.IMAGE_FORMAT), dpi=100) plt.close() def create_team_elo_history_chart(self, team_name): """Create a line chart showing a team's Elo history over time""" - plt.figure(figsize=(10, 6)) team_history = self.teams[team_name]['history'] @@ -457,13 +463,28 @@ class EloSystem: dates = [entry['date'] for entry in team_history] elo_values = [entry['new_elo'] for entry in team_history] + ranks = [entry['new_rank'] for entry in team_history] + + # Create the first plot with elo_values + fig, ax2 = plt.subplots(figsize=(12, 6)) - # Create line chart - plt.plot(range(len(dates)), elo_values, marker='o', linestyle='-', color='gray') + ax2.plot(range(len(dates)), ranks, marker='none', linestyle='-', color='gray', label='Rank') + ax2.set_ylabel('Rank', color='gray') + ax2.tick_params(axis='y', labelcolor='gray') + ax2.invert_yaxis() + ax2.set_xticks(range(len(dates))) + ax2.set_xticklabels(dates, rotation=45, ha='right') # ha='right' helps with alignment + + # Create a second y-axis with the same x-axis + ax1 = ax2.twinx() + ax1.plot(range(len(dates)), elo_values, marker='o', linestyle='-', color='black', label='ELO Values') + ax1.set_xlabel('Dates') + ax1.set_ylabel('ELO Rating', color='black') + ax1.tick_params(axis='y', labelcolor='black') # Add competition labels for i, entry in enumerate(team_history): - plt.annotate(entry['competition'] + f" (#{entry['placement']})", + ax1.annotate(entry['competition'] + f" (#{entry['placement']})", (i, entry['new_elo']), textcoords="offset points", xytext=(0, 10), @@ -471,17 +492,84 @@ class EloSystem: fontsize=8, rotation=45) - plt.xticks(range(len(dates)), dates, rotation=45) - plt.ylabel('Elo Rating') plt.title(f'{team_name} - Elo Rating History') - plt.grid(True, alpha=0.3) + ax2.grid(True, axis='x', alpha=0.3) + ax1.grid(True, alpha=0.3) plt.tight_layout() # Save the chart - plt.savefig(os.path.join(self.output_directory, 'images', f'{clean_filename(team_name)}_history.png'), + plt.savefig(os.path.join(self.output_directory, 'images', f'{clean_filename(team_name)}_history.' + self.IMAGE_FORMAT), dpi=100) plt.close() + def create_competition_result_chart(self, competition_id): + """Create a bar chart of the top teams by Elo rating""" + + competition = self.competition_history[competition_id] + + team_names = [result[1] for result in competition['results']] + team_names = team_names[::-1] + elo_change = [result[3] for result in competition['results']] + elo_change = elo_change[::-1] + + fig = plt.figure(figsize=(12, len(team_names)*0.2175+2)) + ax = fig.add_axes([0.3, 0.1, 0.6, 0.8]) + + # Create bar chart + bars = plt.barh(team_names, elo_change, color='none') + + # Add Elo values at the end of each bar + for i, bar in enumerate(bars): + plt.text(bar.get_width() + 5, bar.get_y() + bar.get_height() / 2, + f"{int(elo_change[i])}", va='center') + + # Create custom colormap + colors = [hex_to_normalized_rgb(self.LINK_COLOR), hex_to_normalized_rgb(self.BORDER_COLOR)] # RGB values for #ffff1e and #ffc400 + custom_yellow_cmap = LinearSegmentedColormap.from_list('custom_yellow', colors) + + for bar in bars: + # Get the coordinates of the bar + x0, y0 = bar.get_xy() + width = bar.get_width() + height = bar.get_height() + + # Create a gradient for the bar + gradient = np.linspace(0, 1, 100).reshape(1, -1) + + # Get colors from the colormap + colors = custom_yellow_cmap(gradient) + + # Set the bar's face color to the gradient + bar.set_facecolor('none') # Remove default color + + # Add the gradient rectangle + gradient_rect = patches.Rectangle((x0, y0), width, height, + linewidth=0, + fill=True, + facecolor=custom_yellow_cmap(0.5)) + + # To create a gradient, add an axial gradient transform + gradient_rect.set_facecolor('none') + ax.add_patch(gradient_rect) + + # Create multiple thin rectangles to simulate a gradient + steps = 50 + for i in range(steps): + left = x0 + (i/steps) * width + rect_width = width/steps + color = custom_yellow_cmap(i/steps) + rect = patches.Rectangle((left, y0), rect_width, height, + linewidth=0, + color=color) + ax.add_patch(rect) + + plt.xlabel('Elo Gain') + plt.title('ELo Gain per Team') + + # Save the chart + plt.savefig(os.path.join(self.output_directory, 'images', competition_id + '_results.' + self.IMAGE_FORMAT), dpi=100) + plt.close() + def optimize_k(self): self.load_and_process_csv_files() error_history = [] diff --git a/team_page.py b/team_page.py index 2529757..79cdb44 100644 --- a/team_page.py +++ b/team_page.py @@ -163,18 +163,17 @@ def get_team_page_html(self, team_name, team_data, team_competitions): </div> """ - html_content += """ + html_content += f""" </div> <div class="chart-container"> - <img src="../images/{}_history.png" alt="{} Elo History"> + <img src="../images/{clean_filename(team_name)}_history.{self.IMAGE_FORMAT}" alt="{team_name} Elo History"> </div> <h2>Competition History</h2> <div style="overflow: scroll;"> <table> <tr> - <th>Date</th> <th>Comp</th> <th>Placement</th> <th>Rank Before</th> @@ -184,7 +183,7 @@ def get_team_page_html(self, team_name, team_data, team_competitions): <th>Elo After</th> <th>Elo Change</th> </tr> - """.format(clean_filename(team_name), team_name) + """ # Add rows for each competition for comp in team_competitions: @@ -195,8 +194,7 @@ def get_team_page_html(self, team_name, team_data, team_competitions): html_content += f""" <tr> - <td>{comp['date']}</td> - <td><a href=../comp/{comp['competition_id']}.html>{comp['competition']}</a></td> + <td><a href=../comp/{comp['competition_id']}.html>{comp['competition']} {comp['date'][2:4]}</a></td> <td>{comp['placement']} / {comp['participants']}</td> <td>{comp['old_rank']}</td> <td>{comp['new_rank']}</td> diff --git a/world_ranking_list.py b/world_ranking_list.py index 067f6ec..e42c0de 100644 --- a/world_ranking_list.py +++ b/world_ranking_list.py @@ -210,7 +210,7 @@ def get_world_ranking_html(self, sorted_teams): <p>Rankings based on {len(self.competition_history)} competitions.</p> <div class="chart-container"> - <img src="images/top_teams_elo.png" alt="Top Teams Elo Chart"> + <img src="images/top_teams_elo.{self.IMAGE_FORMAT}" alt="Top Teams Elo Chart"> </div> <h2>Current Rankings</h2> @@ -234,16 +234,16 @@ def get_world_ranking_html(self, sorted_teams): <td>{team_data['competitions']}</td> </tr>""" - html_content += """ + html_content += f""" </table> <div> <div class="chart-container"> - <img src="images/elo_distribution.png" alt="Elo Distribution"> + <img src="images/elo_distribution.{self.IMAGE_FORMAT}" alt="Elo Distribution"> </div> <div class="timestamp"> - <p>Generated on {}</p> + <p>Generated on {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</p> </div> <div style="display: flex; justify-content: center;"> @@ -252,6 +252,6 @@ def get_world_ranking_html(self, sorted_teams): </div> </body> </html> - """.format(datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + """ return html_content \ No newline at end of file -- GitLab