fix inluence_token setting auto cleanup and fix is_dirty

This commit is contained in:
Maxime Réaux 2026-02-24 15:40:24 +01:00
parent 789756d586
commit 3c54a8d4a7
5 changed files with 114 additions and 18 deletions

View file

@ -215,13 +215,13 @@ class AppController:
self.navigation.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.ROUND, item_id=rnd.id
)
self.is_dirty = True
except DomainError as e:
QMessageBox.warning(
self.view,
"Deletion forbidden",
"Add forbidden",
str(e),
)
return
except RequiresConfirmation as e:
reply = QMessageBox.question(
self.view,
@ -231,6 +231,9 @@ class AppController:
)
if reply == QMessageBox.StandardButton.Yes:
e.action()
else:
return
self.is_dirty = True
self.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
def edit_item(self, item_type: str, item_id: str) -> None:
@ -266,13 +269,13 @@ class AppController:
elif item_type == ItemType.BATTLE:
self.rounds.edit_round_battle(item_id)
self.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
self.is_dirty = True
except DomainError as e:
QMessageBox.warning(
self.view,
"Deletion forbidden",
"Update forbidden",
str(e),
)
return
except RequiresConfirmation as e:
reply = QMessageBox.question(
self.view,
@ -282,6 +285,9 @@ class AppController:
)
if reply == QMessageBox.StandardButton.Yes:
e.action()
else:
return
self.is_dirty = True
self.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
def delete_item(self, item_type: str, item_id: str) -> None:
@ -326,13 +332,13 @@ class AppController:
self.navigation.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.CAMPAIGN, item_id=camp_id
)
self.is_dirty = True
except DomainError as e:
QMessageBox.warning(
self.view,
"Deletion forbidden",
str(e),
)
return
except RequiresConfirmation as e:
reply = QMessageBox.question(
self.view,
@ -342,4 +348,7 @@ class AppController:
)
if reply == QMessageBox.StandardButton.Yes:
e.action()
else:
return
self.is_dirty = True
self.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)

View file

@ -177,9 +177,10 @@ class CampaignController:
except DomainError as e:
QMessageBox.warning(
self.app.view,
"Deletion forbidden",
"Closure forbidden",
str(e),
)
return
self.app.is_dirty = True
self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
self.app.navigation.refresh_and_select(

View file

@ -167,9 +167,10 @@ class RoundController:
except DomainError as e:
QMessageBox.warning(
self.app.view,
"Deletion forbidden",
"Closure forbidden",
str(e),
)
return
self.app.is_dirty = True
self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
self.app.navigation.refresh_and_select(

View file

@ -11,7 +11,11 @@ from warchron.constants import (
IconName,
RANK_TO_ICON,
)
from warchron.model.exception import DomainError, ForbiddenOperation
from warchron.model.exception import (
DomainError,
ForbiddenOperation,
RequiresConfirmation,
)
if TYPE_CHECKING:
from warchron.controller.app_controller import AppController
@ -152,9 +156,10 @@ class WarController:
except DomainError as e:
QMessageBox.warning(
self.app.view,
"Deletion forbidden",
"Closure forbidden",
str(e),
)
return
self.app.is_dirty = True
self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
self.app.navigation.refresh_and_select(
@ -200,6 +205,7 @@ class WarController:
"Setting forbidden",
str(e),
)
return
self.app.is_dirty = True
self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
@ -215,6 +221,7 @@ class WarController:
"Setting forbidden",
str(e),
)
return
self.app.is_dirty = True
self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
@ -230,8 +237,23 @@ class WarController:
"Setting forbidden",
str(e),
)
return
except RequiresConfirmation as e:
reply = QMessageBox.question(
self.app.view,
"Confirm update",
str(e),
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
)
if reply == QMessageBox.StandardButton.Yes:
e.action()
else:
return
self.app.is_dirty = True
self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
self.app.navigation.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war_id
)
# Objective methods

View file

@ -3,8 +3,14 @@ from uuid import uuid4
from datetime import datetime
from typing import Any, Dict, List
from warchron.model.war_event import WarEvent, InfluenceGained, InfluenceSpent
from warchron.model.exception import ForbiddenOperation
from warchron.constants import ContextType
from warchron.model.war_event import (
WarEvent,
InfluenceGained,
InfluenceSpent,
TieResolved,
)
from warchron.model.exception import ForbiddenOperation, RequiresConfirmation
from warchron.model.war_participant import WarParticipant
from warchron.model.objective import Objective
from warchron.model.campaign_participant import CampaignParticipant
@ -55,11 +61,68 @@ class War:
def set_influence_token(self, new_state: bool) -> None:
if self.is_over:
raise ForbiddenOperation("Can't set influence token of a closed war.")
# TODO raise RequiresConfirmation
# * disable: cleanup if any token has already been gained/spent
# * enable: retrigger battle_outcomes and resolve tie again if any draw
def cleanup_token_and_tie() -> None:
new_events: List[WarEvent] = []
for ev in self.events:
if isinstance(ev, (InfluenceSpent, InfluenceGained)):
continue
if isinstance(ev, TieResolved):
ev.set_participant(None)
new_events.append(ev)
self.events = new_events
self.influence_token = new_state
def reset_tie_break() -> None:
new_events: List[WarEvent] = []
for ev in self.events:
if isinstance(ev, (TieResolved)):
if ev.context_type == ContextType.BATTLE:
battle = self.get_battle(ev.context_id)
campaign = self.get_campaign_by_sector(battle.sector_id)
round = campaign.get_round_by_battle(ev.context_id)
round.is_over = False
elif ev.context_type == ContextType.CAMPAIGN:
campaign = self.get_campaign(ev.context_id)
campaign.is_over = False
else:
new_events.append(ev)
self.events = new_events
# TODO Reopen rounds with battle on sector with influence objective
for camp in self.campaigns:
for sect in camp.get_all_sectors():
if sect.influence_objective_id is not None:
round = camp.get_round_by_battle(sect.id)
round.is_over = False
if new_state is False:
if not self.events:
self.influence_token = new_state
return
raise RequiresConfirmation(
"Some influence tokens already exist in this war.\n"
"All tokens will be deleted and tie-breaks will become draw.\n"
"Do you want to continue?",
action=cleanup_token_and_tie,
)
if new_state is True:
has_tie_resolved = any(isinstance(ev, TieResolved) for ev in self.events)
grant_influence = any(
(sect.influence_objective_id is not None)
for camp in self.campaigns
for sect in camp.get_all_sectors()
)
if not has_tie_resolved and not grant_influence:
self.influence_token = new_state
return
raise RequiresConfirmation(
"Some influence tokens and draws exist in this war.\n"
"All influence outcomes and tie-breaks will be reset.\n"
"Do you want to continue?",
action=reset_tie_break,
)
def set_state(self, new_state: bool) -> None:
self.is_over = new_state