Compare commits

..

No commits in common. "2901dcd68c40eed828d8112e795f0587ebf66840" and "c144845376358a49c83c16cedac9e46a8ac0b5a5" have entirely different histories.

21 changed files with 161 additions and 645 deletions

View file

@ -26,7 +26,6 @@ class AppController:
self.current_file: Path | None = None self.current_file: Path | None = None
self.view.on_close_callback = self.on_app_close self.view.on_close_callback = self.on_app_close
self.is_dirty: bool = False self.is_dirty: bool = False
self.players_stats_dirty = True
self.__connect() self.__connect()
self.navigation.refresh_players_view() self.navigation.refresh_players_view()
self.navigation.refresh_wars_view() self.navigation.refresh_wars_view()
@ -61,12 +60,6 @@ class AppController:
self.view.on_add_item = self.add_item self.view.on_add_item = self.add_item
self.view.on_edit_item = self.edit_item self.view.on_edit_item = self.edit_item
self.view.on_delete_item = self.delete_item self.view.on_delete_item = self.delete_item
self.view.tabWidget.currentChanged.connect(self.navigation.on_tab_changed)
def mark_model_dirty(self, *, players_stats: bool = False) -> None:
self.is_dirty = True
if players_stats:
self.players_stats_dirty = True
def on_app_close(self) -> bool: def on_app_close(self) -> bool:
if self.is_dirty: if self.is_dirty:
@ -242,11 +235,10 @@ class AppController:
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
) )
if reply == QMessageBox.StandardButton.Yes: if reply == QMessageBox.StandardButton.Yes:
if e.action: e.action()
e.action()
else: else:
return return
self.mark_model_dirty(players_stats=True) # participation may affect stats self.is_dirty = True
self.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS) self.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
def edit_item(self, item_type: str, item_id: str) -> None: def edit_item(self, item_type: str, item_id: str) -> None:
@ -298,8 +290,7 @@ class AppController:
) )
if reply == QMessageBox.StandardButton.Yes: if reply == QMessageBox.StandardButton.Yes:
try: try:
if e.action: e.action()
e.action()
except DomainError as inner: except DomainError as inner:
QMessageBox.warning( QMessageBox.warning(
self.view, self.view,
@ -309,7 +300,7 @@ class AppController:
return return
else: else:
return return
self.mark_model_dirty(players_stats=(item_type == ItemType.PLAYER)) self.is_dirty = True
self.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS) self.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
def delete_item(self, item_type: str, item_id: str) -> None: def delete_item(self, item_type: str, item_id: str) -> None:
@ -370,8 +361,7 @@ class AppController:
) )
if reply == QMessageBox.StandardButton.Yes: if reply == QMessageBox.StandardButton.Yes:
try: try:
if e.action: e.action()
e.action()
except DomainError as inner: except DomainError as inner:
QMessageBox.warning( QMessageBox.warning(
self.view, self.view,
@ -381,5 +371,5 @@ class AppController:
return return
else: else:
return return
self.mark_model_dirty(players_stats=True) # participation may affect stats self.is_dirty = True
self.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS) self.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)

View file

@ -160,7 +160,7 @@ class CampaignController:
str(e), str(e),
) )
return return
self.app.mark_model_dirty(players_stats=True) self.app.is_dirty = True
self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS) self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
self.app.navigation.refresh_and_select( self.app.navigation.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.CAMPAIGN, item_id=campaign_id RefreshScope.WARS_TREE, item_type=ItemType.CAMPAIGN, item_id=campaign_id

View file

@ -8,12 +8,6 @@ from PyQt6.QtGui import QIcon
class ParticipantOption: class ParticipantOption:
id: str id: str
name: str name: str
wars_played: int | None = None
wars_won: int | None = None
campaigns_played: int | None = None
campaigns_won: int | None = None
battles_played: int | None = None
battles_won: int | None = None
@dataclass(frozen=True, slots=True) @dataclass(frozen=True, slots=True)
@ -141,6 +135,11 @@ class WarParticipantScoreDTO:
objective_icons: Dict[str, QIcon] = field(default_factory=dict) objective_icons: Dict[str, QIcon] = field(default_factory=dict)
@dataclass
class TieDialogData:
title: str
@dataclass @dataclass
class WarSettingsDTO: class WarSettingsDTO:
major_value: int major_value: int

View file

@ -6,11 +6,11 @@ if TYPE_CHECKING:
from warchron.controller.app_controller import AppController from warchron.controller.app_controller import AppController
from warchron.controller.dtos import ( from warchron.controller.dtos import (
TreeSelection, TreeSelection,
ParticipantOption,
WarDTO, WarDTO,
CampaignDTO, CampaignDTO,
RoundDTO, RoundDTO,
) )
from warchron.controller.dtos import ParticipantOption
class NavigationController: class NavigationController:
@ -23,6 +23,13 @@ class NavigationController:
# Display methods # Display methods
def refresh_players_view(self) -> None:
players = self.app.model.get_all_players()
players_for_display: List[ParticipantOption] = [
ParticipantOption(id=p.id, name=p.name) for p in players
]
self.app.view.display_players(players_for_display)
def refresh_wars_view(self) -> None: def refresh_wars_view(self) -> None:
wars = self.app.model.get_all_wars() wars = self.app.model.get_all_wars()
wars_dto: List[WarDTO] = [ wars_dto: List[WarDTO] = [
@ -67,31 +74,6 @@ class NavigationController:
self.app.wars._fill_war_details(first_war.id) self.app.wars._fill_war_details(first_war.id)
self.update_actions_state() self.update_actions_state()
def on_tab_changed(self, index: int) -> None:
tab = self.app.view.get_current_tab()
if tab == "players" and self.app.players_stats_dirty:
self.refresh_players_view()
def refresh_players_view(self) -> None:
players = self.app.model.get_all_players()
players_for_display: List[ParticipantOption] = []
for p in players:
stats = self.app.model.get_player_stats(p.id)
players_for_display.append(
ParticipantOption(
id=p.id,
name=p.name,
wars_played=stats.wars_played,
wars_won=stats.wars_won,
campaigns_played=stats.campaigns_played,
campaigns_won=stats.campaigns_won,
battles_played=stats.battles_played,
battles_won=stats.battles_won,
)
)
self.app.players_stats_dirty = False
self.app.view.display_players(players_for_display)
def refresh(self, scope: RefreshScope) -> None: def refresh(self, scope: RefreshScope) -> None:
match scope: match scope:
case RefreshScope.PLAYERS_LIST: case RefreshScope.PLAYERS_LIST:

View file

@ -1,5 +1,4 @@
from typing import Dict from typing import Dict
from dataclasses import dataclass
from PyQt6.QtGui import QIcon from PyQt6.QtGui import QIcon
@ -12,20 +11,16 @@ from warchron.constants import (
ScoreKind, ScoreKind,
) )
from warchron.controller.dtos import TieDialogData
from warchron.model.tiebreaking import TieContext, TieBreaker from warchron.model.tiebreaking import TieContext, TieBreaker
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.scoring import ParticipantScore, ScoreComputer from warchron.model.scoring import ParticipantScore
from warchron.model.checking import ResultChecker from warchron.model.checking import ResultChecker
from warchron.model.exception import DomainError from warchron.model.exception import DomainError
@dataclass
class TieDialogData:
title: str
class Presenter: class Presenter:
@staticmethod @staticmethod
@ -35,16 +30,17 @@ class Presenter:
campaign: Campaign | None = None, campaign: Campaign | None = None,
round: Round | None = None, round: Round | None = None,
) -> TieDialogData: ) -> TieDialogData:
if ctx.context_type in (ContextType.WAR, ContextType.CAMPAIGN): # TODO display Nth place
rank = Presenter._get_tie_rank(war, ctx) if ctx.context_type == ContextType.WAR:
rank_label = Presenter._build_rank_label(rank) if ctx.objective_id:
level = str(ctx.context_type).capitalize()
if ctx.objective_id is not None:
obj = war.objectives[ctx.objective_id] obj = war.objectives[ctx.objective_id]
return TieDialogData( return TieDialogData(f"War objective tie — {obj.name}")
f"{level} objective tie for {rank_label}{obj.name}" return TieDialogData("War tie")
) if ctx.context_type == ContextType.CAMPAIGN:
return TieDialogData(f"{level} tie for {rank_label}") if ctx.objective_id:
obj = war.objectives[ctx.objective_id]
return TieDialogData(f"Campaign objective tie — {obj.name}")
return TieDialogData("Campaign tie")
if ctx.context_type == ContextType.BATTLE: if ctx.context_type == ContextType.BATTLE:
if campaign: if campaign:
sector = campaign.sectors[ctx.context_id] sector = campaign.sectors[ctx.context_id]
@ -181,57 +177,3 @@ class Presenter:
compute_icon(battle.player_1_id), compute_icon(battle.player_1_id),
compute_icon(battle.player_2_id), compute_icon(battle.player_2_id),
) )
@staticmethod
def _ordinal(n: int) -> str:
if 10 <= n % 100 <= 20:
suffix = "th"
else:
suffix = {1: "st", 2: "nd", 3: "rd"}.get(n % 10, "th")
return f"{n}{suffix}"
@staticmethod
def _build_rank_label(rank: int | None) -> str:
if rank is None:
return ""
return f"{Presenter._ordinal(rank)} place"
@staticmethod
def _get_tie_rank(
war: War,
ctx: TieContext,
) -> int | None:
from warchron.model.checking import ResultChecker
scores = ScoreComputer.compute_scores(
war,
ctx.context_type,
ctx.context_id,
)
if ctx.objective_id is None:
def value_getter(score: ParticipantScore) -> int:
return score.victory_points
score_kind = ScoreKind.VP
else:
obj_id = ctx.objective_id
def value_getter(score: ParticipantScore) -> int:
return score.narrative_points.get(obj_id, 0)
score_kind = ScoreKind.NP
ranking = ResultChecker.get_effective_ranking(
war,
ctx.context_type,
ctx.context_id,
score_kind,
scores,
value_getter,
ctx.objective_id,
)
tied = set(ctx.participants)
for rank, group, _ in ranking:
if tied.intersection(group):
return rank
return None

View file

