This commit is contained in:
Auric Vente 2024-07-18 21:08:11 -06:00
parent fa1f5301ae
commit c95dab8e57
9 changed files with 120 additions and 48 deletions

0
cromulant/__init__.py Normal file
View File

View File

@ -1,4 +1,6 @@
from __future__ import annotations from __future__ import annotations
import random
from typing import ClassVar, Any from typing import ClassVar, Any
from .config import Config from .config import Config
@ -76,7 +78,7 @@ class Ants:
ant.color = Utils.random_color() ant.color = Utils.random_color()
Ants.ants.append(ant) Ants.ants.append(ant)
Storage.save_ants(Ants.ants) Ants.save()
Utils.print(f"Ant hatched: {ant.name}") Utils.print(f"Ant hatched: {ant.name}")
@staticmethod @staticmethod
@ -85,4 +87,17 @@ class Ants:
@staticmethod @staticmethod
def get_names() -> list[str]: def get_names() -> list[str]:
return [ant.name for ant in Ants.ants] return [ant.name for ant in Ants.ants]
@staticmethod
def save() -> None:
Storage.save_ants(Ants.ants)
@staticmethod
def get_lazy() -> Ant:
return min(Ants.ants, key=lambda ant: ant.updated)
@staticmethod
def get_other(ant: Ant) -> Ant:
ants = [a for a in Ants.ants if a.name != ant.name]
return random.choice(ants)

View File

@ -1,20 +1,21 @@
from __future__ import annotations
from pathlib import Path from pathlib import Path
import appdirs # type: ignore import appdirs # type: ignore
class Config: class Config:
title = "Cromulant" title: str = "Cromulant"
width = 800 width: int = 800
height = 600 height: int = 600
max_ants = 100 max_ants: int = 100
here: str here: Path
ants_json: Path ants_json: Path
icon_path: Path icon_path: Path
image_path: Path image_path: Path
names_json: Path names_json: Path
@staticmethod @staticmethod
def prepare() -> None: def prepare() -> None:
Config.here = Path(__file__).parent Config.here = Path(__file__).parent
@ -26,4 +27,4 @@ class Config:
Config.icon_path = Config.here / "img" / "icon_4.jpg" Config.icon_path = Config.here / "img" / "icon_4.jpg"
Config.image_path = Config.here / "img" / "icon_7.jpg" Config.image_path = Config.here / "img" / "icon_7.jpg"
Config.names_json = Config.here / "data" / "names.json" Config.names_json = Config.here / "data" / "names.json"

View File

@ -1,21 +1,30 @@
from PySide6.QtWidgets import QWidget from __future__ import annotations
from PySide6.QtGui import QColor
import random
from PySide6.QtWidgets import QWidget # type: ignore
from PySide6.QtGui import QColor # type: ignore
from PySide6.QtGui import QPainter from PySide6.QtGui import QPainter
from PySide6.QtCore import Qt from PySide6.QtCore import Qt # type: ignore
from PySide6.QtWidgets import QHBoxLayout from PySide6.QtWidgets import QHBoxLayout
from PySide6.QtWidgets import QLabel from PySide6.QtWidgets import QLabel
from PySide6.QtGui import QPaintEvent
from wonderwords import RandomSentence # type: ignore
from .ants import Ant
from .ants import Ants from .ants import Ants
from .window import Window from .window import Window
class CircleWidget(QWidget): class CircleWidget(QWidget): # type: ignore
def __init__(self, color, parent=None): def __init__(self, color: tuple[int, int, int]) -> None:
super().__init__(parent) super().__init__(None)
self.color = QColor(*color) self.color = QColor(*color)
self.setFixedSize(20, 20) self.setFixedSize(20, 20)
def paintEvent(self, event): def paintEvent(self, event: QPaintEvent) -> None:
print(type(event))
painter = QPainter(self) painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.Antialiasing)
painter.setBrush(self.color) painter.setBrush(self.color)
@ -25,16 +34,38 @@ class CircleWidget(QWidget):
class Game: class Game:
@staticmethod @staticmethod
def update_view() -> None: def add_status(ant: Ant) -> None:
for ant in Ants.ants: container = QHBoxLayout()
container = QHBoxLayout() circle = CircleWidget(ant.color)
circle = CircleWidget(ant.color) text = QLabel(ant.status)
text = QLabel(ant.status) container.addWidget(circle)
container.addWidget(circle) container.addWidget(text)
container.addWidget(text) Window.view.addLayout(container)
Window.view.addLayout(container)
@staticmethod @staticmethod
def log(message: str) -> None: def log(message: str) -> None:
Window.log.append(message) Window.log.append(message)
@staticmethod
def get_status() -> None:
ant = Ants.get_lazy()
num = random.randint(1, 10)
if num == 1:
ant.hits += 1
ant.status = f"Took a hit ({ant.hits} total)"
elif num == 2:
ant.triumph += 1
ant.status = f"Scored a triumph ({ant.triumph} total)"
elif num == 3:
s = RandomSentence()
ant.status = s.simple_sentence()
elif (num == 4) and (len(Ants.ants) > 1):
other = Ants.get_other(ant)
ant.status = f"Is thinking about {other.name}"
else:
s = RandomSentence()
ant.status = s.bare_bone_with_adjective()
Game.add_status(ant)
Ants.save()

