Skip to content
Snippets Groups Projects
Commit f0dddbe8 authored by maeries's avatar maeries
Browse files

added comp results as bar chart

parent 8852492a
Branches
No related tags found
No related merge requests found
Pipeline #278425 passed
...@@ -98,7 +98,7 @@ def get_competition_page_html(self, competition_id): ...@@ -98,7 +98,7 @@ def get_competition_page_html(self, competition_id):
height: auto; height: auto;
}} }}
a {{ a {{<
color: black; color: black;
transition: color 0.3s ease; transition: color 0.3s ease;
}} }}
...@@ -163,14 +163,12 @@ def get_competition_page_html(self, competition_id): ...@@ -163,14 +163,12 @@ def get_competition_page_html(self, competition_id):
<p><a href="../index.html">← Back to World Ranking</a></p> <p><a href="../index.html">← Back to World Ranking</a></p>
""" """
html_content += """ html_content += f"""
</div> </div>
<!--
<div class="chart-container"> <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> </div>
-->
<h2>Results</h2> <h2>Results</h2>
<table> <table>
......
File added
...@@ -18,6 +18,7 @@ from world_ranking_list import get_world_ranking_html ...@@ -18,6 +18,7 @@ from world_ranking_list import get_world_ranking_html
# Constants for Elo calculation # Constants for Elo calculation
K_FACTOR = 15 K_FACTOR = 15
INITIAL_ELO = 1500 # Starting Elo for all teams INITIAL_ELO = 1500 # Starting Elo for all teams
IMAGE_FORMAT = "webp"
def expected_score(rating_a, rating_b): def expected_score(rating_a, rating_b):
...@@ -50,6 +51,7 @@ class EloSystem: ...@@ -50,6 +51,7 @@ class EloSystem:
raise raise
with open("header-snippet.html") as header_snippet: with open("header-snippet.html") as header_snippet:
self.header_snippet = header_snippet.read() self.header_snippet = header_snippet.read()
self.IMAGE_FORMAT = IMAGE_FORMAT
def load_competition_meta_data(self): def load_competition_meta_data(self):
if self.competition_type == "combustion": if self.competition_type == "combustion":
...@@ -246,8 +248,10 @@ class EloSystem: ...@@ -246,8 +248,10 @@ class EloSystem:
self.create_world_ranking() self.create_world_ranking()
for competition in self.competition_history: #for competition in self.competition_history:
self.create_competition_page(competition) # self.create_competition_page(competition)
pool.map(self.create_competition_page, self.competition_history)
pool.map(self.create_team_page, self.teams) pool.map(self.create_team_page, self.teams)
...@@ -288,6 +292,9 @@ class EloSystem: ...@@ -288,6 +292,9 @@ class EloSystem:
"""Create a dedicated page for a specific team""" """Create a dedicated page for a specific team"""
print(f"Generating Competition site for {competition_id}") 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) html_content = get_competition_page_html(self, competition_id)
# Write the HTML file # Write the HTML file
...@@ -367,7 +374,7 @@ class EloSystem: ...@@ -367,7 +374,7 @@ class EloSystem:
# plt.tight_layout() # plt.tight_layout()
# Save the chart # 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() plt.close()
def create_elo_distribution_chart(self): def create_elo_distribution_chart(self):
...@@ -443,12 +450,11 @@ class EloSystem: ...@@ -443,12 +450,11 @@ class EloSystem:
plt.tight_layout() plt.tight_layout()
# Save the chart # 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() plt.close()
def create_team_elo_history_chart(self, team_name): def create_team_elo_history_chart(self, team_name):
"""Create a line chart showing a team's Elo history over time""" """Create a line chart showing a team's Elo history over time"""
plt.figure(figsize=(10, 6))
team_history = self.teams[team_name]['history'] team_history = self.teams[team_name]['history']
...@@ -457,13 +463,28 @@ class EloSystem: ...@@ -457,13 +463,28 @@ class EloSystem:
dates = [entry['date'] for entry in team_history] dates = [entry['date'] for entry in team_history]
elo_values = [entry['new_elo'] 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 ax2.plot(range(len(dates)), ranks, marker='none', linestyle='-', color='gray', label='Rank')
plt.plot(range(len(dates)), elo_values, marker='o', linestyle='-', color='gray') 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 # Add competition labels
for i, entry in enumerate(team_history): 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']), (i, entry['new_elo']),
textcoords="offset points", textcoords="offset points",
xytext=(0, 10), xytext=(0, 10),
...@@ -471,17 +492,84 @@ class EloSystem: ...@@ -471,17 +492,84 @@ class EloSystem:
fontsize=8, fontsize=8,
rotation=45) rotation=45)
plt.xticks(range(len(dates)), dates, rotation=45)
plt.ylabel('Elo Rating')
plt.title(f'{team_name} - Elo Rating History') 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() plt.tight_layout()
# Save the chart # 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) dpi=100)
plt.close() 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): def optimize_k(self):
self.load_and_process_csv_files() self.load_and_process_csv_files()
error_history = [] error_history = []
......
...@@ -163,18 +163,17 @@ def get_team_page_html(self, team_name, team_data, team_competitions): ...@@ -163,18 +163,17 @@ def get_team_page_html(self, team_name, team_data, team_competitions):
</div> </div>
""" """
html_content += """ html_content += f"""
</div> </div>
<div class="chart-container"> <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> </div>
<h2>Competition History</h2> <h2>Competition History</h2>
<div style="overflow: scroll;"> <div style="overflow: scroll;">
<table> <table>
<tr> <tr>
<th>Date</th>
<th>Comp</th> <th>Comp</th>
<th>Placement</th> <th>Placement</th>
<th>Rank Before</th> <th>Rank Before</th>
...@@ -184,7 +183,7 @@ def get_team_page_html(self, team_name, team_data, team_competitions): ...@@ -184,7 +183,7 @@ def get_team_page_html(self, team_name, team_data, team_competitions):
<th>Elo After</th> <th>Elo After</th>
<th>Elo Change</th> <th>Elo Change</th>
</tr> </tr>
""".format(clean_filename(team_name), team_name) """
# Add rows for each competition # Add rows for each competition
for comp in team_competitions: for comp in team_competitions:
...@@ -195,8 +194,7 @@ def get_team_page_html(self, team_name, team_data, team_competitions): ...@@ -195,8 +194,7 @@ def get_team_page_html(self, team_name, team_data, team_competitions):
html_content += f""" html_content += f"""
<tr> <tr>
<td>{comp['date']}</td> <td><a href=../comp/{comp['competition_id']}.html>{comp['competition']} {comp['date'][2:4]}</a></td>
<td><a href=../comp/{comp['competition_id']}.html>{comp['competition']}</a></td>
<td>{comp['placement']} / {comp['participants']}</td> <td>{comp['placement']} / {comp['participants']}</td>
<td>{comp['old_rank']}</td> <td>{comp['old_rank']}</td>
<td>{comp['new_rank']}</td> <td>{comp['new_rank']}</td>
......
...@@ -210,7 +210,7 @@ def get_world_ranking_html(self, sorted_teams): ...@@ -210,7 +210,7 @@ def get_world_ranking_html(self, sorted_teams):
<p>Rankings based on {len(self.competition_history)} competitions.</p> <p>Rankings based on {len(self.competition_history)} competitions.</p>
<div class="chart-container"> <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> </div>
<h2>Current Rankings</h2> <h2>Current Rankings</h2>
...@@ -234,16 +234,16 @@ def get_world_ranking_html(self, sorted_teams): ...@@ -234,16 +234,16 @@ def get_world_ranking_html(self, sorted_teams):
<td>{team_data['competitions']}</td> <td>{team_data['competitions']}</td>
</tr>""" </tr>"""
html_content += """ html_content += f"""
</table> </table>
<div> <div>
<div class="chart-container"> <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>
<div class="timestamp"> <div class="timestamp">
<p>Generated on {}</p> <p>Generated on {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</p>
</div> </div>
<div style="display: flex; justify-content: center;"> <div style="display: flex; justify-content: center;">
...@@ -252,6 +252,6 @@ def get_world_ranking_html(self, sorted_teams): ...@@ -252,6 +252,6 @@ def get_world_ranking_html(self, sorted_teams):
</div> </div>
</body> </body>
</html> </html>
""".format(datetime.now().strftime("%Y-%m-%d %H:%M:%S")) """
return html_content return html_content
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment