You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bingo-cli/bingo.py

149 lines
4.6 KiB
Python

#!/usr/bin/env python3
from textual.app import App, ComposeResult
from textual.widgets import Header, Footer, Button, Label, Switch, Static
from textual.containers import ScrollableContainer
from textual.message import Message
from textual.color import Color
from asyncio import sleep
class BingoField(Static):
"""A Bingo field widget."""
cursor_x, cursor_y = 2
class Selected(Message):
"""Send message to the board containing clicked field info"""
def __init__(self, num: int, selected: bool) -> None:
self.num = num
self.selected = selected
super().__init__()
def __init__(self, num, text: str) -> None:
self.text = text
self.num = num
self.selected = False
super().__init__()
def on_mount(self) -> None:
self.styles.content_align = ("center", "middle")
self.styles.border = ("solid", "green")
self.styles.height = '100%'
self.styles.width = '100%'
def on_click(self) -> None:
self.selected = not self.selected
if self.selected:
self.styles.animate("background", 'green', duration=0.1)
self.styles.border = ("solid", "black")
else:
self.styles.animate("background", '#1c1c1c', duration=0.1)
self.styles.border = ("solid", "green")
# The post_message method sends an event to be handled in the DOM
self.post_message(self.Selected(self.num, self.selected))
def render(self) -> str:
return str(self.text)
class BingoApp(App):
"""A Textual app to manage stopwatches."""
CSS_PATH = "bingo.tcss"
BINDINGS = [("d", "toggle_dark", "Toggle dark mode")]
fieldstate = [False for _ in range(25)]
fields = [
'Datenelch',
'6 Stunden Schlaf',
'Tschunk getrunken',
'Spaß gehabt',
'Sticker getauscht',
'DECT genutzt',
'Hardware gehackt',
'Kabel vergessen',
'Halle gesucht',
'$dinge gelötet',
'an SoS teilgenommen',
'Neue Leute kennengelernt',
'Wasser getrunken',
'Waffel gegessen',
'Corona Test gemacht',
'2 Mahlzeiten gegessen',
'Fairydust bewundert',
'Talk angeschaut',
'CCC Merch getragen',
'getrollt',
'In der Lounge getanzt',
'Etwas Neues ausprobiert',
'Maske getragen',
'geduscht',
'Gulasch gegessen'
]
# todo: prng stuff
import random
random.shuffle(fields)
def compose(self) -> ComposeResult:
"""Create child widgets for the app."""
yield Header()
for _ in range(25):
yield BingoField(_, self.fields[_])
yield Footer()
async def on_bingo_field_selected(self, message: BingoField.Selected) -> None:
self.fieldstate[message.num] = message.selected
if self.is_bingo():
self.screen.styles.animate("background", 'red', duration=0.25)
await sleep(0.25)
self.screen.styles.animate("background", 'orange', duration=0.25)
await sleep(0.25)
self.screen.styles.animate("background", 'yellow', duration=0.25)
await sleep(0.25)
self.screen.styles.animate("background", 'green', duration=0.25)
await sleep(0.25)
self.screen.styles.animate("background", 'lightblue', duration=0.25)
await sleep(0.25)
self.screen.styles.animate("background", 'blue', duration=0.25)
await sleep(0.25)
self.screen.styles.animate("background", 'purple', duration=0.25)
await sleep(0.25)
self.screen.styles.animate("background", '#1c1c1c', duration=0.25)
def is_bingo(self):
array = [ self.fieldstate[i:i+5] for i in range(0, len(self.fieldstate), 5)]
# check rows
bingo = any( [ all(row) for row in array ] )
# check cols
bingo = bingo or any([ all(self.fieldstate[num::5]) for num in range(5)])
# check bottom left to upper right
bingo = bingo or all([
self.fieldstate[4],
self.fieldstate[8],
self.fieldstate[12],
self.fieldstate[16],
self.fieldstate[20]
])
# check top left to bottom right
bingo = bingo or all([
self.fieldstate[0],
self.fieldstate[6],
self.fieldstate[12],
self.fieldstate[18],
self.fieldstate[24]
])
return bingo
def action_toggle_dark(self) -> None:
"""An action to toggle dark mode."""
self.dark = not self.dark
if __name__ == "__main__":
app = BingoApp()
app.run()