View File

@ -35,6 +35,11 @@ select = [
"PLR1711", "PLR1711",
] ]
ignore = [
"W292",
"N802",
]
exclude = [ exclude = [
"pyperclip.py", "pyperclip.py",
"tests.py", "tests.py",

View File

@ -1,5 +1,7 @@
from __future__ import annotations
import json import json
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, Any
from .config import Config from .config import Config
@ -9,18 +11,18 @@ if TYPE_CHECKING:
class Storage: class Storage:
@staticmethod @staticmethod
def get_ants() -> None: def get_ants() -> Any:
with Config.ants_json.open() as file: with Config.ants_json.open() as file:
return json.load(file) return json.load(file)
@staticmethod @staticmethod
def save_ants(ants: list["Ant"]) -> None: def save_ants(ants: list[Ant]) -> None:
objs = [ant.to_dict() for ant in ants] objs = [ant.to_dict() for ant in ants]
with Config.ants_json.open("w") as file: with Config.ants_json.open("w") as file:
json.dump(objs, file) json.dump(objs, file)
@staticmethod @staticmethod
def get_names() -> None: def get_names() -> Any:
with Config.names_json.open() as file: with Config.names_json.open() as file:
return json.load(file) return json.load(file)

View File

@ -1,11 +1,15 @@
from __future__ import annotations
import random import random
import colorsys import colorsys
import time import time
from typing import ClassVar
from .storage import Storage from .storage import Storage
class Utils: class Utils:
names: list[str] = [] names: ClassVar[list[str]] = []
@staticmethod @staticmethod
def prepare() -> None: def prepare() -> None:
@ -64,9 +68,14 @@ class Utils:
print(text) # noqa: T201 print(text) # noqa: T201
@staticmethod @staticmethod
def random_color() -> str: def random_color() -> tuple[int, int, int]:
h,s,l = random.random(), 0.5 + random.random()/2.0, 0.4 + random.random()/5.0 h, s, l = (
r, g, b = [int(256*i) for i in colorsys.hls_to_rgb(h,l,s)] random.random(),
0.5 + random.random() / 2.0,
0.4 + random.random() / 5.0,
)
r, g, b = (int(256 * i) for i in colorsys.hls_to_rgb(h, l, s))
return r, g, b return r, g, b
@staticmethod @staticmethod
@ -75,4 +84,4 @@ class Utils:
used = Ants.get_names() used = Ants.get_names()
filtered = [name for name in Utils.names if name not in used] filtered = [name for name in Utils.names if name not in used]
return random.choice(filtered) return random.choice(filtered)

View File

@ -10,9 +10,10 @@ from PySide6.QtWidgets import QPushButton
from PySide6.QtWidgets import QHBoxLayout from PySide6.QtWidgets import QHBoxLayout
from PySide6.QtWidgets import QTextEdit from PySide6.QtWidgets import QTextEdit
from PySide6.QtWidgets import QLabel from PySide6.QtWidgets import QLabel
from PySide6.QtGui import QPixmap from PySide6.QtGui import QPixmap # type: ignore
from PySide6.QtGui import QIcon from PySide6.QtGui import QIcon
from PySide6.QtCore import Qt from PySide6.QtCore import Qt # type: ignore
from PySide6.QtCore import QTimer
from .config import Config from .config import Config
@ -24,6 +25,7 @@ class Window:
view: QGraphicsView view: QGraphicsView
view_scene: QGraphicsScene view_scene: QGraphicsScene
log: QTextEdit log: QTextEdit
timer: QTimer
@staticmethod @staticmethod
def prepare() -> None: def prepare() -> None:
@ -31,6 +33,7 @@ class Window:
Window.add_buttons() Window.add_buttons()
Window.add_view() Window.add_view()
Window.add_log() Window.add_log()
Window.start_timer()
Window.start() Window.start()
@staticmethod @staticmethod
@ -51,18 +54,15 @@ class Window:
def add_buttons() -> None: def add_buttons() -> None:
btn_hatch = QPushButton("Hatch") btn_hatch = QPushButton("Hatch")
btn_terminate = QPushButton("Terminate") btn_terminate = QPushButton("Terminate")
btn_update = QPushButton("Update")
btn_close = QPushButton("Close") btn_close = QPushButton("Close")
btn_hatch.clicked.connect(Window.hatch) btn_hatch.clicked.connect(Window.hatch)
btn_terminate.clicked.connect(Window.terminate) btn_terminate.clicked.connect(Window.terminate)
btn_update.clicked.connect(Window.update_view)
btn_close.clicked.connect(Window.close) btn_close.clicked.connect(Window.close)
layout = QHBoxLayout() layout = QHBoxLayout()
layout.addWidget(btn_hatch) layout.addWidget(btn_hatch)
layout.addWidget(btn_terminate) layout.addWidget(btn_terminate)
layout.addWidget(btn_update)
layout.addWidget(btn_close) layout.addWidget(btn_close)
Window.root.addLayout(layout) Window.root.addLayout(layout)
@ -78,7 +78,9 @@ class Window:
image_label = QLabel() image_label = QLabel()
pixmap = QPixmap(str(Config.image_path)) pixmap = QPixmap(str(Config.image_path))
scaled_pixmap = pixmap.scaled(100, pixmap.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation) scaled_pixmap = pixmap.scaled(
100, pixmap.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation
)
image_label.setPixmap(scaled_pixmap) image_label.setPixmap(scaled_pixmap)
image_label.setFixedWidth(100) image_label.setFixedWidth(100)
container.addWidget(image_label) container.addWidget(image_label)
@ -90,21 +92,27 @@ class Window:
Window.root.addLayout(container) Window.root.addLayout(container)
@staticmethod
def update_view() -> None:
from .game import Game
Game.update_view()
@staticmethod @staticmethod
def hatch() -> None: def hatch() -> None:
from .ants import Ants from .ants import Ants
Ants.hatch() Ants.hatch()
@staticmethod @staticmethod
def terminate() -> None: def terminate() -> None:
from .ants import Ants from .ants import Ants
Ants.terminate() Ants.terminate()
@staticmethod
def start_timer() -> None:
from .game import Game
interval_ms = 3_000
Window.timer = QTimer()
Window.timer.timeout.connect(Game.get_status)
Window.timer.start(interval_ms)
@staticmethod @staticmethod
def start() -> None: def start() -> None:
Window.window.show() Window.window.show()

View File

@ -1,2 +1,3 @@
PySide6 == 6.7.2 PySide6 == 6.7.2
appdirs == 1.4.4 appdirs == 1.4.4
wonderwords == 2.2.0