Extended the code using Copilot with tons of cool features. Read the CHAT.md for what I asked and what it did
This commit is contained in:
+106
@@ -0,0 +1,106 @@
|
||||
"""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]
|
||||
|
||||
Reference in New Issue
Block a user