@ -186,38 +186,16 @@ class RoundController:
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)
workflow = RoundClosureWorkflow(self.app) workflow = RoundClosureWorkflow(self.app)
confirmed = False try:
stop = False workflow.start(war, camp, rnd)
while True: except DomainError as e:
try: QMessageBox.warning(
workflow.start(war, camp, rnd, confirmed) self.app.view,
break "Closure forbidden",
except RequiresConfirmation as e: str(e),
reply = QMessageBox.question( )
self.app.view,
"Confirm closing",
str(e),
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
)
if reply == QMessageBox.StandardButton.Yes:
if e.action:
e.action()
confirmed = True
continue
else:
stop = True
break
except DomainError as e:
QMessageBox.warning(
self.app.view,
"Closure forbidden",
str(e),
)
stop = True
break
if stop:
return return
self.app.mark_model_dirty(players_stats=True) self.app.is_dirty = True
self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS) self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
self.app.navigation.refresh_and_select( self.app.navigation.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.ROUND, item_id=round_id RefreshScope.WARS_TREE, item_type=ItemType.ROUND, item_id=round_id
@ -256,11 +234,10 @@ class RoundController:
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
) )
if reply == QMessageBox.StandardButton.Yes: if reply == QMessageBox.StandardButton.Yes:
if e.action: e.action()
e.action()
else: else:
return return
self.app.mark_model_dirty() self.app.is_dirty = True
self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS) self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
self.app.navigation.refresh_and_select( self.app.navigation.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.ROUND, item_id=round_id RefreshScope.WARS_TREE, item_type=ItemType.ROUND, item_id=round_id

View file

@ -147,7 +147,7 @@ class WarController:
str(e), str(e),
) )
return return
self.app.mark_model_dirty(players_stats=True) self.app.is_dirty = True
self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS) self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
self.app.navigation.refresh_and_select( self.app.navigation.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war_id RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war_id
@ -221,11 +221,10 @@ class WarController:
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
) )
if reply == QMessageBox.StandardButton.Yes: if reply == QMessageBox.StandardButton.Yes:
if e.action: e.action()
e.action()
else: else:
return return
self.app.mark_model_dirty() self.is_dirty = True
self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS) self.app.navigation.refresh(RefreshScope.CURRENT_SELECTION_DETAILS)
self.app.navigation.refresh_and_select( self.app.navigation.refresh_and_select(
RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war_id RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war_id

View file

@ -18,10 +18,8 @@ class Workflow:
class RoundClosureWorkflow(Workflow): class RoundClosureWorkflow(Workflow):
def start( def start(self, war: War, campaign: Campaign, round: Round) -> None:
self, war: War, campaign: Campaign, round: Round, confirmed: bool = False Closer.check_round_closable(round)
) -> None:
Closer.check_round_closable(round, confirmed)
ties = TieBreaker.find_battle_ties(war, round.id) ties = TieBreaker.find_battle_ties(war, round.id)
while ties: while ties:
for tie in ties: for tie in ties:

View file

@ -73,14 +73,6 @@ class Battle:
return return
raise DomainError("Battle has no available places") raise DomainError("Battle has no available places")
def get_participants_ids(self) -> List[str]:
players: List[str] = []
if self.player_1_id:
players.append(self.player_1_id)
if self.player_2_id:
players.append(self.player_2_id)
return players
def clear_battle_players(self) -> None: def clear_battle_players(self) -> None:
self.player_1_id = None self.player_1_id = None
self.player_2_id = None self.player_2_id = None
@ -88,12 +80,6 @@ class Battle:
def is_finished(self) -> bool: def is_finished(self) -> bool:
return self.winner_id is not None or self.is_draw() return self.winner_id is not None or self.is_draw()
def has_player(self) -> bool:
return self.player_1_id is not None or self.player_2_id is not None
def is_complete(self) -> bool:
return self.player_1_id is not None and self.player_2_id is not None
def toDict(self) -> Dict[str, Any]: def toDict(self) -> Dict[str, Any]:
return { return {
"sector_id": self.sector_id, "sector_id": self.sector_id,

View file

@ -1,7 +1,7 @@
from __future__ import annotations from __future__ import annotations
from warchron.constants import ContextType from warchron.constants import ContextType
from warchron.model.exception import ForbiddenOperation, RequiresConfirmation from warchron.model.exception import ForbiddenOperation
from warchron.model.war_event import InfluenceGained from warchron.model.war_event import InfluenceGained
from warchron.model.war import War from warchron.model.war import War
from warchron.model.campaign import Campaign from warchron.model.campaign import Campaign
@ -14,19 +14,13 @@ class Closer:
# Round methods # Round methods
@staticmethod @staticmethod
def check_round_closable(round: Round, confirmed: bool) -> None: def check_round_closable(round: Round) -> None:
if round.is_over: if round.is_over:
raise ForbiddenOperation("Round already closed") raise ForbiddenOperation("Round already closed")
if not confirmed: if not round.all_battles_finished():
if any(not bat.is_complete() for bat in round.battles.values()): raise ForbiddenOperation(
raise RequiresConfirmation( "All battles must be finished to close their round"
"Battle(s) in this round miss player(s).\n" )
"Do you want to continue?",
)
if not round.all_battles_finished():
raise ForbiddenOperation(
"All battles must be finished to close their round"
)
@staticmethod @staticmethod
def apply_battle_outcomes(war: War, campaign: Campaign, battle: Battle) -> None: def apply_battle_outcomes(war: War, campaign: Campaign, battle: Battle) -> None:

View file

@ -26,6 +26,6 @@ class DomainDecision(Exception):
class RequiresConfirmation(DomainDecision): class RequiresConfirmation(DomainDecision):
def __init__(self, message: str, action: Callable[[], None] | None = None): def __init__(self, message: str, action: Callable[[], None]):
super().__init__(message) super().__init__(message)
self.action = action self.action = action

View file

@ -15,7 +15,6 @@ from warchron.model.sector import Sector
from warchron.model.round import Round from warchron.model.round import Round
from warchron.model.choice import Choice from warchron.model.choice import Choice
from warchron.model.battle import Battle from warchron.model.battle import Battle
from warchron.model.statistics import PlayerStats, StatisticsComputer
class Model: class Model:
@ -99,9 +98,6 @@ class Model:
) )
del self.players[player_id] del self.players[player_id]
def get_player_stats(self, player_id: str) -> PlayerStats:
return StatisticsComputer.compute_player_stats(self.wars, player_id)
# War methods # War methods
def get_default_war_values(self) -> Dict[str, Any]: def get_default_war_values(self) -> Dict[str, Any]:

View file

@ -63,7 +63,10 @@ class Pairing:
bat.set_winner(None) bat.set_winner(None)
war.revert_choice_ties(round.id) war.revert_choice_ties(round.id)
if any(bat.has_player() for bat in round.battles.values()): if any(
bat.player_1_id is not None or bat.player_2_id is not None
for bat in round.battles.values()
):
raise RequiresConfirmation( raise RequiresConfirmation(
"Battle(s) already have player(s) assigned for this round.\n" "Battle(s) already have player(s) assigned for this round.\n"
"Battle players will be cleared.\n" "Battle players will be cleared.\n"
@ -326,8 +329,6 @@ class Pairing:
round: Round, round: Round,
remaining: List[str], remaining: List[str],
) -> None: ) -> None:
if not remaining:
return
campaign = war.get_campaign_by_round(round.id) campaign = war.get_campaign_by_round(round.id)
if campaign is None: if campaign is None:
raise DomainError("Campaign not found") raise DomainError("Campaign not found")

View file

@ -166,6 +166,7 @@ class Round:
return any(b.is_finished() for b in self.battles.values()) return any(b.is_finished() for b in self.battles.values())
def all_battles_finished(self) -> bool: def all_battles_finished(self) -> bool:
# TODO exception for participant alone
return all( return all(
b.winner_id is not None or b.is_draw() for b in self.battles.values() b.winner_id is not None or b.is_draw() for b in self.battles.values()
) )

View file

@ -1,101 +0,0 @@
from __future__ import annotations
from typing import Dict
from dataclasses import dataclass
from warchron.constants import ContextType, ScoreKind
from warchron.model.war import War
from warchron.model.scoring import ScoreComputer
from warchron.model.checking import ResultChecker
@dataclass
class PlayerStats:
wars_played: int = 0
wars_won: int = 0
campaigns_played: int = 0
campaigns_won: int = 0
battles_played: int = 0
battles_won: int = 0
class StatisticsComputer:
@staticmethod
def compute_player_stats(
wars: Dict[str, War],
player_id: str,
) -> PlayerStats:
stats = PlayerStats()
for war in wars.values():
# --- WAR PARTICIPANT ---
war_part = next(
(wp for wp in war.participants.values() if wp.player_id == player_id),
None,
)
if not war_part:
continue
stats.wars_played += 1
if war.is_over:
scores = ScoreComputer.compute_scores(war, ContextType.WAR, war.id)
ranking = ResultChecker.get_effective_ranking(
war,
ContextType.WAR,
war.id,
ScoreKind.VP,
scores,
lambda s: s.victory_points,
)
if ranking and war_part.id in ranking[0][1]:
stats.wars_won += 1
# --- CAMPAIGNS ---
for campaign in war.campaigns:
campaign_part = next(
(
cp
for cp in campaign.participants.values()
if cp.war_participant_id == war_part.id
),
None,
)
if not campaign_part:
continue
stats.campaigns_played += 1
if campaign.is_over:
scores = ScoreComputer.compute_scores(
war, ContextType.CAMPAIGN, campaign.id
)
ranking = ResultChecker.get_effective_ranking(
war,
ContextType.CAMPAIGN,
campaign.id,
ScoreKind.VP,
scores,
lambda s: s.victory_points,
)
if ranking and war_part.id in ranking[0][1]:
stats.campaigns_won += 1
# --- BATTLES ---
for rnd in campaign.rounds:
for battle in rnd.battles.values():
if not battle.is_finished():
continue
if campaign_part.id not in (
battle.player_1_id,
battle.player_2_id,
):
continue
stats.battles_played += 1
base_winner = None
if battle.winner_id is not None:
base_winner = campaign.campaign_to_war_part_id(
battle.winner_id
)
winner = ResultChecker.get_effective_winner_id(
war,
ContextType.BATTLE,
battle.sector_id,
base_winner,
)
if winner == war_part.id:
stats.battles_won += 1
return stats

View file

@ -63,9 +63,8 @@ class TieBreaker:
for battle in round.battles.values(): for battle in round.battles.values():
if campaign is None: if campaign is None:
raise DomainError("No campaign for this battle tie") raise DomainError("No campaign for this battle tie")
if not battle.is_complete(): if battle.player_1_id is None or battle.player_2_id is None:
continue raise DomainError("Missing player(s) in this battle context.")
assert battle.player_1_id is not None and battle.player_2_id is not None
p1_id = campaign.campaign_to_war_part_id(battle.player_1_id) p1_id = campaign.campaign_to_war_part_id(battle.player_1_id)
p2_id = campaign.campaign_to_war_part_id(battle.player_2_id) p2_id = campaign.campaign_to_war_part_id(battle.player_2_id)
if not battle.is_draw(): if not battle.is_draw():

View file

@ -13,7 +13,7 @@ class Ui_settingsDialog(object):
def setupUi(self, settingsDialog): def setupUi(self, settingsDialog):
settingsDialog.setObjectName("settingsDialog") settingsDialog.setObjectName("settingsDialog")
settingsDialog.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal) settingsDialog.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
settingsDialog.resize(621, 387) settingsDialog.resize(661, 377)
icon = QtGui.QIcon() icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(".\\src\\warchron\\view\\ui\\../resources/warchron_logo.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) icon.addPixmap(QtGui.QPixmap(".\\src\\warchron\\view\\ui\\../resources/warchron_logo.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
settingsDialog.setWindowIcon(icon) settingsDialog.setWindowIcon(icon)
@ -24,8 +24,8 @@ class Ui_settingsDialog(object):
font.setPointSize(10) font.setPointSize(10)
self.groupBox_2.setFont(font) self.groupBox_2.setFont(font)
self.groupBox_2.setObjectName("groupBox_2") self.groupBox_2.setObjectName("groupBox_2")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.groupBox_2) self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupBox_2)
self.verticalLayout_3.setObjectName("verticalLayout_3") self.verticalLayout_2.setObjectName("verticalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout") self.horizontalLayout.setObjectName("horizontalLayout")
self.label_5 = QtWidgets.QLabel(parent=self.groupBox_2) self.label_5 = QtWidgets.QLabel(parent=self.groupBox_2)
@ -56,58 +56,25 @@ class Ui_settingsDialog(object):
self.horizontalLayout.addWidget(self.label_15) self.horizontalLayout.addWidget(self.label_15)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout.addItem(spacerItem1) self.horizontalLayout.addItem(spacerItem1)
self.verticalLayout_3.addLayout(self.horizontalLayout) self.verticalLayout_2.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label_12 = QtWidgets.QLabel(parent=self.groupBox_2)
self.label_12.setObjectName("label_12")
self.horizontalLayout_2.addWidget(self.label_12)
self.pointsComboBox = QtWidgets.QComboBox(parent=self.groupBox_2)
self.pointsComboBox.setEnabled(False)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pointsComboBox.sizePolicy().hasHeightForWidth())
self.pointsComboBox.setSizePolicy(sizePolicy)
self.pointsComboBox.setObjectName("pointsComboBox")
self.pointsComboBox.addItem("")
self.pointsComboBox.addItem("")
self.horizontalLayout_2.addWidget(self.pointsComboBox)
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_2.addItem(spacerItem2)
self.internalTiebreak = QtWidgets.QCheckBox(parent=self.groupBox_2)
self.internalTiebreak.setEnabled(False)
self.internalTiebreak.setText("")
self.internalTiebreak.setCheckable(True)
self.internalTiebreak.setChecked(True)
self.internalTiebreak.setObjectName("internalTiebreak")
self.horizontalLayout_2.addWidget(self.internalTiebreak)
self.label_20 = QtWidgets.QLabel(parent=self.groupBox_2)
self.label_20.setObjectName("label_20")
self.horizontalLayout_2.addWidget(self.label_20)
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_2.addItem(spacerItem3)
self.verticalLayout_3.addLayout(self.horizontalLayout_2)
self.horizontalLayout_5 = QtWidgets.QHBoxLayout() self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
self.horizontalLayout_5.setObjectName("horizontalLayout_5") self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.label_19 = QtWidgets.QLabel(parent=self.groupBox_2) self.label_12 = QtWidgets.QLabel(parent=self.groupBox_2)
self.label_19.setObjectName("label_19") self.label_12.setObjectName("label_12")
self.horizontalLayout_5.addWidget(self.label_19) self.horizontalLayout_5.addWidget(self.label_12)
self.rankingComboBox_2 = QtWidgets.QComboBox(parent=self.groupBox_2) self.rankingComboBox = QtWidgets.QComboBox(parent=self.groupBox_2)
self.rankingComboBox_2.setEnabled(False) self.rankingComboBox.setEnabled(False)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.rankingComboBox_2.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.rankingComboBox.sizePolicy().hasHeightForWidth())
self.rankingComboBox_2.setSizePolicy(sizePolicy) self.rankingComboBox.setSizePolicy(sizePolicy)
self.rankingComboBox_2.setObjectName("rankingComboBox_2") self.rankingComboBox.setObjectName("rankingComboBox")
self.rankingComboBox_2.addItem("") self.rankingComboBox.addItem("")
self.rankingComboBox_2.addItem("") self.horizontalLayout_5.addWidget(self.rankingComboBox)
self.rankingComboBox_2.addItem("") spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_5.addWidget(self.rankingComboBox_2) self.horizontalLayout_5.addItem(spacerItem2)
spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) self.verticalLayout_2.addLayout(self.horizontalLayout_5)
self.horizontalLayout_5.addItem(spacerItem4)
self.verticalLayout_3.addLayout(self.horizontalLayout_5)
self.verticalLayout_4.addWidget(self.groupBox_2) self.verticalLayout_4.addWidget(self.groupBox_2)
self.groupBox = QtWidgets.QGroupBox(parent=settingsDialog) self.groupBox = QtWidgets.QGroupBox(parent=settingsDialog)
font = QtGui.QFont() font = QtGui.QFont()
@ -128,8 +95,8 @@ class Ui_settingsDialog(object):
self.label_8 = QtWidgets.QLabel(parent=self.groupBox) self.label_8 = QtWidgets.QLabel(parent=self.groupBox)
self.label_8.setObjectName("label_8") self.label_8.setObjectName("label_8")
self.horizontalLayout_3.addWidget(self.label_8) self.horizontalLayout_3.addWidget(self.label_8)
spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_3.addItem(spacerItem5) self.horizontalLayout_3.addItem(spacerItem3)
self.label_9 = QtWidgets.QLabel(parent=self.groupBox) self.label_9 = QtWidgets.QLabel(parent=self.groupBox)
self.label_9.setObjectName("label_9") self.label_9.setObjectName("label_9")
self.horizontalLayout_3.addWidget(self.label_9) self.horizontalLayout_3.addWidget(self.label_9)
@ -140,8 +107,8 @@ class Ui_settingsDialog(object):
self.label_10 = QtWidgets.QLabel(parent=self.groupBox) self.label_10 = QtWidgets.QLabel(parent=self.groupBox)
self.label_10.setObjectName("label_10") self.label_10.setObjectName("label_10")
self.horizontalLayout_3.addWidget(self.label_10) self.horizontalLayout_3.addWidget(self.label_10)
spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_3.addItem(spacerItem6) self.horizontalLayout_3.addItem(spacerItem4)
self.verticalLayout.addLayout(self.horizontalLayout_3) self.verticalLayout.addLayout(self.horizontalLayout_3)
self.horizontalLayout_4 = QtWidgets.QHBoxLayout() self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.horizontalLayout_4.setObjectName("horizontalLayout_4")
@ -154,8 +121,8 @@ class Ui_settingsDialog(object):
self.influenceToken.setChecked(True) self.influenceToken.setChecked(True)
self.influenceToken.setObjectName("influenceToken") self.influenceToken.setObjectName("influenceToken")
self.horizontalLayout_4.addWidget(self.influenceToken) self.horizontalLayout_4.addWidget(self.influenceToken)
spacerItem7 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_4.addItem(spacerItem7) self.horizontalLayout_4.addItem(spacerItem5)
self.verticalLayout.addLayout(self.horizontalLayout_4) self.verticalLayout.addLayout(self.horizontalLayout_4)
self.verticalLayout_4.addWidget(self.groupBox) self.verticalLayout_4.addWidget(self.groupBox)
self.groupBox_3 = QtWidgets.QGroupBox(parent=settingsDialog) self.groupBox_3 = QtWidgets.QGroupBox(parent=settingsDialog)
@ -163,45 +130,13 @@ class Ui_settingsDialog(object):
font.setPointSize(10) font.setPointSize(10)
self.groupBox_3.setFont(font) self.groupBox_3.setFont(font)
self.groupBox_3.setObjectName("groupBox_3") self.groupBox_3.setObjectName("groupBox_3")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupBox_3) self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.groupBox_3)
self.verticalLayout_2.setObjectName("verticalLayout_2") self.verticalLayout_3.setObjectName("verticalLayout_3")
self.horizontalLayout_7 = QtWidgets.QHBoxLayout() self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
self.horizontalLayout_7.setObjectName("horizontalLayout_7") self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.label_21 = QtWidgets.QLabel(parent=self.groupBox_3)
self.label_21.setObjectName("label_21")
self.horizontalLayout_7.addWidget(self.label_21)
self.drawComboBox = QtWidgets.QComboBox(parent=self.groupBox_3)
self.drawComboBox.setEnabled(False)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.drawComboBox.sizePolicy().hasHeightForWidth())
self.drawComboBox.setSizePolicy(sizePolicy)
self.drawComboBox.setObjectName("drawComboBox")
self.drawComboBox.addItem("")
self.drawComboBox.addItem("")
self.drawComboBox.addItem("")
self.horizontalLayout_7.addWidget(self.drawComboBox)
spacerItem8 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_7.addItem(spacerItem8)
self.label_18 = QtWidgets.QLabel(parent=self.groupBox_3)
self.label_18.setObjectName("label_18")
self.horizontalLayout_7.addWidget(self.label_18)
self.shuffle = QtWidgets.QCheckBox(parent=self.groupBox_3)
self.shuffle.setEnabled(False)
self.shuffle.setText("")
self.shuffle.setCheckable(True)
self.shuffle.setChecked(True)
self.shuffle.setObjectName("shuffle")
self.horizontalLayout_7.addWidget(self.shuffle)
spacerItem9 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_7.addItem(spacerItem9)
self.verticalLayout_2.addLayout(self.horizontalLayout_7)
self.horizontalLayout_8 = QtWidgets.QHBoxLayout()
self.horizontalLayout_8.setObjectName("horizontalLayout_8")
self.label_17 = QtWidgets.QLabel(parent=self.groupBox_3) self.label_17 = QtWidgets.QLabel(parent=self.groupBox_3)
self.label_17.setObjectName("label_17") self.label_17.setObjectName("label_17")
self.horizontalLayout_8.addWidget(self.label_17) self.horizontalLayout_7.addWidget(self.label_17)
self.fallbackComboBox = QtWidgets.QComboBox(parent=self.groupBox_3) self.fallbackComboBox = QtWidgets.QComboBox(parent=self.groupBox_3)
self.fallbackComboBox.setEnabled(False) self.fallbackComboBox.setEnabled(False)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed)
@ -211,11 +146,22 @@ class Ui_settingsDialog(object):
self.fallbackComboBox.setSizePolicy(sizePolicy) self.fallbackComboBox.setSizePolicy(sizePolicy)
self.fallbackComboBox.setObjectName("fallbackComboBox") self.fallbackComboBox.setObjectName("fallbackComboBox")
self.fallbackComboBox.addItem("") self.fallbackComboBox.addItem("")
self.fallbackComboBox.addItem("") self.horizontalLayout_7.addWidget(self.fallbackComboBox)
self.horizontalLayout_8.addWidget(self.fallbackComboBox) spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
spacerItem10 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) self.horizontalLayout_7.addItem(spacerItem6)
self.horizontalLayout_8.addItem(spacerItem10) self.label_18 = QtWidgets.QLabel(parent=self.groupBox_3)
self.verticalLayout_2.addLayout(self.horizontalLayout_8) self.label_18.setObjectName("label_18")
self.horizontalLayout_7.addWidget(self.label_18)
self.influenceToken_2 = QtWidgets.QCheckBox(parent=self.groupBox_3)
self.influenceToken_2.setEnabled(False)
self.influenceToken_2.setText("")
self.influenceToken_2.setCheckable(True)
self.influenceToken_2.setChecked(True)
self.influenceToken_2.setObjectName("influenceToken_2")
self.horizontalLayout_7.addWidget(self.influenceToken_2)
spacerItem7 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_7.addItem(spacerItem7)
self.verticalLayout_3.addLayout(self.horizontalLayout_7)
self.horizontalLayout_6 = QtWidgets.QHBoxLayout() self.horizontalLayout_6 = QtWidgets.QHBoxLayout()
self.horizontalLayout_6.setObjectName("horizontalLayout_6") self.horizontalLayout_6.setObjectName("horizontalLayout_6")
self.label_13 = QtWidgets.QLabel(parent=self.groupBox_3) self.label_13 = QtWidgets.QLabel(parent=self.groupBox_3)
@ -226,8 +172,8 @@ class Ui_settingsDialog(object):
self.rematchValue.setMinimum(1) self.rematchValue.setMinimum(1)
self.rematchValue.setObjectName("rematchValue") self.rematchValue.setObjectName("rematchValue")
self.horizontalLayout_6.addWidget(self.rematchValue) self.horizontalLayout_6.addWidget(self.rematchValue)
spacerItem11 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem8 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_6.addItem(spacerItem11) self.horizontalLayout_6.addItem(spacerItem8)
self.label_16 = QtWidgets.QLabel(parent=self.groupBox_3) self.label_16 = QtWidgets.QLabel(parent=self.groupBox_3)
self.label_16.setObjectName("label_16") self.label_16.setObjectName("label_16")
self.horizontalLayout_6.addWidget(self.label_16) self.horizontalLayout_6.addWidget(self.label_16)
@ -236,9 +182,9 @@ class Ui_settingsDialog(object):
self.occupancyValue.setMinimum(1) self.occupancyValue.setMinimum(1)
self.occupancyValue.setObjectName("occupancyValue") self.occupancyValue.setObjectName("occupancyValue")
self.horizontalLayout_6.addWidget(self.occupancyValue) self.horizontalLayout_6.addWidget(self.occupancyValue)
spacerItem12 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem9 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_6.addItem(spacerItem12) self.horizontalLayout_6.addItem(spacerItem9)
self.verticalLayout_2.addLayout(self.horizontalLayout_6) self.verticalLayout_3.addLayout(self.horizontalLayout_6)
self.verticalLayout_4.addWidget(self.groupBox_3) self.verticalLayout_4.addWidget(self.groupBox_3)
self.buttonBox = QtWidgets.QDialogButtonBox(parent=settingsDialog) self.buttonBox = QtWidgets.QDialogButtonBox(parent=settingsDialog)
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
@ -259,14 +205,8 @@ class Ui_settingsDialog(object):
self.label_14.setText(_translate("settingsDialog", "victory points")) self.label_14.setText(_translate("settingsDialog", "victory points"))
self.label_6.setText(_translate("settingsDialog", "Draw")) self.label_6.setText(_translate("settingsDialog", "Draw"))
self.label_15.setText(_translate("settingsDialog", "victory points")) self.label_15.setText(_translate("settingsDialog", "victory points"))
self.label_12.setText(_translate("settingsDialog", "War points mode")) self.label_12.setText(_translate("settingsDialog", "Ranking mode"))
self.pointsComboBox.setItemText(0, _translate("settingsDialog", "Sum battle points")) self.rankingComboBox.setItemText(0, _translate("settingsDialog", "Sum points & tie-breaks"))
self.pointsComboBox.setItemText(1, _translate("settingsDialog", "Sum campaign ranking"))
self.label_20.setText(_translate("settingsDialog", "Count internal tie-breaks"))
self.label_19.setText(_translate("settingsDialog", "Ranking mode"))
self.rankingComboBox_2.setItemText(0, _translate("settingsDialog", "Dense (1-2-2-3)"))
self.rankingComboBox_2.setItemText(1, _translate("settingsDialog", "Shift-up (1-2-2-4)"))
self.rankingComboBox_2.setItemText(2, _translate("settingsDialog", "Shift-down (1-3-3-4)"))
self.groupBox.setTitle(_translate("settingsDialog", "Objectives")) self.groupBox.setTitle(_translate("settingsDialog", "Objectives"))
self.label_4.setText(_translate("settingsDialog", "Major objective")) self.label_4.setText(_translate("settingsDialog", "Major objective"))
self.label_8.setText(_translate("settingsDialog", "narrative points")) self.label_8.setText(_translate("settingsDialog", "narrative points"))
@ -275,14 +215,9 @@ class Ui_settingsDialog(object):
self.label_11.setText(_translate("settingsDialog", "Underlying influence")) self.label_11.setText(_translate("settingsDialog", "Underlying influence"))
self.influenceToken.setText(_translate("settingsDialog", "Token")) self.influenceToken.setText(_translate("settingsDialog", "Token"))
self.groupBox_3.setTitle(_translate("settingsDialog", "Pairing")) self.groupBox_3.setTitle(_translate("settingsDialog", "Pairing"))
self.label_21.setText(_translate("settingsDialog", "Draw priority"))
self.drawComboBox.setItemText(0, _translate("settingsDialog", "Best war ranking"))
self.drawComboBox.setItemText(1, _translate("settingsDialog", "Random"))
self.drawComboBox.setItemText(2, _translate("settingsDialog", "Avoid rematch"))
self.label_18.setText(_translate("settingsDialog", "Shuffle groups"))
self.label_17.setText(_translate("settingsDialog", "Fallback mode")) self.label_17.setText(_translate("settingsDialog", "Fallback mode"))
self.fallbackComboBox.setItemText(0, _translate("settingsDialog", "Avoid rematch")) self.fallbackComboBox.setItemText(0, _translate("settingsDialog", "Best ranking first & avoid rematch"))
self.fallbackComboBox.setItemText(1, _translate("settingsDialog", "Random")) self.label_18.setText(_translate("settingsDialog", "Shuffle"))
self.label_13.setText(_translate("settingsDialog", "Rematch weight")) self.label_13.setText(_translate("settingsDialog", "Rematch weight"))
self.label_16.setText(_translate("settingsDialog", "Occupancy weight")) self.label_16.setText(_translate("settingsDialog", "Occupancy weight"))

