unifomise tiebreak icons + refacto presenter
This commit is contained in:
parent
0081e52e9a
commit
3d0d7874e3
10 changed files with 185 additions and 165 deletions
|
|
@ -49,7 +49,8 @@ class IconName(StrEnum):
|
||||||
NP1ST = auto()
|
NP1ST = auto()
|
||||||
NP2ND = auto()
|
NP2ND = auto()
|
||||||
NP3RD = auto()
|
NP3RD = auto()
|
||||||
TIEBREAK_TOKEN = auto()
|
WINTOKEN = auto()
|
||||||
|
TIEBREAKTOKEN = auto()
|
||||||
VP1STDRAW = auto()
|
VP1STDRAW = auto()
|
||||||
VP1STBREAK = auto()
|
VP1STBREAK = auto()
|
||||||
VP1STTIEDRAW = auto()
|
VP1STTIEDRAW = auto()
|
||||||
|
|
@ -143,11 +144,16 @@ class Icons:
|
||||||
def get_pixmap(cls, name: IconName) -> QPixmap:
|
def get_pixmap(cls, name: IconName) -> QPixmap:
|
||||||
if name in cls._pixmap_cache:
|
if name in cls._pixmap_cache:
|
||||||
return cls._pixmap_cache[name]
|
return cls._pixmap_cache[name]
|
||||||
if name == IconName.TIEBREAK_TOKEN:
|
if name == IconName.TIEBREAKTOKEN:
|
||||||
pix = cls._compose(
|
pix = cls._compose(
|
||||||
cls.get_pixmap(IconName.TIEBREAK),
|
cls.get_pixmap(IconName.TIEBREAK),
|
||||||
cls.get_pixmap(IconName.TOKEN),
|
cls.get_pixmap(IconName.TOKEN),
|
||||||
)
|
)
|
||||||
|
elif name == IconName.WINTOKEN:
|
||||||
|
pix = cls._compose(
|
||||||
|
cls.get_pixmap(IconName.WIN),
|
||||||
|
cls.get_pixmap(IconName.TOKEN),
|
||||||
|
)
|
||||||
elif name == IconName.VP1STDRAW:
|
elif name == IconName.VP1STDRAW:
|
||||||
pix = cls._compose(
|
pix = cls._compose(
|
||||||
cls.get_pixmap(IconName.VP1ST),
|
cls.get_pixmap(IconName.VP1ST),
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ from warchron.model.sector import Sector
|
||||||
from warchron.model.tie_manager import TieContext, TieResolver
|
from warchron.model.tie_manager import TieContext, TieResolver
|
||||||
from warchron.model.score_service import ScoreService
|
from warchron.model.score_service import ScoreService
|
||||||
from warchron.controller.closure_workflow import CampaignClosureWorkflow
|
from warchron.controller.closure_workflow import CampaignClosureWorkflow
|
||||||
from warchron.controller.ranking_icon import RankingIcon
|
|
||||||
from warchron.controller.presenter import TiePresenter
|
from warchron.controller.presenter import Presenter
|
||||||
from warchron.view.campaign_dialog import CampaignDialog
|
from warchron.view.campaign_dialog import CampaignDialog
|
||||||
from warchron.view.campaign_participant_dialog import CampaignParticipantDialog
|
from warchron.view.campaign_participant_dialog import CampaignParticipantDialog
|
||||||
from warchron.view.sector_dialog import SectorDialog
|
from warchron.view.sector_dialog import SectorDialog
|
||||||
|
|
@ -58,11 +58,11 @@ class CampaignController:
|
||||||
vp_icon_map: Dict[str, QIcon] = {}
|
vp_icon_map: Dict[str, QIcon] = {}
|
||||||
objective_icon_maps: Dict[str, Dict[str, QIcon]] = {}
|
objective_icon_maps: Dict[str, Dict[str, QIcon]] = {}
|
||||||
if camp.is_over:
|
if camp.is_over:
|
||||||
vp_icon_map = RankingIcon.compute_icons(
|
vp_icon_map = Presenter.compute_ranking_icons(
|
||||||
war, ContextType.CAMPAIGN, campaign_id, scores
|
war, ContextType.CAMPAIGN, campaign_id, scores
|
||||||
)
|
)
|
||||||
for obj in war.get_objectives_used_as_maj_or_min():
|
for obj in war.get_objectives_used_as_maj_or_min():
|
||||||
objective_icon_maps[obj.id] = RankingIcon.compute_icons(
|
objective_icon_maps[obj.id] = Presenter.compute_ranking_icons(
|
||||||
war,
|
war,
|
||||||
ContextType.CAMPAIGN,
|
ContextType.CAMPAIGN,
|
||||||
camp.id,
|
camp.id,
|
||||||
|
|
@ -177,7 +177,7 @@ class CampaignController:
|
||||||
for pid in active
|
for pid in active
|
||||||
]
|
]
|
||||||
counters = [war.get_influence_tokens(pid) for pid in active]
|
counters = [war.get_influence_tokens(pid) for pid in active]
|
||||||
data = TiePresenter.build_dialog_data(
|
data = Presenter.build_dialog_data(
|
||||||
war, ctx, campaign=war.get_campaign(ctx.context_id)
|
war, ctx, campaign=war.get_campaign(ctx.context_id)
|
||||||
)
|
)
|
||||||
dialog = TieDialog(
|
dialog = TieDialog(
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,27 @@
|
||||||
from warchron.constants import ContextType
|
from typing import Dict
|
||||||
|
|
||||||
|
from PyQt6.QtGui import QIcon
|
||||||
|
|
||||||
|
from warchron.constants import (
|
||||||
|
ContextType,
|
||||||
|
Icons,
|
||||||
|
IconName,
|
||||||
|
VP_RANK_TO_ICON,
|
||||||
|
NP_RANK_TO_ICON,
|
||||||
|
ScoreKind,
|
||||||
|
)
|
||||||
|
|
||||||
from warchron.controller.dtos import TieDialogData
|
from warchron.controller.dtos import TieDialogData
|
||||||
from warchron.model.tie_manager import TieContext
|
from warchron.model.tie_manager import TieContext, TieResolver
|
||||||
from warchron.model.war import War
|
from warchron.model.war import War
|
||||||
from warchron.model.campaign import Campaign
|
from warchron.model.campaign import Campaign
|
||||||
from warchron.model.round import Round
|
from warchron.model.round import Round
|
||||||
|
from warchron.model.score_service import ParticipantScore
|
||||||
|
from warchron.model.result_checker import ResultChecker
|
||||||
|
from warchron.model.exception import DomainError
|
||||||
|
|
||||||
|
|
||||||
class TiePresenter:
|
class Presenter:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def build_dialog_data(
|
def build_dialog_data(
|
||||||
|
|
@ -33,7 +48,7 @@ class TiePresenter:
|
||||||
if ctx.context_type == ContextType.CHOICE:
|
if ctx.context_type == ContextType.CHOICE:
|
||||||
if ctx.sector_id and campaign and round:
|
if ctx.sector_id and campaign and round:
|
||||||
sector = campaign.sectors[ctx.sector_id]
|
sector = campaign.sectors[ctx.sector_id]
|
||||||
kind = TiePresenter._choice_kind(round, ctx)
|
kind = Presenter._choice_kind(round, ctx)
|
||||||
return TieDialogData(f"Choice tie — {sector.name} ({kind})")
|
return TieDialogData(f"Choice tie — {sector.name} ({kind})")
|
||||||
return TieDialogData("Choice tie")
|
return TieDialogData("Choice tie")
|
||||||
return TieDialogData("Tie")
|
return TieDialogData("Tie")
|
||||||
|
|
@ -50,3 +65,114 @@ class TiePresenter:
|
||||||
if choice.secondary_sector_id == ctx.sector_id:
|
if choice.secondary_sector_id == ctx.sector_id:
|
||||||
return "secondary"
|
return "secondary"
|
||||||
return "choice"
|
return "choice"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def compute_ranking_icons(
|
||||||
|
war: War,
|
||||||
|
context_type: ContextType,
|
||||||
|
context_id: str,
|
||||||
|
scores: Dict[str, ParticipantScore],
|
||||||
|
*,
|
||||||
|
objective_id: str | None = None,
|
||||||
|
) -> Dict[str, QIcon]:
|
||||||
|
if objective_id is None:
|
||||||
|
|
||||||
|
def value_getter(score: ParticipantScore) -> int:
|
||||||
|
return score.victory_points
|
||||||
|
|
||||||
|
icon_ranking = VP_RANK_TO_ICON
|
||||||
|
score_kind = ScoreKind.VP
|
||||||
|
else:
|
||||||
|
|
||||||
|
def value_getter(score: ParticipantScore) -> int:
|
||||||
|
return score.narrative_points.get(objective_id, 0)
|
||||||
|
|
||||||
|
icon_ranking = NP_RANK_TO_ICON
|
||||||
|
score_kind = ScoreKind.NP
|
||||||
|
ranking = ResultChecker.get_effective_ranking(
|
||||||
|
war,
|
||||||
|
context_type,
|
||||||
|
context_id,
|
||||||
|
score_kind,
|
||||||
|
scores,
|
||||||
|
value_getter,
|
||||||
|
objective_id,
|
||||||
|
)
|
||||||
|
icon_map: Dict[str, QIcon] = {}
|
||||||
|
for rank, group, token_map in ranking:
|
||||||
|
if objective_id and rank not in icon_ranking:
|
||||||
|
continue
|
||||||
|
base_icon = icon_ranking.get(
|
||||||
|
rank, IconName.VPNTH if objective_id is None else None
|
||||||
|
)
|
||||||
|
if base_icon is None:
|
||||||
|
continue
|
||||||
|
value = value_getter(scores[group[0]])
|
||||||
|
original_group_size = sum(
|
||||||
|
1 for s in scores.values() if value_getter(s) == value
|
||||||
|
)
|
||||||
|
for pid in group:
|
||||||
|
spent = token_map.get(pid, 0)
|
||||||
|
if original_group_size == 1:
|
||||||
|
icon_name = base_icon
|
||||||
|
elif len(group) == 1:
|
||||||
|
if spent > 0:
|
||||||
|
icon_name = getattr(IconName, f"{base_icon.name}BREAK")
|
||||||
|
else:
|
||||||
|
icon_name = base_icon
|
||||||
|
else:
|
||||||
|
if spent > 0:
|
||||||
|
icon_name = getattr(IconName, f"{base_icon.name}TIEDRAW")
|
||||||
|
else:
|
||||||
|
icon_name = getattr(IconName, f"{base_icon.name}DRAW")
|
||||||
|
icon_map[pid] = QIcon(Icons.get_pixmap(icon_name))
|
||||||
|
return icon_map
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def compute_battle_icons(
|
||||||
|
war: War,
|
||||||
|
round_id: str,
|
||||||
|
battle_id: str,
|
||||||
|
) -> tuple[QIcon | None, QIcon | None]:
|
||||||
|
battle = war.get_battle(battle_id)
|
||||||
|
if not (battle.player_1_id and battle.player_2_id and battle.is_finished()):
|
||||||
|
return None, None
|
||||||
|
campaign = war.get_campaign_by_sector(battle.sector_id)
|
||||||
|
if not campaign:
|
||||||
|
raise DomainError("No campaign found for this battle")
|
||||||
|
base_winner = None
|
||||||
|
if battle.winner_id is not None:
|
||||||
|
base_winner = campaign.campaign_to_war_part_id(battle.winner_id)
|
||||||
|
winner_id = ResultChecker.get_effective_winner_id(
|
||||||
|
war,
|
||||||
|
ContextType.BATTLE,
|
||||||
|
battle.sector_id,
|
||||||
|
base_winner,
|
||||||
|
)
|
||||||
|
|
||||||
|
def compute_icon(player: str) -> QIcon | None:
|
||||||
|
base_icon: IconName | None = None
|
||||||
|
if winner_id is None:
|
||||||
|
base_icon = IconName.DRAW
|
||||||
|
elif campaign.war_to_campaign_part_id(winner_id) == player:
|
||||||
|
base_icon = IconName.WIN
|
||||||
|
elif battle.is_draw():
|
||||||
|
base_icon = IconName.TIEBREAK
|
||||||
|
if base_icon is None:
|
||||||
|
return None
|
||||||
|
spent = TieResolver.participant_spent_token(
|
||||||
|
war,
|
||||||
|
ContextType.BATTLE,
|
||||||
|
battle.sector_id,
|
||||||
|
None,
|
||||||
|
campaign.campaign_to_war_part_id(player),
|
||||||
|
)
|
||||||
|
icon_name = (
|
||||||
|
getattr(IconName, f"{base_icon.name}TOKEN") if spent else base_icon
|
||||||
|
)
|
||||||
|
return QIcon(Icons.get_pixmap(icon_name))
|
||||||
|
|
||||||
|
return (
|
||||||
|
compute_icon(battle.player_1_id),
|
||||||
|
compute_icon(battle.player_2_id),
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
from typing import Dict
|
|
||||||
|
|
||||||
from PyQt6.QtGui import QIcon
|
|
||||||
|
|
||||||
from warchron.constants import (
|
|
||||||
ContextType,
|
|
||||||
Icons,
|
|
||||||
IconName,
|
|
||||||
VP_RANK_TO_ICON,
|
|
||||||
NP_RANK_TO_ICON,
|
|
||||||
ScoreKind,
|
|
||||||
)
|
|
||||||
from warchron.model.war import War
|
|
||||||
from warchron.model.score_service import ParticipantScore
|
|
||||||
from warchron.model.result_checker import ResultChecker
|
|
||||||
|
|
||||||
|
|
||||||
class RankingIcon:
|
|
||||||
@staticmethod
|
|
||||||
def compute_icons(
|
|
||||||
war: War,
|
|
||||||
context_type: ContextType,
|
|
||||||
context_id: str,
|
|
||||||
scores: Dict[str, ParticipantScore],
|
|
||||||
*,
|
|
||||||
objective_id: str | None = None,
|
|
||||||
) -> Dict[str, QIcon]:
|
|
||||||
|
|
||||||
if objective_id is None:
|
|
||||||
|
|
||||||
def value_getter(score: ParticipantScore) -> int:
|
|
||||||
return score.victory_points
|
|
||||||
|
|
||||||
icon_ranking = VP_RANK_TO_ICON
|
|
||||||
score_kind = ScoreKind.VP
|
|
||||||
else:
|
|
||||||
|
|
||||||
def value_getter(score: ParticipantScore) -> int:
|
|
||||||
return score.narrative_points.get(objective_id, 0)
|
|
||||||
|
|
||||||
icon_ranking = NP_RANK_TO_ICON
|
|
||||||
score_kind = ScoreKind.NP
|
|
||||||
ranking = ResultChecker.get_effective_ranking(
|
|
||||||
war,
|
|
||||||
context_type,
|
|
||||||
context_id,
|
|
||||||
score_kind,
|
|
||||||
scores,
|
|
||||||
value_getter,
|
|
||||||
objective_id,
|
|
||||||
)
|
|
||||||
icon_map: Dict[str, QIcon] = {}
|
|
||||||
for rank, group, token_map in ranking:
|
|
||||||
if objective_id and rank not in icon_ranking:
|
|
||||||
continue
|
|
||||||
base_icon = icon_ranking.get(
|
|
||||||
rank, IconName.VPNTH if objective_id is None else None
|
|
||||||
)
|
|
||||||
if base_icon is None:
|
|
||||||
continue
|
|
||||||
value = value_getter(scores[group[0]])
|
|
||||||
original_group_size = sum(
|
|
||||||
1 for s in scores.values() if value_getter(s) == value
|
|
||||||
)
|
|
||||||
for pid in group:
|
|
||||||
spent = token_map.get(pid, 0)
|
|
||||||
if original_group_size == 1:
|
|
||||||
icon_name = base_icon
|
|
||||||
elif len(group) == 1:
|
|
||||||
if spent > 0:
|
|
||||||
icon_name = getattr(IconName, f"{base_icon.name}BREAK")
|
|
||||||
else:
|
|
||||||
icon_name = base_icon
|
|
||||||
else:
|
|
||||||
if spent > 0:
|
|
||||||
icon_name = getattr(IconName, f"{base_icon.name}TIEDRAW")
|
|
||||||
else:
|
|
||||||
icon_name = getattr(IconName, f"{base_icon.name}DRAW")
|
|
||||||
icon_map[pid] = QIcon(Icons.get_pixmap(icon_name))
|
|
||||||
return icon_map
|
|
||||||
|
|
@ -18,7 +18,6 @@ from warchron.model.exception import (
|
||||||
RequiresConfirmation,
|
RequiresConfirmation,
|
||||||
)
|
)
|
||||||
from warchron.model.tie_manager import TieResolver, TieContext
|
from warchron.model.tie_manager import TieResolver, TieContext
|
||||||
from warchron.model.result_checker import ResultChecker
|
|
||||||
from warchron.model.pairing import Pairing
|
from warchron.model.pairing import Pairing
|
||||||
from warchron.model.round import Round
|
from warchron.model.round import Round
|
||||||
from warchron.model.war import War
|
from warchron.model.war import War
|
||||||
|
|
@ -36,7 +35,7 @@ from warchron.controller.closure_workflow import (
|
||||||
RoundClosureWorkflow,
|
RoundClosureWorkflow,
|
||||||
RoundPairingWorkflow,
|
RoundPairingWorkflow,
|
||||||
)
|
)
|
||||||
from warchron.controller.presenter import TiePresenter
|
from warchron.controller.presenter import Presenter
|
||||||
from warchron.view.choice_dialog import ChoiceDialog
|
from warchron.view.choice_dialog import ChoiceDialog
|
||||||
from warchron.view.battle_dialog import BattleDialog
|
from warchron.view.battle_dialog import BattleDialog
|
||||||
from warchron.view.tie_dialog import TieDialog
|
from warchron.view.tie_dialog import TieDialog
|
||||||
|
|
@ -47,7 +46,6 @@ class RoundController:
|
||||||
self.app = app
|
self.app = app
|
||||||
|
|
||||||
def _fill_round_details(self, round_id: str) -> None:
|
def _fill_round_details(self, round_id: str) -> None:
|
||||||
# self.app.view.clear_round_page()
|
|
||||||
rnd = self.app.model.get_round(round_id)
|
rnd = self.app.model.get_round(round_id)
|
||||||
camp = self.app.model.get_campaign_by_round(round_id)
|
camp = self.app.model.get_campaign_by_round(round_id)
|
||||||
war = self.app.model.get_war_by_round(round_id)
|
war = self.app.model.get_war_by_round(round_id)
|
||||||
|
|
@ -135,7 +133,6 @@ class RoundController:
|
||||||
player_1_name = self.app.model.get_participant_name(
|
player_1_name = self.app.model.get_participant_name(
|
||||||
camp_part.war_participant_id
|
camp_part.war_participant_id
|
||||||
)
|
)
|
||||||
p1_id = battle.player_1_id
|
|
||||||
else:
|
else:
|
||||||
player_1_name = ""
|
player_1_name = ""
|
||||||
if battle.player_2_id:
|
if battle.player_2_id:
|
||||||
|
|
@ -143,7 +140,6 @@ class RoundController:
|
||||||
player_2_name = self.app.model.get_participant_name(
|
player_2_name = self.app.model.get_participant_name(
|
||||||
camp_part.war_participant_id
|
camp_part.war_participant_id
|
||||||
)
|
)
|
||||||
p2_id = battle.player_2_id
|
|
||||||
else:
|
else:
|
||||||
player_2_name = ""
|
player_2_name = ""
|
||||||
if battle.winner_id:
|
if battle.winner_id:
|
||||||
|
|
@ -153,34 +149,9 @@ class RoundController:
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
winner_name = ""
|
winner_name = ""
|
||||||
p1_icon = None
|
p1_icon, p2_icon = Presenter.compute_battle_icons(
|
||||||
p2_icon = None
|
war, round_id, battle.sector_id
|
||||||
# TODO use uniform draw/tie icon logic with choice, war, campaign...
|
)
|
||||||
if battle.is_draw():
|
|
||||||
p1_icon = Icons.get(IconName.DRAW)
|
|
||||||
p2_icon = Icons.get(IconName.DRAW)
|
|
||||||
context = TieContext(
|
|
||||||
ContextType.BATTLE,
|
|
||||||
battle.sector_id,
|
|
||||||
[p1_id, p2_id],
|
|
||||||
)
|
|
||||||
if TieResolver.was_tie_broken_by_tokens(war, context):
|
|
||||||
effective_winner = ResultChecker.get_effective_winner_id(
|
|
||||||
war, ContextType.BATTLE, battle.sector_id, None
|
|
||||||
)
|
|
||||||
p1_war = None
|
|
||||||
if battle.player_1_id is not None:
|
|
||||||
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)
|
|
||||||
else:
|
|
||||||
p2_icon = QIcon(pixmap)
|
|
||||||
elif battle.winner_id:
|
|
||||||
if battle.winner_id == battle.player_1_id:
|
|
||||||
p1_icon = Icons.get(IconName.WIN)
|
|
||||||
elif battle.winner_id == battle.player_2_id:
|
|
||||||
p2_icon = Icons.get(IconName.WIN)
|
|
||||||
battles_for_display.append(
|
battles_for_display.append(
|
||||||
BattleDTO(
|
BattleDTO(
|
||||||
id=battle.sector_id,
|
id=battle.sector_id,
|
||||||
|
|
@ -293,9 +264,7 @@ class RoundController:
|
||||||
campaign = war.get_campaign_by_round(ctx.context_id)
|
campaign = war.get_campaign_by_round(ctx.context_id)
|
||||||
if campaign:
|
if campaign:
|
||||||
round = war.get_round(ctx.context_id)
|
round = war.get_round(ctx.context_id)
|
||||||
data = TiePresenter.build_dialog_data(
|
data = Presenter.build_dialog_data(war, ctx, round=round, campaign=campaign)
|
||||||
war, ctx, round=round, campaign=campaign
|
|
||||||
)
|
|
||||||
dialog = TieDialog(
|
dialog = TieDialog(
|
||||||
parent=self.app.view,
|
parent=self.app.view,
|
||||||
players=players,
|
players=players,
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ from warchron.model.objective import Objective
|
||||||
from warchron.model.tie_manager import TieContext, TieResolver
|
from warchron.model.tie_manager import TieContext, TieResolver
|
||||||
from warchron.model.score_service import ScoreService
|
from warchron.model.score_service import ScoreService
|
||||||
from warchron.controller.closure_workflow import WarClosureWorkflow
|
from warchron.controller.closure_workflow import WarClosureWorkflow
|
||||||
from warchron.controller.ranking_icon import RankingIcon
|
|
||||||
from warchron.controller.presenter import TiePresenter
|
from warchron.controller.presenter import Presenter
|
||||||
from warchron.view.war_dialog import WarDialog
|
from warchron.view.war_dialog import WarDialog
|
||||||
from warchron.view.objective_dialog import ObjectiveDialog
|
from warchron.view.objective_dialog import ObjectiveDialog
|
||||||
from warchron.view.war_participant_dialog import WarParticipantDialog
|
from warchron.view.war_participant_dialog import WarParticipantDialog
|
||||||
|
|
@ -62,11 +62,11 @@ class WarController:
|
||||||
vp_icon_map: Dict[str, QIcon] = {}
|
vp_icon_map: Dict[str, QIcon] = {}
|
||||||
objective_icon_maps: Dict[str, Dict[str, QIcon]] = {}
|
objective_icon_maps: Dict[str, Dict[str, QIcon]] = {}
|
||||||
if war.is_over:
|
if war.is_over:
|
||||||
vp_icon_map = RankingIcon.compute_icons(
|
vp_icon_map = Presenter.compute_ranking_icons(
|
||||||
war, ContextType.WAR, war_id, scores
|
war, ContextType.WAR, war_id, scores
|
||||||
)
|
)
|
||||||
for obj in war.get_objectives_used_as_maj_or_min():
|
for obj in war.get_objectives_used_as_maj_or_min():
|
||||||
objective_icon_maps[obj.id] = RankingIcon.compute_icons(
|
objective_icon_maps[obj.id] = Presenter.compute_ranking_icons(
|
||||||
war,
|
war,
|
||||||
ContextType.WAR,
|
ContextType.WAR,
|
||||||
war.id,
|
war.id,
|
||||||
|
|
@ -171,7 +171,7 @@ class WarController:
|
||||||
for pid in active
|
for pid in active
|
||||||
]
|
]
|
||||||
counters = [war.get_influence_tokens(pid) for pid in active]
|
counters = [war.get_influence_tokens(pid) for pid in active]
|
||||||
data = TiePresenter.build_dialog_data(
|
data = Presenter.build_dialog_data(
|
||||||
war,
|
war,
|
||||||
ctx,
|
ctx,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ from warchron.model.round import Round
|
||||||
from warchron.model.battle import Battle
|
from warchron.model.battle import Battle
|
||||||
from warchron.model.score_service import ScoreService
|
from warchron.model.score_service import ScoreService
|
||||||
from warchron.model.tie_manager import TieResolver, TieContext
|
from warchron.model.tie_manager import TieResolver, TieContext
|
||||||
from warchron.model.war_event import TieResolved, InfluenceSpent
|
from warchron.model.war_event import TieResolved
|
||||||
from warchron.model.score_service import ParticipantScore
|
from warchron.model.score_service import ParticipantScore
|
||||||
|
|
||||||
ResolveTiesCallback = Callable[
|
ResolveTiesCallback = Callable[
|
||||||
|
|
@ -304,28 +304,6 @@ class Pairing:
|
||||||
return AllocationType.SECONDARY
|
return AllocationType.SECONDARY
|
||||||
return AllocationType.FALLBACK
|
return AllocationType.FALLBACK
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def participant_spent_token(
|
|
||||||
war: War,
|
|
||||||
round_id: str,
|
|
||||||
sector_id: str | None,
|
|
||||||
war_participant_id: str,
|
|
||||||
) -> bool:
|
|
||||||
if sector_id is None:
|
|
||||||
return False
|
|
||||||
for ev in war.events:
|
|
||||||
if not isinstance(ev, InfluenceSpent):
|
|
||||||
continue
|
|
||||||
if ev.context_type != ContextType.CHOICE:
|
|
||||||
continue
|
|
||||||
if ev.context_id != round_id:
|
|
||||||
continue
|
|
||||||
if ev.sector_id != sector_id:
|
|
||||||
continue
|
|
||||||
if ev.participant_id == war_participant_id:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_round_allocation(
|
def get_round_allocation(
|
||||||
war: War,
|
war: War,
|
||||||
|
|
@ -338,14 +316,16 @@ class Pairing:
|
||||||
raise DomainError(f"No campaign found for round {round.id}")
|
raise DomainError(f"No campaign found for round {round.id}")
|
||||||
war_pid = campaign.campaign_to_war_part_id(campaign_participant_id)
|
war_pid = campaign.campaign_to_war_part_id(campaign_participant_id)
|
||||||
|
|
||||||
token_priority = Pairing.participant_spent_token(
|
token_priority = TieResolver.participant_spent_token(
|
||||||
war,
|
war,
|
||||||
|
ContextType.CHOICE,
|
||||||
round.id,
|
round.id,
|
||||||
choice.priority_sector_id,
|
choice.priority_sector_id,
|
||||||
war_pid,
|
war_pid,
|
||||||
)
|
)
|
||||||
token_secondary = Pairing.participant_spent_token(
|
token_secondary = TieResolver.participant_spent_token(
|
||||||
war,
|
war,
|
||||||
|
ContextType.CHOICE,
|
||||||
round.id,
|
round.id,
|
||||||
choice.secondary_sector_id,
|
choice.secondary_sector_id,
|
||||||
war_pid,
|
war_pid,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ from typing import Any, Dict, List, TYPE_CHECKING
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from warchron.model.campaign import Campaign
|
from warchron.model.campaign import Campaign
|
||||||
from warchron.model.war import War
|
from warchron.model.war import War
|
||||||
|
from warchron.constants import ContextType
|
||||||
from warchron.model.exception import (
|
from warchron.model.exception import (
|
||||||
ForbiddenOperation,
|
ForbiddenOperation,
|
||||||
DomainError,
|
DomainError,
|
||||||
|
|
@ -192,7 +193,7 @@ class Round:
|
||||||
victory_condition: str | None,
|
victory_condition: str | None,
|
||||||
comment: str | None,
|
comment: str | None,
|
||||||
) -> None:
|
) -> None:
|
||||||
from warchron.model.pairing import Pairing
|
from warchron.model.tie_manager import TieResolver
|
||||||
|
|
||||||
if self.is_over:
|
if self.is_over:
|
||||||
raise ForbiddenOperation("Can't update battle in a closed round.")
|
raise ForbiddenOperation("Can't update battle in a closed round.")
|
||||||
|
|
@ -226,8 +227,9 @@ class Round:
|
||||||
if (
|
if (
|
||||||
player
|
player
|
||||||
and self.has_choice_with_participant(player)
|
and self.has_choice_with_participant(player)
|
||||||
and Pairing.participant_spent_token(
|
and TieResolver.participant_spent_token(
|
||||||
self.war,
|
self.war,
|
||||||
|
ContextType.CHOICE,
|
||||||
self.id,
|
self.id,
|
||||||
sector_id,
|
sector_id,
|
||||||
self.campaign.campaign_to_war_part_id(player),
|
self.campaign.campaign_to_war_part_id(player),
|
||||||
|
|
|
||||||
|
|
@ -486,3 +486,26 @@ class TieResolver:
|
||||||
continue
|
continue
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def participant_spent_token(
|
||||||
|
war: War,
|
||||||
|
context_type: ContextType,
|
||||||
|
context_id: str,
|
||||||
|
sector_id: str | None,
|
||||||
|
war_participant_id: str,
|
||||||
|
) -> bool:
|
||||||
|
if context_type == ContextType.CHOICE and sector_id is None:
|
||||||
|
return False
|
||||||
|
for ev in war.events:
|
||||||
|
if not isinstance(ev, InfluenceSpent):
|
||||||
|
continue
|
||||||
|
if ev.context_type != context_type:
|
||||||
|
continue
|
||||||
|
if ev.context_id != context_id:
|
||||||
|
continue
|
||||||
|
if ev.sector_id != sector_id:
|
||||||
|
continue
|
||||||
|
if ev.participant_id == war_participant_id:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
|
||||||
|
|
@ -599,12 +599,6 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||||
def show_round_details(self, *, index: int | None) -> None:
|
def show_round_details(self, *, index: int | None) -> None:
|
||||||
self.roundNb.setText(f"Round {index}")
|
self.roundNb.setText(f"Round {index}")
|
||||||
|
|
||||||
def clear_round_page(self) -> None:
|
|
||||||
choices_table = self.choicesTable
|
|
||||||
choices_table.clearContents()
|
|
||||||
battles_table = self.battlesTable
|
|
||||||
battles_table.clearContents()
|
|
||||||
|
|
||||||
def display_round_choices(self, participants: List[ChoiceDTO]) -> None:
|
def display_round_choices(self, participants: List[ChoiceDTO]) -> None:
|
||||||
table = self.choicesTable
|
table = self.choicesTable
|
||||||
table.setSortingEnabled(False)
|
table.setSortingEnabled(False)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue