Spaces:
Sleeping
Sleeping
| """ | |
| Validation utilities for game objects | |
| """ | |
| from typing import List, Dict, Any, Tuple | |
| from src.models.character import Character, DnDRace, DnDClass | |
| from src.models.campaign import Campaign | |
| def validate_character(character: Character) -> Tuple[bool, List[str]]: | |
| """ | |
| Validate character data | |
| Returns: | |
| Tuple of (is_valid, error_messages) | |
| """ | |
| errors = [] | |
| # Name validation | |
| if not character.name or len(character.name.strip()) == 0: | |
| errors.append("Character name cannot be empty") | |
| # Stats validation | |
| stats = character.stats | |
| for stat_name in ['strength', 'dexterity', 'constitution', 'intelligence', 'wisdom', 'charisma']: | |
| stat_value = getattr(stats, stat_name) | |
| if stat_value < 1 or stat_value > 30: | |
| errors.append(f"{stat_name.title()} must be between 1 and 30") | |
| # HP validation | |
| if character.current_hit_points < 0: | |
| errors.append("Current HP cannot be negative") | |
| if character.current_hit_points > character.max_hit_points: | |
| errors.append("Current HP cannot exceed max HP") | |
| if character.max_hit_points < 1: | |
| errors.append("Max HP must be at least 1") | |
| # AC validation | |
| if character.armor_class < 1: | |
| errors.append("Armor class must be at least 1") | |
| # Level validation | |
| if character.level < 1 or character.level > 20: | |
| errors.append("Level must be between 1 and 20") | |
| # XP validation | |
| if character.experience_points < 0: | |
| errors.append("Experience points cannot be negative") | |
| return len(errors) == 0, errors | |
| def validate_campaign(campaign: Campaign) -> Tuple[bool, List[str]]: | |
| """ | |
| Validate campaign data | |
| Returns: | |
| Tuple of (is_valid, error_messages) | |
| """ | |
| errors = [] | |
| # Name validation | |
| if not campaign.name or len(campaign.name.strip()) == 0: | |
| errors.append("Campaign name cannot be empty") | |
| # Summary validation | |
| if not campaign.summary or len(campaign.summary.strip()) == 0: | |
| errors.append("Campaign summary cannot be empty") | |
| # Main conflict validation | |
| if not campaign.main_conflict or len(campaign.main_conflict.strip()) == 0: | |
| errors.append("Main conflict cannot be empty") | |
| # Party size validation | |
| if campaign.party_size < 1 or campaign.party_size > 10: | |
| errors.append("Party size must be between 1 and 10") | |
| # Session validation | |
| if campaign.current_session < 1: | |
| errors.append("Current session must be at least 1") | |
| if campaign.total_sessions < 0: | |
| errors.append("Total sessions cannot be negative") | |
| return len(errors) == 0, errors | |
| def validate_stat_array(stats: Dict[str, int]) -> Tuple[bool, List[str]]: | |
| """Validate D&D ability score array""" | |
| errors = [] | |
| required_stats = ['strength', 'dexterity', 'constitution', 'intelligence', 'wisdom', 'charisma'] | |
| for stat in required_stats: | |
| if stat not in stats: | |
| errors.append(f"Missing required stat: {stat}") | |
| else: | |
| value = stats[stat] | |
| if value < 1 or value > 30: | |
| errors.append(f"{stat.title()} must be between 1 and 30, got {value}") | |
| return len(errors) == 0, errors | |
| def is_valid_race(race: str) -> bool: | |
| """Check if race is valid""" | |
| try: | |
| DnDRace(race) | |
| return True | |
| except ValueError: | |
| return False | |
| def is_valid_class(character_class: str) -> bool: | |
| """Check if class is valid""" | |
| try: | |
| DnDClass(character_class) | |
| return True | |
| except ValueError: | |
| return False | |
| def get_available_races() -> List[str]: | |
| """Get list of available races""" | |
| return [race.value for race in DnDRace] | |
| def get_available_classes() -> List[str]: | |
| """Get list of available classes""" | |
| return [cls.value for cls in DnDClass] | |