From 60992c22df206ea2d4c5bff5c6787fca7b69125a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20R=C3=A9aux?= Date: Mon, 23 Feb 2026 13:16:45 +0100 Subject: [PATCH] fix tie-break loser re-bid --- .../controller/campaign_controller.py | 14 ++++---- src/warchron/model/tie_manager.py | 36 ++++++++++++++++--- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/warchron/controller/campaign_controller.py b/src/warchron/controller/campaign_controller.py index 4c72427..9447058 100644 --- a/src/warchron/controller/campaign_controller.py +++ b/src/warchron/controller/campaign_controller.py @@ -18,7 +18,7 @@ from warchron.model.war import War from warchron.model.campaign import Campaign from warchron.model.campaign_participant import CampaignParticipant from warchron.model.sector import Sector -from warchron.model.tie_manager import TieContext +from warchron.model.tie_manager import TieContext, TieResolver from warchron.model.score_service import ScoreService from warchron.view.campaign_dialog import CampaignDialog from warchron.view.campaign_participant_dialog import CampaignParticipantDialog @@ -144,14 +144,14 @@ class CampaignController: ) -> Dict[str, Dict[str, bool]]: bids_map = {} for ctx in contexts: + active = TieResolver.get_active_participants( + war, ctx.context_type, ctx.context_id, ctx.participants + ) players = [ - ParticipantOption( - id=pid, - name=self.app.model.get_participant_name(pid), - ) - for pid in ctx.participants + ParticipantOption(id=pid, name=self.app.model.get_participant_name(pid)) + for pid in active ] - counters = [war.get_influence_tokens(pid) for pid in ctx.participants] + counters = [war.get_influence_tokens(pid) for pid in active] dialog = TieDialog( parent=self.app.view, players=players, diff --git a/src/warchron/model/tie_manager.py b/src/warchron/model/tie_manager.py index 75cacdb..fd678d7 100644 --- a/src/warchron/model/tie_manager.py +++ b/src/warchron/model/tie_manager.py @@ -35,7 +35,9 @@ class TieResolver: raise RuntimeError("Missing player(s) in this battle context.") p1 = campaign.participants[battle.player_1_id].war_participant_id p2 = campaign.participants[battle.player_2_id].war_participant_id - if not TieResolver.can_tie_be_resolved(war, [p1, p2]): + if not TieResolver.can_tie_be_resolved( + war, ContextType.BATTLE, battle.sector_id, [p1, p2] + ): war.events.append( TieResolved(None, ContextType.BATTLE, battle.sector_id) ) @@ -64,7 +66,9 @@ class TieResolver: tie_id = f"{campaign_id}:score:{score_value}" if TieResolver.is_tie_resolved(war, ContextType.CAMPAIGN, tie_id): continue - if not TieResolver.can_tie_be_resolved(war, participants): + if not TieResolver.can_tie_be_resolved( + war, ContextType.CAMPAIGN, tie_id, participants + ): war.events.append(TieResolved(None, ContextType.CAMPAIGN, tie_id)) continue ties.append( @@ -127,6 +131,16 @@ class TieResolver: groups[-1].append(pid) return groups + @staticmethod + def get_active_participants( + war: War, + context_type: ContextType, + context_id: str, + participants: List[str], + ) -> List[str]: + groups = TieResolver.rank_by_tokens(war, context_type, context_id, participants) + return groups[0] + @staticmethod def resolve_tie_state( war: War, @@ -135,7 +149,14 @@ class TieResolver: participants: List[str], bids: dict[str, bool] | None = None, ) -> None: - # confirmed draw if bids are 0 + active = TieResolver.get_active_participants( + war, context_type, context_id, participants + ) + # confirmed draw if non had bid + if not active: + war.events.append(TieResolved(None, context_type, context_id)) + return + # confirmed draw if current bids are 0 if bids is not None and not any(bids.values()): war.events.append(TieResolved(None, context_type, context_id)) return @@ -147,8 +168,13 @@ class TieResolver: # if tie persists, do nothing, workflow will call again @staticmethod - def can_tie_be_resolved(war: War, participants: List[str]) -> bool: - return any(war.get_influence_tokens(pid) > 0 for pid in participants) + def can_tie_be_resolved( + war: War, context_type: ContextType, context_id: str, participants: List[str] + ) -> bool: + active = TieResolver.get_active_participants( + war, context_type, context_id, participants + ) + return any(war.get_influence_tokens(pid) > 0 for pid in active) @staticmethod def was_tie_broken_by_tokens(