From ac01568c2f801ed6f32cf14f097125c81bede5ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20R=C3=A9aux?= Date: Mon, 2 Feb 2026 14:33:31 +0100 Subject: [PATCH] refactor campaign participant ID --- src/warchron/controller/controller.py | 4 +- src/warchron/model/campaign.py | 165 ++++++++++++++++---------- src/warchron/model/model.py | 27 +++-- src/warchron/model/war.py | 154 +++++++++++++++--------- 4 files changed, 221 insertions(+), 129 deletions(-) diff --git a/src/warchron/controller/controller.py b/src/warchron/controller/controller.py index aa4d6ce..0a41efa 100644 --- a/src/warchron/controller/controller.py +++ b/src/warchron/controller/controller.py @@ -182,7 +182,7 @@ class Controller: self.view.display_campaign_sectors(sectors_for_display) participants = camp.get_all_campaign_participants() participants_for_display = [ - (self.model.get_player_name(p.id), p.leader, p.theme, p.id) + (self.model.get_player_name(p.war_participant_id), p.leader, p.theme, p.id) for p in participants ] self.view.display_campaign_participants(participants_for_display) @@ -392,7 +392,7 @@ class Controller: self.refresh(RefreshScope.CAMPAIGN_DETAILS) elif item_type == ItemType.CAMPAIGN_PARTICIPANT: part = self.model.get_campaign_participant(item_id) - player = self.model.get_player(part.id) + player = self.model.get_player(part.war_participant_id) part_opt = [ParticipantOption(id=player.id, name=player.name)] dialog = CampaignParticipantDialog( self.view, diff --git a/src/warchron/model/campaign.py b/src/warchron/model/campaign.py index 07f4659..7c63e17 100644 --- a/src/warchron/model/campaign.py +++ b/src/warchron/model/campaign.py @@ -1,8 +1,9 @@ from __future__ import annotations -from uuid import uuid4 +from uuid import uuid4 from warchron.model.round import Round, Choice, Battle + class Campaign: def __init__(self, name: str, month: int): self.id: str = str(uuid4()) @@ -21,20 +22,20 @@ class Campaign: def set_month(self, new_month: int): self.month = new_month - + def set_state(self, new_state: bool): self.is_over = new_state def toDict(self): return { - "id" : self.id, - "name" : self.name, - "month" : self.month, + "id": self.id, + "name": self.name, + "month": self.month, # "participants" : self.participants, "rounds": [rnd.toDict() for rnd in self.rounds], - "is_over": self.is_over + "is_over": self.is_over, } - + @staticmethod def fromDict(data: dict): camp = Campaign(name=data["name"], month=data["month"]) @@ -45,47 +46,61 @@ class Campaign: camp.set_state(data.get("is_over", False)) return camp -# Campaign participant methods + # 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: + ##TODO change lookup id target 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: + def add_campaign_participant( + self, war_participant_id: str, leader: str, theme: str + ) -> CampaignParticipant: + ## TODO change lookup id target + if war_participant_id in self.participants: raise ValueError("Player already registered in this campaign") - participant = CampaignParticipant(player_id, leader, theme) + participant = CampaignParticipant( + war_participant_id=war_participant_id, leader=leader, theme=theme + ) self.participants[participant.id] = participant return participant - def get_campaign_participant(self, id: str) -> CampaignParticipant: - return self.participants[id] + def get_campaign_participant(self, participant_id: str) -> CampaignParticipant: + try: + return self.participants[participant_id] + except KeyError: + raise KeyError(f"Participant {participant_id} not in campaign {self.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) + def update_campaign_participant( + self, participant_id: str, *, leader: str, theme: str + ): + part = self.get_campaign_participant(participant_id) + # Can't change referred War.participant part.set_leader(leader) part.set_theme(theme) - def remove_campaign_participant(self, player_id: str): + def remove_campaign_participant(self, participant_id: str): # TODO manage choices referring to it # TODO manage battles referring to it - del self.participants[player_id] + del self.participants[participant_id] -# Sector methods + # Sector methods - def add_sector(self, name: str, round_id: str, major_id: str, minor_id: str, influence_id: str) -> Sector: + 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 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 "" @@ -95,31 +110,37 @@ class Campaign: return list(self.sectors.values()) # TODO manage choices referring to it (round order!) - def update_sector(self, sector_id: str, *, name: str, round_id: str, major_id: str, minor_id: str, influence_id: str): + 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): # TODO manage choices referring to it # TODO manage battles referring to it del self.sectors[sector_id] def get_sectors_in_round(self, round_id: str) -> list[Sector]: - sectors = [ - s for s in self.sectors.values() - if s.round_id == round_id - ] + sectors = [s for s in self.sectors.values() if s.round_id == round_id] return sectors -# Round methods + # Round methods def has_round(self, round_id: str) -> bool: return any(r.id == round_id for r in self.rounds) - + def get_round(self, round_id: str) -> Round: for rnd in self.rounds: if rnd.id == round_id: @@ -128,12 +149,12 @@ class Campaign: def get_all_rounds(self) -> list[Round]: return list(self.rounds) - + def add_round(self) -> Round: round = Round() self.rounds.append(round) 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: @@ -148,77 +169,99 @@ class Campaign: raise KeyError("Round not found in campaign") 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 + if round_id is None: return "" + for rnd in self.rounds: + if rnd.id == round_id: + return rnd.name + return "" -# Choice methods + # 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 update_choice(self, - round_id: str, - participant_id: str, - priority_sector_id: str | None, - secondary_sector_id: str | None, - comment: str | None): + def update_choice( + self, + round_id: str, + participant_id: str, + priority_sector_id: str | None, + secondary_sector_id: str | None, + comment: str | None, + ): rnd = self.get_round(round_id) - rnd.update_choice(participant_id, priority_sector_id, secondary_sector_id, comment) + rnd.update_choice( + participant_id, priority_sector_id, secondary_sector_id, comment + ) def remove_choice(self, round_id: str, participant_id: str) -> Choice: rnd = self.get_round(round_id) rnd.remove_choice(participant_id) -# Battle methods + # Battle methods def create_battle(self, round_id: str, sector_id: str) -> Battle: rnd = self.get_round(round_id) return rnd.create_battle(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): + + 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, + ): rnd = self.get_round(round_id) - rnd.update_battle(sector_id, player_1_id, player_2_id, winner_id, score, victory_condition, comment) + rnd.update_battle( + sector_id, + player_1_id, + player_2_id, + winner_id, + score, + victory_condition, + comment, + ) def remove_battle(self, round_id: str, sector_id: str) -> Battle: rnd = self.get_round(round_id) rnd.remove_battle(sector_id) + class CampaignParticipant: - def __init__(self, player_id: str, leader: str, theme: str): - self.id: str = player_id # ref to War.participants + def __init__(self, *, war_participant_id: str, leader: str, theme: str): + self.id: str = str(uuid4()) + self.war_participant_id: str = war_participant_id # ref to War.participants self.leader: str = leader self.theme: str = theme def set_id(self, new_id: str): self.id = new_id + def set_war_participant(self, new_participant: str): + self.war_participant_id = new_participant + def set_leader(self, new_faction: str): self.leader = new_faction def set_theme(self, new_theme: str): self.theme = new_theme + class Sector: - def __init__(self, name: str, round_id: str, major_id: str, minor_id: str, influence_id: str): + 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 self.round_id: str = round_id - 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 + 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 self.mission: str | None = None self.description: str | None = None diff --git a/src/warchron/model/model.py b/src/warchron/model/model.py index f59356c..3113efc 100644 --- a/src/warchron/model/model.py +++ b/src/warchron/model/model.py @@ -126,11 +126,17 @@ class Model: # TODO don't use this method as participant with same ID (player) can be in several wars! def get_war_by_war_participant(self, participant_id: str) -> War: for war in self.wars.values(): - for part in war.participants.values(): - if part.id == participant_id: - return war + if war.has_participant(participant_id): + return war raise KeyError(f"Participant {participant_id} not found in any War") + def get_war_by_campaign_participant(self, participant_id: str) -> Campaign: + for war in self.wars.values(): + camp = war.get_campaign_by_campaign_participant(participant_id) + if camp is not None: + return war + raise KeyError(f"Participant {participant_id} not found") + def update_war(self, war_id: str, *, name: str, year: int): war = self.get_war(war_id) war.set_name(name) @@ -218,7 +224,6 @@ class Model: return camp raise KeyError(f"Round {round_id} not found") - # TODO don't use this method as participant with same ID (player) can be in several campaigns! def get_campaign_by_campaign_participant(self, participant_id: str) -> Campaign: for war in self.wars.values(): camp = war.get_campaign_by_campaign_participant(participant_id) @@ -308,14 +313,18 @@ class Model: raise KeyError("Participant not found") def update_campaign_participant( - self, participant_id: str, *, leader: str, theme: str + self, + participant_id: str, + *, + leader: str, + theme: str, ): - camp = self.get_campaign_by_campaign_participant(participant_id) - camp.update_campaign_participant(participant_id, leader=leader, theme=theme) + war = self.get_war_by_campaign_participant(participant_id) + war.update_campaign_participant(participant_id, leader=leader, theme=theme) def remove_campaign_participant(self, participant_id: str): - camp = self.get_campaign_by_campaign_participant(participant_id) - camp.remove_campaign_participant(participant_id) + war = self.get_war_by_campaign_participant(participant_id) + war.remove_campaign_participant(participant_id) # Round methods diff --git a/src/warchron/model/war.py b/src/warchron/model/war.py index 698b7f1..ecb1f68 100644 --- a/src/warchron/model/war.py +++ b/src/warchron/model/war.py @@ -1,5 +1,5 @@ from __future__ import annotations -from uuid import uuid4 +from uuid import uuid4 from datetime import datetime from warchron.model.campaign import Campaign, Sector, CampaignParticipant @@ -11,7 +11,7 @@ class War: self.id: str = str(uuid4()) self.name: str = name self.year: int = year - self.participants: dict[str, WarParticipant] = {} + self.participants: dict[str, WarParticipant] = {} self.objectives: dict[str, Objective] = {} self.campaigns: list[Campaign] = [] self.is_over: bool = False @@ -24,20 +24,20 @@ class War: def set_year(self, new_year: int): self.year = new_year - + def set_state(self, new_state: bool): self.is_over = new_state def toDict(self): return { - "id" : self.id, - "name" : self.name, - "year" : self.year, + "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 + "is_over": self.is_over, } - + @staticmethod def fromDict(data: dict): war = War(name=data["name"], year=data["year"]) @@ -48,7 +48,7 @@ class War: war.set_state(data.get("is_over", False)) return war -# Objective methods + # Objective methods def add_objective(self, name: str, description: str) -> Objective: obj = Objective(name, description) @@ -66,17 +66,17 @@ class War: return "" obj = self.objectives.get(objective_id) return obj.name if obj else "" - + def update_objective(self, objective_id: str, *, name: str, description: str): obj = self.get_objective(objective_id) obj.set_name(name) obj.set_description(description) - + def remove_objective(self, objective_id: str): - # TODO manage sectors referring to it + # TODO manage sectors referring to it del self.objectives[objective_id] -# War participant methods + # War participant methods def get_all_war_participants_ids(self) -> set[str]: return set(self.participants.keys()) @@ -105,16 +105,14 @@ class War: # TODO manage campaign_participants referring to it del self.participants[player_id] -# Campaign methods + # 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: - return { - "month": datetime.now().month - } - + 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"] @@ -144,41 +142,64 @@ class War: def get_campaign_by_campaign_participant(self, participant_id: str) -> Campaign: for camp in self.campaigns: - for part in camp.participants.values(): - if part.id == participant_id: - return camp + 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): 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): camp = self.get_campaign(campaign_id) self.campaigns.remove(camp) -# Sector methods + # Sector methods - def add_sector(self, campaign_id, name: str, round_id: str, major_id: str, minor_id: str, influence_id: str) -> Sector: + def add_sector( + self, + campaign_id, + 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, id: str) -> Sector: return self.sectors[id] - def update_sector(self, sector_id: str, *, name: str, round_id: str, major_id: str, minor_id: str, influence_id: str): + def update_sector( + self, + sector_id: str, + *, + name: str, + round_id: str, + major_id: str, + minor_id: str, + influence_id: str, + ): 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) + 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): camp = self.get_campaign_by_sector(sector_id) camp.remove_sector(sector_id) - -# Campaign participant methods + + # Campaign participant methods def get_available_war_participants(self, campaign_id: str) -> list[WarParticipant]: camp = self.get_campaign(campaign_id) @@ -188,9 +209,11 @@ class War: if not camp.has_participant(part.id) ] - def add_campaign_participant(self, campaign_id: str, player_id: str, leader: str, theme: str) -> CampaignParticipant: + 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(player_id, leader, theme) + return camp.add_campaign_participant(participant_id, leader, theme) def get_campaign_participant(self, participant_id) -> CampaignParticipant: for camp in self.campaigns.values(): @@ -199,15 +222,17 @@ class War: return part raise KeyError("Participant not found") - def update_campaign_participant(self, participant_id: str, *, faction: str): + def update_campaign_participant( + self, participant_id: str, *, leader: str, theme: str + ): camp = self.get_campaign_by_campaign_participant(participant_id) - camp.update_campaign_participant(participant_id, faction=faction) + camp.update_campaign_participant(participant_id, leader=leader, theme=theme) def remove_campaign_participant(self, participant_id: str): camp = self.get_campaign_by_campaign_participant(participant_id) camp.remove_campaign_participant(participant_id) -# Round methods + # Round methods def add_round(self, campaign_id: str) -> Round: camp = self.get_campaign(campaign_id) @@ -221,47 +246,62 @@ class War: camp = self.get_campaign_by_round(round_id) camp.remove_round(round_id) -# Choice methods + # 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): + + def update_choice( + self, + round_id: str, + participant_id: str, + priority_sector_id: str | None, + secondary_sector_id: str | None, + comment: str | None, + ): camp = self.get_campaign_by_round(round_id) - camp.update_choice(participant_id, priority_sector_id, secondary_sector_id, comment) + camp.update_choice( + participant_id, priority_sector_id, secondary_sector_id, comment + ) def remove_choice(self, round_id: str, participant_id: str): camp = self.get_campaign_by_round(round_id) camp.remove_choice(round_id, participant_id) -# Battle methods + # 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): + 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, + ): camp = self.get_campaign_by_round(round_id) - camp.update_battle(sector_id, player_1_id, player_2_id, winner_id, score, victory_condition, comment) + camp.update_battle( + sector_id, + player_1_id, + player_2_id, + winner_id, + score, + victory_condition, + comment, + ) def remove_battle(self, round_id: str, sector_id: str): 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()) @@ -276,10 +316,11 @@ class Objective: def set_description(self, new_description: str): self.description = new_description - + + class WarParticipant: def __init__(self, player_id: str, faction: str): - self.id: str = player_id # ref to Model.players + self.id: str = player_id # ref to Model.players self.faction: str = faction def set_id(self, new_id: str): @@ -287,4 +328,3 @@ class WarParticipant: def set_faction(self, new_faction: str): self.faction = new_faction -