display battle tie-break token
This commit is contained in:
parent
818d2886f4
commit
23110383c2
9 changed files with 127 additions and 29 deletions
|
|
@ -4,7 +4,7 @@ from pathlib import Path
|
|||
from typing import Dict
|
||||
|
||||
from PyQt6.QtCore import Qt
|
||||
from PyQt6.QtGui import QIcon
|
||||
from PyQt6.QtGui import QIcon, QPixmap, QPainter
|
||||
|
||||
|
||||
# Paths
|
||||
|
|
@ -17,37 +17,44 @@ ROLE_ID = Qt.ItemDataRole.UserRole + 1
|
|||
|
||||
|
||||
class IconName(str, Enum):
|
||||
UNDO = ("undo",)
|
||||
REDO = ("redo",)
|
||||
PAIRING = ("pairing",)
|
||||
DRAW = ("draw",)
|
||||
DELETE = ("delete",)
|
||||
SAVE_AS = ("save_as",)
|
||||
SAVE = ("save",)
|
||||
NEW = ("new",)
|
||||
EXIT = ("exit",)
|
||||
END = ("end",)
|
||||
OPEN = ("load",)
|
||||
ONGOING = ("ongoing",)
|
||||
EXPORT = ("export",)
|
||||
EDIT = ("edit",)
|
||||
ADD = ("add",)
|
||||
ABOUT = ("about",)
|
||||
WARS = ("wars",)
|
||||
DONE = ("done",)
|
||||
WIN = ("win",)
|
||||
PLAYERS = ("players",)
|
||||
UNDO = "undo"
|
||||
REDO = "redo"
|
||||
PAIRING = "pairing"
|
||||
DRAW = "draw"
|
||||
TIEBREAK = "tie-break"
|
||||
DELETE = "delete"
|
||||
SAVE_AS = "save_as"
|
||||
SAVE = "save"
|
||||
NEW = "new"
|
||||
EXIT = "exit"
|
||||
END = "end"
|
||||
OPEN = "load"
|
||||
ONGOING = "ongoing"
|
||||
EXPORT = "export"
|
||||
EDIT = "edit"
|
||||
ADD = "add"
|
||||
ABOUT = "about"
|
||||
WARS = "wars"
|
||||
DONE = "done"
|
||||
WIN = "win"
|
||||
PLAYERS = "players"
|
||||
WARCHRON = "warchron"
|
||||
TOKEN = "token"
|
||||
TOKENS = "tokens"
|
||||
TIEBREAK_TOKEN = auto()
|
||||
|
||||
|
||||
class Icons:
|
||||
_cache: Dict[str, QIcon] = {}
|
||||
_icon_cache: Dict[IconName, QIcon] = {}
|
||||
|
||||
_pixmap_cache: Dict[IconName, QPixmap] = {}
|
||||
|
||||
_paths = {
|
||||
IconName.UNDO: "arrow-curve-180-left",
|
||||
IconName.REDO: "arrow-curve",
|
||||
IconName.PAIRING: "arrow-switch",
|
||||
IconName.DRAW: "balance.png",
|
||||
IconName.TIEBREAK: "balance-unbalance.png",
|
||||
IconName.DELETE: "cross.png",
|
||||
IconName.SAVE_AS: "disk--pencil.png",
|
||||
IconName.SAVE: "disk.png",
|
||||
|
|
@ -65,14 +72,43 @@ class Icons:
|
|||
IconName.WIN: "trophy.png",
|
||||
IconName.PLAYERS: "users.png",
|
||||
IconName.WARCHRON: "warchron_logo.png",
|
||||
IconName.TOKEN: "point.png",
|
||||
IconName.TOKENS: "points.png",
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get(cls, name: IconName) -> QIcon:
|
||||
if name not in cls._cache:
|
||||
if name not in cls._icon_cache:
|
||||
path = RESOURCES_DIR / cls._paths[name]
|
||||
cls._cache[name] = QIcon(str(path))
|
||||
return cls._cache[name]
|
||||
cls._icon_cache[name] = QIcon(str(path))
|
||||
return cls._icon_cache[name]
|
||||
|
||||
@classmethod
|
||||
def get_pixmap(cls, name: IconName) -> QPixmap:
|
||||
if name in cls._pixmap_cache:
|
||||
return cls._pixmap_cache[name]
|
||||
if name == IconName.TIEBREAK_TOKEN:
|
||||
pix = cls._compose(
|
||||
cls.get_pixmap(IconName.TIEBREAK),
|
||||
cls.get_pixmap(IconName.TOKEN),
|
||||
)
|
||||
else:
|
||||
path = RESOURCES_DIR / cls._paths[name]
|
||||
pix = QPixmap(path.as_posix())
|
||||
cls._pixmap_cache[name] = pix
|
||||
return pix
|
||||
|
||||
@staticmethod
|
||||
def _compose(left: QPixmap, right: QPixmap) -> QPixmap:
|
||||
w = left.width() + right.width()
|
||||
h = max(left.height(), right.height())
|
||||
result = QPixmap(w, h)
|
||||
result.fill(Qt.GlobalColor.transparent)
|
||||
painter = QPainter(result)
|
||||
painter.drawPixmap(0, (h - left.height()) // 2, left)
|
||||
painter.drawPixmap(left.width(), (h - right.height()) // 2, right)
|
||||
painter.end()
|
||||
return result
|
||||
|
||||
|
||||
class ItemType(StrEnum):
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ class BattleDTO:
|
|||
state_icon: QIcon | None
|
||||
player1_icon: QIcon | None
|
||||
player2_icon: QIcon | None
|
||||
player1_tooltip: str | None = None
|
||||
player2_tooltip: str | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@ from typing import List, Dict, TYPE_CHECKING
|
|||
|
||||
from PyQt6.QtWidgets import QDialog
|
||||
from PyQt6.QtWidgets import QMessageBox
|
||||
from PyQt6.QtGui import QIcon
|
||||
|
||||
from warchron.constants import ItemType, RefreshScope, Icons, IconName
|
||||
from warchron.constants import ItemType, RefreshScope, Icons, IconName, ContextType
|
||||
from warchron.model.exception import ForbiddenOperation, DomainError
|
||||
from warchron.model.tie_manager import TieResolver
|
||||
from warchron.model.round import Round
|
||||
from warchron.model.war import War
|
||||
|
||||
|
|
@ -31,6 +33,7 @@ class RoundController:
|
|||
def _fill_round_details(self, round_id: str) -> None:
|
||||
rnd = self.app.model.get_round(round_id)
|
||||
camp = self.app.model.get_campaign_by_round(round_id)
|
||||
war = self.app.model.get_war_by_round(round_id)
|
||||
self.app.view.show_round_details(index=camp.get_round_index(round_id))
|
||||
participants = self.app.model.get_round_participants(round_id)
|
||||
sectors = camp.get_sectors_in_round(round_id)
|
||||
|
|
@ -97,9 +100,29 @@ class RoundController:
|
|||
winner_name = ""
|
||||
p1_icon = None
|
||||
p2_icon = None
|
||||
p1_tooltip = None
|
||||
p2_tooltip = None
|
||||
if battle.is_draw():
|
||||
p1_icon = Icons.get(IconName.DRAW)
|
||||
p2_icon = Icons.get(IconName.DRAW)
|
||||
if TieResolver.was_tie_broken_by_tokens(
|
||||
war, ContextType.BATTLE, battle.sector_id
|
||||
):
|
||||
effective_winner = TieResolver.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.participants[
|
||||
battle.player_1_id
|
||||
].war_participant_id
|
||||
pixmap = Icons.get_pixmap(IconName.TIEBREAK_TOKEN)
|
||||
if effective_winner == p1_war:
|
||||
p1_icon = QIcon(pixmap)
|
||||
p1_tooltip = "Won by tie-break"
|
||||
else:
|
||||
p2_icon = QIcon(pixmap)
|
||||
p2_tooltip = "Won by tie-break"
|
||||
elif battle.winner_id:
|
||||
if battle.winner_id == battle.player_1_id:
|
||||
p1_icon = Icons.get(IconName.WIN)
|
||||
|
|
@ -118,6 +141,8 @@ class RoundController:
|
|||
state_icon=state_icon,
|
||||
player1_icon=p1_icon,
|
||||
player2_icon=p2_icon,
|
||||
player1_tooltip=p1_tooltip,
|
||||
player2_tooltip=p2_tooltip,
|
||||
)
|
||||
)
|
||||
self.app.view.display_round_battles(battles_for_display)
|
||||
|
|
@ -168,6 +193,7 @@ class RoundController:
|
|||
parent=self.app.view,
|
||||
players=players,
|
||||
counters=counters,
|
||||
context_type=ContextType.BATTLE,
|
||||
context_id=ctx.context_id,
|
||||
)
|
||||
if not dialog.exec():
|
||||
|
|
|
|||
|
|
@ -106,3 +106,18 @@ class TieResolver:
|
|||
return ev.participant_id # None if confirmed draw
|
||||
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def was_tie_broken_by_tokens(
|
||||
war: War,
|
||||
context_type: ContextType,
|
||||
context_id: str,
|
||||
) -> bool:
|
||||
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 is not None
|
||||
return False
|
||||
|
|
|
|||
BIN
src/warchron/view/resources/balance-unbalance.png
Normal file
BIN
src/warchron/view/resources/balance-unbalance.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 806 B |
BIN
src/warchron/view/resources/point.png
Normal file
BIN
src/warchron/view/resources/point.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 832 B |
BIN
src/warchron/view/resources/points.png
Normal file
BIN
src/warchron/view/resources/points.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 754 B |
|
|
@ -1,8 +1,9 @@
|
|||
from typing import List, Dict
|
||||
|
||||
from PyQt6.QtWidgets import QWidget, QDialog
|
||||
from PyQt6.QtCore import Qt
|
||||
|
||||
from warchron.constants import Icons, IconName
|
||||
from warchron.constants import Icons, IconName, ContextType, RESOURCES_DIR
|
||||
from warchron.controller.dtos import ParticipantOption
|
||||
from warchron.view.ui.ui_tie_dialog import Ui_tieDialog
|
||||
|
||||
|
|
@ -14,6 +15,7 @@ class TieDialog(QDialog):
|
|||
*,
|
||||
players: List[ParticipantOption],
|
||||
counters: List[int],
|
||||
context_type: ContextType,
|
||||
context_id: str,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
|
|
@ -22,7 +24,13 @@ class TieDialog(QDialog):
|
|||
self._p2_id = players[1].id
|
||||
self.ui: Ui_tieDialog = Ui_tieDialog()
|
||||
self.ui.setupUi(self) # type: ignore
|
||||
self.ui.tieContext.setText("Battle tie") # Change with context
|
||||
self.ui.tieContext.setText(self._get_context_title(context_type))
|
||||
icon_path = (RESOURCES_DIR / Icons._paths[IconName.TOKENS]).as_posix()
|
||||
html = f'<img src="{icon_path}" width="16" height="16"> Remaining token(s)'
|
||||
self.ui.label_2.setText(html)
|
||||
self.ui.label_2.setTextFormat(Qt.TextFormat.RichText)
|
||||
self.ui.label_3.setText(html)
|
||||
self.ui.label_3.setTextFormat(Qt.TextFormat.RichText)
|
||||
self.ui.groupBox_1.setTitle(players[0].name)
|
||||
self.ui.groupBox_2.setTitle(players[1].name)
|
||||
self.ui.tokenCount_1.setText(str(counters[0]))
|
||||
|
|
@ -38,3 +46,13 @@ class TieDialog(QDialog):
|
|||
self._p1_id: self.ui.tokenSpend_1.isChecked(),
|
||||
self._p2_id: self.ui.tokenSpend_2.isChecked(),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _get_context_title(context_type: ContextType) -> str:
|
||||
titles = {
|
||||
ContextType.BATTLE: "Battle tie",
|
||||
ContextType.CAMPAIGN: "Campaign tie",
|
||||
ContextType.WAR: "War tie",
|
||||
ContextType.CHOICE: "Choice tie",
|
||||
}
|
||||
return titles.get(context_type, "Tie")
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from pathlib import Path
|
|||
import calendar
|
||||
|
||||
from PyQt6 import QtWidgets
|
||||
from PyQt6.QtCore import Qt, QPoint
|
||||
from PyQt6.QtCore import Qt, QPoint, QSize
|
||||
from PyQt6.QtWidgets import QWidget, QFileDialog, QTreeWidgetItem, QMenu
|
||||
from PyQt6.QtGui import QCloseEvent
|
||||
|
||||
|
|
@ -540,6 +540,7 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||
table = self.battlesTable
|
||||
table.clearContents()
|
||||
table.setRowCount(len(sectors))
|
||||
self.battlesTable.setIconSize(QSize(32, 16))
|
||||
for row, battle in enumerate(sectors):
|
||||
sector_item = QtWidgets.QTableWidgetItem(battle.sector_name)
|
||||
if battle.state_icon:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue