refactor into submodules
This commit is contained in:
parent
fd7fec5e98
commit
3198b46892
104
BingoBoard.py
Normal file
104
BingoBoard.py
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
from textual.reactive import reactive
|
||||||
|
from textual.widget import Widget
|
||||||
|
from textual.app import ComposeResult
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
import random
|
||||||
|
from asyncio import sleep
|
||||||
|
|
||||||
|
from BingoField import BingoField
|
||||||
|
|
||||||
|
class BingoBoard(Widget):
|
||||||
|
|
||||||
|
fields = reactive([], recompose = True)
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.fieldstate = [False for _ in range(25)]
|
||||||
|
super().__init__()
|
||||||
|
self.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'
|
||||||
|
]
|
||||||
|
self.default_fields = self.fields
|
||||||
|
self.roll_board(int(datetime.now().timestamp()))
|
||||||
|
|
||||||
|
def roll_board(self, seed):
|
||||||
|
self.seed = seed
|
||||||
|
random.seed(seed)
|
||||||
|
self.fields = random.sample(self.default_fields, len(self.fields))
|
||||||
|
|
||||||
|
def watch_fields(self, new_state) -> None:
|
||||||
|
self.fieldstate = [False for _ in range(25)]
|
||||||
|
for idx, field in enumerate(self.query(BingoField)):
|
||||||
|
field.text = new_state[idx]
|
||||||
|
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
"""Create child widgets for the app."""
|
||||||
|
for _ in range(25):
|
||||||
|
yield BingoField(_, self.fields[_])
|
||||||
|
|
||||||
|
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
|
43
BingoField.py
Normal file
43
BingoField.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
from textual.widgets import Static
|
||||||
|
from textual.message import Message
|
||||||
|
from textual.reactive import reactive
|
||||||
|
|
||||||
|
class BingoField(Static):
|
||||||
|
'''A Bingo field widget.'''
|
||||||
|
|
||||||
|
cursor_x, cursor_y = 2, 2
|
||||||
|
text = reactive('')
|
||||||
|
|
||||||
|
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.num = num
|
||||||
|
self.selected = False
|
||||||
|
super().__init__()
|
||||||
|
self.text = text
|
||||||
|
|
||||||
|
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)
|
153
bingo.py
153
bingo.py
@ -2,73 +2,29 @@
|
|||||||
|
|
||||||
from textual.app import App, ComposeResult
|
from textual.app import App, ComposeResult
|
||||||
from textual.widgets import Header, Input, Static, Button
|
from textual.widgets import Header, Input, Static, Button
|
||||||
from textual.widget import Widget
|
|
||||||
from textual.message import Message
|
|
||||||
from textual.containers import Horizontal
|
from textual.containers import Horizontal
|
||||||
from textual.validation import Number
|
from textual.validation import Number
|
||||||
from textual.reactive import reactive
|
|
||||||
|
|
||||||
from asyncio import sleep
|
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import random
|
|
||||||
|
|
||||||
class BingoField(Static):
|
from BingoBoard import BingoBoard
|
||||||
"""A Bingo field widget."""
|
|
||||||
|
|
||||||
cursor_x, cursor_y = 2, 2
|
|
||||||
text = reactive("temp")
|
|
||||||
|
|
||||||
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.num = num
|
|
||||||
self.selected = False
|
|
||||||
super().__init__()
|
|
||||||
self.text = text
|
|
||||||
|
|
||||||
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):
|
class BingoApp(App):
|
||||||
"""A Textual app to run a Bingo board."""
|
'''A Textual app to run a Bingo board.'''
|
||||||
CSS_PATH = "bingo.tcss"
|
CSS_PATH = "bingo.tcss"
|
||||||
|
|
||||||
def compose(self) -> ComposeResult:
|
def compose(self) -> ComposeResult:
|
||||||
"""Create child widgets for the app."""
|
'''Create child widgets for the app.'''
|
||||||
yield Header()
|
yield Header()
|
||||||
yield BingoDisplay()
|
yield BingoDisplay()
|
||||||
|
|
||||||
def action_toggle_dark(self) -> None:
|
def action_toggle_dark(self) -> None:
|
||||||
"""An action to toggle dark mode."""
|
'''An action to toggle dark mode.'''
|
||||||
self.dark = not self.dark
|
self.dark = not self.dark
|
||||||
|
|
||||||
class BingoDisplay(Static):
|
class BingoDisplay(Static):
|
||||||
def compose(self) -> ComposeResult:
|
def compose(self) -> ComposeResult:
|
||||||
"""Create child widgets for the app."""
|
'''Create child widgets for the app.'''
|
||||||
self.board = BingoBoard()
|
self.board = BingoBoard()
|
||||||
yield self.board
|
yield self.board
|
||||||
self.input_field = Input(
|
self.input_field = Input(
|
||||||
@ -89,110 +45,15 @@ class BingoDisplay(Static):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||||
""""""
|
'''Re-roll the board state with current time as seed'''
|
||||||
# reroll
|
|
||||||
self.board.roll_board(int(datetime.now().timestamp()))
|
self.board.roll_board(int(datetime.now().timestamp()))
|
||||||
self.input_field.value = str(self.board.seed)
|
self.input_field.value = str(self.board.seed)
|
||||||
|
|
||||||
def on_input_submitted(self, event: Input.Submitted) -> None:
|
def on_input_submitted(self, event: Input.Submitted) -> None:
|
||||||
|
'''Re-roll the board state with the seed from the input'''
|
||||||
if event.validation_result.is_valid:
|
if event.validation_result.is_valid:
|
||||||
self.board.roll_board(int(event.value))
|
self.board.roll_board(int(event.value))
|
||||||
|
|
||||||
class BingoBoard(Widget):
|
|
||||||
|
|
||||||
fields = reactive([], recompose = True)
|
|
||||||
|
|
||||||
def __init__(self) -> None:
|
|
||||||
self.fieldstate = [False for _ in range(25)]
|
|
||||||
super().__init__()
|
|
||||||
self.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'
|
|
||||||
]
|
|
||||||
self.default_fields = self.fields
|
|
||||||
self.roll_board(int(datetime.now().timestamp()))
|
|
||||||
|
|
||||||
def roll_board(self, seed):
|
|
||||||
self.seed = seed
|
|
||||||
random.seed(seed)
|
|
||||||
self.fields = random.sample(self.default_fields, len(self.fields))
|
|
||||||
|
|
||||||
def watch_fields(self, new_state) -> None:
|
|
||||||
self.fieldstate = [False for _ in range(25)]
|
|
||||||
for idx, field in enumerate(self.query(BingoField)):
|
|
||||||
field.text = new_state[idx]
|
|
||||||
|
|
||||||
def compose(self) -> ComposeResult:
|
|
||||||
"""Create child widgets for the app."""
|
|
||||||
for _ in range(25):
|
|
||||||
yield BingoField(_, self.fields[_])
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = BingoApp()
|
app = BingoApp()
|
||||||
app.run()
|
app.run()
|
||||||
|
Loading…
Reference in New Issue
Block a user