View file

@ -9,8 +9,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>621</width> <width>661</width>
<height>387</height> <height>377</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -31,7 +31,7 @@
<property name="title"> <property name="title">
<string>Scores</string> <string>Scores</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
@ -116,100 +116,17 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_12">
<property name="text">
<string>War points mode</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="pointsComboBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Sum battle points</string>
</property>
</item>
<item>
<property name="text">
<string>Sum campaign ranking</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="internalTiebreak">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_20">
<property name="text">
<string>Count internal tie-breaks</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_18">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_5"> <layout class="QHBoxLayout" name="horizontalLayout_5">
<item> <item>
<widget class="QLabel" name="label_19"> <widget class="QLabel" name="label_12">
<property name="text"> <property name="text">
<string>Ranking mode</string> <string>Ranking mode</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QComboBox" name="rankingComboBox_2"> <widget class="QComboBox" name="rankingComboBox">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
@ -221,23 +138,13 @@
</property> </property>
<item> <item>
<property name="text"> <property name="text">
<string>Dense (1-2-2-3)</string> <string>Sum points &amp; tie-breaks</string>
</property>
</item>
<item>
<property name="text">
<string>Shift-up (1-2-2-4)</string>
</property>
</item>
<item>
<property name="text">
<string>Shift-down (1-3-3-4)</string>
</property> </property>
</item> </item>
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer_5"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@ -390,97 +297,9 @@
<property name="title"> <property name="title">
<string>Pairing</string> <string>Pairing</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_3">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_7"> <layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="label_21">
<property name="text">
<string>Draw priority</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="drawComboBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Best war ranking</string>
</property>
</item>
<item>
<property name="text">
<string>Random</string>
</property>
</item>
<item>
<property name="text">
<string>Avoid rematch</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_18">
<property name="text">
<string>Shuffle groups</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="shuffle">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_17">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item> <item>
<widget class="QLabel" name="label_17"> <widget class="QLabel" name="label_17">
<property name="text"> <property name="text">
@ -501,12 +320,7 @@
</property> </property>
<item> <item>
<property name="text"> <property name="text">
<string>Avoid rematch</string> <string>Best ranking first &amp; avoid rematch</string>
</property>
</item>
<item>
<property name="text">
<string>Random</string>
</property> </property>
</item> </item>
</widget> </widget>
@ -524,6 +338,42 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item>
<widget class="QLabel" name="label_18">
<property name="text">
<string>Shuffle</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="influenceToken_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_17">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</item> </item>
<item> <item>

