diff --git a/src/warchron/controller/dtos.py b/src/warchron/controller/dtos.py index cf063bd..48e2749 100644 --- a/src/warchron/controller/dtos.py +++ b/src/warchron/controller/dtos.py @@ -62,7 +62,7 @@ class CampaignParticipantDTO: class SectorDTO: id: str name: str - round_index: int + round_index: int | None major: str minor: str influence: str @@ -71,7 +71,7 @@ class SectorDTO: @dataclass class RoundDTO: id: str - index: int + index: int | None @dataclass(frozen=True, slots=True) diff --git a/src/warchron/model/battle.py b/src/warchron/model/battle.py index 04a24c7..1f0fd07 100644 --- a/src/warchron/model/battle.py +++ b/src/warchron/model/battle.py @@ -1,3 +1,7 @@ +from __future__ import annotations +from typing import Any, Dict + + class Battle: def __init__( self, @@ -33,3 +37,27 @@ class Battle: def set_comment(self, new_comment: str | None) -> None: self.comment = new_comment + + def toDict(self) -> Dict[str, Any]: + return { + "sector_id": self.sector_id, + "player_1_id": self.player_1_id, + "player_2_id": self.player_2_id, + "winner_id": self.winner_id, + "score": self.score, + "victory_condition": self.victory_condition, + "comment": self.comment, + } + + @staticmethod + def fromDict(data: Dict[str, Any]) -> Battle: + battle = Battle( + data["sector_id"], + data.get("player_1_id"), + data.get("player_2_id"), + ) + battle.winner_id = data.get("winner_id") + battle.score = data.get("score") + battle.victory_condition = data.get("victory_condition") + battle.comment = data.get("comment") + return battle diff --git a/src/warchron/model/campaign.py b/src/warchron/model/campaign.py index 25ef22f..82aea5c 100644 --- a/src/warchron/model/campaign.py +++ b/src/warchron/model/campaign.py @@ -40,7 +40,8 @@ class Campaign: "id": self.id, "name": self.name, "month": self.month, - # "participants" : self.participants, + "participants": [p.toDict() for p in self.participants.values()], + "sectors": [s.toDict() for s in self.sectors.values()], "rounds": [rnd.toDict() for rnd in self.rounds], "is_over": self.is_over, } @@ -49,7 +50,12 @@ class Campaign: def fromDict(data: Dict[str, Any]) -> Campaign: camp = Campaign(name=data["name"], month=data["month"]) camp.set_id(data["id"]) - # camp.participants = data.get("participants", {}) + for p in data.get("participants", []): + part = CampaignParticipant.fromDict(p) + camp.participants[part.id] = part + for s in data.get("sectors", []): + sec = Sector.fromDict(s) + camp.sectors[sec.id] = sec for rnd_data in data.get("rounds", []): camp.rounds.append(Round.fromDict(rnd_data)) camp.set_state(data.get("is_over", False)) @@ -263,10 +269,13 @@ class Campaign: def remove_round(self, round_id: str) -> None: rnd = next((r for r in self.rounds if r.id == round_id), None) + for sect in self.sectors.values(): + if sect.round_id == round_id: + sect.round_id = None if rnd: self.rounds.remove(rnd) - def get_round_index(self, round_id: str) -> int: + def get_round_index(self, round_id: str | None) -> int | None: if round_id is None: return None for index, rnd in enumerate(self.rounds, start=1): diff --git a/src/warchron/model/campaign_participant.py b/src/warchron/model/campaign_participant.py index aa98528..d7fbc63 100644 --- a/src/warchron/model/campaign_participant.py +++ b/src/warchron/model/campaign_participant.py @@ -1,4 +1,5 @@ from __future__ import annotations +from typing import Any, Dict from uuid import uuid4 @@ -22,3 +23,21 @@ class CampaignParticipant: def set_theme(self, new_theme: str) -> None: self.theme = new_theme + + def toDict(self) -> Dict[str, Any]: + return { + "id": self.id, + "war_participant_id": self.war_participant_id, + "leader": self.leader, + "theme": self.theme, + } + + @staticmethod + def fromDict(data: Dict[str, Any]) -> CampaignParticipant: + part = CampaignParticipant( + war_participant_id=data["war_participant_id"], + leader=data.get("leader"), + theme=data.get("theme"), + ) + part.set_id(data["id"]) + return part diff --git a/src/warchron/model/choice.py b/src/warchron/model/choice.py index d49ec66..9c1479c 100644 --- a/src/warchron/model/choice.py +++ b/src/warchron/model/choice.py @@ -1,3 +1,7 @@ +from __future__ import annotations +from typing import Any, Dict + + class Choice: def __init__( self, @@ -25,3 +29,21 @@ class Choice: def set_comment(self, new_comment: str | None) -> None: self.comment = new_comment + + def toDict(self) -> Dict[str, Any]: + return { + "participant_id": self.participant_id, + "priority_sector_id": self.priority_sector_id, + "secondary_sector_id": self.secondary_sector_id, + "comment": self.comment, + } + + @staticmethod + def fromDict(data: Dict[str, Any]) -> Choice: + choice = Choice( + data["participant_id"], + data.get("priority_sector_id"), + data.get("secondary_sector_id"), + ) + choice.comment = data.get("comment") + return choice diff --git a/src/warchron/model/model.py b/src/warchron/model/model.py index 1f448b3..77abd42 100644 --- a/src/warchron/model/model.py +++ b/src/warchron/model/model.py @@ -380,7 +380,9 @@ class Model: return rnd raise KeyError("Round not found") - def get_round_index(self, round_id: str) -> int: + def get_round_index(self, round_id: str | None) -> int | None: + if round_id is None: + return None camp = self.get_campaign_by_round(round_id) return camp.get_round_index(round_id) diff --git a/src/warchron/model/objective.py b/src/warchron/model/objective.py index d3e5d76..e203ab0 100644 --- a/src/warchron/model/objective.py +++ b/src/warchron/model/objective.py @@ -1,4 +1,5 @@ from __future__ import annotations +from typing import Any, Dict from uuid import uuid4 @@ -16,3 +17,16 @@ class Objective: def set_description(self, new_description: str) -> None: self.description = new_description + + def toDict(self) -> Dict[str, Any]: + return { + "id": self.id, + "name": self.name, + "description": self.description, + } + + @staticmethod + def fromDict(data: Dict[str, Any]) -> Objective: + obj = Objective(data["name"], data["description"]) + obj.set_id(data["id"]) + return obj diff --git a/src/warchron/model/round.py b/src/warchron/model/round.py index 2460d4c..a8a1202 100644 --- a/src/warchron/model/round.py +++ b/src/warchron/model/round.py @@ -22,9 +22,8 @@ class Round: def toDict(self) -> Dict[str, Any]: return { "id": self.id, - # "sectors" : self.sectors, - # "choices" : self.choices, - # "battles" : self.battles, + "choices": [c.toDict() for c in self.choices.values()], + "battles": [b.toDict() for b in self.battles.values()], "is_over": self.is_over, } @@ -32,9 +31,12 @@ class Round: def fromDict(data: Dict[str, Any]) -> Round: rnd = Round() rnd.set_id(data["id"]) - # rnd.sectors = data.get("sectors", {}) - # rnd.choices = data.get("choices", {}) - # rnd.battles = data.get("battles", {}) + for c in data.get("choices", []): + choice = Choice.fromDict(c) + rnd.choices[choice.participant_id] = choice + for b in data.get("battles", []): + battle = Battle.fromDict(b) + rnd.battles[battle.sector_id] = battle rnd.set_state(data.get("is_over", False)) return rnd diff --git a/src/warchron/model/sector.py b/src/warchron/model/sector.py index 47cb4a8..65e8895 100644 --- a/src/warchron/model/sector.py +++ b/src/warchron/model/sector.py @@ -1,4 +1,5 @@ from __future__ import annotations +from typing import Any, Dict from uuid import uuid4 @@ -6,14 +7,14 @@ class Sector: def __init__( self, name: str, - round_id: str, + round_id: str | None, major_id: str | None, minor_id: str | None, influence_id: str | None, ): self.id: str = str(uuid4()) self.name: str = name - self.round_id: str = round_id + self.round_id: str | None = 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 @@ -37,3 +38,29 @@ class Sector: def set_influence(self, new_influence_id: str) -> None: self.influence_objective_id = new_influence_id + + def toDict(self) -> Dict[str, Any]: + return { + "id": self.id, + "name": self.name, + "round_id": self.round_id, + "major_objective_id": self.major_objective_id, + "minor_objective_id": self.minor_objective_id, + "influence_objective_id": self.influence_objective_id, + "mission": self.mission, + "description": self.description, + } + + @staticmethod + def fromDict(data: Dict[str, Any]) -> Sector: + sec = Sector( + data["name"], + data["round_id"], + data.get("major_objective_id"), + data.get("minor_objective_id"), + data.get("influence_objective_id"), + ) + sec.set_id(data["id"]) + sec.mission = data.get("mission") + sec.description = data.get("description") + return sec diff --git a/src/warchron/model/war.py b/src/warchron/model/war.py index 892edeb..2f1bc3e 100644 --- a/src/warchron/model/war.py +++ b/src/warchron/model/war.py @@ -41,7 +41,8 @@ class War: "id": self.id, "name": self.name, "year": self.year, - # "participants" : self.participants, + "participants": [part.toDict() for part in self.participants.values()], + "objectives": [obj.toDict() for obj in self.objectives.values()], "campaigns": [camp.toDict() for camp in self.campaigns], "is_over": self.is_over, } @@ -50,7 +51,12 @@ class War: 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 part_data in data.get("participants", []): + part = WarParticipant.fromDict(part_data) + war.participants[part.id] = part + for obj_data in data.get("objectives", []): + obj = Objective.fromDict(obj_data) + war.objectives[obj.id] = obj for camp_data in data.get("campaigns", []): war.campaigns.append(Campaign.fromDict(camp_data)) war.set_state(data.get("is_over", False)) diff --git a/src/warchron/model/war_participant.py b/src/warchron/model/war_participant.py index 4b405f0..0594bf4 100644 --- a/src/warchron/model/war_participant.py +++ b/src/warchron/model/war_participant.py @@ -1,11 +1,12 @@ from __future__ import annotations +from typing import Any, Dict from uuid import uuid4 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.player_id: str = player_id # ref to Model.players self.faction: str = faction def set_id(self, new_id: str) -> None: @@ -16,3 +17,19 @@ class WarParticipant: def set_faction(self, new_faction: str) -> None: self.faction = new_faction + + def toDict(self) -> Dict[str, Any]: + return { + "id": self.id, + "player_id": self.player_id, + "faction": self.faction, + } + + @staticmethod + def fromDict(data: Dict[str, Any]) -> WarParticipant: + part = WarParticipant( + player_id=data["player_id"], + faction=data["faction"], + ) + part.set_id(data["id"]) + return part diff --git a/src/warchron/view/helpers.py b/src/warchron/view/helpers.py index 3e2f585..35d38a5 100644 --- a/src/warchron/view/helpers.py +++ b/src/warchron/view/helpers.py @@ -21,7 +21,7 @@ def format_campaign_label(camp: CampaignDTO) -> str: return f"{camp.name} ({calendar.month_name[camp.month]})" -def format_round_label(index: int) -> str: +def format_round_label(index: int | None) -> str: if index is None: return "" return f"Round {index}" diff --git a/src/warchron/view/sector_dialog.py b/src/warchron/view/sector_dialog.py index 74312dd..66d0194 100644 --- a/src/warchron/view/sector_dialog.py +++ b/src/warchron/view/sector_dialog.py @@ -23,10 +23,11 @@ class SectorDialog(QDialog): super().__init__(parent) self.ui: Ui_sectorDialog = Ui_sectorDialog() self.ui.setupUi(self) # type: ignore + self.ui.sectorName.setText(default_name) self.ui.majorComboBox.addItem("(none)", None) self.ui.minorComboBox.addItem("(none)", None) self.ui.influenceComboBox.addItem("(none)", None) - self.ui.sectorName.setText(default_name) + self.ui.roundComboBox.addItem("(none)", None) for index, rnd in enumerate(rounds, start=1): self.ui.roundComboBox.addItem(format_round_label(index), rnd.id) select_if_exists(self.ui.roundComboBox, default_round_id) diff --git a/src/warchron/view/view.py b/src/warchron/view/view.py index 8a86271..ca2afc4 100644 --- a/src/warchron/view/view.py +++ b/src/warchron/view/view.py @@ -448,7 +448,7 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): if action == edit_action and self.on_edit_item: self.on_edit_item(ItemType.BATTLE, battle_id) - def show_round_details(self, *, index: int) -> None: + def show_round_details(self, *, index: int | None) -> None: self.roundNb.setText(f"Round {index}") def display_round_choices(self, participants: List[ChoiceDTO]) -> None: