72 lines
2.5 KiB
Python
72 lines
2.5 KiB
Python
from __future__ import annotations
|
|
from typing import List, Tuple, Dict, TYPE_CHECKING
|
|
from collections import defaultdict
|
|
|
|
from warchron.constants import ContextType
|
|
from warchron.model.war import War
|
|
from warchron.model.war_event import TieResolved
|
|
from warchron.model.tie_manager import TieResolver
|
|
|
|
if TYPE_CHECKING:
|
|
from warchron.model.score_service import ParticipantScore
|
|
|
|
|
|
class ResultChecker:
|
|
@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 get_effective_ranking(
|
|
war: War,
|
|
context_type: ContextType,
|
|
context_id: str,
|
|
scores: Dict[str, ParticipantScore],
|
|
) -> List[Tuple[int, List[str], Dict[str, int]]]:
|
|
vp_buckets: Dict[int, List[str]] = defaultdict(list)
|
|
for pid, score in scores.items():
|
|
vp_buckets[score.victory_points].append(pid)
|
|
sorted_vps = sorted(vp_buckets.keys(), reverse=True)
|
|
ranking: List[Tuple[int, List[str], Dict[str, int]]] = []
|
|
current_rank = 1
|
|
for vp in sorted_vps:
|
|
participants = vp_buckets[vp]
|
|
tie_id = f"{context_id}:score:{vp}"
|
|
# no tie
|
|
if len(participants) == 1 or not TieResolver.is_tie_resolved(
|
|
war, context_type, tie_id
|
|
):
|
|
ranking.append(
|
|
(current_rank, participants, {pid: 0 for pid in participants})
|
|
)
|
|
current_rank += 1
|
|
continue
|
|
# apply token ranking
|
|
groups = TieResolver.rank_by_tokens(
|
|
war,
|
|
context_type,
|
|
tie_id,
|
|
participants,
|
|
)
|
|
tokens_spent = TieResolver.tokens_spent_map(
|
|
war, context_type, tie_id, participants
|
|
)
|
|
for group in groups:
|
|
group_tokens = {pid: tokens_spent[pid] for pid in group}
|
|
ranking.append((current_rank, group, group_tokens))
|
|
current_rank += 1
|
|
return ranking
|