blackjack-theory-game/gui/components/stats.py
2026-06-13 22:10:39 +02:00

119 lines
5.1 KiB
Python
Executable File

import customtkinter as ctk
class StatsDisplay:
def __init__(self, parent):
self.parent = parent
self.stats_window = None
self.overlay = None
def _load_stats_content(self, window, stats):
"""Original stats content loading"""
for widget in window.winfo_children():
widget.destroy()
# Calculate accuracy (original logic)
total_decisions = stats["correct_decisions"] + stats["incorrect_decisions"]
accuracy = (stats["correct_decisions"] / total_decisions * 100) if total_decisions > 0 else 0
# Main stats display (original layout)
ctk.CTkLabel(window, text="Your Statistics", font=("Arial", 20, "bold")).pack(pady=10)
stats_frame = ctk.CTkFrame(window)
stats_frame.pack(pady=5, padx=10, fill="x")
ctk.CTkLabel(stats_frame, text=f"Total Rounds: {stats['total_rounds']}",
font=("Arial", 16)).pack(anchor="w", pady=2)
ctk.CTkLabel(stats_frame, text=f"Accuracy: {accuracy:.1f}%",
font=("Arial", 16)).pack(anchor="w", pady=2)
ctk.CTkLabel(stats_frame, text=f"Current Streak: {stats['current_streak']}",
font=("Arial", 16)).pack(anchor="w", pady=2)
ctk.CTkLabel(stats_frame, text=f"Longest Streak: {stats['longest_streak']}",
font=("Arial", 16)).pack(anchor="w", pady=2)
# Scenario breakdown (original implementation)
ctk.CTkLabel(window, text="Scenario Breakdown:",
font=("Arial", 16, "bold")).pack(pady=5)
scenario_frame = ctk.CTkFrame(window)
scenario_frame.pack(pady=5, padx=10, fill="x")
for scenario, data in stats["by_scenario"].items():
scenario_total = data["correct"] + data["incorrect"]
scenario_accuracy = (data["correct"] / scenario_total * 100) if scenario_total > 0 else 0
ctk.CTkLabel(
scenario_frame,
text=f"{scenario.replace('_', ' ').title()}: {data['correct']}/{scenario_total} ({scenario_accuracy:.1f}%)",
font=("Arial", 14)
).pack(anchor="w", pady=2)
def _show_final_stats(self, stats):
"""Original final stats window display"""
self.overlay = ctk.CTkFrame(self.parent, fg_color="black")
self.overlay.place(relwidth=1, relheight=1)
self.stats_window = ctk.CTkToplevel(self.parent)
self.stats_window.title("Session Results")
self.stats_window.geometry("500x600")
self.stats_window.overrideredirect(True)
self.stats_window.update_idletasks()
self.stats_window.grab_set()
# Original positioning
stats_x = self.parent.winfo_x() + (self.parent.winfo_width() - 500) // 2
stats_y = self.parent.winfo_y() + (self.parent.winfo_height() - 600) // 2
self.stats_window.geometry(f"+{stats_x}+{stats_y}")
self._load_stats_content(self.stats_window, stats)
# Original close button
ctk.CTkButton(
self.stats_window,
text="Close",
command=self._terminate_app,
font=("Arial", 16),
height=40,
fg_color="#2aa44f" # Professional green
).pack(pady=20, side="bottom", anchor="center")
self.stats_window.protocol("WM_DELETE_WINDOW", self._terminate_app)
def _show_exit_popup(self, stats, on_back_to_start):
"""Exit stats popup with back-to-start button"""
self.overlay = ctk.CTkFrame(self.parent, fg_color="black")
self.overlay.place(relwidth=1, relheight=1)
self.stats_window = ctk.CTkToplevel(self.parent)
self.stats_window.title("Session Results")
self.stats_window.geometry("500x600")
self.stats_window.overrideredirect(True)
self.stats_window.update_idletasks()
self.stats_window.grab_set()
stats_x = self.parent.winfo_x() + (self.parent.winfo_width() - 500) // 2
stats_y = self.parent.winfo_y() + (self.parent.winfo_height() - 600) // 2
self.stats_window.geometry(f"+{stats_x}+{stats_y}")
self._load_stats_content(self.stats_window, stats)
ctk.CTkButton(
self.stats_window,
text="Back to Start",
command=lambda: self._close_exit_popup(on_back_to_start),
font=("Arial", 16),
height=40,
fg_color="#2aa44f"
).pack(pady=20, side="bottom", anchor="center")
def _close_exit_popup(self, callback):
"""Close the exit popup and trigger callback"""
if self.overlay and self.overlay.winfo_exists():
self.overlay.destroy()
if hasattr(self, 'stats_window') and self.stats_window and self.stats_window.winfo_exists():
self.stats_window.destroy()
callback()
def _terminate_app(self):
"""Proper termination handling"""
if self.overlay and self.overlay.winfo_exists():
self.overlay.destroy()
if hasattr(self, 'stats_window') and self.stats_window and self.stats_window.winfo_exists():
self.stats_window.destroy()
self.parent.destroy()