Repository: Chelyocarpus/Delta-Force-Leaderboard
Pull request #58: ♻️🔥 Enhance and unify pie charts, improve code quality
Author: login: Chelyocarpus
Labels: name: Code Quality
description: Improvements could me made
Created: 2025-03-04T02:21:29Z | Merged: 2025-03-04T02:27:50Z

This pull request includes several changes to improve the formatting and functionality of pie charts across various tabs in the GUI, as well as some minor corrections and cleanup in the codebase.

### Chart Enhancements:

* [`src/gui/tabs/attacker_tab.py`](diffhunk://#diff-4f186482dd4c958198976deed97a36e1f3478ca0bad95882b82a749d5af3652bL4-R4): Enhanced the efficiency chart by creating a donut chart, improving slice colors, adding consistent styling, and better handling of null values. [[1]](diffhunk://#diff-4f186482dd4c958198976deed97a36e1f3478ca0bad95882b82a749d5af3652bL4-R4) [[2]](diffhunk://#diff-4f186482dd4c958198976deed97a36e1f3478ca0bad95882b82a749d5af3652bL50-R77) [[3]](diffhunk://#diff-4f186482dd4c958198976deed97a36e1f3478ca0bad95882b82a749d5af3652bL260-R279)
* [`src/gui/tabs/defender_tab.py`](diffhunk://#diff-2b05e74057ac62a1a016277ad31757fd7c3e101d464f893ff031007a5769367eL4-R4): Similar enhancements to the defender efficiency chart, including the creation of a donut chart, better slice colors, consistent styling, and improved handling of null values. [[1]](diffhunk://#diff-2b05e74057ac62a1a016277ad31757fd7c3e101d464f893ff031007a5769367eL4-R4) [[2]](diffhunk://#diff-2b05e74057ac62a1a016277ad31757fd7c3e101d464f893ff031007a5769367eR51-R77) [[3]](diffhunk://#diff-2b05e74057ac62a1a016277ad31757fd7c3e101d464f893ff031007a5769367eL216-R237)
* [`src/gui/tabs/map_tab.py`](diffhunk://#diff-11dcf81c2cb703f4a8e5ef43a035108c4c97975ebf665fb7e1261380ad905c8aL118-R142): Improved the wins chart by increasing the hole size for a better donut appearance, enhancing slice colors, and adding consistent styling.

### Code Cleanup:

* [`leaderboard.py`](diffhunk://#diff-5dfd9ceb0339d01dc694cd6bb36656b858dd39f3164b0c0f9fd4ac6609cb743bL169-L170): Removed unnecessary context menu setup and event handling for the table, simplifying the code. [[1]](diffhunk://#diff-5dfd9ceb0339d01dc694cd6bb36656b858dd39f3164b0c0f9fd4ac6609cb743bL169-L170) [[2]](diffhunk://#diff-5dfd9ceb0339d01dc694cd6bb36656b858dd39f3164b0c0f9fd4ac6609cb743bL437-L450)

### Minor Corrections:

* [`components/process_match_data.py`](diffhunk://#diff-6a0fd1198f27983152744c91bcc24c8119aebd0981b4f13aa8083f409e01bbd4R21-R22): Corrected typos in map names to ensure consistency.


Diff:
diff --git a/components/process_match_data.py b/components/process_match_data.py
index 6b4060a..68f4ded 100644
--- a/components/process_match_data.py
+++ b/components/process_match_data.py
@@ -18,6 +18,8 @@ class Config:
         "Trench ines-Attack and Defend": "Trench Lines - Attack and Defend",
         "Cracked-Attack and Defend": "Cracked - Attack and Defend",
         "Shatted - Attack and Detend": "Shafted - Attack and Defend",
+        "Knite Edge - Attack and Defend": "Knife Edge - Attack and Defend",
+        "Threshold - Attack and Detend": "Threshold - Attack and Defend",
     }
     
     OUTCOME_CORRECTIONS = {
diff --git a/leaderboard.py b/leaderboard.py
index a68b325..41b0c92 100644
--- a/leaderboard.py
+++ b/leaderboard.py
@@ -166,8 +166,6 @@ def setup_table(self):
         self.table.setEditTriggers(QTableWidget.NoEditTriggers)
         self.table.setSelectionBehavior(QTableWidget.SelectRows)
         self.table.setSelectionMode(QTableWidget.SingleSelection)
-        self.table.setContextMenuPolicy(Qt.DefaultContextMenu)
-        self.table.contextMenuEvent = self.tableContextMenuEvent
         self.table.itemClicked.connect(self.on_item_clicked)
         self.table.cellDoubleClicked.connect(self.on_row_double_clicked)
 
@@ -434,20 +432,6 @@ def eventFilter(self, source, event):
         # Remove delete key handling
         return super().eventFilter(source, event)
 
-    def tableContextMenuEvent(self, event):
-        context_menu = QMenu(self)
-        
-        # Keep only the selection actions
-        select_all_action = QAction("Select All", self)
-        select_all_action.triggered.connect(self.table.selectAll)
-        context_menu.addAction(select_all_action)
-        
-        clear_selection_action = QAction("Clear Selection", self)
-        clear_selection_action.triggered.connect(self.table.clearSelection)
-        context_menu.addAction(clear_selection_action)
-        
-        context_menu.exec_(event.globalPos())
-
     def on_snapshot_deleted(self, snapshot_name):
         """Handle snapshot deletion updates"""
         self.load_data_from_db()  # Always refresh the main window when a snapshot is deleted
diff --git a/src/gui/tabs/attacker_tab.py b/src/gui/tabs/attacker_tab.py
index 1a60bfe..7d646ba 100644
--- a/src/gui/tabs/attacker_tab.py
+++ b/src/gui/tabs/attacker_tab.py
@@ -1,7 +1,7 @@
 from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, 
                            QGridLayout, QLabel, QComboBox)
 from PyQt5.QtCore import Qt
-from PyQt5.QtGui import QPainter, QColor
+from PyQt5.QtGui import QPainter, QColor, QFont
 from PyQt5.QtChart import (QPieSeries, QChart, QChartView, QPieSlice)
 import sqlite3
 import logging
@@ -47,28 +47,34 @@ def create_efficiency_chart(self):
         layout = QHBoxLayout()
         layout.setContentsMargins(5, 5, 5, 5)
 
-        # Create pie chart for K/D ratio visualization
+        # Create pie series with hole to make it a donut
         self.efficiency_series = QPieSeries()
+        self.efficiency_series.setHoleSize(0.45)  # Set hole size for donut chart
         kills_slice = self.efficiency_series.append("Kills", 0)
         deaths_slice = self.efficiency_series.append("Deaths", 0)
 
-        # Style slices
-        kills_slice.setBrush(QColor(100, 200, 100))
-        deaths_slice.setBrush(QColor(200, 100, 100))
+        # Enhanced styling with better colors
+        kills_slice.setBrush(QColor(76, 175, 80))  # Vibrant green for kills
+        deaths_slice.setBrush(QColor(244, 67, 54))  # Vibrant red for deaths
         
+        # Style all slices consistently
         for slice in self.efficiency_series.slices():
             slice.setLabelVisible(True)
-            slice.setExploded(True)
-            slice.setExplodeDistanceFactor(0.1)
-            slice.setLabelPosition(QPieSlice.LabelOutside)
+            slice.setExploded(False)  # Disable explosion for cleaner donut look
+            slice.setLabelPosition(QPieSlice.LabelOutside)  # Place labels outside
+            slice.setLabelArmLengthFactor(0.15)  # Shorter arm length for cleaner appearance
+            slice.setLabelFont(QFont("Arial", 9, QFont.Bold))  # Bold font for labels
+            slice.setPen(QColor(240, 240, 240))  # Light border between slices
 
+        # Create and configure chart
         chart = QChart()
         chart.addSeries(self.efficiency_series)
         chart.setAnimationOptions(QChart.SeriesAnimations)
-        chart.legend().setVisible(False)
+        chart.legend().setVisible(False)  # Hide legend as we have labels
         chart.setBackgroundVisible(False)
         chart.setMinimumSize(300, 200)
 
+        # Create chart view with antialiasing
         chart_view = QChartView(chart)
         chart_view.setRenderHint(QPainter.Antialiasing)
         chart_view.setMinimumHeight(200)
@@ -257,12 +263,20 @@ def update_stats(self, map_name=None):
                 for key, value in stat_updates.items():
                     self.stat_labels[key].setText(value)
 
-                # Update chart values
-                total_kills, total_deaths = stats[-2], stats[-1]
-                self.efficiency_series.slices()[0].setValue(total_kills or 0)
-                self.efficiency_series.slices()[1].setValue(total_deaths or 0)
-                self.efficiency_series.slices()[0].setLabel(f"Kills ({total_kills or 0})")
-                self.efficiency_series.slices()[1].setLabel(f"Deaths ({total_deaths or 0})")
+                # Update chart values with improved handling of null values
+                total_kills = stats[-2] or 0
+                total_deaths = stats[-1] or 0
+                
+                # Update pie slices with values and formatted labels
+                self.efficiency_series.slices()[0].setValue(total_kills)
+                self.efficiency_series.slices()[1].setValue(total_deaths)
+                self.efficiency_series.slices()[0].setLabel(f"Kills ({total_kills:,})")
+                self.efficiency_series.slices()[1].setLabel(f"Deaths ({total_deaths:,})")
+                
+                # If both values are zero, set some minimum values to avoid empty chart
+                if total_kills == 0 and total_deaths == 0:
+                    self.efficiency_series.slices()[0].setValue(1)
+                    self.efficiency_series.slices()[1].setValue(1)
 
         # Re-enable UI updates
         self.setUpdatesEnabled(True)
diff --git a/src/gui/tabs/defender_tab.py b/src/gui/tabs/defender_tab.py
index 0a0d201..f65a970 100644
--- a/src/gui/tabs/defender_tab.py
+++ b/src/gui/tabs/defender_tab.py
@@ -1,7 +1,7 @@
 from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, 
                            QGridLayout, QLabel, QComboBox)
 from PyQt5.QtCore import Qt
-from PyQt5.QtGui import QPainter, QColor
+from PyQt5.QtGui import QPainter, QColor, QFont
 from PyQt5.QtChart import (QPieSeries, QChart, QChartView, QPieSlice)
 import sqlite3
 import logging
@@ -48,26 +48,33 @@ def create_efficiency_chart(self):
         layout.setContentsMargins(5, 5, 5, 5)
 
         self.efficiency_series = QPieSeries()
+        self.efficiency_series.setHoleSize(0.45)  # Set hole size to create donut chart
         kills_slice = self.efficiency_series.append("Kills", 0)
         deaths_slice = self.efficiency_series.append("Deaths", 0)
 
-        # Style slices
+        # Enhanced styling with better colors
+        kills_slice.setBrush(QColor(76, 175, 80))  # Vibrant green for kills
+        deaths_slice.setBrush(QColor(244, 67, 54))  # Vibrant red for deaths
+        
+        # Style all slices
         for pie_slice in self.efficiency_series.slices():
             pie_slice.setLabelVisible(True)
-            pie_slice.setExploded(True)
-            pie_slice.setExplodeDistanceFactor(0.1)
-            pie_slice.setLabelPosition(QPieSlice.LabelOutside)
-
-        kills_slice.setBrush(QColor(100, 200, 100))
-        deaths_slice.setBrush(QColor(200, 100, 100))
+            pie_slice.setExploded(False)  # Disable explosion for cleaner donut
+            pie_slice.setLabelPosition(QPieSlice.LabelOutside)  # Place labels outside
+            pie_slice.setLabelArmLengthFactor(0.15)  # Shorter arm length
+            pie_slice.setLabelFont(QFont("Arial", 9, QFont.Bold))  # Bold font for better visibility
+            pie_slice.setPen(QColor(240, 240, 240))  # Light border between slices
 
+        # Create and configure chart
         chart = QChart()
         chart.addSeries(self.efficiency_series)
         chart.setAnimationOptions(QChart.SeriesAnimations)
-        chart.legend().setVisible(False)
+        chart.legend().setVisible(False)  # Hide legend as we have labels
         chart.setBackgroundVisible(False)
         chart.setMinimumSize(300, 200)
+        chart.setTitle("") # Remove title as we have the group box title
 
+        # Create chart view with antialiasing
         chart_view = QChartView(chart)
         chart_view.setRenderHint(QPainter.Antialiasing)
         chart_view.setMinimumHeight(200)
@@ -213,13 +220,21 @@ def get_stats_query(self, map_name):
         return query, query_params
 
     def update_chart(self, kills, deaths):
-        for idx, (value, label) in enumerate([
-            (kills, f"Kills ({kills or 0})"),
-            (deaths, f"Deaths ({deaths or 0})")
-        ]):
-            pie_slice = self.efficiency_series.slices()[idx]
-            pie_slice.setValue(value)
-            pie_slice.setLabel(label)
+        kills = kills or 0
+        deaths = deaths or 0
+        
+        # Update pie slices with values and labels
+        self.efficiency_series.slices()[0].setValue(kills)
+        self.efficiency_series.slices()[1].setValue(deaths)
+        
+        # Update labels with count information
+        self.efficiency_series.slices()[0].setLabel(f"Kills ({kills:,})")
+        self.efficiency_series.slices()[1].setLabel(f"Deaths ({deaths:,})")
+        
+        # If both values are zero, set some minimum values to avoid empty chart
+        if kills == 0 and deaths == 0:
+            self.efficiency_series.slices()[0].setValue(1)
+            self.efficiency_series.slices()[1].setValue(1)
 
     def update_stat_labels(self, stats):
         column_names = list(self.stat_labels.keys())
diff --git a/src/gui/tabs/map_tab.py b/src/gui/tabs/map_tab.py
index 1383f5d..b3f9ad7 100644
--- a/src/gui/tabs/map_tab.py
+++ b/src/gui/tabs/map_tab.py
@@ -115,33 +115,31 @@ def create_wins_chart(self):
 
         # Create pie series and set hole size for donut
         self.pie_series = QPieSeries()
-        self.pie_series.setHoleSize(0.35)
+        self.pie_series.setHoleSize(0.45)  # Increased hole size for better donut appearance
         victory_slice = self.pie_series.append("Victories", 0)
         defeat_slice = self.pie_series.append("Defeats", 0)
 
-        # Style the donut slices
-        victory_slice.setBrush(QColor(100, 200, 100))
-        defeat_slice.setBrush(QColor(200, 100, 100))
+        # Style the donut slices with more vibrant colors
+        victory_slice.setBrush(QColor(76, 175, 80))  # More vibrant green
+        defeat_slice.setBrush(QColor(244, 67, 54))   # More vibrant red
         
         # Set new label properties for each slice
         for slice in self.pie_series.slices():
             slice.setLabelVisible(True)
-            slice.setExploded(True)
-            slice.setExplodeDistanceFactor(0.1)
-            # Changed label arm behavior
-            slice.setLabelArmLengthFactor(0.2)  # Shorter arms
-            slice.setLabelPosition(QPieSlice.LabelInsideNormal)  # Start labels inside
-            # Use horizontal arms instead of angled
-            slice.setLabelPosition(QPieSlice.LabelInsideHorizontal)
+            slice.setExploded(False)  # Disable exploded slices for cleaner donut look
+            slice.setLabelPosition(QPieSlice.LabelOutside)  # Position labels outside
+            slice.setLabelArmLengthFactor(0.15)  # Shorter arms for cleaner look
+            slice.setLabelFont(QFont("Arial", 9, QFont.Bold))  # Add bold font to labels
+            slice.setPen(QColor(240, 240, 240))  # Add light border between slices
 
         chart = QChart()
         chart.addSeries(self.pie_series)
         chart.setAnimationOptions(QChart.SeriesAnimations)
-        chart.legend().setVisible(False)
+        chart.legend().setVisible(False)  # Hide legend since we have labels
         chart.setBackgroundVisible(False)
-        chart.setMinimumSize(300, 200)  # Set minimum size to prevent squishing
+        chart.setMinimumSize(300, 200)
 
-        # Create chart view
+        # Create chart view with antialiasing for smoother edges
         chart_view = QChartView(chart)
         chart_view.setRenderHint(QPainter.Antialiasing)
         chart_view.setMinimumHeight(200)


Reviews:
user: login: sourcery-ai[bot]
body: Hey @Chelyocarpus - I've reviewed your changes - here's some feedback:

**Overall Comments**:
- It looks like you've duplicated the chart styling code across multiple files; consider creating a reusable component or function.
- The formatting of numbers in the chart labels could be improved by using f-strings with appropriate precision.

<details>
<summary>Here's what I looked at during the review</summary>

- 🟡 **General issues**: 1 issue found
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟡 **Complexity**: 2 issues found
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T02:22:39Z

Review comments:
diff_hunk: @@ -48,26 +48,33 @@ def create_efficiency_chart(self):
         layout.setContentsMargins(5, 5, 5, 5)
 
         self.efficiency_series = QPieSeries()
+        self.efficiency_series.setHoleSize(0.45)  # Set hole size to create donut chart
         kills_slice = self.efficiency_series.append("Kills", 0)
         deaths_slice = self.efficiency_series.append("Deaths", 0)
 
-        # Style slices
+        # Enhanced styling with better colors
+        kills_slice.setBrush(QColor(76, 175, 80))  # Vibrant green for kills
+        deaths_slice.setBrush(QColor(244, 67, 54))  # Vibrant red for deaths
+        
+        # Style all slices
         for pie_slice in self.efficiency_series.slices():
             pie_slice.setLabelVisible(True)
-            pie_slice.setExploded(True)
-            pie_slice.setExplodeDistanceFactor(0.1)
-            pie_slice.setLabelPosition(QPieSlice.LabelOutside)
-
-        kills_slice.setBrush(QColor(100, 200, 100))
-        deaths_slice.setBrush(QColor(200, 100, 100))
+            pie_slice.setExploded(False)  # Disable explosion for cleaner donut
+            pie_slice.setLabelPosition(QPieSlice.LabelOutside)  # Place labels outside
+            pie_slice.setLabelArmLengthFactor(0.15)  # Shorter arm length
+            pie_slice.setLabelFont(QFont("Arial", 9, QFont.Bold))  # Bold font for better visibility
+            pie_slice.setPen(QColor(240, 240, 240))  # Light border between slices
path: src/gui/tabs/defender_tab.py
user: login: sourcery-ai[bot]
body: **suggestion:** Consider centralizing styling configurations for pie slices.

The updated styling (e.g., font, arm length, border color) is repeated in multiple files. Consolidating these into a shared helper or configuration might help maintain consistency and simplify future changes.
created_at: 2025-03-04T02:22:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -48,26 +48,33 @@ def create_efficiency_chart(self):
         layout.setContentsMargins(5, 5, 5, 5)
 
         self.efficiency_series = QPieSeries()
+        self.efficiency_series.setHoleSize(0.45)  # Set hole size to create donut chart
         kills_slice = self.efficiency_series.append("Kills", 0)
         deaths_slice = self.efficiency_series.append("Deaths", 0)
 
-        # Style slices
+        # Enhanced styling with better colors
+        kills_slice.setBrush(QColor(76, 175, 80))  # Vibrant green for kills
+        deaths_slice.setBrush(QColor(244, 67, 54))  # Vibrant red for deaths
+        
+        # Style all slices
         for pie_slice in self.efficiency_series.slices():
path: src/gui/tabs/defender_tab.py
user: login: sourcery-ai[bot]
body: **issue (complexity):** Consider extracting the pie slice configuration logic into a helper function to reduce code duplication and improve maintainability of styling details.

Consider extracting the repeated pie slice configuration logic into helper functions. This not only reduces the number of duplicated lines but also isolates styling details for easier future adjustments. For example:

```python
def configure_pie_slice(pie_slice, exploded=False, label_font=("Arial", 9, QFont.Bold)):
    pie_slice.setLabelVisible(True)
    pie_slice.setExploded(exploded)
    pie_slice.setLabelPosition(QPieSlice.LabelOutside)
    pie_slice.setLabelArmLengthFactor(0.15)
    pie_slice.setLabelFont(QFont(*label_font))
    pie_slice.setPen(QColor(240, 240, 240))
```

In your `create_efficiency_chart` method, replace the inline slice styling:

```python
# Style all slices using helper
for pie_slice in self.efficiency_series.slices():
    configure_pie_slice(pie_slice, exploded=False)
```

This way, if additional styling changes are needed, you can modify the helper function instead of updating multiple methods.
created_at: 2025-03-04T02:22:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -47,28 +47,34 @@ def create_efficiency_chart(self):
         layout = QHBoxLayout()
         layout.setContentsMargins(5, 5, 5, 5)
 
-        # Create pie chart for K/D ratio visualization
+        # Create pie series with hole to make it a donut
         self.efficiency_series = QPieSeries()
+        self.efficiency_series.setHoleSize(0.45)  # Set hole size for donut chart
         kills_slice = self.efficiency_series.append("Kills", 0)
         deaths_slice = self.efficiency_series.append("Deaths", 0)
 
-        # Style slices
-        kills_slice.setBrush(QColor(100, 200, 100))
-        deaths_slice.setBrush(QColor(200, 100, 100))
+        # Enhanced styling with better colors
+        kills_slice.setBrush(QColor(76, 175, 80))  # Vibrant green for kills
+        deaths_slice.setBrush(QColor(244, 67, 54))  # Vibrant red for deaths
         
+        # Style all slices consistently
path: src/gui/tabs/attacker_tab.py
user: login: sourcery-ai[bot]
body: **issue (complexity):** Consider extracting the slice styling and series configuration into helper functions or a common base class to reduce code duplication between tabs and improve maintainability by reusing the same logic for both attacker and defender configurations, such as extracting a style_pie_slice helper function and applying it to each slice in the series creation..

Consider extracting the repeated slice styling and series configuration into helper functions (or even a common base class) so that both tabs can reuse the same logic. This refactoring can reduce differences between the attacker and defender configurations while keeping functionality intact.

For example, you might extract a slice styling helper like:

```python
def style_pie_slice(pie_slice, exploded=False):
    pie_slice.setLabelVisible(True)
    pie_slice.setExploded(exploded)
    pie_slice.setLabelPosition(QPieSlice.LabelOutside)
    pie_slice.setLabelArmLengthFactor(0.15)
    pie_slice.setLabelFont(QFont("Arial", 9, QFont.Bold))
    pie_slice.setPen(QColor(240, 240, 240))
```

Then update your series creation like:

```python
self.efficiency_series = QPieSeries()
self.efficiency_series.setHoleSize(0.45)  # donut chart

kills_slice = self.efficiency_series.append("Kills", 0)
kills_slice.setBrush(QColor(76, 175, 80))

deaths_slice = self.efficiency_series.append("Deaths", 0)
deaths_slice.setBrush(QColor(244, 67, 54))

for slice in self.efficiency_series.slices():
    style_pie_slice(slice, exploded=False)
```

Applying similar refactoring in the defender tab will help reduce duplication and simplify future maintenance.
created_at: 2025-03-04T02:22:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -47,28 +47,34 @@ def create_efficiency_chart(self):
         layout = QHBoxLayout()
         layout.setContentsMargins(5, 5, 5, 5)
 
-        # Create pie chart for K/D ratio visualization
+        # Create pie series with hole to make it a donut
         self.efficiency_series = QPieSeries()
+        self.efficiency_series.setHoleSize(0.45)  # Set hole size for donut chart
         kills_slice = self.efficiency_series.append("Kills", 0)
         deaths_slice = self.efficiency_series.append("Deaths", 0)
 
-        # Style slices
-        kills_slice.setBrush(QColor(100, 200, 100))
-        deaths_slice.setBrush(QColor(200, 100, 100))
+        # Enhanced styling with better colors
+        kills_slice.setBrush(QColor(76, 175, 80))  # Vibrant green for kills
+        deaths_slice.setBrush(QColor(244, 67, 54))  # Vibrant red for deaths
         
+        # Style all slices consistently
         for slice in self.efficiency_series.slices():
             slice.setLabelVisible(True)
-            slice.setExploded(True)
-            slice.setExplodeDistanceFactor(0.1)
-            slice.setLabelPosition(QPieSlice.LabelOutside)
+            slice.setExploded(False)  # Disable explosion for cleaner donut look
+            slice.setLabelPosition(QPieSlice.LabelOutside)  # Place labels outside
+            slice.setLabelArmLengthFactor(0.15)  # Shorter arm length for cleaner appearance
+            slice.setLabelFont(QFont("Arial", 9, QFont.Bold))  # Bold font for labels
+            slice.setPen(QColor(240, 240, 240))  # Light border between slices
path: src/gui/tabs/attacker_tab.py
user: login: sourcery-ai[bot]
body: **issue (code-quality):** Extract code out into method ([`extract-method`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/extract-method/))
created_at: 2025-03-04T02:22:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -48,26 +48,33 @@ def create_efficiency_chart(self):
         layout.setContentsMargins(5, 5, 5, 5)
 
         self.efficiency_series = QPieSeries()
+        self.efficiency_series.setHoleSize(0.45)  # Set hole size to create donut chart
         kills_slice = self.efficiency_series.append("Kills", 0)
         deaths_slice = self.efficiency_series.append("Deaths", 0)
 
-        # Style slices
+        # Enhanced styling with better colors
+        kills_slice.setBrush(QColor(76, 175, 80))  # Vibrant green for kills
+        deaths_slice.setBrush(QColor(244, 67, 54))  # Vibrant red for deaths
+        
+        # Style all slices
         for pie_slice in self.efficiency_series.slices():
             pie_slice.setLabelVisible(True)
-            pie_slice.setExploded(True)
-            pie_slice.setExplodeDistanceFactor(0.1)
-            pie_slice.setLabelPosition(QPieSlice.LabelOutside)
-
-        kills_slice.setBrush(QColor(100, 200, 100))
-        deaths_slice.setBrush(QColor(200, 100, 100))
+            pie_slice.setExploded(False)  # Disable explosion for cleaner donut
+            pie_slice.setLabelPosition(QPieSlice.LabelOutside)  # Place labels outside
+            pie_slice.setLabelArmLengthFactor(0.15)  # Shorter arm length
+            pie_slice.setLabelFont(QFont("Arial", 9, QFont.Bold))  # Bold font for better visibility
+            pie_slice.setPen(QColor(240, 240, 240))  # Light border between slices
path: src/gui/tabs/defender_tab.py
user: login: sourcery-ai[bot]
body: **issue (code-quality):** Extract code out into method ([`extract-method`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/extract-method/))
created_at: 2025-03-04T02:22:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -115,33 +115,31 @@ def create_wins_chart(self):
 
         # Create pie series and set hole size for donut
         self.pie_series = QPieSeries()
-        self.pie_series.setHoleSize(0.35)
+        self.pie_series.setHoleSize(0.45)  # Increased hole size for better donut appearance
         victory_slice = self.pie_series.append("Victories", 0)
         defeat_slice = self.pie_series.append("Defeats", 0)
 
-        # Style the donut slices
-        victory_slice.setBrush(QColor(100, 200, 100))
-        defeat_slice.setBrush(QColor(200, 100, 100))
+        # Style the donut slices with more vibrant colors
+        victory_slice.setBrush(QColor(76, 175, 80))  # More vibrant green
+        defeat_slice.setBrush(QColor(244, 67, 54))   # More vibrant red
         
         # Set new label properties for each slice
         for slice in self.pie_series.slices():
             slice.setLabelVisible(True)
-            slice.setExploded(True)
-            slice.setExplodeDistanceFactor(0.1)
-            # Changed label arm behavior
-            slice.setLabelArmLengthFactor(0.2)  # Shorter arms
-            slice.setLabelPosition(QPieSlice.LabelInsideNormal)  # Start labels inside
-            # Use horizontal arms instead of angled
-            slice.setLabelPosition(QPieSlice.LabelInsideHorizontal)
+            slice.setExploded(False)  # Disable exploded slices for cleaner donut look
+            slice.setLabelPosition(QPieSlice.LabelOutside)  # Position labels outside
+            slice.setLabelArmLengthFactor(0.15)  # Shorter arms for cleaner look
+            slice.setLabelFont(QFont("Arial", 9, QFont.Bold))  # Add bold font to labels
+            slice.setPen(QColor(240, 240, 240))  # Add light border between slices
path: src/gui/tabs/map_tab.py
user: login: sourcery-ai[bot]
body: **issue (code-quality):** Extract code out into method ([`extract-method`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/extract-method/))
created_at: 2025-03-04T02:22:39Z
author_association: CONTRIBUTOR

PR comments:
user: login: sourcery-ai[bot]
created_at: 2025-03-04T02:21:33Z
body: <!-- Generated by sourcery-ai[bot]: start review_guide -->

## Reviewer's Guide by Sourcery

This pull request improves the pie charts by converting them to donut charts with enhanced styling and data handling. It also includes code cleanup by removing unnecessary context menu functionality from the leaderboard table and corrects typos in map names.

_No diagrams generated as the changes look simple and do not need a visual representation._

### File-Level Changes

| Change | Details | Files |
| ------ | ------- | ----- |
| Enhanced pie charts to donut charts with improved styling and data handling across multiple tabs. | <ul><li>Converted pie charts to donut charts by adjusting the hole size.</li><li>Improved slice colors for better visual representation.</li><li>Implemented consistent styling across all donut charts.</li><li>Enhanced handling of null values to prevent empty charts.</li><li>Added bold font to labels for better visibility.</li><li>Added light borders between slices for better separation.</li></ul> | `src/gui/tabs/attacker_tab.py`<br/>`src/gui/tabs/defender_tab.py`<br/>`src/gui/tabs/map_tab.py` |
| Removed unnecessary context menu setup and event handling from the leaderboard table. | <ul><li>Removed the context menu policy setting.</li><li>Removed the custom context menu event handler.</li><li>Simplified the table interaction by removing context menu options.</li></ul> | `leaderboard.py` |
| Corrected typos in map names to ensure consistency. | <ul><li>Corrected 'Shatted - Attack and Detend' to 'Shafted - Attack and Defend'.</li><li>Corrected 'Knite Edge - Attack and Defend' to 'Knife Edge - Attack and Defend'.</li><li>Corrected 'Threshold - Attack and Detend' to 'Threshold - Attack and Defend'.</li></ul> | `components/process_match_data.py` |

---

<details>
<summary>Tips and commands</summary>

#### Interacting with Sourcery

- **Trigger a new review:** Comment `@sourcery-ai review` on the pull request.
- **Continue discussions:** Reply directly to Sourcery's review comments.
- **Generate a GitHub issue from a review comment:** Ask Sourcery to create an
  issue from a review comment by replying to it. You can also reply to a
  review comment with `@sourcery-ai issue` to create an issue from it.
- **Generate a pull request title:** Write `@sourcery-ai` anywhere in the pull
  request title to generate a title at any time. You can also comment
  `@sourcery-ai title` on the pull request to (re-)generate the title at any time.
- **Generate a pull request summary:** Write `@sourcery-ai summary` anywhere in
  the pull request body to generate a PR summary at any time exactly where you
  want it. You can also comment `@sourcery-ai summary` on the pull request to
  (re-)generate the summary at any time.
- **Generate reviewer's guide:** Comment `@sourcery-ai guide` on the pull
  request to (re-)generate the reviewer's guide at any time.
- **Resolve all Sourcery comments:** Comment `@sourcery-ai resolve` on the
  pull request to resolve all Sourcery comments. Useful if you've already
  addressed all the comments and don't want to see them anymore.
- **Dismiss all Sourcery reviews:** Comment `@sourcery-ai dismiss` on the pull
  request to dismiss all existing Sourcery reviews. Especially useful if you
  want to start fresh with a new review - don't forget to comment
  `@sourcery-ai review` to trigger a new review!
- **Generate a plan of action for an issue:** Comment `@sourcery-ai plan` on
  an issue to generate a plan of action for it.

#### Customizing Your Experience

Access your [dashboard](https://app.sourcery.ai) to:
- Enable or disable review features such as the Sourcery-generated pull request
  summary, the reviewer's guide, and others.
- Change the review language.
- Add, remove or edit custom review instructions.
- Adjust other review settings.

#### Getting Help

- [Contact our support team](mailto:support@sourcery.ai) for questions or feedback.
- Visit our [documentation](https://docs.sourcery.ai) for detailed guides and information.
- Keep in touch with the Sourcery team by following us on [X/Twitter](https://x.com/SourceryAI), [LinkedIn](https://www.linkedin.com/company/sourcery-ai/) or [GitHub](https://github.com/sourcery-ai).

</details>

<!-- Generated by sourcery-ai[bot]: end review_guide -->
author_association: CONTRIBUTOR
user: login: Chelyocarpus
created_at: 2025-03-04T02:26:01Z
body: @sourcery-ai title
author_association: OWNER