Surn commited on
Commit
bf6658b
·
verified ·
1 Parent(s): 0692942

Update wrdler/gradio_ui.py

Browse files
Files changed (1) hide show
  1. wrdler/gradio_ui.py +54 -7
wrdler/gradio_ui.py CHANGED
@@ -300,7 +300,14 @@ def get_wordlist_files() -> List[str]:
300
 
301
  @lru_cache(maxsize=32)
302
  def load_word_list_gradio(selected_file: Optional[str] = None) -> Dict[int, List[str]]:
303
- """Load word list without Streamlit dependencies."""
 
 
 
 
 
 
 
304
  import re
305
 
306
  words_by_len: Dict[int, List[str]] = {4: [], 5: [], 6: []}
@@ -313,6 +320,14 @@ def load_word_list_gradio(selected_file: Optional[str] = None) -> Dict[int, List
313
  else:
314
  path = os.path.join(words_dir, "wordlist.txt")
315
 
 
 
 
 
 
 
 
 
316
  with open(path, "r", encoding="utf-8") as f:
317
  text = f.read()
318
 
@@ -333,17 +348,28 @@ def load_word_list_gradio(selected_file: Optional[str] = None) -> Dict[int, List
333
 
334
  # Check minimum requirements
335
  counts = {k: len(v) for k, v in words_by_len.items()}
 
 
336
  if all(counts[k] >= MIN_REQUIRED for k in (4, 5, 6)):
337
  return words_by_len
338
 
339
- # Fallback for insufficient words
 
 
 
 
 
340
  return {
341
  4: words_by_len[4] if counts[4] >= MIN_REQUIRED else FALLBACK_WORDS[4],
342
  5: words_by_len[5] if counts[5] >= MIN_REQUIRED else FALLBACK_WORDS[5],
343
  6: words_by_len[6] if counts[6] >= MIN_REQUIRED else FALLBACK_WORDS[6],
344
  }
345
 
 
 
 
346
  except Exception:
 
347
  return FALLBACK_WORDS.copy()
348
 
349
 
@@ -358,13 +384,17 @@ def create_new_game_state(
358
  ai_topic: str = ""
359
  ) -> Dict[str, Any]:
360
  """Create a new game state dictionary for gr.State."""
 
 
361
  # Handle AI Generated word list
362
  if wordlist == "AI Generated" and ai_topic.strip():
 
363
  import re as re_module
364
  # Convert topic to filename (same logic as _save_ai_words_to_file)
365
  safe_topic = re_module.sub(r'[^\w\s-]', '', ai_topic.strip().lower()).strip()
366
  safe_topic = re_module.sub(r'[-\s]+', '_', safe_topic)
367
  topic_filename = f"{safe_topic}.txt"
 
368
 
369
  # First try to load existing words from the topic file
370
  words_by_len = None
@@ -374,14 +404,25 @@ def create_new_game_state(
374
  has_enough = all(len(existing_words.get(length, [])) >= MIN_REQUIRED for length in (4, 5, 6))
375
  if has_enough:
376
  words_by_len = existing_words
377
- except Exception:
378
- pass
 
 
 
 
 
 
379
 
380
  # If no existing file or not enough words, generate new AI words
381
  if words_by_len is None:
382
  try:
 
 
383
  # Generate AI words - returns list of 75 words
384
  ai_words, _, _ = generate_ai_words(topic=ai_topic.strip())
 
 
 
385
  # Convert to words_by_len format
386
  words_by_len = {4: [], 5: [], 6: []}
387
  for word in ai_words:
@@ -392,13 +433,19 @@ def create_new_game_state(
392
  for length in (4, 5, 6):
393
  if len(words_by_len[length]) < MIN_REQUIRED:
394
  # Fall back to default words
 
395
  words_by_len[length] = FALLBACK_WORDS[length].copy()
396
  except Exception as e:
397
  # Fall back to default word list on error
 
 
 
398
  words_by_len = load_word_list_gradio("classic.txt")
399
  else:
 
400
  words_by_len = load_word_list_gradio(wordlist if wordlist != "AI Generated" else "classic.txt")
401
 
 
402
  puzzle = generate_puzzle(
403
  grid_rows=GRID_ROWS,
404
  grid_cols=GRID_COLS,
@@ -532,7 +579,7 @@ def get_cell_label(state: Dict[str, Any], row: int, col: int) -> str:
532
  letter = letter_map.get(coord_str, "")
533
  return letter if letter else "\u00A0" # Non-breaking space for empty revealed cells
534
  else:
535
- return "?"
536
 
537
 
538
  def get_cell_variant(state: Dict[str, Any], row: int, col: int) -> str:
@@ -681,7 +728,7 @@ def render_score_panel_html(state: Dict[str, Any]) -> str:
681
  f'</tr>'
682
  )
683
  else:
684
- hidden = "?" * len(text)
685
  base_points = len(text)
686
  table_rows.append(
687
  f'<tr class="hidden">'
@@ -1352,7 +1399,7 @@ def create_app() -> gr.Blocks:
1352
  with gr.Row(elem_classes=["wrdler-grid-row"]):
1353
  for col in range(GRID_COLS):
1354
  btn = gr.Button(
1355
- value="?",
1356
  variant="primary",
1357
  size="sm",
1358
  min_width=20,
 
300
 
301
  @lru_cache(maxsize=32)
302
  def load_word_list_gradio(selected_file: Optional[str] = None) -> Dict[int, List[str]]:
303
+ """Load word list without Streamlit dependencies.
304
+
305
+ Returns:
306
+ Dict mapping word length to list of words
307
+
308
+ Note: For AI generation scenarios, raises FileNotFoundError if file doesn't exist.
309
+ For regular wordlist loading, returns FALLBACK_WORDS on any error.
310
+ """
311
  import re
312
 
313
  words_by_len: Dict[int, List[str]] = {4: [], 5: [], 6: []}
 
320
  else:
321
  path = os.path.join(words_dir, "wordlist.txt")
322
 
323
+ # Check if file exists - raise FileNotFoundError for AI topics
324
+ if not os.path.isfile(path):
325
+ # If this looks like an AI-generated topic file (not a standard wordlist), raise exception
326
+ if selected_file and not selected_file.startswith(("wordlist", "classic", "scrabble")):
327
+ raise FileNotFoundError(f"Word list file not found: {selected_file}")
328
+ # For standard wordlists, fall through to fallback
329
+ raise FileNotFoundError(f"Standard wordlist not found: {path}")
330
+
331
  with open(path, "r", encoding="utf-8") as f:
332
  text = f.read()
333
 
 
348
 
349
  # Check minimum requirements
350
  counts = {k: len(v) for k, v in words_by_len.items()}
351
+
352
+ # If file has sufficient words, return them
353
  if all(counts[k] >= MIN_REQUIRED for k in (4, 5, 6)):
354
  return words_by_len
355
 
356
+ # File exists but has insufficient words
357
+ # For AI topic files, raise exception to trigger generation
358
+ if selected_file and not selected_file.startswith(("wordlist", "classic", "scrabble")):
359
+ raise ValueError(f"File {selected_file} has insufficient words: {counts}")
360
+
361
+ # For standard wordlists with insufficient words, return what we have mixed with fallback
362
  return {
363
  4: words_by_len[4] if counts[4] >= MIN_REQUIRED else FALLBACK_WORDS[4],
364
  5: words_by_len[5] if counts[5] >= MIN_REQUIRED else FALLBACK_WORDS[5],
365
  6: words_by_len[6] if counts[6] >= MIN_REQUIRED else FALLBACK_WORDS[6],
366
  }
367
 
368
+ except (FileNotFoundError, ValueError):
369
+ # Re-raise for AI generation scenarios
370
+ raise
371
  except Exception:
372
+ # For other errors (e.g., permission issues), fall back to defaults
373
  return FALLBACK_WORDS.copy()
374
 
375
 
 
384
  ai_topic: str = ""
385
  ) -> Dict[str, Any]:
386
  """Create a new game state dictionary for gr.State."""
387
+ # print(f"[DEBUG] create_new_game_state called with wordlist={wordlist}, ai_topic='{ai_topic}'")
388
+
389
  # Handle AI Generated word list
390
  if wordlist == "AI Generated" and ai_topic.strip():
391
+ # print(f"[DEBUG] AI Generation condition met! Topic: '{ai_topic.strip()}'")
392
  import re as re_module
393
  # Convert topic to filename (same logic as _save_ai_words_to_file)
394
  safe_topic = re_module.sub(r'[^\w\s-]', '', ai_topic.strip().lower()).strip()
395
  safe_topic = re_module.sub(r'[-\s]+', '_', safe_topic)
396
  topic_filename = f"{safe_topic}.txt"
397
+ # print(f"[DEBUG] Topic filename: {topic_filename}")
398
 
399
  # First try to load existing words from the topic file
400
  words_by_len = None
 
404
  has_enough = all(len(existing_words.get(length, [])) >= MIN_REQUIRED for length in (4, 5, 6))
405
  if has_enough:
406
  words_by_len = existing_words
407
+ # print(f"[DEBUG] ✅ Loaded {sum(len(v) for v in existing_words.values())} existing words from {topic_filename}")
408
+ else:
409
+ pass
410
+ # print(f"[DEBUG] ⚠️ File {topic_filename} exists but has insufficient words. Will generate AI words.")
411
+ except (FileNotFoundError, ValueError) as ex:
412
+ print(f"[DEBUG] File {topic_filename} not found or insufficient. Will generate AI words.")
413
+ except Exception as ex:
414
+ print(f"[DEBUG] Error loading {topic_filename}: {ex}. Will generate AI words.")
415
 
416
  # If no existing file or not enough words, generate new AI words
417
  if words_by_len is None:
418
  try:
419
+ # print(f"[DEBUG] 🎮 Starting AI word generation for topic '{ai_topic.strip()}'...")
420
+
421
  # Generate AI words - returns list of 75 words
422
  ai_words, _, _ = generate_ai_words(topic=ai_topic.strip())
423
+
424
+ # print(f"[DEBUG] ✅ AI generation complete! Got {len(ai_words)} words")
425
+
426
  # Convert to words_by_len format
427
  words_by_len = {4: [], 5: [], 6: []}
428
  for word in ai_words:
 
433
  for length in (4, 5, 6):
434
  if len(words_by_len[length]) < MIN_REQUIRED:
435
  # Fall back to default words
436
+ # print(f"[DEBUG] ⚠️ Not enough {length}-letter words, using fallback")
437
  words_by_len[length] = FALLBACK_WORDS[length].copy()
438
  except Exception as e:
439
  # Fall back to default word list on error
440
+ # print(f"[DEBUG] ❌ AI generation exception: {e}")
441
+ import traceback
442
+ traceback.print_exc()
443
  words_by_len = load_word_list_gradio("classic.txt")
444
  else:
445
+ # print(f"[DEBUG] Using regular wordlist: {wordlist}")
446
  words_by_len = load_word_list_gradio(wordlist if wordlist != "AI Generated" else "classic.txt")
447
 
448
+ # print(f"[DEBUG] Creating puzzle with {sum(len(v) for v in words_by_len.values())} total words")
449
  puzzle = generate_puzzle(
450
  grid_rows=GRID_ROWS,
451
  grid_cols=GRID_COLS,
 
579
  letter = letter_map.get(coord_str, "")
580
  return letter if letter else "\u00A0" # Non-breaking space for empty revealed cells
581
  else:
582
+ return " " # Empty space for unrevealed cells instead of "?"
583
 
584
 
585
  def get_cell_variant(state: Dict[str, Any], row: int, col: int) -> str:
 
728
  f'</tr>'
729
  )
730
  else:
731
+ hidden = "_" * len(text)
732
  base_points = len(text)
733
  table_rows.append(
734
  f'<tr class="hidden">'
 
1399
  with gr.Row(elem_classes=["wrdler-grid-row"]):
1400
  for col in range(GRID_COLS):
1401
  btn = gr.Button(
1402
+ value=" ",
1403
  variant="primary",
1404
  size="sm",
1405
  min_width=20,