1818 TILE_UNCLICKED_BG_COLOR ,
1919 TILE_UNCLICKED_TEXT_COLOR ,
2020)
21- from src .utils .text_processing import split_phrase_into_lines , get_line_style_for_lines
21+ from src .utils .text_processing import get_line_style_for_lines , split_phrase_into_lines
2222
2323# Global variables for game state
2424board = [] # 2D array of phrases
@@ -41,23 +41,23 @@ def generate_board(seed_val: int, phrases):
4141 Also resets the clicked_tiles (ensuring the FREE SPACE is clicked) and sets the global today_seed.
4242 """
4343 global board , today_seed , clicked_tiles
44-
44+
4545 todays_seed = datetime .date .today ().strftime ("%Y%m%d" )
4646 random .seed (seed_val )
47-
47+
4848 shuffled_phrases = random .sample (phrases , 24 )
4949 shuffled_phrases .insert (12 , FREE_SPACE_TEXT )
50-
51- board = [shuffled_phrases [i : i + 5 ] for i in range (0 , 25 , 5 )]
52-
50+
51+ board = [shuffled_phrases [i : i + 5 ] for i in range (0 , 25 , 5 )]
52+
5353 clicked_tiles .clear ()
5454 for r , row in enumerate (board ):
5555 for c , phrase in enumerate (row ):
5656 if phrase .upper () == FREE_SPACE_TEXT :
5757 clicked_tiles .add ((r , c ))
58-
58+
5959 today_seed = f"{ todays_seed } .{ seed_val } "
60-
60+
6161 return board
6262
6363
@@ -67,19 +67,19 @@ def toggle_tile(row, col):
6767 Updates the UI and checks for winner.
6868 """
6969 global clicked_tiles
70-
70+
7171 # Don't allow toggling the free space
7272 if (row , col ) == (2 , 2 ):
7373 return
74-
74+
7575 key = (row , col )
7676 if key in clicked_tiles :
7777 clicked_tiles .remove (key )
7878 else :
7979 clicked_tiles .add (key )
80-
80+
8181 check_winner ()
82-
82+
8383 for view_key , (container , tile_buttons_local ) in board_views .items ():
8484 for (r , c ), tile in tile_buttons_local .items ():
8585 phrase = board [r ][c ]
@@ -89,22 +89,22 @@ def toggle_tile(row, col):
8989 else :
9090 new_card_style = f"background-color: { TILE_UNCLICKED_BG_COLOR } ; color: { TILE_UNCLICKED_TEXT_COLOR } ; border: none;"
9191 new_label_color = TILE_UNCLICKED_TEXT_COLOR
92-
92+
9393 tile ["card" ].style (new_card_style )
9494 lines = split_phrase_into_lines (phrase )
9595 line_count = len (lines )
9696 new_label_style = get_line_style_for_lines (line_count , new_label_color )
97-
97+
9898 for label_info in tile ["labels" ]:
9999 lbl = label_info ["ref" ]
100100 lbl .classes (label_info ["base_classes" ])
101101 lbl .style (new_label_style )
102102 lbl .update ()
103-
103+
104104 tile ["card" ].update ()
105-
105+
106106 container .update ()
107-
107+
108108 try :
109109 js_code = """
110110 setTimeout(function() {
@@ -125,7 +125,7 @@ def check_winner():
125125 """
126126 global bingo_patterns
127127 new_patterns = []
128-
128+
129129 # Check rows and columns.
130130 for i in range (5 ):
131131 if all ((i , j ) in clicked_tiles for j in range (5 )):
@@ -141,7 +141,7 @@ def check_winner():
141141 new_patterns .append ("diag_main" )
142142
143143 # Check anti-diagonal.
144- if all ((i , 4 - i ) in clicked_tiles for i in range (5 )):
144+ if all ((i , 4 - i ) in clicked_tiles for i in range (5 )):
145145 if "diag_anti" not in bingo_patterns :
146146 new_patterns .append ("diag_anti" )
147147
@@ -153,7 +153,7 @@ def check_winner():
153153 new_patterns .append ("blackout" )
154154
155155 # 4 Corners: top-left, top-right, bottom-left, bottom-right.
156- if all (pos in clicked_tiles for pos in [(0 ,0 ), (0 ,4 ), (4 ,0 ), (4 ,4 )]):
156+ if all (pos in clicked_tiles for pos in [(0 , 0 ), (0 , 4 ), (4 , 0 ), (4 , 4 )]):
157157 if "four_corners" not in bingo_patterns :
158158 new_patterns .append ("four_corners" )
159159
@@ -164,12 +164,19 @@ def check_winner():
164164 new_patterns .append ("plus" )
165165
166166 # X shape: both diagonals complete.
167- if all ((i , i ) in clicked_tiles for i in range (5 )) and all ((i , 4 - i ) in clicked_tiles for i in range (5 )):
167+ if all ((i , i ) in clicked_tiles for i in range (5 )) and all (
168+ (i , 4 - i ) in clicked_tiles for i in range (5 )
169+ ):
168170 if "x_shape" not in bingo_patterns :
169171 new_patterns .append ("x_shape" )
170172
171173 # Outside edges (perimeter): all border cells clicked.
172- perimeter_cells = {(0 , c ) for c in range (5 )} | {(4 , c ) for c in range (5 )} | {(r , 0 ) for r in range (5 )} | {(r , 4 ) for r in range (5 )}
174+ perimeter_cells = (
175+ {(0 , c ) for c in range (5 )}
176+ | {(4 , c ) for c in range (5 )}
177+ | {(r , 0 ) for r in range (5 )}
178+ | {(r , 4 ) for r in range (5 )}
179+ )
173180 if all (cell in clicked_tiles for cell in perimeter_cells ):
174181 if "perimeter" not in bingo_patterns :
175182 new_patterns .append ("perimeter" )
@@ -228,21 +235,21 @@ def generate_new_board(phrases):
228235 global board_iteration
229236 board_iteration += 1
230237 generate_board (board_iteration , phrases )
231-
238+
232239 # Update all board views (both home and stream)
233240 from src .ui .board_builder import build_board
234-
241+
235242 for view_key , (container , tile_buttons_local ) in board_views .items ():
236243 container .clear ()
237244 tile_buttons_local .clear ()
238245 build_board (container , tile_buttons_local , toggle_tile , board , clicked_tiles )
239246 container .update ()
240-
247+
241248 # Update the seed label if available
242- if ' seed_label' in globals () and seed_label :
249+ if " seed_label" in globals () and seed_label :
243250 seed_label .set_text (f"Seed: { today_seed } " )
244251 seed_label .update ()
245-
252+
246253 reset_board ()
247254
248255
@@ -253,24 +260,26 @@ def close_game():
253260 """
254261 global is_game_closed , header_label
255262 is_game_closed = True
256-
263+
257264 # Update header text on the current view
258265 if header_label :
259266 header_label .set_text (CLOSED_HEADER_TEXT )
260267 header_label .update ()
261-
268+
262269 # Hide all board views (both home and stream)
263270 for view_key , (container , tile_buttons_local ) in board_views .items ():
264271 container .style ("display: none;" )
265272 container .update ()
266-
273+
267274 # Modify the controls row to only show the New Board button
268275 if controls_row :
269276 controls_row .clear ()
270277 with controls_row :
271- with ui .button ("" , icon = "autorenew" , on_click = reopen_game ).classes ("rounded-full w-12 h-12" ) as new_game_btn :
278+ with ui .button ("" , icon = "autorenew" , on_click = reopen_game ).classes (
279+ "rounded-full w-12 h-12"
280+ ) as new_game_btn :
272281 ui .tooltip ("Start New Game" )
273-
282+
274283 # Update stream page as well - this will trigger sync_board_state on connected clients
275284 # Note: ui.broadcast() was used in older versions of NiceGUI, but may not be available
276285 try :
@@ -279,7 +288,7 @@ def close_game():
279288 # In newer versions of NiceGUI, broadcast might not be available
280289 # We rely on the timer-based sync instead
281290 logging .info ("ui.broadcast not available, relying on timer-based sync" )
282-
291+
283292 # Notify that game has been closed
284293 ui .notify ("Game has been closed" , color = "red" , duration = 3 )
285294
@@ -290,48 +299,50 @@ def reopen_game():
290299 This regenerates a new board and resets the UI.
291300 """
292301 global is_game_closed , header_label , board_iteration
293-
302+
294303 # Reset game state
295304 is_game_closed = False
296-
305+
297306 # Update header text back to original for the current view
298307 if header_label :
299308 header_label .set_text (HEADER_TEXT )
300309 header_label .update ()
301-
310+
302311 # Generate a new board
303312 from src .utils .file_operations import read_phrases_file
313+
304314 phrases = read_phrases_file ()
305-
315+
306316 board_iteration += 1
307317 generate_board (board_iteration , phrases )
308-
318+
309319 # Rebuild the controls row with all buttons
310320 from src .ui .controls import rebuild_controls_row
321+
311322 if controls_row :
312323 rebuild_controls_row (controls_row )
313-
324+
314325 # Recreate and show all board views
315326 from src .ui .board_builder import build_board
316-
327+
317328 for view_key , (container , tile_buttons_local ) in board_views .items ():
318329 container .style ("display: block;" )
319330 container .clear ()
320331 tile_buttons_local .clear ()
321332 build_board (container , tile_buttons_local , toggle_tile , board , clicked_tiles )
322333 container .update ()
323-
334+
324335 # Reset clicked tiles except for FREE SPACE
325336 reset_board ()
326-
337+
327338 # Notify that a new game has started
328339 ui .notify ("New game started" , color = "green" , duration = 3 )
329-
340+
330341 # Update stream page and all other connected clients
331342 # This will trigger sync_board_state on all clients including the stream view
332343 try :
333344 ui .broadcast () # Broadcast changes to all connected clients
334345 except AttributeError :
335346 # In newer versions of NiceGUI, broadcast might not be available
336347 # We rely on the timer-based sync instead
337- logging .info ("ui.broadcast not available, relying on timer-based sync" )
348+ logging .info ("ui.broadcast not available, relying on timer-based sync" )
0 commit comments