View file

@ -67,7 +67,7 @@ class Ui_tieDialog(object):
def retranslateUi(self, tieDialog): def retranslateUi(self, tieDialog):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
tieDialog.setWindowTitle(_translate("tieDialog", "Tie-break")) tieDialog.setWindowTitle(_translate("tieDialog", "Tie"))
self.tieContext.setText(_translate("tieDialog", "Battle tie")) self.tieContext.setText(_translate("tieDialog", "Battle tie"))

View file

@ -14,7 +14,7 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Tie-break</string> <string>Tie</string>
</property> </property>
<property name="windowIcon"> <property name="windowIcon">
<iconset> <iconset>

View file

@ -200,47 +200,15 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
elif action == delete_action and self.on_delete_item: elif action == delete_action and self.on_delete_item:
self.on_delete_item(ItemType.PLAYER, player_id) self.on_delete_item(ItemType.PLAYER, player_id)
def _make_ratio_item(
self, won: int | None, played: int | None
) -> QtWidgets.QTableWidgetItem:
if not played:
text = ""
ratio = -1.0
else:
won = won or 0
text = f"{won} / {played}"
ratio = won / played
item = QtWidgets.QTableWidgetItem(text)
item.setData(Qt.ItemDataRole.UserRole, ratio)
return item
def display_players(self, players: List[ParticipantOption]) -> None: def display_players(self, players: List[ParticipantOption]) -> None:
# TODO display stats (war, campaign battles...)
table = self.playersTable table = self.playersTable
table.setSortingEnabled(False) table.setSortingEnabled(False)
table.setColumnCount(4)
table.setHorizontalHeaderLabels(["Name", "Wars", "Campaigns", "Battles"])
table.setRowCount(len(players)) table.setRowCount(len(players))
for row, player in enumerate(players): for row, player in enumerate(players):
play_item = QtWidgets.QTableWidgetItem(player.name) play_item = QtWidgets.QTableWidgetItem(player.name)
wars_item = self._make_ratio_item(
player.wars_won,
player.wars_played,
)
camp_item = self._make_ratio_item(
player.campaigns_won,
player.campaigns_played,
)
bat_item = self._make_ratio_item(
player.battles_won,
player.battles_played,
)
play_item.setData(Qt.ItemDataRole.UserRole, player.id) play_item.setData(Qt.ItemDataRole.UserRole, player.id)
table.setItem(row, 0, play_item) table.setItem(row, 0, play_item)
table.setItem(row, 1, wars_item)
table.setItem(row, 2, camp_item)
table.setItem(row, 3, bat_item)
table.setSortingEnabled(True) table.setSortingEnabled(True)
table.sortItems(0, Qt.SortOrder.AscendingOrder) table.sortItems(0, Qt.SortOrder.AscendingOrder)
table.resizeColumnsToContents() table.resizeColumnsToContents()