From 94007bb7b1bf0bc429d5c33ec7ab17114fae6ae8 Mon Sep 17 00:00:00 2001
From: Marius Heidenreich <marius.heidenreich@tu-dortmund.de>
Date: Sun, 16 Mar 2025 04:08:54 +0100
Subject: [PATCH] claude bessere plots

---
 main.py | 126 ++++++++++++++++++++++++++++++++------------------------
 1 file changed, 73 insertions(+), 53 deletions(-)

diff --git a/main.py b/main.py
index d1ef53f..2eadb03 100644
--- a/main.py
+++ b/main.py
@@ -19,6 +19,7 @@ class EloSystem:
         self.output_directory = output_directory
         self.teams = {}  # Dictionary to store team Elo ratings
         self.match_history = []  # List to store all match results for history tracking
+        self.competition_history = {}  # Dictionary to store competition results
         self.initialize_output_directory()
 
     def initialize_output_directory(self):
@@ -63,7 +64,7 @@ class EloSystem:
                                 'competitions': 0,
                                 'history': []
                             }
-                        teams_in_competition.append(team_name)
+                        teams_in_competition.append((rank, team_name))
                 except StopIteration:
                     # File is empty
                     continue
@@ -79,6 +80,7 @@ class EloSystem:
                         team_name = row[1].strip() if len(row) > 1 else row[0].strip()
                     else:
                         # If no explicit ranking, use row index
+                        rank = len(teams_in_competition) + 1
                         team_name = row[0].strip()
 
                     # Initialize the team if not seen before
@@ -88,20 +90,36 @@ class EloSystem:
                             'competitions': 0,
                             'history': []
                         }
-                    teams_in_competition.append(team_name)
+                    teams_in_competition.append((rank, team_name))
+
+            # Sort teams by rank
+            teams_in_competition.sort(key=lambda x: x[0])
+
+            # Store competition results
+            date = datetime.now().strftime("%Y-%m-%d")  # Use current date as competition date
+            self.competition_history[competition_name] = {
+                'date': date,
+                'results': teams_in_competition
+            }
+
+            # Extract just team names in order
+            team_names = [team[1] for team in teams_in_competition]
 
             # Update competition count for each team
-            for team_name in teams_in_competition:
+            for team_name in team_names:
                 self.teams[team_name]['competitions'] += 1
 
             # Update Elo ratings based on this competition's results
-            self.update_elo_for_competition(teams_in_competition, competition_name)
+            self.update_elo_for_competition(team_names, competition_name)
 
     def update_elo_for_competition(self, teams_in_order, competition_name):
         """Update Elo ratings for all teams in a competition"""
         # For each team, compare with teams ranked below them
         date = datetime.now().strftime("%Y-%m-%d")  # Use current date as competition date
 
+        # Store pre-competition Elo ratings
+        pre_competition_elo = {team: self.teams[team]['elo'] for team in teams_in_order}
+
         for i in range(len(teams_in_order)):
             for j in range(i + 1, len(teams_in_order)):
                 team_a = teams_in_order[i]
@@ -110,6 +128,21 @@ class EloSystem:
                 # Team A is ranked higher than Team B
                 self.update_elo_pair(team_a, team_b, 1, 0, competition_name, date)
 
+        # Store post-competition Elo ratings and changes
+        for team in teams_in_order:
+            elo_change = self.teams[team]['elo'] - pre_competition_elo[team]
+            rank = teams_in_order.index(team) + 1
+
+            # Store in team history
+            self.teams[team]['history'].append({
+                'date': date,
+                'competition': competition_name,
+                'rank': rank,
+                'previous_elo': pre_competition_elo[team],
+                'new_elo': self.teams[team]['elo'],
+                'elo_change': elo_change
+            })
+
     def update_elo_pair(self, team_a, team_b, score_a, score_b, competition_name, date):
         """Update Elo ratings for a pair of teams based on their match outcome"""
         # Get current Elo ratings
@@ -139,13 +172,10 @@ class EloSystem:
         }
         self.match_history.append(match_info)
 
-        # Update team Elo ratings and history
+        # Update team Elo ratings
         self.teams[team_a]['elo'] = new_rating_a
         self.teams[team_b]['elo'] = new_rating_b
 
-        self.teams[team_a]['history'].append({'date': date, 'elo': new_rating_a, 'competition': competition_name})
-        self.teams[team_b]['history'].append({'date': date, 'elo': new_rating_b, 'competition': competition_name})
-
     def expected_score(self, rating_a, rating_b):
         """Calculate the expected score for a player with rating_a against a player with rating_b"""
         return 1 / (1 + math.pow(10, (rating_b - rating_a) / 400))
@@ -227,7 +257,7 @@ class EloSystem:
 </head>
 <body>
     <h1>Team Elo Rankings</h1>
-    <p>Rankings based on {len(self.match_history)} matches from {self.count_competitions()} competitions.</p>
+    <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">
@@ -277,9 +307,8 @@ class EloSystem:
         if team_data['history']:
             self.create_team_elo_history_chart(team_name)
 
