detect campaign tie
This commit is contained in:
parent
7c9c941864
commit
60d8e6ca15
9 changed files with 203 additions and 116 deletions
|
|
@ -1,17 +1,27 @@
|
|||
from typing import List, Dict
|
||||
from typing import List, Dict, DefaultDict
|
||||
from dataclasses import dataclass
|
||||
from collections import defaultdict
|
||||
|
||||
from warchron.constants import ContextType
|
||||
from warchron.model.exception import ForbiddenOperation
|
||||
from warchron.model.war import War
|
||||
from warchron.model.round import Round
|
||||
from warchron.model.battle import Battle
|
||||
from warchron.model.war_event import InfluenceSpent, TieResolved
|
||||
from warchron.model.score_service import ScoreService
|
||||
|
||||
|
||||
@dataclass
|
||||
class TieContext:
|
||||
context_type: ContextType
|
||||
context_id: str
|
||||
participants: List[str] # war_participant_ids
|
||||
|
||||
|
||||
class TieResolver:
|
||||
|
||||
@staticmethod
|
||||
def find_round_ties(round: Round, war: War) -> List[Battle]:
|
||||
def find_battle_ties(war: War, round_id: str) -> List[TieContext]:
|
||||
round = war.get_round(round_id)
|
||||
campaign = war.get_campaign_by_round(round_id)
|
||||
ties = []
|
||||
for battle in round.battles.values():
|
||||
if not battle.is_draw():
|
||||
|
|
@ -22,10 +32,53 @@ class TieResolver:
|
|||
and e.context_id == battle.sector_id
|
||||
for e in war.events
|
||||
)
|
||||
if not resolved:
|
||||
ties.append(battle)
|
||||
if resolved:
|
||||
continue
|
||||
if campaign is None:
|
||||
raise RuntimeError("No campaign for this battle tie")
|
||||
if battle.player_1_id is None or battle.player_2_id is None:
|
||||
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
|
||||
ties.append(
|
||||
TieContext(
|
||||
context_type=ContextType.BATTLE,
|
||||
context_id=battle.sector_id,
|
||||
participants=[p1, p2],
|
||||
)
|
||||
)
|
||||
return ties
|
||||
|
||||
@staticmethod
|
||||
def find_campaign_ties(war: War, campaign_id: str) -> List[TieContext]:
|
||||
resolved = any(
|
||||
isinstance(e, TieResolved)
|
||||
and e.context_type == ContextType.CAMPAIGN
|
||||
and e.context_id == campaign_id
|
||||
for e in war.events
|
||||
)
|
||||
if resolved:
|
||||
return []
|
||||
scores = ScoreService.compute_scores(war, ContextType.CAMPAIGN, campaign_id)
|
||||
buckets: DefaultDict[int, List[str]] = defaultdict(list)
|
||||
for pid, score in scores.items():
|
||||
buckets[score.victory_points].append(pid)
|
||||
ties = []
|
||||
for participants in buckets.values():
|
||||
if len(participants) > 1:
|
||||
ties.append(
|
||||
TieContext(
|
||||
context_type=ContextType.CAMPAIGN,
|
||||
context_id=campaign_id,
|
||||
participants=participants,
|
||||
)
|
||||
)
|
||||
return ties
|
||||
|
||||
@staticmethod
|
||||
def find_war_ties(war: War) -> List[TieContext]:
|
||||
return [] # TODO
|
||||
|
||||
@staticmethod
|
||||
def apply_bids(
|
||||
war: War,
|
||||
|
|
@ -88,25 +141,6 @@ class TieResolver:
|
|||
def can_tie_be_resolved(war: War, participants: List[str]) -> bool:
|
||||
return any(war.get_influence_tokens(pid) > 0 for pid in participants)
|
||||
|
||||
@staticmethod
|
||||
def get_effective_winner_id(
|
||||
war: War,
|
||||
context_type: ContextType,
|
||||
context_id: str,
|
||||
base_winner_id: str | None,
|
||||
) -> str | None:
|
||||
if base_winner_id is not None:
|
||||
return base_winner_id
|
||||
for ev in reversed(war.events):
|
||||
if (
|
||||
isinstance(ev, TieResolved)
|
||||
and ev.context_type == context_type
|
||||
and ev.context_id == context_id
|
||||
):
|
||||
return ev.participant_id # None if confirmed draw
|
||||
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def was_tie_broken_by_tokens(
|
||||
war: War,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue