from __future__ import annotations from uuid import uuid4 from datetime import datetime from typing import Any, Dict, List from warchron.model.campaign import Campaign, Sector, CampaignParticipant from warchron.model.round import Round, Choice, Battle class War: def __init__(self, name: str, year: int) -> None: self.id: str = str(uuid4()) self.name: str = name self.year: int = year self.participants: Dict[str, WarParticipant] = {} self.objectives: Dict[str, Objective] = {} self.campaigns: List[Campaign] = [] self.is_over: bool = False def set_id(self, new_id: str) -> None: self.id = new_id def set_name(self, new_name: str) -> None: self.name = new_name def set_year(self, new_year: int) -> None: self.year = new_year def set_state(self, new_state: bool) -> None: self.is_over = new_state def toDict(self) -> Dict[str, Any]: return { "id": self.id, "name": self.name, "year": self.year, # "participants" : self.participants, "campaigns": [camp.toDict() for camp in self.campaigns], "is_over": self.is_over, } @staticmethod def fromDict(data: Dict[str, Any]) -> War: war = War(name=data["name"], year=data["year"]) war.set_id(data["id"]) # war.participants = data.get("participants", {}) for camp_data in data.get("campaigns", []): war.campaigns.append(Campaign.fromDict(camp_data)) war.set_state(data.get("is_over", False)) return war # Objective methods def add_objective(self, name: str, description: str) -> Objective: obj = Objective(name, description) self.objectives[obj.id] = obj return obj def get_objective(self, id: str) -> Objective: return self.objectives[id] def get_all_objectives(self) -> List[Objective]: return list(self.objectives.values()) def get_objective_name(self, objective_id: str | None) -> str: if objective_id is None: return "" obj = self.objectives.get(objective_id) return obj.name if obj else "" def update_objective( self, objective_id: str, *, name: str, description: str ) -> None: obj = self.get_objective(objective_id) obj.set_name(name) obj.set_description(description) def remove_objective(self, objective_id: str) -> None: # TODO manage sectors referring to it del self.objectives[objective_id] # War participant methods def get_all_war_participants_ids(self) -> set[str]: return set(self.participants.keys()) def has_participant(self, participant_id: str) -> bool: return participant_id in self.participants def has_player(self, player_id: str) -> bool: return any(part.player_id == player_id for part in self.participants.values()) def add_war_participant(self, player_id: str, faction: str) -> WarParticipant: if self.has_player(player_id): raise ValueError("Player already registered in this war") participant = WarParticipant(player_id=player_id, faction=faction) self.participants[participant.id] = participant return participant def get_war_participant(self, id: str) -> WarParticipant: return self.participants[id] def get_all_war_participants(self) -> List[WarParticipant]: return list(self.participants.values()) def update_war_participant(self, player_id: str, *, faction: str) -> None: part = self.get_war_participant(player_id) # Can't change referred Model.players part.set_faction(faction) def remove_war_participant(self, player_id: str) -> None: # TODO manage campaign_participants referring to it del self.participants[player_id] # Campaign methods def has_campaign(self, campaign_id: str) -> bool: return any(c.id == campaign_id for c in self.campaigns) def get_default_campaign_values(self) -> Dict[str, Any]: return {"month": datetime.now().month} def add_campaign(self, name: str, month: int | None = None) -> Campaign: if month is None: month = self.get_default_campaign_values()["month"] campaign = Campaign(name, month) self.campaigns.append(campaign) return campaign def get_campaign(self, campaign_id: str) -> Campaign: for camp in self.campaigns: if camp.id == campaign_id: return camp raise KeyError(f"Campaign {campaign_id} not found in War {self.id}") def get_campaign_by_round(self, round_id: str) -> Campaign: for camp in self.campaigns: for rnd in camp.rounds: if rnd.id == round_id: return camp raise KeyError(f"Round {round_id} not found in any Campaign") def get_campaign_by_sector(self, sector_id: str) -> Campaign: for camp in self.campaigns: for sect in camp.sectors.values(): if sect.id == sector_id: return camp raise KeyError(f"Sector {sector_id} not found in any Campaign") def get_campaign_by_campaign_participant(self, participant_id: str) -> Campaign: for camp in self.campaigns: if camp.has_participant(participant_id): return camp raise KeyError(f"Participant {participant_id} not found in any Campaign") def update_campaign(self, campaign_id: str, *, name: str, month: int) -> None: camp = self.get_campaign(campaign_id) camp.set_name(name) camp.set_month(month) def get_all_campaigns(self) -> List[Campaign]: return list(self.campaigns) def remove_campaign(self, campaign_id: str) -> None: camp = self.get_campaign(campaign_id) self.campaigns.remove(camp) # Sector methods def add_sector( self, campaign_id: str, name: str, round_id: str, major_id: str, minor_id: str, influence_id: str, ) -> Sector: camp = self.get_campaign(campaign_id) return camp.add_sector(name, round_id, major_id, minor_id, influence_id) def get_sector(self, sector_id: str) -> Sector: for camp in self.campaigns: for sect in camp.sectors.values(): if sect.id == sector_id: return sect raise KeyError("Sector not found") def update_sector( self, sector_id: str, *, name: str, round_id: str, major_id: str, minor_id: str, influence_id: str, ) -> None: camp = self.get_campaign_by_sector(sector_id) camp.update_sector( sector_id, name=name, round_id=round_id, major_id=major_id, minor_id=minor_id, influence_id=influence_id, ) def remove_sector(self, sector_id: str) -> None: camp = self.get_campaign_by_sector(sector_id) camp.remove_sector(sector_id) # Campaign participant methods def get_available_war_participants(self, campaign_id: str) -> List[WarParticipant]: camp = self.get_campaign(campaign_id) return [ part for part in self.participants.values() if not camp.has_war_participant(part.id) ] def add_campaign_participant( self, campaign_id: str, participant_id: str, leader: str, theme: str ) -> CampaignParticipant: camp = self.get_campaign(campaign_id) return camp.add_campaign_participant(participant_id, leader, theme) def get_campaign_participant(self, participant_id: str) -> CampaignParticipant: for camp in self.campaigns: for part in camp.participants.values(): if part.id == participant_id: return part raise KeyError("Participant not found") def update_campaign_participant( self, participant_id: str, *, leader: str, theme: str ) -> None: camp = self.get_campaign_by_campaign_participant(participant_id) camp.update_campaign_participant(participant_id, leader=leader, theme=theme) def remove_campaign_participant(self, participant_id: str) -> None: camp = self.get_campaign_by_campaign_participant(participant_id) camp.remove_campaign_participant(participant_id) # Round methods def add_round(self, campaign_id: str) -> Round: camp = self.get_campaign(campaign_id) return camp.add_round() def add_battle(self, campaign_id: str) -> Round: camp = self.get_campaign(campaign_id) return camp.add_round() def remove_round(self, round_id: str) -> None: camp = self.get_campaign_by_round(round_id) camp.remove_round(round_id) # Choice methods def create_choice(self, round_id: str, participant_id: str) -> Choice: camp = self.get_campaign_by_round(round_id) return camp.create_choice(round_id, participant_id) def update_choice( self, round_id: str, participant_id: str, priority_sector_id: str | None, secondary_sector_id: str | None, comment: str | None, ) -> None: camp = self.get_campaign_by_round(round_id) camp.update_choice( round_id, participant_id, priority_sector_id, secondary_sector_id, comment ) def remove_choice(self, round_id: str, participant_id: str) -> None: camp = self.get_campaign_by_round(round_id) camp.remove_choice(round_id, participant_id) # Battle methods def create_battle(self, round_id: str, sector_id: str) -> Battle: camp = self.get_campaign_by_round(round_id) return camp.create_battle(round_id, sector_id) def update_battle( self, round_id: str, sector_id: str, player_1_id: str | None, player_2_id: str | None, winner_id: str | None, score: str | None, victory_condition: str | None, comment: str | None, ) -> None: camp = self.get_campaign_by_round(round_id) camp.update_battle( round_id, sector_id, player_1_id, player_2_id, winner_id, score, victory_condition, comment, ) def remove_battle(self, round_id: str, sector_id: str) -> None: camp = self.get_campaign_by_round(round_id) camp.remove_battle(round_id, sector_id) class Objective: def __init__(self, name: str, description: str): self.id: str = str(uuid4()) self.name: str = name self.description: str = description def set_id(self, new_id: str) -> None: self.id = new_id def set_name(self, new_name: str) -> None: self.name = new_name def set_description(self, new_description: str) -> None: self.description = new_description class WarParticipant: def __init__(self, *, player_id: str, faction: str): self.id: str = str(uuid4()) self.player_id: str = player_id # ref to WarModel.players self.faction: str = faction def set_id(self, new_id: str) -> None: self.id = new_id def set_player(self, new_player: str) -> None: self.player_id = new_player def set_faction(self, new_faction: str) -> None: self.faction = new_faction