Compare commits

...

4 commits

Author SHA1 Message Date
Maxime Réaux
87670329c2 fix unique participant in war & campaign 2026-02-03 09:28:04 +01:00
Maxime Réaux
49bf6d7ea8 refactor war participant ID + fix campaign participant 2026-02-03 08:25:25 +01:00
Maxime Réaux
ac01568c2f refactor campaign participant ID 2026-02-02 14:33:31 +01:00
Maxime Réaux
fbb1c913ba refacto update ; pretify code 2026-02-02 10:41:16 +01:00
11 changed files with 832 additions and 422 deletions

View file

@ -1,5 +1,6 @@
import sys import sys
import os import os
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "src")) sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "src"))
from PyQt6.QtWidgets import QApplication from PyQt6.QtWidgets import QApplication

View file

@ -6,6 +6,7 @@ from PyQt6.QtCore import Qt
ROLE_TYPE = Qt.ItemDataRole.UserRole ROLE_TYPE = Qt.ItemDataRole.UserRole
ROLE_ID = Qt.ItemDataRole.UserRole + 1 ROLE_ID = Qt.ItemDataRole.UserRole + 1
class ItemType(StrEnum): class ItemType(StrEnum):
PLAYER = "player" PLAYER = "player"
WAR = "war" WAR = "war"
@ -18,6 +19,7 @@ class ItemType(StrEnum):
CHOICE = "choice" CHOICE = "choice"
BATTLE = "battle" BATTLE = "battle"
class RefreshScope(Enum): class RefreshScope(Enum):
NONE = auto() NONE = auto()
PLAYERS_LIST = auto() PLAYERS_LIST = auto()
@ -25,4 +27,3 @@ class RefreshScope(Enum):
WAR_DETAILS = auto() WAR_DETAILS = auto()
CAMPAIGN_DETAILS = auto() CAMPAIGN_DETAILS = auto()
ROUND_DETAILS = auto() ROUND_DETAILS = auto()

View file

