first commit
This commit is contained in:
commit
69acfd0389
|
@ -0,0 +1,6 @@
|
||||||
|
venv/*
|
||||||
|
.directory
|
||||||
|
*.pyc
|
||||||
|
__pycache__/
|
||||||
|
.mypy_cache/
|
||||||
|
ants.db
|
|
@ -0,0 +1,68 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import utils
|
||||||
|
from database import Database
|
||||||
|
|
||||||
|
class Ant:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
now = utils.now()
|
||||||
|
self.id: int
|
||||||
|
self.created = now
|
||||||
|
self.updated = now
|
||||||
|
self.name = ""
|
||||||
|
self.status = ""
|
||||||
|
self.hits = 0
|
||||||
|
self.triumph = 0
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
return self.name or "Nameless"
|
||||||
|
|
||||||
|
def get_age(self):
|
||||||
|
now = utils.now()
|
||||||
|
return utils.time_ago(self.created, now)
|
||||||
|
|
||||||
|
def describe(self):
|
||||||
|
print(f"Name is {self.get_name()}")
|
||||||
|
print(f"It hatched {self.get_age()}")
|
||||||
|
|
||||||
|
class Ants:
|
||||||
|
ants: list[Ant] = []
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_all() -> None:
|
||||||
|
Database.cursor.execute("SELECT id, created, updated, name, status, hits, triumph FROM ants")
|
||||||
|
|
||||||
|
rows = Database.cursor.fetchall()
|
||||||
|
ants = []
|
||||||
|
|
||||||
|
for row in rows:
|
||||||
|
ant = Ant()
|
||||||
|
ant.id = row[0]
|
||||||
|
ant.created = row[1]
|
||||||
|
ant.updated = row[2]
|
||||||
|
ant.name = row[3]
|
||||||
|
ant.status = row[4]
|
||||||
|
ant.hits = row[5]
|
||||||
|
ant.triumph = row[6]
|
||||||
|
ants.append(ant)
|
||||||
|
|
||||||
|
Database.connection.commit()
|
||||||
|
return ants
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def hatch() -> None:
|
||||||
|
now = utils.now()
|
||||||
|
|
||||||
|
Database.cursor.execute(
|
||||||
|
"INSERT INTO ants (created, updated) VALUES (?, ?)",
|
||||||
|
(now, now),
|
||||||
|
)
|
||||||
|
|
||||||
|
Database.connection.commit()
|
||||||
|
Database.cursor.execute("SELECT last_insert_rowid()")
|
||||||
|
row = Database.cursor.fetchone()
|
||||||
|
|
||||||
|
ant = Ant()
|
||||||
|
ant.id = row[0]
|
||||||
|
|
||||||
|
print(f"Ant hatched: {ant.id}")
|
|
@ -0,0 +1,21 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import sqlite3
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
class Database:
|
||||||
|
connection: sqlite3.Connection
|
||||||
|
cursor: sqlite3.Cursor
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def prepare() -> None:
|
||||||
|
Database.connection = sqlite3.connect("ants.db")
|
||||||
|
Database.cursor = Database.connection.cursor()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create() -> None:
|
||||||
|
with Path("schema.sql").open("r") as file:
|
||||||
|
schema = file.read()
|
||||||
|
|
||||||
|
Database.cursor.executescript(schema)
|
||||||
|
Database.connection.commit()
|
|
@ -0,0 +1,24 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from database import Database
|
||||||
|
from window import Window
|
||||||
|
from ants import Ants
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
Database.prepare()
|
||||||
|
Database.create()
|
||||||
|
|
||||||
|
Ants.get_all()
|
||||||
|
|
||||||
|
for ant in Ants.ants:
|
||||||
|
ant.describe()
|
||||||
|
|
||||||
|
Window.make()
|
||||||
|
Window.add_buttons()
|
||||||
|
Window.add_view()
|
||||||
|
Window.start()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -0,0 +1 @@
|
||||||
|
PySide6 == 6.7.2
|
|
@ -0,0 +1,22 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS ants (
|
||||||
|
-- Internal ID of the ant
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
|
||||||
|
-- The date when the ant was created
|
||||||
|
created INTEGER NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
-- The date when the ant was last changed
|
||||||
|
updated INTEGER NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
-- The public name of the ant
|
||||||
|
name TEXT NOT NULL DEFAULT "",
|
||||||
|
|
||||||
|
-- The current text of the ant
|
||||||
|
status TEXT NOT NULL DEFAULT "",
|
||||||
|
|
||||||
|
-- The total number of hits taken
|
||||||
|
hits INTEGER NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
-- The total number of triumph achieved
|
||||||
|
triumph INTEGER NOT NULL DEFAULT 0
|
||||||
|
);
|
|
@ -0,0 +1,49 @@
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def now() -> float:
|
||||||
|
return int(time.time())
|
||||||
|
|
||||||
|
|
||||||
|
def singular_or_plural(num: float, singular: str, plural: str) -> str:
|
||||||
|
if num == 1:
|
||||||
|
return singular
|
||||||
|
|
||||||
|
return plural
|
||||||
|
|
||||||
|
|
||||||
|
def time_ago(start_time: float, end_time: float) -> str:
|
||||||
|
diff = end_time - start_time
|
||||||
|
seconds = int(diff)
|
||||||
|
|
||||||
|
if seconds < 60:
|
||||||
|
word = singular_or_plural(seconds, "second", "seconds")
|
||||||
|
return f"{seconds} {word} ago"
|
||||||
|
|
||||||
|
minutes = seconds // 60
|
||||||
|
|
||||||
|
if minutes < 60:
|
||||||
|
word = singular_or_plural(minutes, "minute", "minutes")
|
||||||
|
return f"{minutes} {word} ago"
|
||||||
|
|
||||||
|
hours = minutes / 60
|
||||||
|
|
||||||
|
if hours < 24:
|
||||||
|
word = singular_or_plural(hours, "hour", "hours")
|
||||||
|
return f"{hours:.1f} {word} ago"
|
||||||
|
|
||||||
|
days = hours / 24
|
||||||
|
|
||||||
|
if days < 30:
|
||||||
|
word = singular_or_plural(days, "day", "days")
|
||||||
|
return f"{days:.1f} {word} ago"
|
||||||
|
|
||||||
|
months = days / 30
|
||||||
|
|
||||||
|
if months < 12:
|
||||||
|
word = singular_or_plural(months, "month", "months")
|
||||||
|
return f"{months:.1f} {word} ago"
|
||||||
|
|
||||||
|
years = months / 12
|
||||||
|
word = singular_or_plural(years, "year", "years")
|
||||||
|
return f"{years:.1f} {word} ago"
|
|
@ -0,0 +1,60 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QHBoxLayout, QWidget
|
||||||
|
from PySide6.QtWidgets import QGraphicsView, QGraphicsScene, QVBoxLayout
|
||||||
|
|
||||||
|
from ants import Ants
|
||||||
|
|
||||||
|
|
||||||
|
class Window:
|
||||||
|
title = "Cromulant"
|
||||||
|
width = 800
|
||||||
|
height = 600
|
||||||
|
app: QApplication
|
||||||
|
window: QMainWindow
|
||||||
|
root: QWidget
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def make() -> None:
|
||||||
|
Window.app = QApplication([])
|
||||||
|
Window.window = QMainWindow()
|
||||||
|
Window.window.setWindowTitle(Window.title)
|
||||||
|
Window.window.resize(Window.width, Window.height)
|
||||||
|
Window.root = QWidget()
|
||||||
|
Window.window.setCentralWidget(Window.root)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_buttons() -> None:
|
||||||
|
btn_hatch = QPushButton("Hatch Ant")
|
||||||
|
btn_terminate = QPushButton("Terminate")
|
||||||
|
|
||||||
|
btn_hatch.clicked.connect(Window.hatch)
|
||||||
|
btn_terminate.clicked.connect(Window.terminate)
|
||||||
|
|
||||||
|
layout = QHBoxLayout()
|
||||||
|
layout.addWidget(btn_hatch)
|
||||||
|
layout.addWidget(btn_terminate)
|
||||||
|
|
||||||
|
Window.root.setLayout(layout)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_view() -> None:
|
||||||
|
Window.view = QGraphicsView()
|
||||||
|
Window.scene = QGraphicsScene()
|
||||||
|
Window.view.setScene(Window.scene)
|
||||||
|
|
||||||
|
layout = QVBoxLayout(Window.root)
|
||||||
|
layout.addWidget(Window.view)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def hatch() -> None:
|
||||||
|
Ants.hatch()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def terminate() -> None:
|
||||||
|
Ants.terminate()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def start() -> None:
|
||||||
|
Window.window.show()
|
||||||
|
Window.app.exec()
|
Loading…
Reference in New Issue