Sound System: - Add soundStore with volume/mute persistence - Add useSound hook with Web Audio API fallback - Add SoundControl component for in-game volume adjustment - Play sounds for correct/incorrect, steal, timer, victory/defeat Team Chat: - Add TeamChat component with collapsible panel - Add team_message WebSocket event (team-only visibility) - Store up to 50 messages per session Emoji Reactions: - Add EmojiReactions bar with 8 emojis - Add ReactionOverlay with floating animations (Framer Motion) - Add rate limiting (1 reaction per 3 seconds) - Broadcast reactions to all players in room Admin Monitor: - Add Monitor page showing active rooms from Redis - Display player counts, team composition, status - Add ability to close problematic rooms Admin Settings: - Add Settings page for game configuration - Configure points/times by difficulty, steal penalty, max players - Store config in JSON file with service helpers CSV Import/Export: - Add export endpoint with optional filters - Add import endpoint with validation and error reporting - Add UI buttons and import result modal in Questions page Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
79 lines
2.4 KiB
Python
79 lines
2.4 KiB
Python
"""Service for managing dynamic game configuration."""
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Dict, Any
|
|
|
|
from app.schemas.game_config import GameSettingsSchema
|
|
|
|
|
|
# Path to the config file
|
|
CONFIG_FILE = Path(__file__).parent.parent / "data" / "config.json"
|
|
|
|
# Default configuration
|
|
DEFAULT_CONFIG: Dict[str, Any] = {
|
|
"points_by_difficulty": {"1": 100, "2": 200, "3": 300, "4": 400, "5": 500},
|
|
"times_by_difficulty": {"1": 15, "2": 20, "3": 25, "4": 35, "5": 45},
|
|
"steal_penalty_percent": 50,
|
|
"max_players_per_team": 4,
|
|
"steal_time_percent": 50,
|
|
}
|
|
|
|
|
|
def _ensure_config_file():
|
|
"""Ensure the config file exists with default values."""
|
|
if not CONFIG_FILE.exists():
|
|
CONFIG_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
with open(CONFIG_FILE, "w") as f:
|
|
json.dump(DEFAULT_CONFIG, f, indent=2)
|
|
|
|
|
|
def get_game_settings() -> Dict[str, Any]:
|
|
"""Load game settings from JSON file."""
|
|
_ensure_config_file()
|
|
try:
|
|
with open(CONFIG_FILE, "r") as f:
|
|
return json.load(f)
|
|
except (json.JSONDecodeError, IOError):
|
|
# Return defaults if file is corrupted
|
|
return DEFAULT_CONFIG.copy()
|
|
|
|
|
|
def update_game_settings(settings: GameSettingsSchema) -> Dict[str, Any]:
|
|
"""Update game settings in JSON file."""
|
|
_ensure_config_file()
|
|
config = settings.model_dump()
|
|
with open(CONFIG_FILE, "w") as f:
|
|
json.dump(config, f, indent=2)
|
|
return config
|
|
|
|
|
|
def get_points_for_difficulty(difficulty: int) -> int:
|
|
"""Get points for a specific difficulty level."""
|
|
settings = get_game_settings()
|
|
return settings["points_by_difficulty"].get(str(difficulty), 300)
|
|
|
|
|
|
def get_time_for_difficulty(difficulty: int) -> int:
|
|
"""Get time (in seconds) for a specific difficulty level."""
|
|
settings = get_game_settings()
|
|
return settings["times_by_difficulty"].get(str(difficulty), 25)
|
|
|
|
|
|
def get_steal_penalty_multiplier() -> float:
|
|
"""Get steal penalty as a multiplier (0-1)."""
|
|
settings = get_game_settings()
|
|
return settings["steal_penalty_percent"] / 100.0
|
|
|
|
|
|
def get_steal_time_multiplier() -> float:
|
|
"""Get steal time as a multiplier (0-1)."""
|
|
settings = get_game_settings()
|
|
return settings["steal_time_percent"] / 100.0
|
|
|
|
|
|
def get_max_players_per_team() -> int:
|
|
"""Get maximum players allowed per team."""
|
|
settings = get_game_settings()
|
|
return settings["max_players_per_team"]
|