@ -6,7 +6,18 @@ from warchron.view.view import View
from warchron.constants import ItemType, RefreshScope from warchron.constants import ItemType, RefreshScope
from warchron.controller.dtos import ParticipantOption from warchron.controller.dtos import ParticipantOption
from warchron.view.view import PlayerDialog, WarDialog, CampaignDialog, ObjectiveDialog, WarParticipantDialog, CampaignParticipantDialog, SectorDialog, ChoicesDialog, BattlesDialog from warchron.view.view import (
PlayerDialog,
WarDialog,
CampaignDialog,
ObjectiveDialog,
WarParticipantDialog,
CampaignParticipantDialog,
SectorDialog,
ChoicesDialog,
BattlesDialog,
)
class Controller: class Controller:
def __init__(self, model: Model, view: View): def __init__(self, model: Model, view: View):
@ -38,7 +49,9 @@ class Controller:
self.view.addObjectiveBtn.clicked.connect(self.add_objective) self.view.addObjectiveBtn.clicked.connect(self.add_objective)
self.view.addWarParticipantBtn.clicked.connect(self.add_war_participant) self.view.addWarParticipantBtn.clicked.connect(self.add_war_participant)
self.view.addSectorBtn.clicked.connect(self.add_sector) self.view.addSectorBtn.clicked.connect(self.add_sector)
self.view.addCampaignParticipantBtn.clicked.connect(self.add_campaign_participant) self.view.addCampaignParticipantBtn.clicked.connect(
self.add_campaign_participant
)
self.view.on_edit_item = self.edit_item self.view.on_edit_item = self.edit_item
self.view.on_delete_item = self.delete_item self.view.on_delete_item = self.delete_item
@ -48,7 +61,9 @@ class Controller:
self.view, self.view,
"Unsaved changes", "Unsaved changes",
"You have unsaved changes. Do you want to save before quitting?", "You have unsaved changes. Do you want to save before quitting?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No | QMessageBox.StandardButton.Cancel QMessageBox.StandardButton.Yes
| QMessageBox.StandardButton.No
| QMessageBox.StandardButton.Cancel,
) )
if reply == QMessageBox.StandardButton.Yes: if reply == QMessageBox.StandardButton.Yes:
self.save() self.save()
@ -56,15 +71,15 @@ class Controller:
return False return False
return True return True
# Menu bar methods # Menu bar methods
def new(self): def new(self):
if self.is_dirty: if self.is_dirty:
reply = QMessageBox.question( reply = QMessageBox.question(
self.view, self.view,
"Unsaved changes", "Unsaved changes",
"Discard current campaign?", "Discard current campaign?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
) )
if reply != QMessageBox.StandardButton.Yes: if reply != QMessageBox.StandardButton.Yes:
return return
@ -81,7 +96,7 @@ class Controller:
self.view, self.view,
"Unsaved changes", "Unsaved changes",
"Discard current campaign?", "Discard current campaign?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
) )
if reply != QMessageBox.StandardButton.Yes: if reply != QMessageBox.StandardButton.Yes:
return return
@ -94,7 +109,7 @@ class Controller:
self.refresh_players_view() self.refresh_players_view()
self.refresh_wars_view() self.refresh_wars_view()
self.update_window_title() self.update_window_title()
def save(self): def save(self):
if not self.current_file: if not self.current_file:
self.save_as() self.save_as()
@ -112,7 +127,7 @@ class Controller:
self.is_dirty = False self.is_dirty = False
self.update_window_title() self.update_window_title()
# Display methods # Display methods
def update_window_title(self): def update_window_title(self):
base = "WarChron" base = "WarChron"
@ -137,12 +152,18 @@ class Controller:
self.view.show_war_details(name=war.name, year=war.year) self.view.show_war_details(name=war.name, year=war.year)
objectives = war.get_all_objectives() objectives = war.get_all_objectives()
self.view.display_war_objectives(objectives) self.view.display_war_objectives(objectives)
participants = war.get_all_war_participants() war_parts = war.get_all_war_participants()
participants_for_display = [ participants_for_display = [
(self.model.get_player_name(p.id), p.faction, p.id) (
for p in participants self.model.get_player_name(
p.player_id,
),
p.faction,
p.id,
)
for p in war_parts
] ]
self.view.display_war_participants(participants_for_display) self.view.display_war_participants(participants_for_display)
def _fill_campaign_details(self, campaign_id: str): def _fill_campaign_details(self, campaign_id: str):
camp = self.model.get_campaign(campaign_id) camp = self.model.get_campaign(campaign_id)
@ -155,14 +176,28 @@ class Controller:
major_name = war.get_objective_name(sect.major_objective_id) major_name = war.get_objective_name(sect.major_objective_id)
minor_name = war.get_objective_name(sect.minor_objective_id) minor_name = war.get_objective_name(sect.minor_objective_id)
influence_name = war.get_objective_name(sect.influence_objective_id) influence_name = war.get_objective_name(sect.influence_objective_id)
sectors_for_display.append((sect.name,round_index,major_name,minor_name,influence_name,sect.id)) sectors_for_display.append(
(
sect.name,
round_index,
major_name,
minor_name,
influence_name,
sect.id,
)
)
self.view.display_campaign_sectors(sectors_for_display) self.view.display_campaign_sectors(sectors_for_display)
participants = camp.get_all_campaign_participants() camp_parts = camp.get_all_campaign_participants()
participants_for_display = [ participants_for_display = [
(self.model.get_player_name(p.id), p.leader, p.theme, p.id) (
for p in participants self.model.get_participant_name(p.war_participant_id),
p.leader,
p.theme,
p.id,
)
for p in camp_parts
] ]
self.view.display_campaign_participants(participants_for_display) self.view.display_campaign_participants(participants_for_display)
def _fill_round_details(self, round_id: str): def _fill_round_details(self, round_id: str):
rnd = self.model.get_round(round_id) rnd = self.model.get_round(round_id)
@ -174,29 +209,47 @@ class Controller:
for part in participants: for part in participants:
choice = rnd.get_choice(part.id) choice = rnd.get_choice(part.id)
if not choice: if not choice:
choice=self.model.create_choice(round_id=rnd.id, participant_id=part.id) choice = self.model.create_choice(
priority_name = camp.get_sector_name(choice.priority_sector_id) if choice else "" round_id=rnd.id, participant_id=part.id
secondary_name = camp.get_sector_name(choice.secondary_sector_id) if choice else "" )
choices_for_display.append(( priority_name = (
self.model.get_player_name(part.id), camp.get_sector_name(choice.priority_sector_id) if choice else ""
priority_name, )
secondary_name, secondary_name = (
choice.participant_id camp.get_sector_name(choice.secondary_sector_id) if choice else ""
)) )
choices_for_display.append(
(
self.model.get_player_name(part.id),
priority_name,
secondary_name,
choice.participant_id,
)
)
self.view.display_round_choices(choices_for_display) self.view.display_round_choices(choices_for_display)
battles_for_display = [] battles_for_display = []
for sect in sectors: for sect in sectors:
battle = rnd.get_battle(sect.id) battle = rnd.get_battle(sect.id)
if not battle: if not battle:
battle=self.model.create_battle(round_id=rnd.id, sector_id=sect.id) battle = self.model.create_battle(round_id=rnd.id, sector_id=sect.id)
player_1_name = self.model.get_player_name(battle.player_1_id) if battle.player_1_id else "" player_1_name = (
player_2_name = self.model.get_player_name(battle.player_2_id) if battle.player_2_id else "" self.model.get_player_name(battle.player_1_id)
battles_for_display.append(( if battle.player_1_id
camp.get_sector_name(battle.sector_id), else ""
player_1_name, )
player_2_name, player_2_name = (
battle.sector_id self.model.get_player_name(battle.player_2_id)
)) if battle.player_2_id
else ""
)
battles_for_display.append(
(
camp.get_sector_name(battle.sector_id),
player_1_name,
player_2_name,
battle.sector_id,
)
)
self.view.display_round_battles(battles_for_display) self.view.display_round_battles(battles_for_display)
def on_tree_selection_changed(self, selection): def on_tree_selection_changed(self, selection):
@ -248,9 +301,11 @@ class Controller:
self._fill_round_details(self.selected_round_id) self._fill_round_details(self.selected_round_id)
self.update_window_title() self.update_window_title()
# Common command methods # Common command methods
def refresh_and_select(self, scope: RefreshScope, *, item_type: ItemType, item_id: str): def refresh_and_select(
self, scope: RefreshScope, *, item_type: ItemType, item_id: str
):
self.refresh(scope) self.refresh(scope)
self.view.select_tree_item(item_type=item_type, item_id=item_id) self.view.select_tree_item(item_type=item_type, item_id=item_id)
@ -261,7 +316,7 @@ class Controller:
if dialog.exec() == QDialog.DialogCode.Accepted: if dialog.exec() == QDialog.DialogCode.Accepted:
name = dialog.get_player_name() name = dialog.get_player_name()
if not self._validate_player_inputs(name): if not self._validate_player_inputs(name):
return return
self.model.update_player(item_id, name=name) self.model.update_player(item_id, name=name)
self.refresh(RefreshScope.PLAYERS_LIST) self.refresh(RefreshScope.PLAYERS_LIST)
elif item_type == ItemType.WAR: elif item_type == ItemType.WAR:
@ -273,20 +328,28 @@ class Controller:
if not self._validate_war_inputs(name, year): if not self._validate_war_inputs(name, year):
return return
self.model.update_war(item_id, name=name, year=year) self.model.update_war(item_id, name=name, year=year)
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war.id) self.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war.id
)
elif item_type == ItemType.CAMPAIGN: elif item_type == ItemType.CAMPAIGN:
camp = self.model.get_campaign(item_id) camp = self.model.get_campaign(item_id)
dialog = CampaignDialog(self.view, default_name=camp.name, default_month=camp.month) dialog = CampaignDialog(
self.view, default_name=camp.name, default_month=camp.month
)
if dialog.exec() == QDialog.DialogCode.Accepted: if dialog.exec() == QDialog.DialogCode.Accepted:
name = dialog.get_campaign_name() name = dialog.get_campaign_name()
month = dialog.get_campaign_month() month = dialog.get_campaign_month()
if not self._validate_campaign_inputs(name, month): if not self._validate_campaign_inputs(name, month):
return return
self.model.update_campaign(item_id, name=name, month=month) self.model.update_campaign(item_id, name=name, month=month)
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.CAMPAIGN, item_id=camp.id) self.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.CAMPAIGN, item_id=camp.id
)
elif item_type == ItemType.OBJECTIVE: elif item_type == ItemType.OBJECTIVE:
obj = self.model.get_objective(item_id) obj = self.model.get_objective(item_id)
dialog = ObjectiveDialog(self.view, default_name=obj.name, default_description=obj.description) dialog = ObjectiveDialog(
self.view, default_name=obj.name, default_description=obj.description
)
if dialog.exec() == QDialog.DialogCode.Accepted: if dialog.exec() == QDialog.DialogCode.Accepted:
name = dialog.get_objective_name() name = dialog.get_objective_name()
description = dialog.get_objective_description() description = dialog.get_objective_description()
@ -295,14 +358,14 @@ class Controller:
self.model.update_objective(item_id, name=name, description=description) self.model.update_objective(item_id, name=name, description=description)
self.refresh(RefreshScope.WAR_DETAILS) self.refresh(RefreshScope.WAR_DETAILS)
elif item_type == ItemType.WAR_PARTICIPANT: elif item_type == ItemType.WAR_PARTICIPANT:
part = self.model.get_war_participant(item_id) camp_part = self.model.get_war_participant(item_id)
player = self.model.get_player(part.id) player = self.model.get_player(camp_part.player_id)
dialog = WarParticipantDialog( dialog = WarParticipantDialog(
self.view, self.view,
players=[player], players=[player],
default_player_id=part.id, default_player_id=camp_part.id,
default_faction=part.faction, default_faction=camp_part.faction,
editable_player=False editable_player=False,
) )
if dialog.exec() == QDialog.DialogCode.Accepted: if dialog.exec() == QDialog.DialogCode.Accepted:
faction = dialog.get_participant_faction() faction = dialog.get_participant_faction()
@ -331,30 +394,33 @@ class Controller:
minor_id = dialog.get_minor_id() minor_id = dialog.get_minor_id()
influence_id = dialog.get_influence_id() influence_id = dialog.get_influence_id()
self.model.update_sector( self.model.update_sector(
item_id, item_id,
name=name, name=name,
round_id=round_id, round_id=round_id,
major_id=major_id, major_id=major_id,
minor_id=minor_id, minor_id=minor_id,
influence_id=influence_id influence_id=influence_id,
) )
self.refresh(RefreshScope.CAMPAIGN_DETAILS) self.refresh(RefreshScope.CAMPAIGN_DETAILS)
elif item_type == ItemType.CAMPAIGN_PARTICIPANT: elif item_type == ItemType.CAMPAIGN_PARTICIPANT:
part = self.model.get_campaign_participant(item_id) camp_part = self.model.get_campaign_participant(item_id)
player = self.model.get_player(part.id) war_part = self.model.get_war_participant(camp_part.war_participant_id)
player = self.model.get_player(war_part.player_id)
part_opt = [ParticipantOption(id=player.id, name=player.name)] part_opt = [ParticipantOption(id=player.id, name=player.name)]
dialog = CampaignParticipantDialog( dialog = CampaignParticipantDialog(
self.view, self.view,
participants=part_opt, participants=part_opt,
default_participant_id=part.id, default_participant_id=camp_part.id,
default_leader=part.leader, default_leader=camp_part.leader,
default_theme=part.theme, default_theme=camp_part.theme,
editable_player=False editable_player=False,
) )
if dialog.exec() == QDialog.DialogCode.Accepted: if dialog.exec() == QDialog.DialogCode.Accepted:
leader = dialog.get_participant_leader() leader = dialog.get_participant_leader()
theme = dialog.get_participant_theme() theme = dialog.get_participant_theme()
self.model.update_campaign_participant(item_id, leader=leader, theme=theme) self.model.update_campaign_participant(
item_id, leader=leader, theme=theme
)
self.refresh(RefreshScope.CAMPAIGN_DETAILS) self.refresh(RefreshScope.CAMPAIGN_DETAILS)
elif item_type == ItemType.CHOICE: elif item_type == ItemType.CHOICE:
self.edit_round_choice(item_id) self.edit_round_choice(item_id)
@ -368,7 +434,7 @@ class Controller:
self.view, self.view,
"Confirm deletion", "Confirm deletion",
"Are you sure you want to delete this item?", "Are you sure you want to delete this item?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
) )
if reply != QMessageBox.StandardButton.Yes: if reply != QMessageBox.StandardButton.Yes:
return return
@ -382,7 +448,9 @@ class Controller:
war = self.model.get_war_by_campaign(item_id) war = self.model.get_war_by_campaign(item_id)
war_id = war.id war_id = war.id
self.model.remove_campaign(item_id) self.model.remove_campaign(item_id)
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war_id) self.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war_id
)
elif item_type == ItemType.OBJECTIVE: elif item_type == ItemType.OBJECTIVE:
self.model.remove_objective(item_id) self.model.remove_objective(item_id)
self.refresh(RefreshScope.WAR_DETAILS) self.refresh(RefreshScope.WAR_DETAILS)
@ -399,22 +467,22 @@ class Controller:
camp = self.model.get_campaign_by_round(item_id) camp = self.model.get_campaign_by_round(item_id)
camp_id = camp.id camp_id = camp.id
self.model.remove_round(item_id) self.model.remove_round(item_id)
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.CAMPAIGN, item_id=camp_id) self.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.CAMPAIGN, item_id=camp_id
)
self.is_dirty = True self.is_dirty = True
# Player methods # Player methods
def _validate_player_inputs(self, name: str) -> bool: def _validate_player_inputs(self, name: str) -> bool:
if not name.strip(): if not name.strip():
QMessageBox.warning( QMessageBox.warning(
self.view, self.view, "Invalid name", "Player name cannot be empty."
"Invalid name",
"Player name cannot be empty."
) )
return False return False
return True return True
def add_player(self): def add_player(self):
dialog = PlayerDialog(self.view) dialog = PlayerDialog(self.view)
result = dialog.exec() # modal blocking dialog result = dialog.exec() # modal blocking dialog
if result == QDialog.DialogCode.Accepted: if result == QDialog.DialogCode.Accepted:
@ -423,29 +491,25 @@ class Controller:
return return
self.model.add_player(name) self.model.add_player(name)
self.is_dirty = True self.is_dirty = True
self.refresh(RefreshScope.PLAYERS_LIST) self.refresh(RefreshScope.PLAYERS_LIST)
# War methods # War methods
def _validate_war_inputs(self, name: str, year: int) -> bool: def _validate_war_inputs(self, name: str, year: int) -> bool:
if not name.strip(): if not name.strip():
QMessageBox.warning( QMessageBox.warning(self.view, "Invalid name", "War name cannot be empty.")
self.view,
"Invalid name",
"War name cannot be empty."
)
return False return False
if not (1970 <= year <= 3000): if not (1970 <= year <= 3000):
QMessageBox.warning( QMessageBox.warning(
self.view, self.view, "Invalid year", "Year must be between 1970 and 3000."
"Invalid year",
"Year must be between 1970 and 3000."
) )
return False return False
return True return True
def add_war(self): def add_war(self):
dialog = WarDialog(self.view, default_year=self.model.get_default_war_values()["year"]) dialog = WarDialog(
self.view, default_year=self.model.get_default_war_values()["year"]
)
result = dialog.exec() # modal blocking dialog result = dialog.exec() # modal blocking dialog
if result == QDialog.DialogCode.Accepted: if result == QDialog.DialogCode.Accepted:
name = dialog.get_war_name() name = dialog.get_war_name()
@ -454,16 +518,16 @@ class Controller:
return return
war = self.model.add_war(name, year) war = self.model.add_war(name, year)
self.is_dirty = True self.is_dirty = True
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war.id) self.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war.id
)
# Objective methods # Objective methods
def _validate_objective_inputs(self, name: str, description: str) -> bool: def _validate_objective_inputs(self, name: str, description: str) -> bool:
if not name.strip(): if not name.strip():
QMessageBox.warning( QMessageBox.warning(
self.view, self.view, "Invalid name", "Objective name cannot be empty."
"Invalid name",
"Objective name cannot be empty."
) )
return False return False
return True return True
@ -477,12 +541,12 @@ class Controller:
name = dialog.get_objective_name() name = dialog.get_objective_name()
description = dialog.get_objective_description() description = dialog.get_objective_description()
if not self._validate_objective_inputs(name, description): if not self._validate_objective_inputs(name, description):
return return
self.model.add_objective(self.selected_war_id, name, description) self.model.add_objective(self.selected_war_id, name, description)
self.is_dirty = True self.is_dirty = True
self.refresh(RefreshScope.WAR_DETAILS) self.refresh(RefreshScope.WAR_DETAILS)
# War participant methods # War participant methods
def add_war_participant(self): def add_war_participant(self):
if not self.selected_war_id: if not self.selected_war_id:
@ -494,26 +558,22 @@ class Controller:
player_id = dialog.get_player_id() player_id = dialog.get_player_id()
faction = dialog.get_participant_faction() faction = dialog.get_participant_faction()
if not player_id: if not player_id:
return return
self.model.add_war_participant(self.selected_war_id, player_id, faction) self.model.add_war_participant(self.selected_war_id, player_id, faction)
self.is_dirty = True self.is_dirty = True
self.refresh(RefreshScope.WAR_DETAILS) self.refresh(RefreshScope.WAR_DETAILS)
# Campaign methods # Campaign methods
def _validate_campaign_inputs(self, name: str, month: int) -> bool: def _validate_campaign_inputs(self, name: str, month: int) -> bool:
if not name.strip(): if not name.strip():
QMessageBox.warning( QMessageBox.warning(
self.view, self.view, "Invalid name", "Campaign name cannot be empty."
"Invalid name",
"Campaign name cannot be empty."
) )
return False return False
if not (1 <= month <= 12): if not (1 <= month <= 12):
QMessageBox.warning( QMessageBox.warning(
self.view, self.view, "Invalid month", "Month must be between 1 and 12."
"Invalid month",
"Month must be between 1 and 12."
) )
return False return False
return True return True
@ -521,7 +581,12 @@ class Controller:
def add_campaign(self): def add_campaign(self):
if not self.selected_war_id: if not self.selected_war_id:
return return
dialog = CampaignDialog(self.view, default_month=self.model.get_default_campaign_values(self.selected_war_id)["month"]) dialog = CampaignDialog(
self.view,
default_month=self.model.get_default_campaign_values(self.selected_war_id)[
"month"
],
)
if dialog.exec() != QDialog.DialogCode.Accepted: if dialog.exec() != QDialog.DialogCode.Accepted:
return return
name = dialog.get_campaign_name() name = dialog.get_campaign_name()
@ -530,15 +595,22 @@ class Controller:
return return
camp = self.model.add_campaign(self.selected_war_id, name, month) camp = self.model.add_campaign(self.selected_war_id, name, month)
self.is_dirty = True self.is_dirty = True
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.CAMPAIGN, item_id=camp.id) self.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.CAMPAIGN, item_id=camp.id
)
# Campaign participant methods # Campaign participant methods
def add_campaign_participant(self): def add_campaign_participant(self):
if not self.selected_campaign_id: if not self.selected_campaign_id:
return return
participants = self.model.get_available_war_participants(self.selected_campaign_id) participants = self.model.get_available_war_participants(
part_opts = [ParticipantOption(id=p.id, name=self.model.get_player_name(p.id)) for p in participants] self.selected_campaign_id
)
part_opts = [
ParticipantOption(id=p.id, name=self.model.get_player_name(p.player_id))
for p in participants
]
dialog = CampaignParticipantDialog(self.view, participants=part_opts) dialog = CampaignParticipantDialog(self.view, participants=part_opts)
if dialog.exec() != QDialog.DialogCode.Accepted: if dialog.exec() != QDialog.DialogCode.Accepted:
return return
@ -546,19 +618,21 @@ class Controller:
leader = dialog.get_participant_leader() leader = dialog.get_participant_leader()
theme = dialog.get_participant_theme() theme = dialog.get_participant_theme()
if not player_id: if not player_id:
return return
self.model.add_campaign_participant(self.selected_campaign_id, player_id, leader, theme) self.model.add_campaign_participant(
self.selected_campaign_id, player_id, leader, theme
)
self.is_dirty = True self.is_dirty = True
self.refresh(RefreshScope.CAMPAIGN_DETAILS) self.refresh(RefreshScope.CAMPAIGN_DETAILS)
# Sector methods # Sector methods
def _validate_sector_inputs(self, name: str, round_id: str, major_id: str, minor_id: str, influence_id:str) -> bool: def _validate_sector_inputs(
self, name: str, round_id: str, major_id: str, minor_id: str, influence_id: str
) -> bool:
if not name.strip(): if not name.strip():
QMessageBox.warning( QMessageBox.warning(
self.view, self.view, "Invalid name", "Sector name cannot be empty."
"Invalid name",
"Sector name cannot be empty."
) )
return False return False
# allow same objectives in different fields? # allow same objectives in different fields?
@ -571,7 +645,9 @@ class Controller:
camp = self.model.get_campaign(self.selected_campaign_id) camp = self.model.get_campaign(self.selected_campaign_id)
rounds = camp.get_all_rounds() rounds = camp.get_all_rounds()
objectives = war.get_all_objectives() objectives = war.get_all_objectives()
dialog = SectorDialog(self.view, default_name="", rounds=rounds, objectives=objectives) dialog = SectorDialog(
self.view, default_name="", rounds=rounds, objectives=objectives
)
if dialog.exec() != QDialog.DialogCode.Accepted: if dialog.exec() != QDialog.DialogCode.Accepted:
return return
name = dialog.get_sector_name() name = dialog.get_sector_name()
@ -579,22 +655,28 @@ class Controller:
major_id = dialog.get_major_id() major_id = dialog.get_major_id()
minor_id = dialog.get_minor_id() minor_id = dialog.get_minor_id()
influence_id = dialog.get_influence_id() influence_id = dialog.get_influence_id()
if not self._validate_sector_inputs(name, round_id, major_id, minor_id, influence_id): if not self._validate_sector_inputs(
return name, round_id, major_id, minor_id, influence_id
self.model.add_sector(self.selected_campaign_id, name, round_id, major_id, minor_id, influence_id) ):
return
self.model.add_sector(
self.selected_campaign_id, name, round_id, major_id, minor_id, influence_id
)
self.is_dirty = True self.is_dirty = True
self.refresh(RefreshScope.CAMPAIGN_DETAILS) self.refresh(RefreshScope.CAMPAIGN_DETAILS)
# Round methods # Round methods
def add_round(self): def add_round(self):
if not self.selected_campaign_id: if not self.selected_campaign_id:
return return
rnd = self.model.add_round(self.selected_campaign_id) rnd = self.model.add_round(self.selected_campaign_id)
self.is_dirty = True self.is_dirty = True
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.ROUND, item_id=rnd.id) self.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.ROUND, item_id=rnd.id
)
# Choice methods # Choice methods
def edit_round_choice(self, choice_id: str): def edit_round_choice(self, choice_id: str):
round_id = self.selected_round_id round_id = self.selected_round_id
@ -609,27 +691,27 @@ class Controller:
return return
part = camp.participants[choice.participant_id] part = camp.participants[choice.participant_id]
player = self.model.get_player(part.id) player = self.model.get_player(part.id)
part_opt = ParticipantOption(id=player.id, name=player.name) part_opt = ParticipantOption(id=player.id, name=player.name)
dialog = ChoicesDialog( dialog = ChoicesDialog(
self.view, self.view,
participants = [part_opt], participants=[part_opt],
default_participant_id=part.id, default_participant_id=part.id,
sectors=sectors, sectors=sectors,
default_priority_id = choice.priority_sector_id, default_priority_id=choice.priority_sector_id,
default_secondary_id = choice.secondary_sector_id, default_secondary_id=choice.secondary_sector_id,
default_comment = choice.comment, default_comment=choice.comment,
) )
if dialog.exec() != QDialog.DialogCode.Accepted: if dialog.exec() != QDialog.DialogCode.Accepted:
return return
# TODO replace by update_choice through self.model... self.model.update_choice(
rnd.update_choice( round_id=round_id,
participant_id = part.id, participant_id=part.id,
priority_sector_id = dialog.get_priority_id(), priority_sector_id=dialog.get_priority_id(),
secondary_sector_id = dialog.get_secondary_id(), secondary_sector_id=dialog.get_secondary_id(),
comment = dialog.get_comment() comment=dialog.get_comment(),
) )
# Battle methods # Battle methods
def edit_round_battle(self, battle_id: str): def edit_round_battle(self, battle_id: str):
round_id = self.selected_round_id round_id = self.selected_round_id
@ -645,31 +727,28 @@ class Controller:
part_opts: list[ParticipantOption] = [] part_opts: list[ParticipantOption] = []
for part in participants: for part in participants:
player = self.model.get_player(part.id) player = self.model.get_player(part.id)
part_opts.append( part_opts.append(ParticipantOption(id=part.id, name=player.name))
ParticipantOption(id=part.id, name=player.name)
)
dialog = BattlesDialog( dialog = BattlesDialog(
self.view, self.view,
sectors = [sect], sectors=[sect],
default_sector_id = sect.id, default_sector_id=sect.id,
players = part_opts, players=part_opts,
default_player_1_id = battle.player_1_id, default_player_1_id=battle.player_1_id,
default_player_2_id = battle.player_2_id, default_player_2_id=battle.player_2_id,
default_winner_id = battle.winner_id, default_winner_id=battle.winner_id,
default_score = battle.score, default_score=battle.score,
default_victory_condition = battle.victory_condition, default_victory_condition=battle.victory_condition,
default_comment = battle.comment, default_comment=battle.comment,
) )
if dialog.exec() != QDialog.DialogCode.Accepted: if dialog.exec() != QDialog.DialogCode.Accepted:
return return
# TODO replace by update_battle through self.model... self.model.update_battle(
rnd.update_battle( round_id=round_id,
sector_id = sect.id, sector_id=sect.id,
player_1_id = dialog.get_player_1_id(), player_1_id=dialog.get_player_1_id(),
player_2_id = dialog.get_player_2_id(), player_2_id=dialog.get_player_2_id(),
winner_id = dialog.get_winner_id(), winner_id=dialog.get_winner_id(),
score = dialog.get_score(), score=dialog.get_score(),
victory_condition = dialog.get_victory_condition(), victory_condition=dialog.get_victory_condition(),
comment = dialog.get_comment(), comment=dialog.get_comment(),
) )

