"""High score and game statistics management.""" import json from pathlib import Path from typing import Optional, Dict, List from dataclasses import dataclass, asdict from datetime import datetime @dataclass class GameRecord: """A single game record.""" player_name: str score: int length: int speed: int timestamp: str @classmethod def from_dict(cls, data: dict) -> 'GameRecord': return cls(**data) def to_dict(self) -> dict: return asdict(self) class HighScoreManager: """Manages high scores and game statistics by player.""" def __init__(self): self.scores_file = Path.home() / '.snake_scores.json' self.game_records: List[GameRecord] = [] self.load_scores() def load_scores(self) -> None: """Load scores from file.""" if self.scores_file.exists(): try: with open(self.scores_file, 'r') as f: data = json.load(f) self.game_records = [GameRecord.from_dict(r) for r in data.get('records', [])] except (json.JSONDecodeError, IOError): self.game_records = [] else: self.game_records = [] def save_game(self, player_name: str, score: int, length: int, speed: int) -> None: """Save a completed game.""" record = GameRecord( player_name=player_name, score=score, length=length, speed=speed, timestamp=datetime.now().isoformat() ) self.game_records.append(record) self._save_to_file() def _save_to_file(self) -> None: """Save scores to file.""" try: with open(self.scores_file, 'w') as f: json.dump({ 'records': [r.to_dict() for r in self.game_records] }, f, indent=2) except IOError as e: print(f"Warning: Could not save scores: {e}") def get_player_stats(self, player_name: str) -> dict: """Get game statistics for a specific player.""" player_records = [r for r in self.game_records if r.player_name == player_name] if not player_records: return { 'total_games': 0, 'high_score': 0, 'average_score': 0, 'total_length': 0, } scores = [r.score for r in player_records] return { 'total_games': len(player_records), 'high_score': max(scores), 'average_score': sum(scores) // len(scores), 'total_length': sum(r.length for r in player_records), } def get_all_stats(self) -> Dict[str, dict]: """Get statistics for all players.""" player_names = set(r.player_name for r in self.game_records) return {name: self.get_player_stats(name) for name in player_names} def get_leaderboard(self, limit: int = 10) -> List[tuple]: """Get top scores across all players.""" # Group by player and get their best score player_best_scores = {} for record in self.game_records: if record.player_name not in player_best_scores: player_best_scores[record.player_name] = record.score else: player_best_scores[record.player_name] = max(player_best_scores[record.player_name], record.score) # Sort by score descending sorted_scores = sorted(player_best_scores.items(), key=lambda x: x[1], reverse=True) return sorted_scores[:limit]