choice tie-break and random fallback + exception cleanup + war<->camp pid

This commit is contained in:
Maxime Réaux 2026-03-12 16:28:20 +01:00
parent 241d7f10f5
commit 241e76c937
15 changed files with 241 additions and 157 deletions

View file

@ -111,7 +111,15 @@ class AppController:
path = self.view.ask_open_file()
if not path:
return
self.model.load(path)
try:
self.model.load(path)
except RuntimeError as e:
QMessageBox.warning(
self.view,
"Add forbidden",
str(e),
)
return
self.current_file = path
self.is_dirty = False
self.navigation.refresh_players_view()

View file

@ -14,7 +14,7 @@ from warchron.controller.dtos import (
RoundDTO,
CampaignParticipantScoreDTO,
)
from warchron.model.exception import ForbiddenOperation, DomainError
from warchron.model.exception import AbortedOperation, DomainError
from warchron.model.war import War
from warchron.model.campaign import Campaign
from warchron.model.campaign_participant import CampaignParticipant
@ -196,7 +196,7 @@ class CampaignController:
)
if not dialog.exec():
TieResolver.cancel_tie_break(war, ctx)
raise ForbiddenOperation("Tie resolution cancelled")
raise AbortedOperation("Tie resolution cancelled")
bids_map[ctx.key()] = dialog.get_bids()
return bids_map

View file

@ -104,12 +104,8 @@ class RoundPairingWorkflow:
def start(self, war: War, round: Round) -> None:
Pairing.check_round_pairable(round)
ties = TieResolver.find_choice_ties(war, round.id)
while ties:
bids_map = self.app.rounds.resolve_ties(war, ties)
for tie in ties:
bids = bids_map[tie.key()]
TieResolver.apply_bids(war, tie, bids)
TieResolver.resolve_tie_state(war, tie, bids)
ties = TieResolver.find_choice_ties(war, round.id)
Pairing.assign_battles_to_participants(war, round)
Pairing.assign_battles_to_participants(
war,
round,
resolve_ties_callback=self.app.rounds.resolve_ties,
)

View file

@ -6,7 +6,7 @@ from PyQt6.QtGui import QIcon
from warchron.constants import ItemType, RefreshScope, Icons, IconName, ContextType
from warchron.model.exception import (
ForbiddenOperation,
AbortedOperation,
DomainError,
RequiresConfirmation,
)
@ -119,9 +119,7 @@ class RoundController:
)
p1_war = None
if battle.player_1_id is not None:
p1_war = camp.participants[
battle.player_1_id
].war_participant_id
p1_war = camp.campaign_to_war_part_id(battle.player_1_id)
pixmap = Icons.get_pixmap(IconName.TIEBREAK_TOKEN)
if effective_winner == p1_war:
p1_icon = QIcon(pixmap)
@ -192,10 +190,19 @@ class RoundController:
workflow = RoundPairingWorkflow(self.app)
try:
workflow.start(war, rnd)
except AbortedOperation as e:
QMessageBox.warning(
self.app.view,
"Canceled pairing",
str(e),
)
for bat in rnd.battles.values():
bat.cleanup_battle_players()
return
except DomainError as e:
QMessageBox.warning(
self.app.view,
"Closure forbidden",
"Pairing impossible",
str(e),
)
return
@ -238,7 +245,7 @@ class RoundController:
)
if not dialog.exec():
TieResolver.cancel_tie_break(war, ctx)
raise ForbiddenOperation("Tie resolution cancelled")
raise AbortedOperation("Tie resolution cancelled")
bids_map[ctx.key()] = dialog.get_bids()
return bids_map

View file

@ -10,7 +10,7 @@ from warchron.constants import (
)
from warchron.model.exception import (
DomainError,
ForbiddenOperation,
AbortedOperation,
RequiresConfirmation,
)
@ -190,7 +190,7 @@ class WarController:
)
if not dialog.exec():
TieResolver.cancel_tie_break(war, ctx)
raise ForbiddenOperation("Tie resolution cancelled")
raise AbortedOperation("Tie resolution cancelled")
bids_map[ctx.key()] = dialog.get_bids()
return bids_map