View file

@ -1,5 +1,6 @@
from dataclasses import dataclass from dataclasses import dataclass
@dataclass(frozen=True) @dataclass(frozen=True)
class ParticipantOption: class ParticipantOption:
id: str id: str

View file

@ -1,8 +1,9 @@
from __future__ import annotations from __future__ import annotations
from uuid import uuid4 from uuid import uuid4
from warchron.model.round import Round, Choice, Battle from warchron.model.round import Round, Choice, Battle
class Campaign: class Campaign:
def __init__(self, name: str, month: int): def __init__(self, name: str, month: int):
self.id: str = str(uuid4()) self.id: str = str(uuid4())
@ -21,20 +22,20 @@ class Campaign:
def set_month(self, new_month: int): def set_month(self, new_month: int):
self.month = new_month self.month = new_month
def set_state(self, new_state: bool): def set_state(self, new_state: bool):
self.is_over = new_state self.is_over = new_state
def toDict(self): def toDict(self):
return { return {
"id" : self.id, "id": self.id,
"name" : self.name, "name": self.name,
"month" : self.month, "month": self.month,
# "participants" : self.participants, # "participants" : self.participants,
"rounds": [rnd.toDict() for rnd in self.rounds], "rounds": [rnd.toDict() for rnd in self.rounds],
"is_over": self.is_over "is_over": self.is_over,
} }
@staticmethod @staticmethod
def fromDict(data: dict): def fromDict(data: dict):
camp = Campaign(name=data["name"], month=data["month"]) camp = Campaign(name=data["name"], month=data["month"])
@ -45,47 +46,65 @@ class Campaign:
camp.set_state(data.get("is_over", False)) camp.set_state(data.get("is_over", False))
return camp return camp
# Campaign participant methods # Campaign participant methods
def get_all_campaign_participants_ids(self) -> set[str]: def get_all_campaign_participants_ids(self) -> set[str]:
return set(self.participants.keys()) return set(self.participants.keys())
def has_participant(self, player_id: str) -> bool: def has_participant(self, participant_id: str) -> bool:
return player_id in self.participants return participant_id in self.participants
def add_campaign_participant(self, player_id: str, leader: str, theme: str) -> CampaignParticipant: def has_war_participant(self, war_participant_id: str) -> bool:
if player_id in self.participants: return any(
part.war_participant_id == war_participant_id
for part in self.participants.values()
)
def add_campaign_participant(
self, war_participant_id: str, leader: str, theme: str
) -> CampaignParticipant:
if self.has_war_participant(war_participant_id):
raise ValueError("Player already registered in this campaign") 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 self.participants[participant.id] = participant
return participant return participant
def get_campaign_participant(self, id: str) -> CampaignParticipant: def get_campaign_participant(self, participant_id: str) -> CampaignParticipant:
return self.participants[id] 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]: def get_all_campaign_participants(self) -> list[CampaignParticipant]:
return list(self.participants.values()) return list(self.participants.values())
def update_campaign_participant(self, player_id: str, *, leader: str, theme: str): def update_campaign_participant(
part = self.get_campaign_participant(player_id) 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_leader(leader)
part.set_theme(theme) 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 choices referring to it
# TODO manage battles 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) sect = Sector(name, round_id, major_id, minor_id, influence_id)
self.sectors[sect.id] = sect self.sectors[sect.id] = sect
return sect return sect
def get_sector(self, sector_id: str) -> Sector: def get_sector(self, sector_id: str) -> Sector:
return self.sectors[sector_id] return self.sectors[sector_id]
def get_sector_name(self, sector_id: str) -> str: def get_sector_name(self, sector_id: str) -> str:
if sector_id is None: if sector_id is None:
return "" return ""
@ -95,31 +114,37 @@ class Campaign:
return list(self.sectors.values()) return list(self.sectors.values())
# TODO manage choices referring to it (round order!) # 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 = self.get_sector(sector_id)
sect.set_name(name) sect.set_name(name)
sect.set_round(round_id) sect.set_round(round_id)
sect.set_major(major_id) sect.set_major(major_id)
sect.set_minor(minor_id) sect.set_minor(minor_id)
sect.set_influence(influence_id) sect.set_influence(influence_id)
def remove_sector(self, sector_id: str): def remove_sector(self, sector_id: str):
# TODO manage choices referring to it # TODO manage choices referring to it
# TODO manage battles referring to it # TODO manage battles referring to it
del self.sectors[sector_id] del self.sectors[sector_id]
def get_sectors_in_round(self, round_id: str) -> list[Sector]: def get_sectors_in_round(self, round_id: str) -> list[Sector]:
sectors = [ sectors = [s for s in self.sectors.values() if s.round_id == round_id]
s for s in self.sectors.values()
if s.round_id == round_id
]
return sectors return sectors
# Round methods # Round methods
def has_round(self, round_id: str) -> bool: def has_round(self, round_id: str) -> bool:
return any(r.id == round_id for r in self.rounds) return any(r.id == round_id for r in self.rounds)
def get_round(self, round_id: str) -> Round: def get_round(self, round_id: str) -> Round:
for rnd in self.rounds: for rnd in self.rounds:
if rnd.id == round_id: if rnd.id == round_id:
@ -128,12 +153,12 @@ class Campaign:
def get_all_rounds(self) -> list[Round]: def get_all_rounds(self) -> list[Round]:
return list(self.rounds) return list(self.rounds)
def add_round(self) -> Round: def add_round(self) -> Round:
round = Round() round = Round()
self.rounds.append(round) self.rounds.append(round)
return round return round
def remove_round(self, round_id: str): def remove_round(self, round_id: str):
rnd = next((r for r in self.rounds if r.id == round_id), None) rnd = next((r for r in self.rounds if r.id == round_id), None)
if rnd: if rnd:
@ -148,56 +173,106 @@ class Campaign:
raise KeyError("Round not found in campaign") raise KeyError("Round not found in campaign")
def get_round_name(self, round_id: str | None) -> str: def get_round_name(self, round_id: str | None) -> str:
if round_id is None: if round_id is None:
return ""
for rnd in self.rounds:
if rnd.id == round_id:
return rnd.name
return "" 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: def create_choice(self, round_id: str, participant_id: str) -> Choice:
rnd = self.get_round(round_id) rnd = self.get_round(round_id)
return rnd.create_choice(participant_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,
):
rnd = self.get_round(round_id)
rnd.update_choice(
participant_id, priority_sector_id, secondary_sector_id, comment
)
def remove_choice(self, round_id: str, participant_id: str) -> Choice: def remove_choice(self, round_id: str, participant_id: str) -> Choice:
rnd = self.get_round(round_id) rnd = self.get_round(round_id)
rnd.remove_choice(participant_id) rnd.remove_choice(participant_id)
# Battle methods # Battle methods
def create_battle(self, round_id: str, sector_id: str) -> Battle: def create_battle(self, round_id: str, sector_id: str) -> Battle:
rnd = self.get_round(round_id) rnd = self.get_round(round_id)
return rnd.create_battle(sector_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,
):
rnd = self.get_round(round_id)
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: def remove_battle(self, round_id: str, sector_id: str) -> Battle:
rnd = self.get_round(round_id) rnd = self.get_round(round_id)
rnd.remove_battle(sector_id) rnd.remove_battle(sector_id)
class CampaignParticipant: class CampaignParticipant:
def __init__(self, player_id: str, leader: str, theme: str): def __init__(
self.id: str = player_id # ref to War.participants self, *, war_participant_id: str, leader: str | None, theme: str | None
self.leader: str = leader ):
self.theme: str = theme self.id: str = str(uuid4())
self.war_participant_id: str = war_participant_id # ref to War.participants
self.leader: str | None = leader
self.theme: str | None = theme
def set_id(self, new_id: str): def set_id(self, new_id: str):
self.id = new_id 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): def set_leader(self, new_faction: str):
self.leader = new_faction self.leader = new_faction
def set_theme(self, new_theme: str): def set_theme(self, new_theme: str):
self.theme = new_theme self.theme = new_theme
class Sector: 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 | None,
minor_id: str | None,
influence_id: str | None,
):
self.id: str = str(uuid4()) self.id: str = str(uuid4())
self.name: str = name self.name: str = name
self.round_id: str = round_id self.round_id: str = round_id
self.major_objective_id: str | None = major_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.minor_objective_id: str | None = minor_id # ref to War.objectives
self.influence_objective_id: str | None = influence_id # ref to War.objectives self.influence_objective_id: str | None = influence_id # ref to War.objectives
self.mission: str | None = None self.mission: str | None = None
self.description: str | None = None self.description: str | None = None

