Huge refactor of the libstormgames library. It is hopefully mostly backwards compatible. Still lots of testing to do, and probably some fixes needed, but this is a good start.
This commit is contained in:
176
scoreboard.py
Normal file
176
scoreboard.py
Normal file
@ -0,0 +1,176 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Scoreboard handling for Storm Games.
|
||||
|
||||
Provides functionality for:
|
||||
- Tracking high scores with player names
|
||||
- Saving/loading high scores from configuration
|
||||
"""
|
||||
|
||||
import time
|
||||
from .services import ConfigService
|
||||
from .speech import Speech
|
||||
|
||||
# For backward compatibility
|
||||
from .config import localConfig, write_config, read_config
|
||||
|
||||
class Scoreboard:
|
||||
"""Handles high score tracking with player names."""
|
||||
|
||||
def __init__(self, score=0, config_service=None, speech=None):
|
||||
"""Initialize scoreboard.
|
||||
|
||||
Args:
|
||||
score (int): Initial score (default: 0)
|
||||
config_service (ConfigService): Config service (default: global instance)
|
||||
speech (Speech): Speech system (default: global instance)
|
||||
"""
|
||||
self.config_service = config_service or ConfigService.get_instance()
|
||||
self.speech = speech or Speech.get_instance()
|
||||
self.current_score = score
|
||||
self.high_scores = []
|
||||
|
||||
# For backward compatibility
|
||||
read_config()
|
||||
|
||||
try:
|
||||
# Try to use config_service
|
||||
self.config_service.local_config.add_section("scoreboard")
|
||||
except:
|
||||
# Fallback to old method
|
||||
try:
|
||||
localConfig.add_section("scoreboard")
|
||||
except:
|
||||
pass
|
||||
|
||||
# Load existing high scores
|
||||
for i in range(1, 11):
|
||||
try:
|
||||
# Try to use config_service
|
||||
score = self.config_service.local_config.getint("scoreboard", f"score_{i}")
|
||||
name = self.config_service.local_config.get("scoreboard", f"name_{i}")
|
||||
self.high_scores.append({
|
||||
'name': name,
|
||||
'score': score
|
||||
})
|
||||
except:
|
||||
# Fallback to old method
|
||||
try:
|
||||
score = localConfig.getint("scoreboard", f"score_{i}")
|
||||
name = localConfig.get("scoreboard", f"name_{i}")
|
||||
self.high_scores.append({
|
||||
'name': name,
|
||||
'score': score
|
||||
})
|
||||
except:
|
||||
self.high_scores.append({
|
||||
'name': "Player",
|
||||
'score': 0
|
||||
})
|
||||
|
||||
# Sort high scores by score value in descending order
|
||||
self.high_scores.sort(key=lambda x: x['score'], reverse=True)
|
||||
|
||||
def get_score(self):
|
||||
"""Get current score."""
|
||||
return self.current_score
|
||||
|
||||
def get_high_scores(self):
|
||||
"""Get list of high scores."""
|
||||
return self.high_scores
|
||||
|
||||
def decrease_score(self, points=1):
|
||||
"""Decrease the current score."""
|
||||
self.current_score -= int(points)
|
||||
return self
|
||||
|
||||
def increase_score(self, points=1):
|
||||
"""Increase the current score."""
|
||||
self.current_score += int(points)
|
||||
return self
|
||||
|
||||
def set_score(self, score):
|
||||
"""Set the current score to a specific value."""
|
||||
self.current_score = int(score)
|
||||
return self
|
||||
|
||||
def reset_score(self):
|
||||
"""Reset the current score to zero."""
|
||||
self.current_score = 0
|
||||
return self
|
||||
|
||||
def check_high_score(self):
|
||||
"""Check if current score qualifies as a high score.
|
||||
|
||||
Returns:
|
||||
int: Position (1-10) if high score, None if not
|
||||
"""
|
||||
for i, entry in enumerate(self.high_scores):
|
||||
if self.current_score > entry['score']:
|
||||
return i + 1
|
||||
return None
|
||||
|
||||
def add_high_score(self, name=None):
|
||||
"""Add current score to high scores if it qualifies.
|
||||
|
||||
Args:
|
||||
name (str): Player name (if None, will prompt user)
|
||||
|
||||
Returns:
|
||||
bool: True if score was added, False if not
|
||||
"""
|
||||
position = self.check_high_score()
|
||||
if position is None:
|
||||
return False
|
||||
|
||||
# Get player name
|
||||
if name is None:
|
||||
# Import get_input here to avoid circular imports
|
||||
from .input import get_input
|
||||
name = get_input("New high score! Enter your name:", "Player")
|
||||
if name is None: # User cancelled
|
||||
name = "Player"
|
||||
|
||||
# Insert new score at correct position
|
||||
self.high_scores.insert(position - 1, {
|
||||
'name': name,
|
||||
'score': self.current_score
|
||||
})
|
||||
|
||||
# Keep only top 10
|
||||
self.high_scores = self.high_scores[:10]
|
||||
|
||||
# Save to config - try both methods for maximum compatibility
|
||||
try:
|
||||
# Try new method first
|
||||
for i, entry in enumerate(self.high_scores):
|
||||
self.config_service.local_config.set("scoreboard", f"score_{i+1}", str(entry['score']))
|
||||
self.config_service.local_config.set("scoreboard", f"name_{i+1}", entry['name'])
|
||||
|
||||
# Try to write with config_service
|
||||
try:
|
||||
self.config_service.write_local_config()
|
||||
except Exception as e:
|
||||
# Fallback to old method if config_service fails
|
||||
for i, entry in enumerate(self.high_scores):
|
||||
localConfig.set("scoreboard", f"score_{i+1}", str(entry['score']))
|
||||
localConfig.set("scoreboard", f"name_{i+1}", entry['name'])
|
||||
write_config()
|
||||
|
||||
except Exception as e:
|
||||
# If all else fails, try direct old method
|
||||
for i, entry in enumerate(self.high_scores):
|
||||
localConfig.set("scoreboard", f"score_{i+1}", str(entry['score']))
|
||||
localConfig.set("scoreboard", f"name_{i+1}", entry['name'])
|
||||
write_config()
|
||||
|
||||
# Announce success
|
||||
try:
|
||||
self.speech.messagebox(f"Congratulations {name}! You got position {position} on the scoreboard!")
|
||||
except:
|
||||
# Fallback to global speak function
|
||||
from .speech import speak
|
||||
speak(f"Congratulations {name}! You got position {position} on the scoreboard!")
|
||||
|
||||
time.sleep(1)
|
||||
return True
|
Reference in New Issue
Block a user