warchron_app/src/warchron/model/closure_service.py

101 lines
3.3 KiB
Python

from __future__ import annotations
from typing import List
from warchron.constants import ContextType
from warchron.model.exception import ForbiddenOperation
from warchron.model.war_event import InfluenceGained
from warchron.model.war import War
from warchron.model.campaign import Campaign
from warchron.model.round import Round
from warchron.model.battle import Battle
class ClosureService:
# Round methods
@staticmethod
def check_round_closable(round: Round) -> None:
if round.is_over:
raise ForbiddenOperation("Round already closed")
if not round.all_battles_finished():
raise ForbiddenOperation(
"All battles must be finished to close their round"
)
@staticmethod
def apply_battle_outcomes(war: War, campaign: Campaign, battle: Battle) -> None:
from warchron.model.result_checker import ResultChecker
already_granted = any(
isinstance(e, InfluenceGained)
and e.context_id == f"battle:{battle.sector_id}"
for e in war.events
)
if already_granted:
return
base_winner = None
if battle.winner_id is not None:
base_winner = campaign.participants[battle.winner_id].war_participant_id
effective_winner = ResultChecker.get_effective_winner_id(
war,
ContextType.BATTLE,
battle.sector_id,
base_winner,
)
if effective_winner is None:
return
sector = campaign.sectors[battle.sector_id]
if sector.influence_objective_id and war.influence_token:
war.events.append(
InfluenceGained(
participant_id=effective_winner,
amount=1,
context_type=ContextType.BATTLE,
context_id=f"battle:{battle.sector_id}",
)
)
@staticmethod
def finalize_round(round: Round) -> None:
round.is_over = True
# Campaign methods
@staticmethod
def check_campaign_closable(campaign: Campaign) -> None:
if campaign.is_over:
raise ForbiddenOperation("Campaign already closed")
if not campaign.all_rounds_finished():
raise ForbiddenOperation(
"All rounds must be closed to close their campaign"
)
@staticmethod
def finalize_campaign(campaign: Campaign) -> None:
campaign.is_over = True
# War methods
@staticmethod
def close_war(war: War) -> List[str]:
if not war.all_campaigns_finished():
raise RuntimeError("All campaigns must be finished to close their war")
ties: List[str] = []
# for campaign in war.campaigns:
# # compute score
# # if participants have same score
# ties.append(
# ResolutionContext(
# context_type=ContextType.WAR,
# context_id=war.id,
# participant_ids=[
# war.participants[war_participant_id],
# war.participants[war_participant_id],
# ],
# )
# )
if ties:
return ties
war.is_over = True
return []