View file

@ -8,12 +8,13 @@ from warchron.model.war import War, Objective, WarParticipant
from warchron.model.campaign import Campaign, Sector, CampaignParticipant from warchron.model.campaign import Campaign, Sector, CampaignParticipant
from warchron.model.round import Round, Choice, Battle from warchron.model.round import Round, Choice, Battle
class Model: class Model:
def __init__(self): def __init__(self):
self.players: dict[str, Player] = {} self.players: dict[str, Player] = {}
self.wars: dict[str, War] = {} self.wars: dict[str, War] = {}
# File management methods # File management methods
def new(self): def new(self):
self.players.clear() self.players.clear()
@ -23,13 +24,13 @@ class Model:
self.players.clear() self.players.clear()
self.wars.clear() self.wars.clear()
self._load_data(path) self._load_data(path)
def save(self, path: Path): def save(self, path: Path):
self._save_data(path) self._save_data(path)
def _load_data(self, path: Path): def _load_data(self, path: Path):
if not path.exists() or path.stat().st_size == 0: if not path.exists() or path.stat().st_size == 0:
return # Start empty return # Start empty
try: try:
with open(path, "r", encoding="utf-8") as f: with open(path, "r", encoding="utf-8") as f:
data = json.load(f) data = json.load(f)
@ -40,7 +41,7 @@ class Model:
self.players[player.id] = player self.players[player.id] = player
for w in data.get("wars", []): for w in data.get("wars", []):
war = War.fromDict(w) war = War.fromDict(w)
self.wars[war.id] = war self.wars[war.id] = war
except json.JSONDecodeError: except json.JSONDecodeError:
raise RuntimeError("Data file is corrupted") raise RuntimeError("Data file is corrupted")
@ -50,12 +51,12 @@ class Model:
data = { data = {
"version": "1.0", "version": "1.0",
"players": [p.toDict() for p in self.players.values()], "players": [p.toDict() for p in self.players.values()],
"wars": [w.toDict() for w in self.wars.values()] "wars": [w.toDict() for w in self.wars.values()],
} }
with open(path, "w", encoding="utf-8") as f: with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2) json.dump(data, f, indent=2)
# Player methods # Player methods
def add_player(self, name): def add_player(self, name):
player = Player(name) player = Player(name)
@ -64,7 +65,7 @@ class Model:
def get_player(self, id): def get_player(self, id):
return self.players[id] return self.players[id]
def get_player_name(self, player_id: str) -> str: def get_player_name(self, player_id: str) -> str:
return self.players[player_id].name return self.players[player_id].name
@ -79,12 +80,10 @@ class Model:
# TODO manage war_participants referring to it # TODO manage war_participants referring to it
del self.players[player_id] del self.players[player_id]
# War methods # War methods
def get_default_war_values(self) -> dict: def get_default_war_values(self) -> dict:
return { return {"year": datetime.now().year}
"year": datetime.now().year
}
def add_war(self, name: str, year: int) -> War: def add_war(self, name: str, year: int) -> War:
war = War(name, year) war = War(name, year)
@ -93,7 +92,7 @@ class Model:
def get_war(self, id) -> War: def get_war(self, id) -> War:
return self.wars[id] return self.wars[id]
def get_war_by_campaign(self, campaign_id: str) -> War: def get_war_by_campaign(self, campaign_id: str) -> War:
for war in self.wars.values(): for war in self.wars.values():
for camp in war.campaigns: for camp in war.campaigns:
@ -124,14 +123,19 @@ class Model:
return war return war
raise KeyError(f"Objective {objective_id} not found in any War") raise KeyError(f"Objective {objective_id} not found in any War")
# 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: def get_war_by_war_participant(self, participant_id: str) -> War:
for war in self.wars.values(): for war in self.wars.values():
for part in war.participants.values(): if war.has_participant(participant_id):
if part.id == participant_id: return war
return war
raise KeyError(f"Participant {participant_id} not found in any War") raise KeyError(f"Participant {participant_id} not found in any War")
def get_war_by_campaign_participant(self, participant_id: str) -> War:
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): def update_war(self, war_id: str, *, name: str, year: int):
war = self.get_war(war_id) war = self.get_war(war_id)
war.set_name(name) war.set_name(name)
@ -143,7 +147,7 @@ class Model:
def remove_war(self, war_id: str): def remove_war(self, war_id: str):
del self.wars[war_id] del self.wars[war_id]
# Objective methods # Objective methods
def add_objective(self, war_id: str, name: str, description: str) -> Objective: def add_objective(self, war_id: str, name: str, description: str) -> Objective:
war = self.get_war(war_id) war = self.get_war(war_id)
@ -164,17 +168,17 @@ class Model:
war = self.get_war_by_objective(objective_id) war = self.get_war_by_objective(objective_id)
war.remove_objective(objective_id) war.remove_objective(objective_id)
# War participant methods # War participant methods
def get_available_players(self, war_id: str) -> list[Player]: def get_available_players(self, war_id: str) -> list[Player]:
war = self.get_war(war_id) war = self.get_war(war_id)
return [ return [
player player for player in self.players.values() if not war.has_player(player.id)
for player in self.players.values()
if not war.has_participant(player.id)
] ]
def add_war_participant(self, war_id: str, player_id: str, faction: str) -> WarParticipant: def add_war_participant(
self, war_id: str, player_id: str, faction: str
) -> WarParticipant:
war = self.get_war(war_id) war = self.get_war(war_id)
return war.add_war_participant(player_id, faction) return war.add_war_participant(player_id, faction)
@ -193,7 +197,7 @@ class Model:
war = self.get_war_by_war_participant(participant_id) war = self.get_war_by_war_participant(participant_id)
war.remove_war_participant(participant_id) war.remove_war_participant(participant_id)
# Campaign methods # Campaign methods
def get_default_campaign_values(self, war_id: str) -> dict: def get_default_campaign_values(self, war_id: str) -> dict:
war = self.get_war(war_id) war = self.get_war(war_id)
@ -217,7 +221,6 @@ class Model:
return camp return camp
raise KeyError(f"Round {round_id} not found") 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: def get_campaign_by_campaign_participant(self, participant_id: str) -> Campaign:
for war in self.wars.values(): for war in self.wars.values():
camp = war.get_campaign_by_campaign_participant(participant_id) camp = war.get_campaign_by_campaign_participant(participant_id)
@ -240,9 +243,17 @@ class Model:
war = self.get_war_by_campaign(campaign_id) war = self.get_war_by_campaign(campaign_id)
war.remove_campaign(campaign_id) war.remove_campaign(campaign_id)
# Sector methods # Sector methods
def add_sector(self, campaign_id: str, name: str, round_id: str, major_id: str, minor_id: str, influence_id: str) -> Sector: 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) camp = self.get_campaign(campaign_id)
return camp.add_sector(name, round_id, major_id, minor_id, influence_id) return camp.add_sector(name, round_id, major_id, minor_id, influence_id)
@ -254,24 +265,47 @@ class Model:
return sect return sect
raise KeyError("Sector not found") 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): def update_sector(
self,
sector_id: str,
*,
name: str,
round_id: str,
major_id: str,
minor_id: str,
influence_id: str,
):
war = self.get_war_by_sector(sector_id) war = self.get_war_by_sector(sector_id)
war.update_sector(sector_id, name=name, round_id=round_id, major_id=major_id, minor_id=minor_id, influence_id=influence_id) war.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): def remove_sector(self, sector_id: str):
camp = self.get_campaign_by_sector(sector_id) camp = self.get_campaign_by_sector(sector_id)
camp.remove_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]: def get_available_war_participants(self, campaign_id: str) -> list[WarParticipant]:
war = self.get_war_by_campaign(campaign_id) war = self.get_war_by_campaign(campaign_id)
return war.get_available_war_participants(campaign_id) return war.get_available_war_participants(campaign_id)
def add_campaign_participant(self, camp_id: str, player_id: str, leader: str, theme: str) -> CampaignParticipant: def add_campaign_participant(
self, camp_id: str, player_id: str, leader: str, theme: str
) -> CampaignParticipant:
camp = self.get_campaign(camp_id) camp = self.get_campaign(camp_id)
return camp.add_campaign_participant(player_id, leader, theme) return camp.add_campaign_participant(player_id, leader, theme)
def get_participant_name(self, participant_id: str) -> str:
war = self.get_war_by_war_participant(participant_id)
war_part = war.get_war_participant(participant_id)
return self.players[war_part.player_id].name
def get_campaign_participant(self, participant_id) -> CampaignParticipant: def get_campaign_participant(self, participant_id) -> CampaignParticipant:
for war in self.wars.values(): for war in self.wars.values():
for camp in war.campaigns: for camp in war.campaigns:
@ -280,20 +314,26 @@ class Model:
return part return part
raise KeyError("Participant not found") raise KeyError("Participant not found")
def update_campaign_participant(self, participant_id: str, *, leader: str, theme: str): def update_campaign_participant(
camp = self.get_campaign_by_campaign_participant(participant_id) self,
camp.update_campaign_participant(participant_id, leader=leader, theme=theme) participant_id: str,
*,
leader: str,
theme: str,
):
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): def remove_campaign_participant(self, participant_id: str):
camp = self.get_campaign_by_campaign_participant(participant_id) war = self.get_war_by_campaign_participant(participant_id)
camp.remove_campaign_participant(participant_id) war.remove_campaign_participant(participant_id)
# Round methods # Round methods
def add_round(self, campaign_id: str) -> Round: def add_round(self, campaign_id: str) -> Round:
camp = self.get_campaign(campaign_id) camp = self.get_campaign(campaign_id)
return camp.add_round() return camp.add_round()
def get_round(self, round_id: str) -> Round: def get_round(self, round_id: str) -> Round:
for war in self.wars.values(): for war in self.wars.values():
for camp in war.campaigns: for camp in war.campaigns:
@ -305,7 +345,7 @@ class Model:
def get_round_index(self, round_id: str) -> int: def get_round_index(self, round_id: str) -> int:
camp = self.get_campaign_by_round(round_id) camp = self.get_campaign_by_round(round_id)
return camp.get_round_index(round_id) return camp.get_round_index(round_id)
def get_round_sectors(self, round_id: str) -> list[Sector]: def get_round_sectors(self, round_id: str) -> list[Sector]:
camp = self.get_campaign_by_round(round_id) camp = self.get_campaign_by_round(round_id)
return [s for s in camp.sectors.values() if s.round_id == round_id] return [s for s in camp.sectors.values() if s.round_id == round_id]
@ -318,33 +358,65 @@ class Model:
war = self.get_war_by_round(round_id) war = self.get_war_by_round(round_id)
war.remove_round(round_id) war.remove_round(round_id)
# Choice methods # Choice methods
def create_choice(self, round_id: str, participant_id: str) -> Choice: def create_choice(self, round_id: str, participant_id: str) -> Choice:
war = self.get_war_by_round(round_id) war = self.get_war_by_round(round_id)
return war.create_choice(round_id, participant_id) return war.create_choice(round_id, participant_id)
def remove_choice(self, round_id: str, participant_id: str):
war = self.get_war_by_round(round_id)
war.remove_choice(round_id, participant_id)
def get_round_choices_data(self, round_id: str): def get_round_choices_data(self, round_id: str):
camp = self.get_campaign_by_round(round_id) camp = self.get_campaign_by_round(round_id)
rnd = self.get_round(round_id) rnd = self.get_round(round_id)
participants = camp.participants.values() participants = camp.participants.values()
sectors = [ sectors = [s for s in camp.sectors.values() if s.round_id == round_id]
s for s in camp.sectors.values()
if s.round_id == round_id
]
return camp, rnd, participants, sectors return camp, rnd, participants, sectors
# Battle methods def update_choice(
self,
round_id: str,
participant_id: str,
priority_sector_id: str | None,
secondary_sector_id: str | None,
comment: str | None,
):
war = self.get_war_by_round(round_id)
war.update_choice(
round_id, participant_id, priority_sector_id, secondary_sector_id, comment
)
def remove_choice(self, round_id: str, participant_id: str):
war = self.get_war_by_round(round_id)
war.remove_choice(round_id, participant_id)
# Battle methods
def create_battle(self, round_id: str, sector_id: str) -> Battle: def create_battle(self, round_id: str, sector_id: str) -> Battle:
war = self.get_war_by_round(round_id) war = self.get_war_by_round(round_id)
return war.create_battle(round_id, sector_id) return war.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,
):
war = self.get_war_by_round(round_id)
war.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): def remove_battle(self, round_id: str, sector_id: str):
war = self.get_war_by_round(round_id) war = self.get_war_by_round(round_id)
war.remove_battle(round_id, sector_id) war.remove_battle(round_id, sector_id)

