Skip to content

Revisión automática de la práctica 04-formas

Este es el resultado de una revisión automática de la prácica 04-formas, tal y como la hemos recogido de este repositorio de entrega. Por favor, ten en cuenta que al ser una revisión automática, realizada en parte con la ayuda de un asistente de inteligencia artificial generativa, puede incluir errores, y ser incorrecta. Pero leela con atención, porque creemos que puede tener información útil. Si tienes cualquier duda, o crees que la revisión es errónea, por favor, consulta con los profesores de la asignatura.


Comprobación de archivos con extension '.py'

  • Archivos Python excluidos de la búsqueda: pixels.py
  • Archivos Python encontrados (excluyendo esos): formas.py

Correcto, se elige formas.py como entrega.

Comprobación con ficheros de solución

Los archivos son diferentes de los de la solución.

Prueba automática del programa

Pruebas realizadas por 04-formas/tests/test_argumentos.py:

***ERROR:***
 Error ejecutando los tests: Command '['python3', '-m', 'unittest', 'test_argumentos.py']' timed out after 30 seconds

Pruebas realizadas por 04-formas/tests/test_formas.py:

***ERROR:***
 Error ejecutando los tests: Command '['python3', '-m', 'unittest', 'test_formas.py']' timed out after 30 seconds

Pruebas realizadas por 04-formas/tests/test_funciones.py:

***ERROR:***
 Error ejecutando los tests: Command '['python3', '-m', 'unittest', 'test_funciones.py']' timed out after 30 seconds

Revisión automática de programa

Programa revisado:

import sys

import pixels
from pixels import tam_lienzo, pinta, espera


def lee_formas():
    """Lee los argumentos de línea de comandos y construye una lista de
    diccionarios que representan las formas."""
    COLORES_VALIDOS = {'red', 'green', 'blue', 'yellow', 'orange', 'purple', 'black', 'white'}

    argumentos = sys.argv[1:]
    formas = []

    while len(argumentos) > 0:
        forma = argumentos[0]

        try:
            if forma == "cuad":
                if len(argumentos) < 4:
                    print(f"Error cuad: El numero de argumentos es incorrecto. Por favor, introduce (x,y,lado)")
                    break

                coord_cuadx = int(argumentos[1])
                coord_cuady = int(argumentos[2])
                lado_c = int(argumentos[3])

                color_cuad = "black"
                args_a_consumir = 4

                if len(argumentos) > 4:
                    if argumentos[4] in COLORES_VALIDOS:
                        color_cuad = argumentos[4]
                        args_a_consumir = 5

                print(f"Forma detectada: Cuadrado en {coord_cuadx} x {coord_cuady}, lado {lado_c}, color {color_cuad}")
                formas.append({'tipo': 'cuad', 'x': coord_cuadx, 'y': coord_cuady, 'lado': lado_c, 'color': color_cuad})

                argumentos = argumentos[args_a_consumir:]

            elif forma == "rect":
                if len(argumentos) < 5:
                    print("Error rect: El numero de argumentos es incorrecto. Por favor, introduce (x,y,ancho,alto)")
                    break

                coord_rectx = int(argumentos[1])
                coord_recty = int(argumentos[2])
                ancho_r = int(argumentos[3])
                alto_r = int(argumentos[4])

                color_rect = "black"
                args_a_consumir = 5

                if len(argumentos) > 5:
                    if argumentos[5] in COLORES_VALIDOS:
                        color_rect = argumentos[5]
                        args_a_consumir = 6

                print(
                    f"Forma detectada: Rectangulo en {coord_rectx} x {coord_recty}, {ancho_r}x{alto_r}, color {color_rect}")
                formas.append({'tipo': 'rect', 'x': coord_rectx, 'y': coord_recty, 'ancho': ancho_r, 'alto': alto_r,
                               'color': color_rect})

                argumentos = argumentos[args_a_consumir:]

            else:
                print(f"Forma: {forma} desconocida. Solo puedo dibujar usando cuad y rect")
                break

        except ValueError:
            print(f"Error: Las coordenadas y dimensiones para '{forma}' tienen que ser un numero entero.")
            break
        except IndexError:
            print("Error: Faltan argumentos.")
            break



    ...

    return formas


def dibuja_cuadrado(x_ini, y_ini, lado, color="black"):
    for dx in range(lado):
        # Bucle 'dy' (delta y) de 0 a 'lado'
        for dy in range(lado):
            # Coordenada final del píxel
            px = x_ini + dx
            py = y_ini + dy

            # Comprobar si el píxel (px, py) está dentro de los límites del lienzo
            if 0 <= px < pixels.ancho and 0 <= py < pixels.alto:
                pinta(px, py, color)



    """Dibuja un cuadrado en el lienzo."""
    ...


