|
|
|
|
|
""" |
|
|
Direct grid generation test to identify word boundary/display issues. |
|
|
""" |
|
|
|
|
|
import sys |
|
|
from pathlib import Path |
|
|
|
|
|
|
|
|
project_root = Path(__file__).parent |
|
|
sys.path.insert(0, str(project_root)) |
|
|
|
|
|
from src.services.crossword_generator_fixed import CrosswordGeneratorFixed |
|
|
|
|
|
def test_direct_grid_generation(): |
|
|
"""Test grid generation directly with controlled words.""" |
|
|
|
|
|
print("🔍 Direct Grid Generation Test\n") |
|
|
|
|
|
generator = CrosswordGeneratorFixed(vector_service=None) |
|
|
|
|
|
|
|
|
test_words = [ |
|
|
{"word": "MACHINE", "clue": "Device with moving parts"}, |
|
|
{"word": "COMPUTER", "clue": "Electronic device"}, |
|
|
{"word": "EXPERT", "clue": "Person with specialized knowledge"}, |
|
|
{"word": "SCIENCE", "clue": "Systematic study"}, |
|
|
{"word": "CAMERA", "clue": "Device for taking photos"}, |
|
|
{"word": "METHOD", "clue": "Systematic approach"} |
|
|
] |
|
|
|
|
|
print("=" * 60) |
|
|
print("TEST 1: Direct grid creation") |
|
|
print("=" * 60) |
|
|
|
|
|
|
|
|
result = generator._create_grid(test_words) |
|
|
|
|
|
if result: |
|
|
print("✅ Grid generation successful!") |
|
|
|
|
|
grid = result["grid"] |
|
|
placed_words = result["placed_words"] |
|
|
clues = result["clues"] |
|
|
|
|
|
print(f"Grid size: {len(grid)}x{len(grid[0])}") |
|
|
print(f"Words placed: {len(placed_words)}") |
|
|
print(f"Clues generated: {len(clues)}") |
|
|
|
|
|
|
|
|
print("\nGenerated Grid:") |
|
|
print_grid_with_coordinates(grid) |
|
|
|
|
|
|
|
|
print("\nPlaced Words:") |
|
|
for i, word_info in enumerate(placed_words): |
|
|
print(f" {i+1}. {word_info['word']} at ({word_info['row']}, {word_info['col']}) {word_info['direction']}") |
|
|
|
|
|
|
|
|
print("\nGenerated Clues:") |
|
|
for clue in clues: |
|
|
print(f" {clue['number']}. {clue['direction']}: {clue['word']} - {clue['text']}") |
|
|
|
|
|
|
|
|
print("\n" + "=" * 60) |
|
|
print("ANALYSIS") |
|
|
print("=" * 60) |
|
|
|
|
|
analyze_grid_issues(grid, placed_words, clues) |
|
|
|
|
|
else: |
|
|
print("❌ Grid generation failed") |
|
|
|
|
|
|
|
|
print("\n" + "=" * 60) |
|
|
print("TEST 2: Scenario with potential extension words") |
|
|
print("=" * 60) |
|
|
|
|
|
|
|
|
extension_words = [ |
|
|
{"word": "MACHINE", "clue": "Device with moving parts"}, |
|
|
{"word": "MACHINERY", "clue": "Mechanical equipment"}, |
|
|
{"word": "EXPERT", "clue": "Specialist"}, |
|
|
{"word": "TECHNOLOGY", "clue": "Applied science"}, |
|
|
] |
|
|
|
|
|
result2 = generator._create_grid(extension_words) |
|
|
|
|
|
if result2: |
|
|
print("✅ Extension test grid generated!") |
|
|
|
|
|
grid2 = result2["grid"] |
|
|
placed_words2 = result2["placed_words"] |
|
|
|
|
|
print("\nExtension Test Grid:") |
|
|
print_grid_with_coordinates(grid2) |
|
|
|
|
|
print("\nPlaced Words:") |
|
|
for i, word_info in enumerate(placed_words2): |
|
|
print(f" {i+1}. {word_info['word']} at ({word_info['row']}, {word_info['col']}) {word_info['direction']}") |
|
|
|
|
|
|
|
|
check_machine_machinery_issue(grid2, placed_words2) |
|
|
|
|
|
else: |
|
|
print("❌ Extension test grid generation failed") |
|
|
|
|
|
def print_grid_with_coordinates(grid): |
|
|
"""Print grid with row and column coordinates.""" |
|
|
if not grid: |
|
|
print(" Empty grid") |
|
|
return |
|
|
|
|
|
|
|
|
print(" ", end="") |
|
|
for c in range(len(grid[0])): |
|
|
print(f"{c:2d}", end="") |
|
|
print() |
|
|
|
|
|
|
|
|
for r in range(len(grid)): |
|
|
print(f" {r:2d}: ", end="") |
|
|
for c in range(len(grid[0])): |
|
|
cell = grid[r][c] |
|
|
if cell == ".": |
|
|
print(" .", end="") |
|
|
else: |
|
|
print(f" {cell}", end="") |
|
|
print() |
|
|
|
|
|
def analyze_grid_issues(grid, placed_words, clues): |
|
|
"""Analyze the grid for potential boundary/display issues.""" |
|
|
|
|
|
print("Checking for potential issues...") |
|
|
|
|
|
issues = [] |
|
|
|
|
|
|
|
|
for word_info in placed_words: |
|
|
word = word_info["word"] |
|
|
row = word_info["row"] |
|
|
col = word_info["col"] |
|
|
direction = word_info["direction"] |
|
|
|
|
|
grid_word = extract_word_from_grid(grid, row, col, direction, len(word)) |
|
|
|
|
|
if grid_word != word: |
|
|
issues.append(f"Word mismatch: '{word}' expected at ({row},{col}) {direction}, but grid shows '{grid_word}'") |
|
|
|
|
|
|
|
|
all_sequences = find_all_letter_sequences(grid) |
|
|
intended_words = {(w["row"], w["col"], w["direction"]): w["word"] for w in placed_words} |
|
|
|
|
|
for seq_info in all_sequences: |
|
|
row, col, direction, seq_word = seq_info |
|
|
key = (row, col, direction) |
|
|
|
|
|
if key not in intended_words: |
|
|
if len(seq_word) > 1: |
|
|
issues.append(f"Unintended sequence: '{seq_word}' at ({row},{col}) {direction}") |
|
|
elif intended_words[key] != seq_word: |
|
|
issues.append(f"Sequence mismatch: expected '{intended_words[key]}' but found '{seq_word}' at ({row},{col}) {direction}") |
|
|
|
|
|
|
|
|
for clue in clues: |
|
|
clue_word = clue["word"] |
|
|
pos = clue["position"] |
|
|
clue_row = pos["row"] |
|
|
clue_col = pos["col"] |
|
|
clue_direction = clue["direction"] |
|
|
|
|
|
|
|
|
direction_map = {"across": "horizontal", "down": "vertical"} |
|
|
normalized_direction = direction_map.get(clue_direction, clue_direction) |
|
|
|
|
|
grid_word = extract_word_from_grid(grid, clue_row, clue_col, normalized_direction, len(clue_word)) |
|
|
|
|
|
if grid_word != clue_word: |
|
|
issues.append(f"Clue mismatch: clue says '{clue_word}' at ({clue_row},{clue_col}) {clue_direction}, but grid shows '{grid_word}'") |
|
|
|
|
|
|
|
|
if issues: |
|
|
print("❌ Issues found:") |
|
|
for issue in issues: |
|
|
print(f" {issue}") |
|
|
else: |
|
|
print("✅ No issues detected - grid appears consistent") |
|
|
|
|
|
def extract_word_from_grid(grid, row, col, direction, expected_length): |
|
|
"""Extract word from grid at given position and direction.""" |
|
|
if row >= len(grid) or col >= len(grid[0]) or row < 0 or col < 0: |
|
|
return "OUT_OF_BOUNDS" |
|
|
|
|
|
word = "" |
|
|
|
|
|
if direction in ["horizontal", "across"]: |
|
|
for i in range(expected_length): |
|
|
if col + i >= len(grid[0]): |
|
|
return word + "[TRUNCATED]" |
|
|
word += grid[row][col + i] |
|
|
elif direction in ["vertical", "down"]: |
|
|
for i in range(expected_length): |
|
|
if row + i >= len(grid): |
|
|
return word + "[TRUNCATED]" |
|
|
word += grid[row + i][col] |
|
|
|
|
|
return word |
|
|
|
|
|
def find_all_letter_sequences(grid): |
|
|
"""Find all letter sequences (horizontal and vertical) in the grid.""" |
|
|
sequences = [] |
|
|
|
|
|
|
|
|
for r in range(len(grid)): |
|
|
current_word = "" |
|
|
start_col = None |
|
|
|
|
|
for c in range(len(grid[0])): |
|
|
if grid[r][c] != ".": |
|
|
if start_col is None: |
|
|
start_col = c |
|
|
current_word += grid[r][c] |
|
|
else: |
|
|
if current_word and len(current_word) > 1: |
|
|
sequences.append((r, start_col, "horizontal", current_word)) |
|
|
current_word = "" |
|
|
start_col = None |
|
|
|
|
|
|
|
|
if current_word and len(current_word) > 1: |
|
|
sequences.append((r, start_col, "horizontal", current_word)) |
|
|
|
|
|
|
|
|
for c in range(len(grid[0])): |
|
|
current_word = "" |
|
|
start_row = None |
|
|
|
|
|
for r in range(len(grid)): |
|
|
if grid[r][c] != ".": |
|
|
if start_row is None: |
|
|
start_row = r |
|
|
current_word += grid[r][c] |
|
|
else: |
|
|
if current_word and len(current_word) > 1: |
|
|
sequences.append((start_row, c, "vertical", current_word)) |
|
|
current_word = "" |
|
|
start_row = None |
|
|
|
|
|
|
|
|
if current_word and len(current_word) > 1: |
|
|
sequences.append((start_row, c, "vertical", current_word)) |
|
|
|
|
|
return sequences |
|
|
|
|
|
def check_machine_machinery_issue(grid, placed_words): |
|
|
"""Specifically check for MACHINE vs MACHINERY confusion.""" |
|
|
|
|
|
print("\nChecking for MACHINE/MACHINERY issue:") |
|
|
|
|
|
machine_words = [w for w in placed_words if "MACHINE" in w["word"]] |
|
|
|
|
|
if not machine_words: |
|
|
print(" No MACHINE-related words found") |
|
|
return |
|
|
|
|
|
for word_info in machine_words: |
|
|
word = word_info["word"] |
|
|
row = word_info["row"] |
|
|
col = word_info["col"] |
|
|
direction = word_info["direction"] |
|
|
|
|
|
print(f" Found: '{word}' at ({row},{col}) {direction}") |
|
|
|
|
|
|
|
|
grid_word = extract_word_from_grid(grid, row, col, direction, len(word)) |
|
|
print(f" Grid shows: '{grid_word}'") |
|
|
|
|
|
|
|
|
if direction == "horizontal": |
|
|
|
|
|
end_col = col + len(word) |
|
|
if end_col < len(grid[0]) and grid[row][end_col] != ".": |
|
|
extra_letters = "" |
|
|
check_col = end_col |
|
|
while check_col < len(grid[0]) and grid[row][check_col] != ".": |
|
|
extra_letters += grid[row][check_col] |
|
|
check_col += 1 |
|
|
if extra_letters: |
|
|
print(f" ⚠️ Extra letters after word: '{extra_letters}'") |
|
|
print(f" This might make '{word}' appear as '{word + extra_letters}'") |
|
|
|
|
|
if __name__ == "__main__": |
|
|
test_direct_grid_generation() |