View file

@ -1,10 +1,11 @@
from uuid import uuid4 from uuid import uuid4
class Player: class Player:
def __init__(self, name ): def __init__(self, name):
self.id = str(uuid4()) self.id = str(uuid4())
self.name = name self.name = name
def set_id(self, new_id): def set_id(self, new_id):
self.id = new_id self.id = new_id
@ -12,13 +13,10 @@ class Player:
self.name = name self.name = name
def toDict(self): def toDict(self):
return { return {"id": self.id, "name": self.name}
"id" : self.id,
"name" : self.name
}
@staticmethod @staticmethod
def fromDict(data: dict): def fromDict(data: dict):
play = Player(name=data["name"]) play = Player(name=data["name"])
play.set_id(data["id"]) play.set_id(data["id"])
return play return play

View file

@ -4,6 +4,7 @@ from pathlib import Path
DATA_FILE = Path("data/warmachron.json") DATA_FILE = Path("data/warmachron.json")
def load_data(): def load_data():
if not DATA_FILE.exists() or DATA_FILE.stat().st_size == 0: if not DATA_FILE.exists() or DATA_FILE.stat().st_size == 0:
return {"version": 1, "players": {}, "wars": []} return {"version": 1, "players": {}, "wars": []}
@ -14,6 +15,7 @@ def load_data():
except json.JSONDecodeError: except json.JSONDecodeError:
raise RuntimeError("Data file is corrupted") raise RuntimeError("Data file is corrupted")
def save_data(data): def save_data(data):
if DATA_FILE.exists(): if DATA_FILE.exists():
shutil.copy(DATA_FILE, DATA_FILE.with_suffix(".json.bak")) shutil.copy(DATA_FILE, DATA_FILE.with_suffix(".json.bak"))

View file

