Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • main
1 result

Target

Select target project
  • GET racing FOSS / formula student elo
1 result
Select Git revision
  • main
1 result
Show changes

Commits on Source 2

5 files
+ 167
60
Compare changes
  • Side-by-side
  • Inline

Files

Original line number Diff line number Diff line
@@ -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>
+141 −38
Original line number Diff line number Diff line
@@ -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":
@@ -155,6 +157,9 @@ class EloSystem:
        # For each team, compare with teams ranked below them
        date = self.get_competition_date(competition_id)  # Use current date as competition date

        old_world_ranking = sorted(self.teams.items(), key=lambda x: x[1]['elo'], reverse=True)
        old_world_ranking = tuple(name for name, _ in old_world_ranking)

        for i in range(len(teams_in_order)):
            for j in range(i + 1, len(teams_in_order)):
                team_a = teams_in_order[i]
@@ -165,29 +170,41 @@ class EloSystem:

        # Store post-competition Elo ratings and changes
        for team in teams_in_order:
            rank = teams_in_order.index(team) + 1
            placement = teams_in_order.index(team) + 1
            previous_elo = self.teams[team]['elo']
            elo_change = self.teams[team]['delta_elo']
            old_rank = old_world_ranking.index(team) + 1
            new_rank = 0

            # Store in team history
            self.teams[team]['history'].append({
                'date': date.strftime("%Y-%m-%d"),
                'competition': self.get_competition_name(competition_id),
                'competition_id': competition_id,
                'rank': rank,
                'placement': placement,
                'participants': len(teams_in_order),
                'previous_elo': previous_elo,
                'new_elo': self.teams[team]['elo'] + self.teams[team]['delta_elo'],
                'elo_change': elo_change
                'elo_change': elo_change,
                'old_rank': old_rank,
                'new_rank': new_rank,
                'rank_change': new_rank - old_rank
            })

            # Store in competition history
            self.competition_history[competition_id]['results'][rank-1][2] = previous_elo
            self.competition_history[competition_id]['results'][rank-1][3] = elo_change
            self.competition_history[competition_id]['results'][placement-1][2] = previous_elo
            self.competition_history[competition_id]['results'][placement-1][3] = elo_change

            self.teams[team]['elo'] = self.teams[team]['elo'] + self.teams[team]['delta_elo']
            self.teams[team]['delta_elo'] = 0

        for team in teams_in_order:
            new_world_ranking = sorted(self.teams.items(), key=lambda x: x[1]['elo'], reverse=True)
            new_world_ranking = tuple(name for name, _ in new_world_ranking)
            new_rank = new_world_ranking.index(team) + 1
            self.teams[team]['history'][-1]['new_rank'] = new_rank
            self.teams[team]['history'][-1]['rank_change'] = new_rank - self.teams[team]['history'][-1]['old_rank']

    def update_elo_pair(self, team_a, team_b, score_a, score_b, competition_id, date):
        """Update Elo ratings for a pair of teams based on their match outcome"""
        # Get current Elo ratings
@@ -231,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)

@@ -273,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
@@ -352,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):
@@ -428,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']

@@ -442,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))

        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 line chart
        plt.plot(range(len(dates)), elo_values, marker='o', linestyle='-', color='gray')
        # 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['rank']})",
            ax1.annotate(entry['competition'] + f" (#{entry['placement']})",
                         (i, entry['new_elo']),
                         textcoords="offset points",
                         xytext=(0, 10),
@@ -456,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 = []
+18 −12
Original line number Diff line number Diff line
@@ -149,8 +149,8 @@ def get_team_page_html(self, team_name, team_data, team_competitions):

    # Calculate average ranking if available
    if team_competitions:
        avg_rank = sum(comp['rank'] for comp in team_competitions) / len(team_competitions)
        best_rank = min(comp['rank'] for comp in team_competitions)
        avg_rank = sum(comp['placement'] for comp in team_competitions) / len(team_competitions)
        best_rank = min(comp['placement'] for comp in team_competitions)

        html_content += f"""
            <div class="stat-box">
@@ -163,39 +163,45 @@ 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>Competition</th>
                    <th>Comp</th>
                    <th>Placement</th>
                    <th>Rank Before</th>
                    <th>Rank After</th>
                    <th>Rank Change</th>
                    <th>Elo Before</th>
                    <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:
        elo_change = comp['elo_change']
        change_class = "positive" if elo_change > 0 else "negative" if elo_change < 0 else ""
        elo_change_class = "positive" if elo_change > 0 else "negative" if elo_change < 0 else ""
        rank_change = comp['rank_change']
        rank_change_class = "positive" if rank_change < 0 else "negative" if rank_change > 0 else ""

        html_content += f"""
            <tr>
                <td>{comp['date']}</td>
                <td><a href=../comp/{comp['competition_id']}.html>{comp['competition']}</a></td>
                <td>{comp['rank']} / {comp['participants']}</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>
                <td class="{rank_change_class}">{'+' if rank_change > 0 else ''}{comp['rank_change']}</td>
                <td>{int(comp['previous_elo'])}</td>
                <td>{int(comp['new_elo'])}</td>
                <td class="{change_class}">{'+' if elo_change > 0 else ''}{elo_change:.1f}</td>
                <td class="{elo_change_class}">{'+' if elo_change > 0 else ''}{elo_change:.1f}</td>
            </tr>"""

    html_content += """
Original line number Diff line number Diff line
@@ -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