def dibuja_rectangulo(x_ini, y_ini, ancho, alto, color="black"):
    for dx in range(ancho):
        # Bucle 'dy' (delta y) de 0 a 'alto'
        for dy in range(alto):
            # Coordenada final del píxel
            px = x_ini + dx
            py = y_ini + dy

            # Comprobar si el píxel (px, py) está dentro de los límites del lienzo
            if 0 <= px < pixels.ancho and 0 <= py < pixels.alto:
                pinta(px, py, color)
    """Dibuja un rectángulo en el lienzo."""
    ...


def main():
    """Programa principal"""


tam_lienzo()
formas = lee_formas()

for forma in formas:
    tipo = forma["tipo"]
    x = forma["x"]
    y = forma["y"]
    color = forma.get("color", "black")  # .get() es una buena forma de obtener el color o "black"

    # --- CORRECCIÓN ---
    # Debe coincidir con lo que guarda lee_formas ('cuad', no 'cuadrado')
    if tipo == "cuad":
        lado = forma["lado"]
        dibuja_cuadrado(x, y, lado, color)

    # --- CORRECCIÓN ---
    # Debe coincidir con lo que guarda lee_formas ('rect', no 'rectángulo')
    elif tipo == "rect":
        ancho_forma = forma["ancho"]
        alto_forma = forma["alto"]
        dibuja_rectangulo(x, y, ancho_forma, alto_forma, color)

# Llama a espera() al final para mantener la ventana abierta
espera()

if __name__ == "__main__":
    main()

Análisis

Cumple con el enunciado

El programa no cumple completamente con el enunciado.

  • Las funciones dibuja_cuadrado() y dibuja_rectangulo() no devuelven True o False como exige el enunciado, a pesar de que su documentación lo menciona. Actualmente no tienen sentencias return, por lo que devuelven None implícitamente.
  • En lee_formas(), al detectar un error (ej.: argumentos insuficientes o valores no enteros), detiene el procesamiento con break, ignorando las formas válidas que puedan venir después. El enunciado requiere devolver solo las formas válidas, no abortar ante el primer error.
  • Aunque el dibujo de píxeles se realiza correctamente dentro de los límites del lienzo, no se verifica si la figura completa cabe en el lienzo antes de dibujar (como exige el enunciado para devolver False si "se sale del lienzo"). Actualmente pinta solo los píxeles que entran, pero no rechaza la figura completa si parte de ella está fuera.

Es fácil de leer y entender

El código es mayormente comprensible para un principiante:

  • Los nombres de variables son descriptivos (ej.: coord_cuadx, lado_c).
  • Los comentarios explican el propósito de los bucles y condiciones.
  • La estructura de lee_formas() sigue un flujo lógico al procesar cada forma.
    Sin embargo, la falta de manejo de errores robusto (como continuar tras un error) y la ausencia de return en las funciones de dibujo pueden generar confusión sobre el comportamiento esperado.

Sigue buenas prácticas de programación

Presenta algunas buenas prácticas, pero con fallos críticos:

  • Uso de constantes para colores válidos (COLORES_VALIDOS), evitando "números mágicos".
  • Validación de tipos (con try/except para ValueError).
  • No maneja errores de forma resiliente: al encontrar un argumento inválido, detiene todo el procesamiento en lugar de omitir solo esa forma.
  • Falta coherencia con el enunciado: las funciones de dibujo no implementan el retorno de True/False ni la verificación de límites completa requerida.
  • Los bucles de dibujo verifican píxeles individuales, pero no evalúan si la figura completa cabe en el lienzo, lo que contradice el requisito de devolver False si "se sale".

Recomendaciones de mejora

  1. En lee_formas():

    • Reemplaza break por continue al detectar errores, para omitir solo la forma inválida y seguir procesando las siguientes. Por ejemplo:
      if len(argumentos) < 4:
          print("Error cuad: Faltan argumentos. Se omite esta figura.")
          argumentos = argumentos[1:]  # Avanza al siguiente argumento
          continue
  2. En dibuja_cuadrado() y dibuja_rectangulo():

    • Verifica primero si la figura cabe completa en el lienzo:
      if x_ini + lado > pixels.ancho or y_ini + lado > pixels.alto:
          return False  # Fuera de límites
    • Devuelve True tras dibujar (solo si toda la figura cabe):
      for dx in range(lado):
          for dy in range(lado):
              pinta(x_ini + dx, y_ini + dy, color)
      return True
  3. Simplifica la validación de colores:

    • El enunciado no exige restringir colores a una lista específica. Si pixels.py maneja colores inválidos, elimina COLORES_VALIDOS y usa el color directamente (con valor por defecto "black").
  4. Evita código redundante:

    • En lee_formas(), elimina los print de depuración como "Forma detectada:..." si no son requeridos por el enunciado.