@ -1,5 +1,6 @@
from __future__ import annotations from __future__ import annotations
from uuid import uuid4 from uuid import uuid4
class Round: class Round:
def __init__(self): def __init__(self):
@ -20,7 +21,7 @@ class Round:
# "sectors" : self.sectors, # "sectors" : self.sectors,
# "choices" : self.choices, # "choices" : self.choices,
# "battles" : self.battles, # "battles" : self.battles,
"is_over": self.is_over "is_over": self.is_over,
} }
@staticmethod @staticmethod
@ -32,47 +33,58 @@ class Round:
# rnd.battles = data.get("battles", {}) # rnd.battles = data.get("battles", {})
rnd.set_state(data.get("is_over", False)) rnd.set_state(data.get("is_over", False))
return rnd return rnd
# Choice methods # Choice methods
def get_choice(self, participant_id: str) -> Choice | None: def get_choice(self, participant_id: str) -> Choice | None:
return self.choices.get(participant_id) return self.choices.get(participant_id)
def create_choice(self, participant_id: str) -> Choice: def create_choice(self, participant_id: str) -> Choice:
if participant_id not in self.choices: if participant_id not in self.choices:
choice = Choice( choice = Choice(
participant_id = participant_id, participant_id=participant_id,
priority_sector_id = None, priority_sector_id=None,
secondary_sector_id = None secondary_sector_id=None,
) )
self.choices[participant_id] = choice self.choices[participant_id] = choice
return self.choices[participant_id] return self.choices[participant_id]
def update_choice(self, participant_id: str, priority_sector_id: str | None, secondary_sector_id: str | None, comment: str | None): def update_choice(
self,
participant_id: str,
priority_sector_id: str | None,
secondary_sector_id: str | None,
comment: str | None,
):
choice = self.get_choice(participant_id) choice = self.get_choice(participant_id)
choice.set_priority(priority_sector_id) choice.set_priority(priority_sector_id)
choice.set_secondary(secondary_sector_id) choice.set_secondary(secondary_sector_id)
choice.set_comment(comment) choice.set_comment(comment)
def remove_choice(self,participant_id: str): def remove_choice(self, participant_id: str):
del self.choices[participant_id] del self.choices[participant_id]
# Battle methods # Battle methods
def get_battle(self, sector_id: str) -> Battle | None: def get_battle(self, sector_id: str) -> Battle | None:
return self.battles.get(sector_id) return self.battles.get(sector_id)
def create_battle(self, sector_id: str) -> Battle: def create_battle(self, sector_id: str) -> Battle:
if sector_id not in self.battles: if sector_id not in self.battles:
battle = Battle( battle = Battle(sector_id=sector_id, player_1_id=None, player_2_id=None)
sector_id = sector_id,
player_1_id = None,
player_2_id = None
)
self.battles[sector_id] = battle self.battles[sector_id] = battle
return self.battles[sector_id] return self.battles[sector_id]
def update_battle(self, 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,
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,
):
bat = self.get_battle(sector_id) bat = self.get_battle(sector_id)
bat.set_player_1(player_1_id) bat.set_player_1(player_1_id)
bat.set_player_2(player_2_id) bat.set_player_2(player_2_id)
@ -81,14 +93,24 @@ class Round:
bat.set_victory_condition(victory_condition) bat.set_victory_condition(victory_condition)
bat.set_comment(comment) bat.set_comment(comment)
def remove_battle(self,sector_id: str): def remove_battle(self, sector_id: str):
del self.battles[sector_id] del self.battles[sector_id]
class Choice: class Choice:
def __init__(self, participant_id: str, priority_sector_id: str | None = None, secondary_sector_id: str | None = None): def __init__(
self.participant_id: str = participant_id # ref to Campaign.participants self,
self.priority_sector_id: str | None = priority_sector_id # ref to Campaign.sectors participant_id: str,
self.secondary_sector_id: str | None = secondary_sector_id # ref to Campaign.sectors priority_sector_id: str | None = None,
secondary_sector_id: str | None = None,
):
self.participant_id: str = participant_id # ref to Campaign.participants
self.priority_sector_id: str | None = (
priority_sector_id # ref to Campaign.sectors
)
self.secondary_sector_id: str | None = (
secondary_sector_id # ref to Campaign.sectors
)
self.comment: str | None = None self.comment: str | None = None
def set_id(self, new_id: str): def set_id(self, new_id: str):
@ -103,11 +125,17 @@ class Choice:
def set_comment(self, new_comment: str): def set_comment(self, new_comment: str):
self.comment = new_comment self.comment = new_comment
class Battle: class Battle:
def __init__(self, sector_id: str, player_1_id: str | None = None, player_2_id: str | None = None): def __init__(
self.sector_id: str = sector_id # ref to Campaign.sector self,
self.player_1_id: str | None = player_1_id # ref to Campaign.participants sector_id: str,
self.player_2_id: str | None = player_2_id # ref to Campaign.participants player_1_id: str | None = None,
player_2_id: str | None = None,
):
self.sector_id: str = sector_id # ref to Campaign.sector
self.player_1_id: str | None = player_1_id # ref to Campaign.participants
self.player_2_id: str | None = player_2_id # ref to Campaign.participants
self.winner_id: str | None = None self.winner_id: str | None = None
self.score: str | None = None self.score: str | None = None
self.victory_condition: str | None = None self.victory_condition: str | None = None
@ -121,7 +149,7 @@ class Battle:
def set_player_2(self, new_player_id: str): def set_player_2(self, new_player_id: str):
self.player_2_id = new_player_id self.player_2_id = new_player_id
def set_winner(self, new_player_id: str): def set_winner(self, new_player_id: str):
self.winner_id = new_player_id self.winner_id = new_player_id
@ -132,4 +160,4 @@ class Battle:
self.victory_condition = new_victory_condition self.victory_condition = new_victory_condition
def set_comment(self, new_comment: str): def set_comment(self, new_comment: str):
self.comment = new_comment self.comment = new_comment

View file

@ -1,5 +1,5 @@
from __future__ import annotations from __future__ import annotations
from uuid import uuid4 from uuid import uuid4
from datetime import datetime from datetime import datetime
from warchron.model.campaign import Campaign, Sector, CampaignParticipant from warchron.model.campaign import Campaign, Sector, CampaignParticipant
@ -11,7 +11,7 @@ class War:
self.id: str = str(uuid4()) self.id: str = str(uuid4())
self.name: str = name self.name: str = name
self.year: int = year self.year: int = year
self.participants: dict[str, WarParticipant] = {} self.participants: dict[str, WarParticipant] = {}
self.objectives: dict[str, Objective] = {} self.objectives: dict[str, Objective] = {}
self.campaigns: list[Campaign] = [] self.campaigns: list[Campaign] = []
self.is_over: bool = False self.is_over: bool = False
@ -24,20 +24,20 @@ class War:
def set_year(self, new_year: int): def set_year(self, new_year: int):
self.year = new_year self.year = new_year
def set_state(self, new_state: bool): def set_state(self, new_state: bool):
self.is_over = new_state self.is_over = new_state
def toDict(self): def toDict(self):
return { return {
"id" : self.id, "id": self.id,
"name" : self.name, "name": self.name,
"year" : self.year, "year": self.year,
# "participants" : self.participants, # "participants" : self.participants,
"campaigns": [camp.toDict() for camp in self.campaigns], "campaigns": [camp.toDict() for camp in self.campaigns],
"is_over": self.is_over "is_over": self.is_over,
} }
@staticmethod @staticmethod
def fromDict(data: dict): def fromDict(data: dict):
war = War(name=data["name"], year=data["year"]) war = War(name=data["name"], year=data["year"])
@ -48,7 +48,7 @@ class War:
war.set_state(data.get("is_over", False)) war.set_state(data.get("is_over", False))
return war return war
# Objective methods # Objective methods
def add_objective(self, name: str, description: str) -> Objective: def add_objective(self, name: str, description: str) -> Objective:
obj = Objective(name, description) obj = Objective(name, description)
@ -66,28 +66,31 @@ class War:
return "" return ""
obj = self.objectives.get(objective_id) obj = self.objectives.get(objective_id)
return obj.name if obj else "" return obj.name if obj else ""
def update_objective(self, objective_id: str, *, name: str, description: str): def update_objective(self, objective_id: str, *, name: str, description: str):
obj = self.get_objective(objective_id) obj = self.get_objective(objective_id)
obj.set_name(name) obj.set_name(name)
obj.set_description(description) obj.set_description(description)
def remove_objective(self, objective_id: str): def remove_objective(self, objective_id: str):
# TODO manage sectors referring to it # TODO manage sectors referring to it
del self.objectives[objective_id] del self.objectives[objective_id]
# War participant methods # War participant methods
def get_all_war_participants_ids(self) -> set[str]: def get_all_war_participants_ids(self) -> set[str]:
return set(self.participants.keys()) return set(self.participants.keys())
def has_participant(self, player_id: str) -> bool: def has_participant(self, participant_id: str) -> bool:
return player_id in self.participants 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: def add_war_participant(self, player_id: str, faction: str) -> WarParticipant:
if player_id in self.participants: if self.has_player(player_id):
raise ValueError("Player already registered in this war") raise ValueError("Player already registered in this war")
participant = WarParticipant(player_id, faction) participant = WarParticipant(player_id=player_id, faction=faction)
self.participants[participant.id] = participant self.participants[participant.id] = participant
return participant return participant
@ -99,22 +102,21 @@ class War:
def update_war_participant(self, player_id: str, *, faction: str): def update_war_participant(self, player_id: str, *, faction: str):
part = self.get_war_participant(player_id) part = self.get_war_participant(player_id)
# Can't change referred Model.players
part.set_faction(faction) part.set_faction(faction)
def remove_war_participant(self, player_id: str): def remove_war_participant(self, player_id: str):
# TODO manage campaign_participants referring to it # TODO manage campaign_participants referring to it
del self.participants[player_id] del self.participants[player_id]
# Campaign methods # Campaign methods
def has_campaign(self, campaign_id: str) -> bool: def has_campaign(self, campaign_id: str) -> bool:
return any(c.id == campaign_id for c in self.campaigns) return any(c.id == campaign_id for c in self.campaigns)
def get_default_campaign_values(self) -> dict: def get_default_campaign_values(self) -> dict:
return { return {"month": datetime.now().month}
"month": datetime.now().month
}
def add_campaign(self, name: str, month: int | None = None) -> Campaign: def add_campaign(self, name: str, month: int | None = None) -> Campaign:
if month is None: if month is None:
month = self.get_default_campaign_values()["month"] month = self.get_default_campaign_values()["month"]
@ -144,53 +146,78 @@ class War:
def get_campaign_by_campaign_participant(self, participant_id: str) -> Campaign: def get_campaign_by_campaign_participant(self, participant_id: str) -> Campaign:
for camp in self.campaigns: for camp in self.campaigns:
for part in camp.participants.values(): if camp.has_participant(participant_id):
if part.id == participant_id: return camp
return camp
raise KeyError(f"Participant {participant_id} not found in any Campaign") raise KeyError(f"Participant {participant_id} not found in any Campaign")
def update_campaign(self, campaign_id: str, *, name: str, month: int): def update_campaign(self, campaign_id: str, *, name: str, month: int):
camp = self.get_campaign(campaign_id) camp = self.get_campaign(campaign_id)
camp.set_name(name) camp.set_name(name)
camp.set_month(month) camp.set_month(month)
def get_all_campaigns(self) -> list[Campaign]: def get_all_campaigns(self) -> list[Campaign]:
return list(self.campaigns) return list(self.campaigns)
def remove_campaign(self, campaign_id: str): def remove_campaign(self, campaign_id: str):
camp = self.get_campaign(campaign_id) camp = self.get_campaign(campaign_id)
self.campaigns.remove(camp) 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) camp = self.get_campaign(campaign_id)
return camp.add_sector(name, round_id, major_id, minor_id, influence_id) return camp.add_sector(name, round_id, major_id, minor_id, influence_id)
def get_sector(self, id: str) -> Sector: def get_sector(self, id: str) -> Sector:
return self.sectors[id] 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 = 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): def remove_sector(self, sector_id: str):
camp = self.get_campaign_by_sector(sector_id) camp = self.get_campaign_by_sector(sector_id)
camp.remove_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]: def get_available_war_participants(self, campaign_id: str) -> list[WarParticipant]:
camp = self.get_campaign(campaign_id) camp = self.get_campaign(campaign_id)
return [ return [
part part
for part in self.participants.values() for part in self.participants.values()
if not camp.has_participant(part.id) if not camp.has_war_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) 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: def get_campaign_participant(self, participant_id) -> CampaignParticipant:
for camp in self.campaigns.values(): for camp in self.campaigns.values():
@ -199,44 +226,86 @@ class War:
return part return part
raise KeyError("Participant not found") 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 = 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): def remove_campaign_participant(self, participant_id: str):
camp = self.get_campaign_by_campaign_participant(participant_id) camp = self.get_campaign_by_campaign_participant(participant_id)
camp.remove_campaign_participant(participant_id) camp.remove_campaign_participant(participant_id)
# Round methods # Round methods
def add_round(self, campaign_id: str) -> Round: def add_round(self, campaign_id: str) -> Round:
camp = self.get_campaign(campaign_id) camp = self.get_campaign(campaign_id)
return camp.add_round() 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): def remove_round(self, round_id: str):
camp = self.get_campaign_by_round(round_id) camp = self.get_campaign_by_round(round_id)
camp.remove_round(round_id) camp.remove_round(round_id)
# Choice methods # Choice methods
def create_choice(self, round_id: str, participant_id: str) -> Choice: def create_choice(self, round_id: str, participant_id: str) -> Choice:
camp = self.get_campaign_by_round(round_id) camp = self.get_campaign_by_round(round_id)
return camp.create_choice(round_id, participant_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,
):
camp = self.get_campaign_by_round(round_id)
camp.update_choice(
participant_id, priority_sector_id, secondary_sector_id, comment
)
def remove_choice(self, round_id: str, participant_id: str): def remove_choice(self, round_id: str, participant_id: str):
camp = self.get_campaign_by_round(round_id) camp = self.get_campaign_by_round(round_id)
camp.remove_choice(round_id, participant_id) camp.remove_choice(round_id, participant_id)
# Battle methods # Battle methods
def create_battle(self, round_id: str, sector_id: str) -> Battle: def create_battle(self, round_id: str, sector_id: str) -> Battle:
camp = self.get_campaign_by_round(round_id) camp = self.get_campaign_by_round(round_id)
return camp.create_battle(round_id, sector_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,
):
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,
)
def remove_battle(self, round_id: str, sector_id: str): def remove_battle(self, round_id: str, sector_id: str):
camp = self.get_campaign_by_round(round_id) camp = self.get_campaign_by_round(round_id)
camp.remove_battle(round_id, sector_id) camp.remove_battle(round_id, sector_id)
class Objective: class Objective:
def __init__(self, name: str, description: str): def __init__(self, name: str, description: str):
self.id: str = str(uuid4()) self.id: str = str(uuid4())
@ -251,15 +320,19 @@ class Objective:
def set_description(self, new_description: str): def set_description(self, new_description: str):
self.description = new_description self.description = new_description
class WarParticipant: class WarParticipant:
def __init__(self, player_id: str, faction: str): def __init__(self, *, player_id: str, faction: str):
self.id: str = player_id # ref to Model.players self.id: str = str(uuid4())
self.player_id: str = player_id # ref to WarModel.players
self.faction: str = faction self.faction: str = faction
def set_id(self, new_id: str): def set_id(self, new_id: str):
self.id = new_id self.id = new_id
def set_player(self, new_player: str):
self.player_id = new_player
def set_faction(self, new_faction: str): def set_faction(self, new_faction: str):
self.faction = new_faction self.faction = new_faction

