2026-01-28 16:25:40 +01:00
|
|
|
from __future__ import annotations
|
2026-01-19 18:55:07 +01:00
|
|
|
from uuid import uuid4
|
|
|
|
|
|
2026-01-30 15:32:44 +01:00
|
|
|
from warchron.model.round import Round, Choice, Battle
|
2026-01-19 18:55:07 +01:00
|
|
|
|
|
|
|
|
class Campaign:
|
2026-01-28 16:25:40 +01:00
|
|
|
def __init__(self, name: str, month: int):
|
|
|
|
|
self.id: str = str(uuid4())
|
|
|
|
|
self.name: str = name
|
|
|
|
|
self.month: int = month
|
2026-01-30 00:34:22 +01:00
|
|
|
self.participants: dict[str, CampaignParticipant] = {}
|
|
|
|
|
self.sectors: dict[str, Sector] = {}
|
2026-01-30 15:32:44 +01:00
|
|
|
self.rounds: list[Round] = []
|
2026-01-19 18:55:07 +01:00
|
|
|
self.is_over = False
|
|
|
|
|
|
2026-01-28 16:25:40 +01:00
|
|
|
def set_id(self, new_id: str):
|
2026-01-19 18:55:07 +01:00
|
|
|
self.id = new_id
|
|
|
|
|
|
2026-01-28 16:25:40 +01:00
|
|
|
def set_name(self, new_name: str):
|
2026-01-19 18:55:07 +01:00
|
|
|
self.name = new_name
|
|
|
|
|
|
2026-01-28 16:25:40 +01:00
|
|
|
def set_month(self, new_month: int):
|
2026-01-19 18:55:07 +01:00
|
|
|
self.month = new_month
|
|
|
|
|
|
2026-01-28 16:25:40 +01:00
|
|
|
def set_state(self, new_state: bool):
|
2026-01-19 18:55:07 +01:00
|
|
|
self.is_over = new_state
|
|
|
|
|
|
|
|
|
|
def toDict(self):
|
|
|
|
|
return {
|
|
|
|
|
"id" : self.id,
|
|
|
|
|
"name" : self.name,
|
|
|
|
|
"month" : self.month,
|
2026-01-28 16:25:40 +01:00
|
|
|
# "participants" : self.participants,
|
2026-01-21 08:31:48 +01:00
|
|
|
"rounds": [rnd.toDict() for rnd in self.rounds],
|
2026-01-19 18:55:07 +01:00
|
|
|
"is_over": self.is_over
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
2026-01-21 08:31:48 +01:00
|
|
|
def fromDict(data: dict):
|
2026-01-22 23:42:47 +01:00
|
|
|
camp = Campaign(name=data["name"], month=data["month"])
|
2026-01-21 08:31:48 +01:00
|
|
|
camp.set_id(data["id"])
|
2026-01-28 16:25:40 +01:00
|
|
|
# camp.participants = data.get("participants", {})
|
2026-01-21 08:31:48 +01:00
|
|
|
for rnd_data in data.get("rounds", []):
|
|
|
|
|
camp.rounds.append(Round.fromDict(rnd_data))
|
|
|
|
|
camp.set_state(data.get("is_over", False))
|
|
|
|
|
return camp
|
2026-01-28 16:25:40 +01:00
|
|
|
|
2026-01-30 00:34:22 +01:00
|
|
|
# Campaign participant methods
|
|
|
|
|
|
|
|
|
|
def get_all_campaign_participants_ids(self) -> set[str]:
|
|
|
|
|
return set(self.participants.keys())
|
|
|
|
|
|
|
|
|
|
def has_participant(self, player_id: str) -> bool:
|
|
|
|
|
return player_id in self.participants
|
|
|
|
|
|
|
|
|
|
def add_campaign_participant(self, player_id: str, leader: str, theme: str) -> CampaignParticipant:
|
|
|
|
|
if player_id in self.participants:
|
|
|
|
|
raise ValueError("Player already registered in this campaign")
|
|
|
|
|
participant = CampaignParticipant(player_id, leader, theme)
|
|
|
|
|
self.participants[participant.id] = participant
|
|
|
|
|
return participant
|
|
|
|
|
|
|
|
|
|
def get_campaign_participant(self, id: str) -> CampaignParticipant:
|
|
|
|
|
return self.participants[id]
|
|
|
|
|
|
|
|
|
|
def get_all_campaign_participants(self) -> list[CampaignParticipant]:
|
|
|
|
|
return list(self.participants.values())
|
|
|
|
|
|
|
|
|
|
def update_campaign_participant(self, player_id: str, *, leader: str, theme: str):
|
|
|
|
|
part = self.get_campaign_participant(player_id)
|
|
|
|
|
part.set_leader(leader)
|
|
|
|
|
part.set_theme(theme)
|
|
|
|
|
|
|
|
|
|
def remove_campaign_participant(self, player_id: str):
|
2026-01-30 15:32:44 +01:00
|
|
|
# TODO manage choices referring to it
|
|
|
|
|
# TODO manage battles referring to it
|
2026-01-30 00:34:22 +01:00
|
|
|
del self.participants[player_id]
|
|
|
|
|
|
|
|
|
|
# Sector methods
|
|
|
|
|
|
|
|
|
|
def add_sector(self, name: str, round_id: str, major_id: str, minor_id: str, influence_id: str) -> Sector:
|
|
|
|
|
sect = Sector(name, round_id, major_id, minor_id, influence_id)
|
|
|
|
|
self.sectors[sect.id] = sect
|
|
|
|
|
return sect
|
|
|
|
|
|
2026-01-30 15:32:44 +01:00
|
|
|
def get_sector(self, sector_id: str) -> Sector:
|
|
|
|
|
return self.sectors[sector_id]
|
|
|
|
|
|
|
|
|
|
def get_sector_name(self, sector_id: str) -> str:
|
|
|
|
|
if sector_id is None:
|
|
|
|
|
return ""
|
|
|
|
|
return self.sectors[sector_id].name
|
2026-01-30 00:34:22 +01:00
|
|
|
|
|
|
|
|
def get_all_sectors(self) -> list[Sector]:
|
|
|
|
|
return list(self.sectors.values())
|
|
|
|
|
|
2026-01-30 15:32:44 +01:00
|
|
|
# TODO manage choices referring to it (round order!)
|
2026-01-30 00:34:22 +01:00
|
|
|
def update_sector(self, sector_id: str, *, name: str, round_id: str, major_id: str, minor_id: str, influence_id: str):
|
|
|
|
|
sect = self.get_sector(sector_id)
|
|
|
|
|
sect.set_name(name)
|
|
|
|
|
sect.set_round(round_id)
|
|
|
|
|
sect.set_major(major_id)
|
|
|
|
|
sect.set_minor(minor_id)
|
|
|
|
|
sect.set_influence(influence_id)
|
|
|
|
|
|
|
|
|
|
def remove_sector(self, sector_id: str):
|
2026-01-30 15:32:44 +01:00
|
|
|
# TODO manage choices referring to it
|
|
|
|
|
# TODO manage battles referring to it
|
2026-01-30 00:34:22 +01:00
|
|
|
del self.sectors[sector_id]
|
|
|
|
|
|
|
|
|
|
# Round methods
|
|
|
|
|
|
2026-01-28 16:25:40 +01:00
|
|
|
def has_round(self, round_id: str) -> bool:
|
|
|
|
|
return any(r.id == round_id for r in self.rounds)
|
2026-01-21 07:43:04 +01:00
|
|
|
|
2026-01-28 16:25:40 +01:00
|
|
|
def get_round(self, round_id: str) -> Round:
|
2026-01-30 15:32:44 +01:00
|
|
|
for rnd in self.rounds:
|
|
|
|
|
if rnd.id == round_id:
|
|
|
|
|
return rnd
|
|
|
|
|
raise KeyError(f"Round {round_id} not found")
|
2026-01-21 07:43:04 +01:00
|
|
|
|
|
|
|
|
def get_all_rounds(self) -> list[Round]:
|
|
|
|
|
return list(self.rounds)
|
|
|
|
|
|
|
|
|
|
def add_round(self) -> Round:
|
|
|
|
|
round = Round()
|
|
|
|
|
self.rounds.append(round)
|
2026-01-22 23:42:47 +01:00
|
|
|
return round
|
|
|
|
|
|
|
|
|
|
def remove_round(self, round_id: str):
|
|
|
|
|
rnd = next((r for r in self.rounds if r.id == round_id), None)
|
|
|
|
|
if rnd:
|
|
|
|
|
self.rounds.remove(rnd)
|
2026-01-27 11:49:37 +01:00
|
|
|
|
|
|
|
|
def get_round_index(self, round_id: str) -> int:
|
2026-01-30 00:34:22 +01:00
|
|
|
if round_id is None:
|
|
|
|
|
return None
|
2026-01-27 11:49:37 +01:00
|
|
|
for index, rnd in enumerate(self.rounds, start=1):
|
|
|
|
|
if rnd.id == round_id:
|
|
|
|
|
return index
|
|
|
|
|
raise KeyError("Round not found in campaign")
|
2026-01-28 16:25:40 +01:00
|
|
|
|
2026-01-30 00:34:22 +01:00
|
|
|
def get_round_name(self, round_id: str | None) -> str:
|
|
|
|
|
if round_id is None:
|
|
|
|
|
return ""
|
|
|
|
|
for rnd in self.rounds:
|
|
|
|
|
if rnd.id == round_id:
|
|
|
|
|
return rnd.name
|
|
|
|
|
return ""
|
|
|
|
|
|
2026-01-30 15:32:44 +01:00
|
|
|
# Choice methods
|
|
|
|
|
|
|
|
|
|
def create_choice(self, round_id: str, participant_id: str) -> Choice:
|
|
|
|
|
rnd = self.get_round(round_id)
|
|
|
|
|
return rnd.create_choice(participant_id)
|
|
|
|
|
|
|
|
|
|
def remove_choice(self, round_id: str, participant_id: str) -> Choice:
|
|
|
|
|
rnd = self.get_round(round_id)
|
|
|
|
|
rnd.remove_choice(participant_id)
|
|
|
|
|
|
2026-01-28 16:25:40 +01:00
|
|
|
class CampaignParticipant:
|
2026-01-30 00:34:22 +01:00
|
|
|
def __init__(self,player_id: str, leader: str, theme: str):
|
|
|
|
|
self.id: str = player_id # ref to War.participants
|
2026-01-28 16:25:40 +01:00
|
|
|
self.leader: str = leader
|
2026-01-30 00:34:22 +01:00
|
|
|
self.theme: str = theme
|
|
|
|
|
|
|
|
|
|
def set_id(self, new_id: str):
|
|
|
|
|
self.id = new_id
|
|
|
|
|
|
|
|
|
|
def set_leader(self, new_faction: str):
|
|
|
|
|
self.leader = new_faction
|
|
|
|
|
|
|
|
|
|
def set_theme(self, new_theme: str):
|
|
|
|
|
self.theme = new_theme
|
2026-01-28 16:25:40 +01:00
|
|
|
|
|
|
|
|
class Sector:
|
|
|
|
|
def __init__(self, name: str, round_id: str, major_id: str, minor_id: str, influence_id: str):
|
|
|
|
|
self.id: str = str(uuid4())
|
|
|
|
|
self.name: str = name
|
2026-01-30 00:34:22 +01:00
|
|
|
self.round_id: str = round_id
|
2026-01-30 10:52:19 +01:00
|
|
|
self.major_objective_id: str | None = major_id # ref to War.objectives
|
|
|
|
|
self.minor_objective_id: str | None = minor_id # ref to War.objectives
|
|
|
|
|
self.influence_objective_id: str | None = influence_id # ref to War.objectives
|
2026-01-30 00:34:22 +01:00
|
|
|
|
|
|
|
|
def set_id(self, new_id: str):
|
|
|
|
|
self.id = new_id
|
|
|
|
|
|
|
|
|
|
def set_name(self, new_name: str):
|
|
|
|
|
self.name = new_name
|
|
|
|
|
|
|
|
|
|
def set_round(self, new_round_id: str):
|
|
|
|
|
self.round_id = new_round_id
|
|
|
|
|
|
|
|
|
|
def set_major(self, new_major_id: str):
|
|
|
|
|
self.major_objective_id = new_major_id
|
|
|
|
|
|
|
|
|
|
def set_minor(self, new_minor_id: str):
|
|
|
|
|
self.minor_objective_id = new_minor_id
|
|
|
|
|
|
|
|
|
|
def set_influence(self, new_influence_id: str):
|
|
|
|
|
self.influence_objective_id = new_influence_id
|