Skip to content

Latest commit

 

History

History
225 lines (172 loc) · 8.06 KB

File metadata and controls

225 lines (172 loc) · 8.06 KB

Bugfix: Cálculo Incorrecto de Patrones con Área Parcial

🐛 Problema reportado

El usuario reportó dos problemas relacionados con el cálculo de patrones de protección:

  1. Patrón "Aleatorio" (random): Solo aplicaba el patrón en una franja superior del JSON cargado, no en toda la imagen
  2. Patrón "Centro" (center): Detectaba el centro en la parte superior en lugar del centro real del JSON

🔍 Causa raíz

El problema estaba en cómo se calculaba el bounding box y el centro en las funciones de patrones (pixel_patterns.py):

Comportamiento incorrecto anterior:

def _center(changes: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
    """Ordenar píxeles desde el centro hacia afuera."""
    min_x, max_x, min_y, max_y = _bbox(changes)  # ❌ Calcula bbox solo de los CAMBIOS
    cx = (min_x + max_x) / 2.0
    cy = (min_y + max_y) / 2.0
    
    return sorted(changes, key=lambda c: math.hypot(int(c['x']) - cx, int(c['y']) - cy))

El problema: _bbox(changes) calculaba el bounding box solo de los píxeles con cambios detectados, no del área completa del JSON.

Por qué ocurría:

  1. Usuario carga un JSON Guard con área completa: {startX: 0, startY: 0, width: 200, height: 200}

  2. Bot detecta cambios solo en zona superior: píxeles en coordenadas y: 10-50

  3. La función _center() calcula centro basándose solo en esos cambios:

    • min_y = 10, max_y = 50
    • Centro calculado: cy = (10 + 50) / 2 = 30
    • Centro real del JSON: cy = (0 + 200) / 2 = 100
  4. Resultado: El patrón "centro" prioriza píxeles cerca de y=30 (parte superior) en lugar de y=100 (centro real)

Afectación de patrones:

Los siguientes patrones calculaban incorrectamente el centro/bounding box:

  • center - Desde el centro hacia afuera
  • borders - Desde los bordes hacia el centro
  • spiral / spiralClockwise / spiralCounterClockwise - Espirales desde el centro
  • priority - Prioridad centro vs bordes
  • quadrant - Distribución por cuadrantes
  • anchorPoints - Puntos de anclaje estratégicos

✅ Solución implementada

1. Nuevo parámetro area en funciones de patrones

Archivo: server/pixel_patterns.py

Agregado parámetro opcional area a todas las funciones que calculan centro o bounding box:

def _center(changes: List[Dict[str, Any]], area: Optional[Dict[str, Any]] = None) -> List[Dict[str, Any]]:
    """Ordenar píxeles desde el centro hacia afuera.
    
    Args:
        changes: Lista de cambios a ordenar
        area: Área completa del JSON (opcional) para calcular el centro correcto
    """
    if area and isinstance(area, dict):
        # ✅ Usar el área COMPLETA del JSON para calcular el centro
        start_x = area.get('startX', 0)
        start_y = area.get('startY', 0)
        width = area.get('width', 0)
        height = area.get('height', 0)
        
        if width > 0 and height > 0:
            cx = start_x + width / 2.0
            cy = start_y + height / 2.0
        else:
            # Fallback al bounding box de los cambios si el área no es válida
            min_x, max_x, min_y, max_y = _bbox(changes)
            cx = (min_x + max_x) / 2.0
            cy = (min_y + max_y) / 2.0
    else:
        # Usar bounding box de los cambios si no hay área (retrocompatibilidad)
        min_x, max_x, min_y, max_y = _bbox(changes)
        cx = (min_x + max_x) / 2.0
        cy = (min_y + max_y) / 2.0
    
    return sorted(changes, key=lambda c: math.hypot(int(c['x']) - cx, int(c['y']) - cy))

2. Actualizada firma de select_pixels_by_pattern

def select_pixels_by_pattern(
    pattern: str, 
    changes: List[Dict[str, Any]], 
    count: int, 
    area: Optional[Dict[str, Any]] = None  # ✅ Nuevo parámetro
) -> List[Dict[str, Any]]:
    """Seleccionar píxeles usando un patrón específico.
    
    Args:
        pattern: Nombre del patrón a usar
        changes: Lista de cambios disponibles
        count: Número máximo de píxeles a seleccionar
        area: Área completa del JSON (opcional) con campos startX, startY, width, height
        
    Returns:
        Lista de píxeles ordenados según el patrón
    """

3. Actualizado switch de patrones

Todos los patrones que necesitan área ahora la reciben:

if p == 'center':
    ordered = _center(pool, area)  # ✅ Pasa área
elif p == 'borders':
    ordered = _borders(pool, area)  # ✅ Pasa área
elif p == 'spiral':
    ordered = _spiral_like(pool, None, area)  # ✅ Pasa área
elif p == 'spiralClockwise':
    ordered = _spiral_like(pool, True, area)  # ✅ Pasa área
# ... etc

4. Actualizado orchestrator para pasar área

Archivo: server/session_orchestrator.py

# Extraer área del preview para calcular centros correctos
area = None
try:
    area = preview.get('protectedArea') or preview.get('area')
except Exception:
    pass

try:
    selected = select_pixels_by_pattern(
        str(guard_config.get('protectionPattern', 'random')), 
        changes, 
        pick,
        area  # ✅ Pasa el área completa del JSON
    )
except Exception:
    selected = changes[:pick]

🎯 Resultado

Antes (❌ Incorrecto):

JSON cargado: {startX: 0, startY: 0, width: 200, height: 200}
Cambios detectados: píxeles en y: 10-50 (zona superior)

Patrón "center":
  Centro calculado: (100, 30) ← basado solo en los cambios
  Prioriza píxeles en parte superior

Patrón "random":
  Aplica solo en franja superior donde hay cambios

Después (✅ Correcto):

JSON cargado: {startX: 0, startY: 0, width: 200, height: 200}
Cambios detectados: píxeles en y: 10-50 (zona superior)

Patrón "center":
  Centro calculado: (100, 100) ← basado en área COMPLETA del JSON
  Prioriza píxeles más cercanos al centro real

Patrón "random":
  Aplica en toda el área del JSON, priorizando cambios detectados

📋 Patrones afectados y corregidos

Patrón Problema Corrección
center Centro calculado solo en zona con cambios Usa centro del área completa
borders Bordes calculados solo en zona con cambios Usa bordes del área completa
spiral / spiralClockwise / spiralCounterClockwise Espiral desde centro incorrecto Espiral desde centro del área completa
priority Prioridad centro/bordes incorrecta Usa centro y bordes del área completa
quadrant Cuadrantes calculados solo en zona con cambios Divide área completa en 4 cuadrantes
anchorPoints Puntos de anclaje solo en zona con cambios Ancla en esquinas y centro del área completa
lineUp/Down/Left/Right ✅ No afectados (ordenan por coordenadas) Sin cambios
zigzag ✅ No afectado (ordena por filas) Sin cambios
diagonal ✅ No afectado (ordena por suma x+y) Sin cambios
random ✅ No afectado (shuffle aleatorio) Sin cambios

🧪 Cómo verificar

  1. Carga un JSON Guard con área grande (ej: 200x200)
  2. Asegúrate que solo hay cambios en una zona pequeña (ej: esquina superior)
  3. Selecciona patrón "Centro"
  4. Inicia sesión y observa qué píxeles se reparan primero
  5. Resultado esperado: Se deben priorizar píxeles más cercanos al centro del JSON (100, 100), no al centro de la zona con cambios

📝 Archivos modificados

  • server/pixel_patterns.py:

    • Agregado parámetro area a select_pixels_by_pattern()
    • Actualizado _center(), _borders(), _spiral_like(), _priority(), _quadrant(), _anchor_points()
    • Actualizado switch de patrones para pasar área
  • server/session_orchestrator.py:

    • Extraer área del preview antes de llamar a select_pixels_by_pattern()
    • Pasar área en ambas llamadas (orchestrate_loop y _do_one_guard_round)

🔄 Retrocompatibilidad

El parámetro area es opcional con valor por defecto None. Si no se proporciona:

  • ✅ Funciona como antes (usa bounding box de los cambios)
  • ✅ No rompe código existente
  • ✅ Compatible con llamadas antiguas que no pasen área

Fecha: 1 de octubre de 2025
Reportado por: Usuario (alvaroalonso)
Fix por: GitHub Copilot