View file

@ -21,6 +21,7 @@ from warchron.view.ui.ui_battle_result_dialog import Ui_battleResultDialog
# utils... # utils...
def select_if_exists(combo, value): def select_if_exists(combo, value):
if value is None: if value is None:
return return
@ -28,17 +29,21 @@ def select_if_exists(combo, value):
if idx != -1: if idx != -1:
combo.setCurrentIndex(idx) combo.setCurrentIndex(idx)
def format_war_label(war) -> str: def format_war_label(war) -> str:
return f"{war.name} ({war.year})" return f"{war.name} ({war.year})"
def format_campaign_label(camp) -> str: def format_campaign_label(camp) -> str:
return f"{camp.name} ({calendar.month_name[camp.month]})" return f"{camp.name} ({calendar.month_name[camp.month]})"
def format_round_label(round, index: int) -> str: def format_round_label(round, index: int) -> str:
if index is None: if index is None:
return "" return ""
return f"Round {index}" return f"Round {index}"
class View(QtWidgets.QMainWindow, Ui_MainWindow): class View(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None): def __init__(self, parent=None):
super(View, self).__init__(parent) super(View, self).__init__(parent)
@ -51,24 +56,46 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
self.on_delete_item = None self.on_delete_item = None
self.show_details(None) self.show_details(None)
self.playersTable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.playersTable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.playersTable.customContextMenuRequested.connect(self._on_players_table_context_menu) self.playersTable.customContextMenuRequested.connect(
self._on_players_table_context_menu
)
self.warsTree.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.warsTree.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.warsTree.customContextMenuRequested.connect(self._on_wars_tree_context_menu) self.warsTree.customContextMenuRequested.connect(
self._on_wars_tree_context_menu
)
self.addCampaignBtn.clicked.connect(self._on_add_campaign_clicked) self.addCampaignBtn.clicked.connect(self._on_add_campaign_clicked)
self.addRoundBtn.clicked.connect(self._on_add_round_clicked) self.addRoundBtn.clicked.connect(self._on_add_round_clicked)
# Pages # Pages
self.warParticipantsTable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.warParticipantsTable.setContextMenuPolicy(
self.warParticipantsTable.customContextMenuRequested.connect(self._on_war_participants_table_context_menu) Qt.ContextMenuPolicy.CustomContextMenu
self.objectivesTable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) )
self.objectivesTable.customContextMenuRequested.connect(self._on_objectives_table_context_menu) self.warParticipantsTable.customContextMenuRequested.connect(
self.campaignParticipantsTable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self._on_war_participants_table_context_menu
self.campaignParticipantsTable.customContextMenuRequested.connect(self._on_campaign_participants_table_context_menu) )
self.objectivesTable.setContextMenuPolicy(
Qt.ContextMenuPolicy.CustomContextMenu
)
self.objectivesTable.customContextMenuRequested.connect(
self._on_objectives_table_context_menu
)
self.campaignParticipantsTable.setContextMenuPolicy(
Qt.ContextMenuPolicy.CustomContextMenu
)
self.campaignParticipantsTable.customContextMenuRequested.connect(
self._on_campaign_participants_table_context_menu
)
self.sectorsTable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.sectorsTable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.sectorsTable.customContextMenuRequested.connect(self._on_sectors_table_context_menu) self.sectorsTable.customContextMenuRequested.connect(
self._on_sectors_table_context_menu
)
self.choicesTable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.choicesTable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.choicesTable.customContextMenuRequested.connect(self._on_choices_table_context_menu) self.choicesTable.customContextMenuRequested.connect(
self._on_choices_table_context_menu
)
self.battlesTable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.battlesTable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.battlesTable.customContextMenuRequested.connect(self._on_battles_table_context_menu) self.battlesTable.customContextMenuRequested.connect(
self._on_battles_table_context_menu
)
def _emit_selection_changed(self, current, previous): def _emit_selection_changed(self, current, previous):
if not self.on_tree_selection_changed: if not self.on_tree_selection_changed:
@ -76,10 +103,12 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
if not current: if not current:
self.on_tree_selection_changed(None) self.on_tree_selection_changed(None)
return return
self.on_tree_selection_changed({ self.on_tree_selection_changed(
"type": current.data(0, ROLE_TYPE), {
"id": current.data(0, ROLE_ID), "type": current.data(0, ROLE_TYPE),
}) "id": current.data(0, ROLE_ID),
}
)
def get_current_tab(self) -> str: def get_current_tab(self) -> str:
index = self.tabWidget.currentIndex() index = self.tabWidget.currentIndex()
@ -89,7 +118,7 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
return "wars" return "wars"
return "" return ""
# General popups # General popups
def closeEvent(self, event: QCloseEvent): def closeEvent(self, event: QCloseEvent):
if self.on_close_callback: if self.on_close_callback:
@ -101,23 +130,17 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
def ask_open_file(self) -> Path | None: def ask_open_file(self) -> Path | None:
filename, _ = QFileDialog.getOpenFileName( filename, _ = QFileDialog.getOpenFileName(
self, self, "Open war history", "", "WarChron files (*.json)"
"Open war history",
"",
"WarChron files (*.json)"
) )
return Path(filename) if filename else None return Path(filename) if filename else None
def ask_save_file(self) -> Path | None: def ask_save_file(self) -> Path | None:
filename, _ = QFileDialog.getSaveFileName( filename, _ = QFileDialog.getSaveFileName(
self, self, "Save war history", "", "WarChron files (*.json)"
"Save war history",
"",
"WarChron files (*.json)"
) )
return Path(filename) if filename else None return Path(filename) if filename else None
# Players view # Players view
def _on_players_table_context_menu(self, pos): def _on_players_table_context_menu(self, pos):
item = self.playersTable.itemAt(pos) item = self.playersTable.itemAt(pos)
@ -146,7 +169,7 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
table.setItem(row, 0, play_item) table.setItem(row, 0, play_item)
table.resizeColumnsToContents() table.resizeColumnsToContents()
# Wars view # Wars view
def _on_add_campaign_clicked(self): def _on_add_campaign_clicked(self):
if self.on_add_campaign: if self.on_add_campaign:
@ -216,6 +239,7 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
if walk(item.child(i)): if walk(item.child(i)):
return True return True
return False return False
for i in range(self.warsTree.topLevelItemCount()): for i in range(self.warsTree.topLevelItemCount()):
if walk(self.warsTree.topLevelItem(i)): if walk(self.warsTree.topLevelItem(i)):
return return
@ -224,10 +248,7 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
item = self.warsTree.currentItem() item = self.warsTree.currentItem()
if not item: if not item:
return None return None
return { return {"type": item.data(0, ROLE_TYPE), "id": item.data(0, ROLE_ID)}
"type": item.data(0, ROLE_TYPE),
"id": item.data(0, ROLE_ID)
}
def show_details(self, item_type: str | None): def show_details(self, item_type: str | None):
if item_type == ItemType.WAR: if item_type == ItemType.WAR:
@ -239,7 +260,7 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
else: else:
self.selectedDetailsStack.setCurrentWidget(self.pageEmpty) self.selectedDetailsStack.setCurrentWidget(self.pageEmpty)
# War page # War page
def _on_objectives_table_context_menu(self, pos): def _on_objectives_table_context_menu(self, pos):
item = self.objectivesTable.itemAt(pos) item = self.objectivesTable.itemAt(pos)
@ -305,7 +326,7 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
table.setItem(row, 1, fact_item) table.setItem(row, 1, fact_item)
table.resizeColumnsToContents() table.resizeColumnsToContents()
# Campaign page # Campaign page
def _on_sectors_table_context_menu(self, pos): def _on_sectors_table_context_menu(self, pos):
item = self.sectorsTable.itemAt(pos) item = self.sectorsTable.itemAt(pos)
@ -347,13 +368,19 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
self.campaignName.setText(name) self.campaignName.setText(name)
self.campaignMonth.setText(calendar.month_name[month]) self.campaignMonth.setText(calendar.month_name[month])
def display_campaign_sectors(self, sectors: list[tuple[str, str, str, str, str, str]]): def display_campaign_sectors(
self, sectors: list[tuple[str, str, str, str, str, str]]
):
table = self.sectorsTable table = self.sectorsTable
table.clearContents() table.clearContents()
table.setRowCount(len(sectors)) table.setRowCount(len(sectors))
for row, (name, round_index, major, minor, influence, pid) in enumerate(sectors): for row, (name, round_index, major, minor, influence, pid) in enumerate(
sectors
):
name_item = QtWidgets.QTableWidgetItem(name) name_item = QtWidgets.QTableWidgetItem(name)
round_item = QtWidgets.QTableWidgetItem(format_round_label(None, round_index)) round_item = QtWidgets.QTableWidgetItem(
format_round_label(None, round_index)
)
major_item = QtWidgets.QTableWidgetItem(major) major_item = QtWidgets.QTableWidgetItem(major)
minor_item = QtWidgets.QTableWidgetItem(minor) minor_item = QtWidgets.QTableWidgetItem(minor)
influence_item = QtWidgets.QTableWidgetItem(influence) influence_item = QtWidgets.QTableWidgetItem(influence)
@ -365,7 +392,9 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
table.setItem(row, 4, influence_item) table.setItem(row, 4, influence_item)
table.resizeColumnsToContents() table.resizeColumnsToContents()
def display_campaign_participants(self, participants: list[tuple[str, str, str, str]]): def display_campaign_participants(
self, participants: list[tuple[str, str, str, str]]
):
table = self.campaignParticipantsTable table = self.campaignParticipantsTable
table.clearContents() table.clearContents()
table.setRowCount(len(participants)) table.setRowCount(len(participants))
@ -379,7 +408,7 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
table.setItem(row, 2, theme_item) table.setItem(row, 2, theme_item)
table.resizeColumnsToContents() table.resizeColumnsToContents()
# Round page # Round page
def _on_choices_table_context_menu(self, pos): def _on_choices_table_context_menu(self, pos):
item = self.choicesTable.itemAt(pos) item = self.choicesTable.itemAt(pos)
@ -422,7 +451,9 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
table = self.choicesTable table = self.choicesTable
table.clearContents() table.clearContents()
table.setRowCount(len(participants)) table.setRowCount(len(participants))
for row, (participant, priority, secondary, choice_id) in enumerate(participants): for row, (participant, priority, secondary, choice_id) in enumerate(
participants
):
participant_item = QtWidgets.QTableWidgetItem(participant) participant_item = QtWidgets.QTableWidgetItem(participant)
priority_item = QtWidgets.QTableWidgetItem(priority) priority_item = QtWidgets.QTableWidgetItem(priority)
secondary_item = QtWidgets.QTableWidgetItem(secondary) secondary_item = QtWidgets.QTableWidgetItem(secondary)
@ -446,6 +477,7 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
table.setItem(row, 2, player_2_item) table.setItem(row, 2, player_2_item)
table.resizeColumnsToContents() table.resizeColumnsToContents()
class PlayerDialog(QDialog): class PlayerDialog(QDialog):
def __init__(self, parent=None, *, default_name: str = ""): def __init__(self, parent=None, *, default_name: str = ""):
super().__init__(parent) super().__init__(parent)
@ -456,8 +488,11 @@ class PlayerDialog(QDialog):
def get_player_name(self) -> str: def get_player_name(self) -> str:
return self.ui.playerName.text().strip() return self.ui.playerName.text().strip()
class WarDialog(QDialog): class WarDialog(QDialog):
def __init__(self, parent=None, default_name: str = "", default_year: int | None = None): def __init__(
self, parent=None, default_name: str = "", default_year: int | None = None
):
super().__init__(parent) super().__init__(parent)
self.ui = Ui_warDialog() self.ui = Ui_warDialog()
self.ui.setupUi(self) self.ui.setupUi(self)
@ -467,12 +502,15 @@ class WarDialog(QDialog):
def get_war_name(self) -> str: def get_war_name(self) -> str:
return self.ui.warName.text().strip() return self.ui.warName.text().strip()
def get_war_year(self) -> int: def get_war_year(self) -> int:
return int(self.ui.warYear.value()) return int(self.ui.warYear.value())
class CampaignDialog(QDialog): class CampaignDialog(QDialog):
def __init__(self, parent=None, default_name: str = "", default_month: int | None = None): def __init__(
self, parent=None, default_name: str = "", default_month: int | None = None
):
super().__init__(parent) super().__init__(parent)
self.ui = Ui_campaignDialog() self.ui = Ui_campaignDialog()
self.ui.setupUi(self) self.ui.setupUi(self)
@ -485,7 +523,8 @@ class CampaignDialog(QDialog):
def get_campaign_month(self) -> int: def get_campaign_month(self) -> int:
return int(self.ui.campaignMonth.value()) return int(self.ui.campaignMonth.value())
class ObjectiveDialog(QDialog): class ObjectiveDialog(QDialog):
def __init__(self, parent=None, *, default_name="", default_description=""): def __init__(self, parent=None, *, default_name="", default_description=""):
super().__init__(parent) super().__init__(parent)
@ -499,9 +538,18 @@ class ObjectiveDialog(QDialog):
def get_objective_description(self) -> str: def get_objective_description(self) -> str:
return self.ui.objectiveDescription.toPlainText().strip() return self.ui.objectiveDescription.toPlainText().strip()
class WarParticipantDialog(QDialog): class WarParticipantDialog(QDialog):
def __init__(self, parent=None, *, players: list, default_player_id=None, default_faction="", editable_player=True): def __init__(
self,
parent=None,
*,
players: list,
default_player_id=None,
default_faction="",
editable_player=True,
):
super().__init__(parent) super().__init__(parent)
self.ui = Ui_warParticipantDialog() self.ui = Ui_warParticipantDialog()
self.ui.setupUi(self) self.ui.setupUi(self)
@ -516,9 +564,19 @@ class WarParticipantDialog(QDialog):
def get_participant_faction(self) -> str: def get_participant_faction(self) -> str:
return self.ui.faction.text().strip() return self.ui.faction.text().strip()
class CampaignParticipantDialog(QDialog): class CampaignParticipantDialog(QDialog):
def __init__(self, parent=None, *, participants: list[ParticipantOption], default_participant_id=None, default_leader="", default_theme="", editable_player=True): def __init__(
self,
parent=None,
*,
participants: list[ParticipantOption],
default_participant_id=None,
default_leader="",
default_theme="",
editable_player=True,
):
super().__init__(parent) super().__init__(parent)
self.ui = Ui_campaignParticipantDialog() self.ui = Ui_campaignParticipantDialog()
self.ui.setupUi(self) self.ui.setupUi(self)
@ -533,13 +591,25 @@ class CampaignParticipantDialog(QDialog):
return self.ui.playerComboBox.currentData() return self.ui.playerComboBox.currentData()
def get_participant_leader(self) -> str: def get_participant_leader(self) -> str:
return self.ui.leader.text().strip() return self.ui.leader.text().strip()
def get_participant_theme(self) -> str: def get_participant_theme(self) -> str:
return self.ui.theme.text().strip() return self.ui.theme.text().strip()
class SectorDialog(QDialog): class SectorDialog(QDialog):
def __init__(self, parent=None, *, default_name="", rounds: list, default_round_id=None, objectives: list, default_major_id=None, default_minor_id=None, default_influence_id=None): def __init__(
self,
parent=None,
*,
default_name="",
rounds: list,
default_round_id=None,
objectives: list,
default_major_id=None,
default_minor_id=None,
default_influence_id=None,
):
super().__init__(parent) super().__init__(parent)
self.ui = Ui_sectorDialog() self.ui = Ui_sectorDialog()
self.ui.setupUi(self) self.ui.setupUi(self)
@ -562,25 +632,30 @@ class SectorDialog(QDialog):
return self.ui.sectorName.text().strip() return self.ui.sectorName.text().strip()
def get_round_id(self) -> str: def get_round_id(self) -> str:
return self.ui.roundComboBox.currentData() return self.ui.roundComboBox.currentData()
def get_major_id(self) -> str: def get_major_id(self) -> str:
return self.ui.majorComboBox.currentData() return self.ui.majorComboBox.currentData()
def get_minor_id(self) -> str: def get_minor_id(self) -> str:
return self.ui.minorComboBox.currentData() return self.ui.minorComboBox.currentData()
def get_influence_id(self) -> str: def get_influence_id(self) -> str:
return self.ui.influenceComboBox.currentData() return self.ui.influenceComboBox.currentData()
class ChoicesDialog(QDialog): class ChoicesDialog(QDialog):
def __init__(self, parent = None, *, def __init__(
participants: list, self,
default_participant_id = None, parent=None,
sectors: list, *,
default_priority_id = None, participants: list,
default_secondary_id = None, default_participant_id=None,
default_comment = None): sectors: list,
default_priority_id=None,
default_secondary_id=None,
default_comment=None,
):
super().__init__(parent) super().__init__(parent)
self.ui = Ui_choicesDialog() self.ui = Ui_choicesDialog()
self.ui.setupUi(self) self.ui.setupUi(self)
@ -598,32 +673,37 @@ class ChoicesDialog(QDialog):
self.ui.choiceComment.setPlainText(default_comment) self.ui.choiceComment.setPlainText(default_comment)
def get_participant_id(self) -> str: def get_participant_id(self) -> str:
return self.ui.playerComboBox.currentData() return self.ui.playerComboBox.currentData()
def get_priority_id(self) -> str: def get_priority_id(self) -> str:
return self.ui.priorityComboBox.currentData() return self.ui.priorityComboBox.currentData()
def get_secondary_id(self) -> str: def get_secondary_id(self) -> str:
return self.ui.secondaryComboBox.currentData() return self.ui.secondaryComboBox.currentData()
def get_comment(self) -> str: def get_comment(self) -> str:
return self.ui.choiceComment.toPlainText().strip() return self.ui.choiceComment.toPlainText().strip()
class BattlesDialog(QDialog): class BattlesDialog(QDialog):
def __init__(self, parent = None, *, def __init__(
sectors: list, self,
default_sector_id = None, parent=None,
players: list, *,
default_player_1_id = None, sectors: list,
default_player_2_id = None, default_sector_id=None,
default_winner_id = None, players: list,
default_score = None, default_player_1_id=None,
default_victory_condition = None, default_player_2_id=None,
default_comment = None): default_winner_id=None,
default_score=None,
default_victory_condition=None,
default_comment=None,
):
super().__init__(parent) super().__init__(parent)
self.ui = Ui_battleResultDialog() self.ui = Ui_battleResultDialog()
self.ui.setupUi(self) self.ui.setupUi(self)
for sect in sectors: for sect in sectors:
self.ui.sectorComboBox.addItem(sect.name, sect.id) self.ui.sectorComboBox.addItem(sect.name, sect.id)
select_if_exists(self.ui.sectorComboBox, default_sector_id) select_if_exists(self.ui.sectorComboBox, default_sector_id)
self.ui.sectorComboBox.setEnabled(False) self.ui.sectorComboBox.setEnabled(False)
@ -645,16 +725,16 @@ class BattlesDialog(QDialog):
self.ui.battleComment.setPlainText(default_comment) self.ui.battleComment.setPlainText(default_comment)
def get_sector_id(self) -> str: def get_sector_id(self) -> str:
return self.ui.sectorComboBox.currentData() return self.ui.sectorComboBox.currentData()
def get_player_1_id(self) -> str: def get_player_1_id(self) -> str:
return self.ui.player1ComboBox.currentData() return self.ui.player1ComboBox.currentData()
def get_player_2_id(self) -> str: def get_player_2_id(self) -> str:
return self.ui.player2ComboBox.currentData() return self.ui.player2ComboBox.currentData()
def get_winner_id(self) -> str: def get_winner_id(self) -> str:
return self.ui.winnerComboBox.currentData() return self.ui.winnerComboBox.currentData()
def get_score(self) -> str: def get_score(self) -> str:
return self.ui.score.text().strip() return self.ui.score.text().strip()
@ -663,4 +743,4 @@ class BattlesDialog(QDialog):
return self.ui.victoryCondition.text().strip() return self.ui.victoryCondition.text().strip()
def get_comment(self) -> str: def get_comment(self) -> str:
return self.ui.battleComment.toPlainText().strip() return self.ui.battleComment.toPlainText().strip()