#!/usr/bin/env python3 """ Test to analyze the visual representation issue that might cause words to appear extended. """ import sys from pathlib import Path # Add project root to path project_root = Path(__file__).parent.parent # Go up from test-integration to backend-py sys.path.insert(0, str(project_root)) from src.services.crossword_generator_fixed import CrosswordGeneratorFixed def analyze_visual_word_extensions(): """Analyze how visual word extensions might occur in the crossword grid.""" print("🔍 Analyzing Visual Word Extension Issues\n") generator = CrosswordGeneratorFixed(vector_service=None) # Create a scenario that might produce the "visual extension" effect # Based on the crossword images, it seems like words are appearing to extend # when they shouldn't grid = [["." for _ in range(15)] for _ in range(15)] placed_words = [] print("=" * 60) print("SCENARIO 1: Creating potential visual extension") print("=" * 60) # Step 1: Place MACHINE if generator._can_place_word(grid, "MACHINE", 7, 3, "horizontal"): generator._place_word(grid, "MACHINE", 7, 3, "horizontal") placed_words.append({ "word": "MACHINE", "row": 7, "col": 3, "direction": "horizontal", "number": 1 }) print("✅ Placed MACHINE at (7, 3) horizontal") # Step 2: Place a word that intersects at the end of MACHINE # This might create the visual illusion of extension if generator._can_place_word(grid, "EXPERT", 5, 9, "vertical"): # E intersects with E in MACHINE generator._place_word(grid, "EXPERT", 5, 9, "vertical") placed_words.append({ "word": "EXPERT", "row": 5, "col": 9, "direction": "vertical", "number": 2 }) print("✅ Placed EXPERT at (5, 9) vertical") # Step 3: Place another intersecting word that might create confusion if generator._can_place_word(grid, "TYPOGRAPHY", 7, 10, "horizontal"): # Starts right after MACHINE generator._place_word(grid, "TYPOGRAPHY", 7, 10, "horizontal") placed_words.append({ "word": "TYPOGRAPHY", "row": 7, "col": 10, "direction": "horizontal", "number": 3 }) print("✅ Placed TYPOGRAPHY at (7, 10) horizontal") print("\nCurrent grid state:") print_detailed_grid(grid, placed_words) # Analyze what the human eye might see print("\n" + "=" * 60) print("VISUAL ANALYSIS") print("=" * 60) analyze_row_sequences(grid, placed_words, 7) # Analyze row 7 specifically analyze_column_sequences(grid, placed_words, 9) # Analyze column 9 specifically # Test another scenario print("\n" + "=" * 60) print("SCENARIO 2: Adjacent word placement") print("=" * 60) grid2 = [["." for _ in range(15)] for _ in range(15)] placed_words2 = [] # Place words that are adjacent but should be separate if generator._can_place_word(grid2, "SCIENCE", 6, 2, "horizontal"): generator._place_word(grid2, "SCIENCE", 6, 2, "horizontal") placed_words2.append({ "word": "SCIENCE", "row": 6, "col": 2, "direction": "horizontal", "number": 1 }) # Try to place a word immediately after with no gap if generator._can_place_word(grid2, "TECHNOLOGY", 6, 9, "horizontal"): generator._place_word(grid2, "TECHNOLOGY", 6, 9, "horizontal") placed_words2.append({ "word": "TECHNOLOGY", "row": 6, "col": 9, "direction": "horizontal", "number": 2 }) print("⚠️ Placed TECHNOLOGY immediately after SCIENCE") else: print("✅ Correctly prevented TECHNOLOGY placement immediately after SCIENCE") print("\nGrid 2 state:") print_detailed_grid(grid2, placed_words2) # Check what boundary checking should prevent print("\n" + "=" * 60) print("BOUNDARY VALIDATION TEST") print("=" * 60) test_boundary_edge_cases(generator) def print_detailed_grid(grid, placed_words, highlight_rows=None): """Print grid with detailed analysis.""" print("Grid with word boundaries marked:") print(" ", end="") for c in range(min(15, len(grid[0]))): print(f"{c:2d}", end="") print() for r in range(min(15, len(grid))): print(f"{r:2d}: ", end="") for c in range(min(15, len(grid[0]))): cell = grid[r][c] if cell == ".": print(" .", end="") else: print(f" {cell}", end="") print() 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']}") def analyze_row_sequences(grid, placed_words, row): """Analyze letter sequences in a specific row.""" print(f"\nAnalyzing row {row} sequences:") # Extract all letters in the row row_letters = [] for c in range(len(grid[0])): if grid[row][c] != ".": row_letters.append((c, grid[row][c])) if not row_letters: print(" No letters in this row") return print(f" Letters found: {row_letters}") # Find continuous sequences sequences = [] current_seq = [] for i, (col, letter) in enumerate(row_letters): if not current_seq or col == row_letters[i-1][0] + 1: current_seq.append((col, letter)) else: if len(current_seq) > 1: sequences.append(current_seq) current_seq = [(col, letter)] if len(current_seq) > 1: sequences.append(current_seq) print(f" Continuous sequences: {len(sequences)}") for i, seq in enumerate(sequences): word = "".join([letter for col, letter in seq]) start_col = seq[0][0] print(f" Sequence {i+1}: '{word}' starting at column {start_col}") # Check if this matches intended words intended = False for word_info in placed_words: if (word_info["direction"] == "horizontal" and word_info["row"] == row and word_info["col"] == start_col and word_info["word"] == word): intended = True print(f" ✅ This is the intended word '{word_info['word']}'") break if not intended and len(word) > 1: print(f" ❌ This appears to be an unintended word formation!") def analyze_column_sequences(grid, placed_words, col): """Analyze letter sequences in a specific column.""" print(f"\nAnalyzing column {col} sequences:") # Extract all letters in the column col_letters = [] for r in range(len(grid)): if grid[r][col] != ".": col_letters.append((r, grid[r][col])) if not col_letters: print(" No letters in this column") return print(f" Letters found: {col_letters}") # Find continuous sequences sequences = [] current_seq = [] for i, (row, letter) in enumerate(col_letters): if not current_seq or row == col_letters[i-1][0] + 1: current_seq.append((row, letter)) else: if len(current_seq) > 1: sequences.append(current_seq) current_seq = [(row, letter)] if len(current_seq) > 1: sequences.append(current_seq) print(f" Continuous sequences: {len(sequences)}") for i, seq in enumerate(sequences): word = "".join([letter for row, letter in seq]) start_row = seq[0][0] print(f" Sequence {i+1}: '{word}' starting at row {start_row}") # Check if this matches intended words intended = False for word_info in placed_words: if (word_info["direction"] == "vertical" and word_info["col"] == col and word_info["row"] == start_row and word_info["word"] == word): intended = True print(f" ✅ This is the intended word '{word_info['word']}'") break if not intended and len(word) > 1: print(f" ❌ This appears to be an unintended word formation!") def test_boundary_edge_cases(generator): """Test specific boundary edge cases.""" # Test case 1: Words that touch but shouldn't form a continuous sequence grid = [["." for _ in range(10)] for _ in range(10)] # Place first word generator._place_word(grid, "CAT", 5, 2, "horizontal") # Try to place second word immediately adjacent (should be blocked) can_place = generator._can_place_word(grid, "DOG", 5, 5, "horizontal") print(f"Can place 'DOG' immediately after 'CAT': {can_place}") if can_place: print("❌ PROBLEM: Adjacent words allowed - this could create visual extension!") print("Current grid after CAT:") for r in range(3, 8): print(f"Row {r}: ", end="") for c in range(8): print(f"{grid[r][c]} ", end="") print() generator._place_word(grid, "DOG", 5, 5, "horizontal") print("After adding DOG:") for r in range(3, 8): print(f"Row {r}: ", end="") for c in range(8): print(f"{grid[r][c]} ", end="") print() else: print("✅ Correctly prevented adjacent word placement") # Test case 2: Check gap requirement can_place_with_gap = generator._can_place_word(grid, "DOG", 5, 6, "horizontal") print(f"Can place 'DOG' with 1-cell gap after 'CAT': {can_place_with_gap}") if __name__ == "__main__": analyze_visual_word_extensions()