From 91040eb3904de5734154210dac7469a1cfba1ecb Mon Sep 17 00:00:00 2001 From: Auric Vente Date: Fri, 19 Jul 2024 05:28:49 -0600 Subject: [PATCH] Mods --- cromulant/ants.py | 17 +++++--------- cromulant/config.py | 10 ++++++-- cromulant/game.py | 57 ++++++++++++++++++++++++++++++++------------- cromulant/utils.py | 16 +++++++++++++ cromulant/window.py | 14 +++++++---- requirements.txt | 3 ++- 6 files changed, 82 insertions(+), 35 deletions(-) diff --git a/cromulant/ants.py b/cromulant/ants.py index 6f718e0..c88927e 100644 --- a/cromulant/ants.py +++ b/cromulant/ants.py @@ -17,9 +17,9 @@ class Ant: self.updated = now self.name = "" self.status = "" + self.method = "normal" self.triumph = 0 self.hits = 0 - self.color: tuple[int, int, int] def to_dict(self) -> dict[str, Any]: return { @@ -27,9 +27,9 @@ class Ant: "updated": self.updated, "name": self.name, "status": self.status, + "method": self.method, "hits": self.hits, "triumph": self.triumph, - "color": self.color, } def from_dict(self, data: dict[str, Any]) -> None: @@ -37,12 +37,10 @@ class Ant: self.updated = data["updated"] self.name = data["name"] self.status = data["status"] + self.method = data["method"] self.hits = data["hits"] self.triumph = data["triumph"] - c = data["color"] - self.color = (c[0], c[1], c[2]) - def get_name(self) -> str: return self.name or "Nameless" @@ -76,7 +74,6 @@ class Ants: ant.created = now ant.updated = now ant.name = Utils.random_name() - ant.color = Utils.random_color(ant.name) Ants.ants.append(ant) image_path = Config.hatched_image_path @@ -136,16 +133,14 @@ class Ants: return min(Ants.ants, key=lambda ant: ant.updated) @staticmethod - def set_status(ant: Ant, status: str) -> None: + def set_status(ant: Ant, status: str, method: str) -> None: from .game import Game status = status.strip() - - if not status: - return - ant.status = status + ant.method = method ant.updated = Utils.now() + Game.add_status(ant) Ants.save() diff --git a/cromulant/config.py b/cromulant/config.py index 22924f8..0028c48 100644 --- a/cromulant/config.py +++ b/cromulant/config.py @@ -23,13 +23,19 @@ class Config: space_1: int = 20 max_messages: int = 200 loop_delay_fast: int = 3_000 - loop_delay_normal: int = 30_000 - loop_delay_slow: int = 60_000 + loop_delay_normal: int = 60_000 + loop_delay_slow: int = 120_000 hatch_burst: int = 3 font_size: int = 20 info_separator: str = " - " font_path: Path emoji_font_path: Path + triumph_color: tuple[int, int, int] = (255, 255, 0) + hit_color: tuple[int, int, int] = (255, 0, 77) + triumph_icon: str = "😀" + hit_icon: str = "🎃" + triumph_message: str = "Scored a triumph" + hit_message: str = "Took a hit" @staticmethod def prepare() -> None: diff --git a/cromulant/game.py b/cromulant/game.py index 661e866..8780b96 100644 --- a/cromulant/game.py +++ b/cromulant/game.py @@ -31,8 +31,22 @@ class Game: @staticmethod def add_status(ant: Ant) -> None: container = QHBoxLayout() - image_label = Game.get_image(Config.status_image_path, ant.color) - right_container = Game.make_right_container(ant.name, ant.status) + status = ant.status + color = None + + if ant.method == "triumph": + total = f"({ant.triumph} total)" + status = f"{Config.triumph_icon} {Config.triumph_message} {total}" + color = Config.triumph_color + elif ant.method == "hit": + total = f"({ant.hits} total)" + status = f"{Config.hit_icon} {Config.hit_message} {total}" + color = Config.hit_color + elif ant.method == "thinking": + status = f"Thinking about {status}" + + image_label = Game.get_image(Config.status_image_path, color) + right_container = Game.make_right_container(ant.name, status) container.addWidget(image_label) container.addSpacing(Config.space_1) @@ -40,9 +54,14 @@ class Game: Game.add_view_container(container) @staticmethod - def add_message(title: str, message: str, image_path: Path) -> None: + def add_message( + title: str, + message: str, + image_path: Path, + color: tuple[int, int, int] = (255, 255, 255), + ) -> None: container = QHBoxLayout() - image_label = Game.get_image(image_path, (255, 255, 255)) + image_label = Game.get_image(image_path, color) right_container = Game.make_right_container(title, message) container.addWidget(image_label) @@ -65,7 +84,7 @@ class Game: def make_right_container(title: str, message: str) -> QWidget: root = QWidget() container = QVBoxLayout() - container.setAlignment(Qt.AlignmentFlag.AlignTop) + container.setAlignment(Qt.AlignTop) title_label = QLabel(title) title_label.setStyleSheet("font-weight: bold;") @@ -83,24 +102,25 @@ class Game: return root @staticmethod - def get_image(image_path: Path, border_color: tuple[int, int, int]) -> QLabel: + def get_image( + image_path: Path, color: tuple[int, int, int] | None = None + ) -> QLabel: image_label = QLabel() pixmap = QPixmap(str(image_path)) scaled_pixmap = pixmap.scaled( Config.image_size, pixmap.height(), - Qt.AspectRatioMode.KeepAspectRatio, - Qt.TransformationMode.SmoothTransformation, + Qt.KeepAspectRatio, + Qt.SmoothTransformation, ) image_label.setPixmap(scaled_pixmap) image_label.setFixedSize(scaled_pixmap.size()) - border_rgb = Utils.get_rgb(border_color) - image_label.setStyleSheet( - f"border: 2px solid {border_rgb};" - ) + if color: + rgb = Utils.get_rgb(color) + image_label.setStyleSheet(f"border: 2px solid {rgb};") return image_label @@ -115,26 +135,31 @@ class Game: num = random.randint(1, 10) s = RandomSentence() status = "" + method = "normal" if num == 1: ant.triumph += 1 - status = f"😀 Scored a triumph ({ant.triumph} total)" + method = "triumph" elif num == 2: ant.hits += 1 - status = f"🎃 Took a hit ({ant.hits} total)" + method = "hit" elif (num == 3) and (num_ants > 1): other = Ants.get_other(ant) - status = f"🫠 Is thinking about {other.name}" + status = other.name + method = "thinking" elif num == 4: status = s.simple_sentence() elif num == 5: status = s.bare_bone_sentence() elif num == 6: status = s.bare_bone_with_adjective() + elif num == 7: + status = Utils.get_random_emoji(3) + method = "thinking" else: status = s.sentence() - Ants.set_status(ant, status) + Ants.set_status(ant, status, method) @staticmethod def initial_fill() -> None: diff --git a/cromulant/utils.py b/cromulant/utils.py index c433030..68e641b 100644 --- a/cromulant/utils.py +++ b/cromulant/utils.py @@ -1,10 +1,13 @@ from __future__ import annotations + import random import colorsys import time from typing import ClassVar +from fontTools.ttLib import TTFont # type: ignore +from .config import Config from .storage import Storage @@ -92,3 +95,16 @@ class Utils: @staticmethod def get_rgb(color: tuple[int, int, int]) -> str: return f"rgb{color}" + + @staticmethod + def get_random_character(font_path: str, num: int) -> str: + font = TTFont(font_path) + cmap = font["cmap"] + unicode_map = cmap.getBestCmap() + characters = [chr(code_point) for code_point in unicode_map] + selected = random.sample(characters, num) + return " ".join(selected) + + @staticmethod + def get_random_emoji(num: int) -> str: + return Utils.get_random_character(str(Config.emoji_font_path), num) diff --git a/cromulant/window.py b/cromulant/window.py index c6579af..68c3024 100644 --- a/cromulant/window.py +++ b/cromulant/window.py @@ -29,7 +29,7 @@ class SpecialButton(QPushButton): # type: ignore middleClicked = Signal() def mousePressEvent(self, e: QMouseEvent) -> None: - if e.button() == Qt.MouseButton.MiddleButton: + if e.button() == Qt.MiddleButton: self.middleClicked.emit() else: super().mousePressEvent(e) @@ -63,7 +63,7 @@ class Window: central_widget = QWidget() Window.root = QVBoxLayout() central_widget.setLayout(Window.root) - Window.root.setAlignment(Qt.AlignmentFlag.AlignTop) + Window.root.setAlignment(Qt.AlignTop) Window.window.setCentralWidget(central_widget) Window.window.setWindowIcon(QIcon(str(Config.icon_path))) @@ -102,7 +102,9 @@ class Window: btn_hatch.middleClicked.connect(lambda: Ants.hatch_burst()) btn_terminate = SpecialButton("Terminate") - btn_terminate.setToolTip("Terminate a random ant\nMiddle Click to terminate all") + btn_terminate.setToolTip( + "Terminate a random ant\nMiddle Click to terminate all" + ) btn_terminate.clicked.connect(lambda e: Ants.terminate()) btn_terminate.middleClicked.connect(lambda: Ants.terminate_all()) @@ -135,7 +137,7 @@ class Window: Window.view = QVBoxLayout() parent.addLayout(Window.view) - Window.view.setAlignment(Qt.AlignmentFlag.AlignTop) + Window.view.setAlignment(Qt.AlignTop) Window.scroll_area.setWidget(container) Window.root.addWidget(Window.scroll_area) @@ -204,7 +206,9 @@ class Window: root.setContentsMargins(0, 0, 0, 0) container = QHBoxLayout() Window.info = SpecialButton("---") - Window.info.setToolTip("Scroll to the bottom\nMiddle Click to scroll to the top") + Window.info.setToolTip( + "Scroll to the bottom\nMiddle Click to scroll to the top" + ) Window.info.clicked.connect(Window.to_bottom) Window.info.middleClicked.connect(Window.to_top) Window.info.setMinimumSize(35, 35) diff --git a/requirements.txt b/requirements.txt index 06ad559..d2d3bea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ PySide6 == 6.7.2 appdirs == 1.4.4 -wonderwords == 2.2.0 \ No newline at end of file +wonderwords == 2.2.0 +fonttools == 4.53.1 \ No newline at end of file