From b8e0943b07109314083fa73b6b126ce4914ed7c6 Mon Sep 17 00:00:00 2001 From: Felix Pankratz Date: Thu, 9 May 2024 14:37:52 +0200 Subject: [PATCH 1/7] set rng seed from timestamp --- bingo.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bingo.py b/bingo.py index 1f4eec1..6b5a05b 100644 --- a/bingo.py +++ b/bingo.py @@ -8,10 +8,13 @@ from textual.color import Color from asyncio import sleep +from datetime import datetime +import random + class BingoField(Static): """A Bingo field widget.""" - cursor_x, cursor_y = 2 + cursor_x, cursor_y = 2, 2 class Selected(Message): """Send message to the board containing clicked field info""" @@ -83,8 +86,9 @@ class BingoApp(App): 'Gulasch gegessen' ] - # todo: prng stuff - import random + # get rng seed from current time + seed = int(datetime.now().timestamp()) + random.seed(seed) random.shuffle(fields) def compose(self) -> ComposeResult: From 1181e75ea0f825c1d07a24c7b28e879cd74e022c Mon Sep 17 00:00:00 2001 From: Felix Pankratz Date: Thu, 9 May 2024 16:00:34 +0200 Subject: [PATCH 2/7] add inputs, refactor a bit --- bingo.py | 43 ++++++++++++++++++++++++++++++++----------- bingo.tcss | 21 ++++++++++++++++++++- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/bingo.py b/bingo.py index 6b5a05b..e3bd527 100644 --- a/bingo.py +++ b/bingo.py @@ -1,10 +1,10 @@ #!/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.widgets import Header, Footer, Input, Label, Static, Button from textual.message import Message from textual.color import Color +from textual.containers import Horizontal from asyncio import sleep @@ -51,11 +51,40 @@ class BingoField(Static): return str(self.text) class BingoApp(App): - """A Textual app to manage stopwatches.""" + """A Textual app to run a Bingo board.""" CSS_PATH = "bingo.tcss" BINDINGS = [("d", "toggle_dark", "Toggle dark mode")] + def compose(self) -> ComposeResult: + """Create child widgets for the app.""" + yield Header() + yield BingoDisplay() + yield Footer() + + def action_toggle_dark(self) -> None: + """An action to toggle dark mode.""" + self.dark = not self.dark + +class BingoDisplay(Static): + def compose(self) -> ComposeResult: + """Create child widgets for the app.""" + yield BingoBoard() + input_field = Input( + type='integer', + placeholder='UNIX timestamp', + max_length=10, + classes='seed_input' + ) + input_field.border_title = 'Seed' + yield Horizontal( + input_field, + Button('re-roll', classes='roll_btn'), + classes='bottom_line' + ) + +class BingoBoard(Static): + fieldstate = [False for _ in range(25)] fields = [ @@ -93,13 +122,9 @@ class BingoApp(App): 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(): @@ -143,10 +168,6 @@ class BingoApp(App): ]) 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() diff --git a/bingo.tcss b/bingo.tcss index 1f8dd44..43a57f2 100644 --- a/bingo.tcss +++ b/bingo.tcss @@ -1,6 +1,25 @@ -Screen { +BingoBoard { layout: grid; grid-size: 5 5; + height: 100%; +} + +BingoDisplay { + layout: vertical; + height: 100%; +} + +.bottom_line { + height: auto; + dock: bottom; +} + +.seed_input { + width: 50%; + border-title-align: left; +} +.roll_btn { + width: 50%; } .box { From a90adbb16549955e156c7733b13aecf16ebc1615 Mon Sep 17 00:00:00 2001 From: Felix Pankratz Date: Thu, 9 May 2024 16:13:53 +0200 Subject: [PATCH 3/7] display seed, add input validation --- bingo.py | 10 ++++++++-- bingo.tcss | 11 +++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/bingo.py b/bingo.py index e3bd527..f13418d 100644 --- a/bingo.py +++ b/bingo.py @@ -5,6 +5,7 @@ from textual.widgets import Header, Footer, Input, Label, Static, Button from textual.message import Message from textual.color import Color from textual.containers import Horizontal +from textual.validation import Number from asyncio import sleep @@ -69,12 +70,17 @@ class BingoApp(App): class BingoDisplay(Static): def compose(self) -> ComposeResult: """Create child widgets for the app.""" - yield BingoBoard() + self.board = BingoBoard() + yield self.board input_field = Input( + str(self.board.seed), type='integer', placeholder='UNIX timestamp', max_length=10, - classes='seed_input' + classes='seed_input', + validators=[ + Number(minimum=1000000000, maximum = int(datetime.now().timestamp())) + ] ) input_field.border_title = 'Seed' yield Horizontal( diff --git a/bingo.tcss b/bingo.tcss index 43a57f2..5161d28 100644 --- a/bingo.tcss +++ b/bingo.tcss @@ -15,11 +15,11 @@ BingoDisplay { } .seed_input { - width: 50%; + width: 70%; border-title-align: left; } .roll_btn { - width: 50%; + width: 30%; } .box { @@ -28,3 +28,10 @@ BingoDisplay { text-align: center; content-align: center middle; } + +Input.-valid { + border: tall $success 60%; +} +Input.-valid:focus { + border: tall $success; +} From 3cded45cfd9c1fcd19b4bc22b4cc3a0b8ccee79f Mon Sep 17 00:00:00 2001 From: Felix Pankratz Date: Thu, 9 May 2024 18:22:46 +0200 Subject: [PATCH 4/7] Implement reroll --- bingo.py | 105 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 41 deletions(-) diff --git a/bingo.py b/bingo.py index f13418d..1b66823 100644 --- a/bingo.py +++ b/bingo.py @@ -2,10 +2,12 @@ from textual.app import App, ComposeResult from textual.widgets import Header, Footer, Input, Label, Static, Button +from textual.widget import Widget from textual.message import Message from textual.color import Color from textual.containers import Horizontal from textual.validation import Number +from textual.reactive import reactive from asyncio import sleep @@ -16,6 +18,7 @@ class BingoField(Static): """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""" @@ -25,10 +28,10 @@ class BingoField(Static): super().__init__() def __init__(self, num, text: str) -> None: - self.text = text self.num = num self.selected = False super().__init__() + self.text = text def on_mount(self) -> None: self.styles.content_align = ("center", "middle") @@ -72,59 +75,79 @@ class BingoDisplay(Static): """Create child widgets for the app.""" self.board = BingoBoard() yield self.board - input_field = Input( + self.input_field = Input( str(self.board.seed), type='integer', placeholder='UNIX timestamp', max_length=10, classes='seed_input', validators=[ - Number(minimum=1000000000, maximum = int(datetime.now().timestamp())) + Number(minimum=1000000000, maximum = 2000000000) ] ) - input_field.border_title = 'Seed' + self.input_field.border_title = 'Seed' yield Horizontal( - input_field, + self.input_field, Button('re-roll', classes='roll_btn'), classes='bottom_line' ) -class BingoBoard(Static): - - 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' - ] - - # get rng seed from current time - seed = int(datetime.now().timestamp()) - random.seed(seed) - random.shuffle(fields) + def on_button_pressed(self, event: Button.Pressed) -> None: + """""" + # reroll + self.board.roll_board(int(datetime.now().timestamp())) + self.input_field.value = str(self.board.seed) + +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.roll_board(int(datetime.now().timestamp())) + + def roll_board(self, seed): + print('rolling board.') + self.seed = seed + random.seed(seed) + self.fields = random.sample(self.fields, len(self.fields)) + print('board after shuf:') + print(self.fields) + + def watch_fields(self, new_state) -> None: + print('watch_fields: called') + 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.""" From 725b30256debba8ef0b7aeb614f94dd581a88970 Mon Sep 17 00:00:00 2001 From: Felix Pankratz Date: Thu, 9 May 2024 18:40:15 +0200 Subject: [PATCH 5/7] remove footer, add input method --- bingo.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/bingo.py b/bingo.py index 1b66823..5e7a16e 100644 --- a/bingo.py +++ b/bingo.py @@ -58,13 +58,10 @@ class BingoApp(App): """A Textual app to run a Bingo board.""" CSS_PATH = "bingo.tcss" - BINDINGS = [("d", "toggle_dark", "Toggle dark mode")] - def compose(self) -> ComposeResult: """Create child widgets for the app.""" yield Header() yield BingoDisplay() - yield Footer() def action_toggle_dark(self) -> None: """An action to toggle dark mode.""" @@ -88,7 +85,7 @@ class BingoDisplay(Static): self.input_field.border_title = 'Seed' yield Horizontal( self.input_field, - Button('re-roll', classes='roll_btn'), + Button.error(':game_die: re-roll', classes='roll_btn'), classes='bottom_line' ) @@ -98,6 +95,10 @@ class BingoDisplay(Static): self.board.roll_board(int(datetime.now().timestamp())) self.input_field.value = str(self.board.seed) + def on_input_submitted(self, event: Input.Submitted) -> None: + if event.validation_result: + self.board.roll_board(int(event.value)) + class BingoBoard(Widget): fields = reactive([], recompose = True) @@ -132,19 +133,15 @@ class BingoBoard(Widget): 'geduscht', 'Gulasch gegessen' ] - + self.default_fields = self.fields self.roll_board(int(datetime.now().timestamp())) def roll_board(self, seed): - print('rolling board.') self.seed = seed random.seed(seed) - self.fields = random.sample(self.fields, len(self.fields)) - print('board after shuf:') - print(self.fields) + self.fields = random.sample(self.default_fields, len(self.fields)) def watch_fields(self, new_state) -> None: - print('watch_fields: called') self.fieldstate = [False for _ in range(25)] for idx, field in enumerate(self.query(BingoField)): field.text = new_state[idx] From 3a266e3bfcc9e35c0219965fcebfe113c061ec97 Mon Sep 17 00:00:00 2001 From: Felix Pankratz Date: Thu, 9 May 2024 18:41:44 +0200 Subject: [PATCH 6/7] fix input validation --- bingo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bingo.py b/bingo.py index 5e7a16e..6d635ec 100644 --- a/bingo.py +++ b/bingo.py @@ -96,7 +96,7 @@ class BingoDisplay(Static): self.input_field.value = str(self.board.seed) def on_input_submitted(self, event: Input.Submitted) -> None: - if event.validation_result: + if event.validation_result.is_valid: self.board.roll_board(int(event.value)) class BingoBoard(Widget): From bf921be42383873115e87c843536064cb3074790 Mon Sep 17 00:00:00 2001 From: Felix Pankratz Date: Thu, 9 May 2024 18:42:41 +0200 Subject: [PATCH 7/7] remove unused imports --- bingo.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bingo.py b/bingo.py index 6d635ec..0910281 100644 --- a/bingo.py +++ b/bingo.py @@ -1,10 +1,9 @@ #!/usr/bin/env python3 from textual.app import App, ComposeResult -from textual.widgets import Header, Footer, Input, Label, Static, Button +from textual.widgets import Header, Input, Static, Button from textual.widget import Widget from textual.message import Message -from textual.color import Color from textual.containers import Horizontal from textual.validation import Number from textual.reactive import reactive