-        # Get matches involving this team
-        team_matches = [match for match in self.match_history
-                        if match['team_a'] == team_name or match['team_b'] == team_name]
+        # Filter history for this team's competitions
+        team_competitions = sorted(team_data['history'], key=lambda x: x['date'], reverse=True)
 
         html_content = f"""<!DOCTYPE html>
 <html lang="en">
@@ -360,6 +389,12 @@ class EloSystem:
             font-size: 14px;
             color: #666;
         }}
+        .positive {{
+            color: green;
+        }}
+        .negative {{
+            color: red;
+        }}
     </style>
 </head>
 <body>
@@ -377,21 +412,19 @@ class EloSystem:
         </div>
 """
 
-        # Calculate win rate if applicable
-        if team_matches:
-            wins = sum(1 for match in team_matches
-                       if (match['team_a'] == team_name and match['score_a'] > match['score_b'])
-                       or (match['team_b'] == team_name and match['score_b'] > match['score_a']))
-            win_rate = (wins / len(team_matches)) * 100
+        # 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)
 
             html_content += f"""
         <div class="stat-box">
-            <div class="stat-value">{len(team_matches)}</div>
-            <div class="stat-label">Total Matches</div>
+            <div class="stat-value">{avg_rank:.1f}</div>
+            <div class="stat-label">Avg. Placement</div>
         </div>
         <div class="stat-box">
-            <div class="stat-value">{win_rate:.1f}%</div>
-            <div class="stat-label">Win Rate</div>
+            <div class="stat-value">{best_rank}</div>
+            <div class="stat-label">Best Placement</div>
         </div>
 """
 
@@ -402,40 +435,31 @@ class EloSystem:
         <img src="images/{}_history.png" alt="{} Elo History">
     </div>
 
-    <h2>Match History</h2>
+    <h2>Competition History</h2>
     <table>
         <tr>
             <th>Date</th>
             <th>Competition</th>
-            <th>Opponent</th>
-            <th>Result</th>
+            <th>Placement</th>
+            <th>Elo Before</th>
+            <th>Elo After</th>
             <th>Elo Change</th>
         </tr>
 """.format(self.clean_filename(team_name), team_name)
 
-        # Add rows for each match
-        for match in sorted(team_matches, key=lambda x: x['date'], reverse=True):
-            if match['team_a'] == team_name:
-                opponent = match['team_b']
-                old_elo = match['old_elo_a']
-                new_elo = match['new_elo_a']
-                result = "Win" if match['score_a'] > match['score_b'] else "Loss"
-            else:
-                opponent = match['team_a']
-                old_elo = match['old_elo_b']
-                new_elo = match['new_elo_b']
-                result = "Win" if match['score_b'] > match['score_a'] else "Loss"
-
-            elo_change = new_elo - old_elo
-            change_color = "green" if elo_change > 0 else "red"
+        # 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 ""
 
             html_content += f"""
         <tr>
-            <td>{match['date']}</td>
-            <td>{match['competition']}</td>
-            <td><a href="team_{self.clean_filename(opponent)}.html">{opponent}</a></td>
-            <td>{result}</td>
-            <td style="color: {change_color}">{'+' if elo_change > 0 else ''}{elo_change:.1f}</td>
+            <td>{comp['date']}</td>
+            <td>{comp['competition']}</td>
+            <td>{comp['rank']}</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>
         </tr>"""
 
         html_content += """
@@ -515,15 +539,15 @@ class EloSystem:
         team_history.sort(key=lambda x: x['date'])
 
         dates = [entry['date'] for entry in team_history]
-        elo_values = [entry['elo'] for entry in team_history]
+        elo_values = [entry['new_elo'] for entry in team_history]
 
         # Create line chart
         plt.plot(range(len(dates)), elo_values, marker='o', linestyle='-', color='blue')
 
         # Add competition labels
         for i, entry in enumerate(team_history):
-            plt.annotate(entry['competition'],
-                         (i, entry['elo']),
+            plt.annotate(entry['competition'] + f" (#{entry['rank']})",
+                         (i, entry['new_elo']),
                          textcoords="offset points",
                          xytext=(0, 10),
                          ha='center',
@@ -541,10 +565,6 @@ class EloSystem:
                     dpi=100)
         plt.close()
 
-    def count_competitions(self):
-        """Count the number of unique competitions"""
-        return len(set(match['competition'] for match in self.match_history))
-
     def clean_filename(self, filename):
         """Clean a string to make it suitable for use as a filename"""
         # Replace spaces and special characters
@@ -556,7 +576,7 @@ def main():
     import argparse
 
     parser = argparse.ArgumentParser(description='Process competition results and generate Elo rankings website')
-    parser.add_argument('--input', default='data', help='Directory containing CSV result files')
+    parser.add_argument('--input', default='csv_files', help='Directory containing CSV result files')
     parser.add_argument('--output', default='elo_website', help='Output directory for the website')
 
     args = parser.parse_args()
-- 
GitLab