Skip to content

Commit 7aaf2a0

Browse files
apiadclaude
andcommitted
docs(reviews): add Proyecto I code reviews (batch 5: #258,#259,#261,#267,#268)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent f7f74d3 commit 7aaf2a0

5 files changed

Lines changed: 691 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Revisión detallada — Issue #258
2+
3+
- **Estudiante:** Liber Chaos González
4+
- **Grupo:** C-111
5+
- **Repositorio:** https://github.com/Liibbeerr/Universidad
6+
- **Descripción del issue:** organizador de eventos de un local de videojuegos: reservar para jugar en consolas, computadoras y juegos de mesa.
7+
- **Clon local:** `.playground/proyecto1-eval/repos/258-universidad`
8+
9+
## Nota metodológica importante
10+
11+
El proyecto **no es una aplicación de consola** (`main.py` + menú `input()`), sino una **aplicación web con Streamlit**. La rúbrica asume consola, pero aquí el punto de entrada es `Main.py` y se ejecuta con `streamlit run Main.py`. Adapté la ejecución dinámica en consecuencia: arranqué el servidor Streamlit headless y, además, recorrí todas las páginas y ramas del formulario con el arnés oficial `streamlit.testing.v1.AppTest`, que ejecuta el script real y captura excepciones. Esto es el equivalente fiel a "recorrer el menú" para una app Streamlit.
12+
13+
## Ejecución dinámica realizada
14+
15+
Entorno aislado con `uv venv` (Python 3.11) + `uv pip install streamlit pandas` (streamlit 1.59.0, pandas 3.0.3). El `venv/` versionado en el repo es de Windows (`pyvenv.cfg` apunta a `C:\Users\Liber\...`) y no sirve en Linux; no hay `requirements.txt`.
16+
17+
Pasos y observaciones:
18+
19+
1. **Compilación** de los 7 módulos con `py_compile`: los 7 compilan sin errores de sintaxis.
20+
2. **Arranque headless** `streamlit run Main.py --server.headless true`: el servidor levanta limpio, `GET /` → HTTP 200, `/_stcore/health` → HTTP 200. Sin Traceback en el log.
21+
3. **Recorrido de páginas vía `AppTest`** (`Main.py:15` menú lateral):
22+
- **Inicio** (`Inicio.py:3`): renderiza sin excepciones.
23+
- **Calendario** (`Calendario.py:6`): renderiza la tabla desde `Fecha.json` con `pd.read_json` y muestra el formulario de eliminación. Sin excepciones.
24+
- **Reservar** (`Reservas.py:10`): renderiza el formulario. Probé las **tres ramas** del selector "¿Qué desea Jugar?":
25+
- Juegos de mesa 🎲 → `Juegos_mesa()` — OK, sin excepción.
26+
- Consolas 🎮 → `Consolas()` — OK, sin excepción.
27+
- Computadoras 💻 → `Computadora()` — OK, sin excepción.
28+
4. **Submisión válida end-to-end** (mesa, nombre `prueba_valida`, contraseña `abcd`, 2 personas, 10:00–12:00, juego "Uno" en "Mesa para 4"): salieron los mensajes `Hora valida...`, `Reserva válida: Uno en Mesa para 4 con Ninguno` y `Reserva guardadada correctamente`; y **la reserva se persistió correctamente** en `Fecha.json` (pasó de 1 a 2 registros). Restauré el archivo tras la prueba.
29+
5. **Submisión rechazada** (mismo formulario con el default D&D + 2 personas): el sistema mostró `Para jugar D&D tiene que haber un mínimo de 3 personas` y **no** guardó nada. La compuerta de validación funciona.
30+
6. **Casos límite de `Ver_hora`** (`Validaciones.py:30`) probados directamente: `10:00–14:00`→válido; `10:00–10:30`→rechaza (<1h); `09:00–11:00`→rechaza (antes de apertura); `15:00–19:00`→rechaza (después de cierre); `14:00–12:00`→rechaza (inicio>fin); `10:00–10:00`→rechaza (iguales). **Bug encontrado:** con una cadena de hora sin cero a la izquierda (`"9:00:00"`) lanza `ValueError: invalid literal for int() with base 10: '9:'`. En el flujo normal de la UI no ocurre (el `time_input` de Streamlit siempre entrega `HH:MM:SS` con cero delante), pero el parseo por posiciones fijas es frágil.
31+
32+
**Veredicto de ejecución: la aplicación funciona.** Arranca, las tres páginas renderizan sin fallos, las tres ramas de reserva operan, la validación rechaza casos inválidos y una reserva válida se guarda de verdad en el JSON. El único error real observado es el de `Ver_hora` con horas de un dígito, inalcanzable desde la UI.
33+
34+
## Dimensión 1 — Qué hace el programa
35+
36+
Aplicación web (Streamlit) para gestionar reservas de un salón de juegos con tres áreas: juegos de mesa, consolas y computadoras. Punto de entrada `Main.py:27` (`main()`), que arma un menú lateral con tres páginas (`Main.py:17`): **Inicio** (bienvenida y horario, `Inicio.py`), **Reservar** (formulario de reserva, `Reservas.py`) y **Calendario** (tabla de reservas + eliminación, `Calendario.py`).
37+
38+
El flujo principal (`Reservas.py:24-66`): el usuario elige tipo de actividad, rellena nombre, contraseña, fecha, hora inicio/fin y número de personas, selecciona los recursos concretos según la rama (`Juegos.py`) y pulsa "Reservar". Se validan nombre/contraseña (`Validar_nombre`), horas (`Ver_hora`) y reglas específicas del recurso (`Recursos_jm`/`Recursos_con`/`Recursos_pc`); si todo pasa, la reserva se serializa a `Fecha.json`. El calendario lee ese mismo JSON y permite borrar una reserva autenticando con contraseña del usuario + contraseña maestra del local (`"1234"`, `Eliminar_evento.py:18`).
39+
40+
## Dimensión 2 — Organización del código
41+
42+
Buena para primer año. El código está **repartido en 7 módulos** con responsabilidades claras, no en un `Main.py` monolítico:
43+
44+
- `Main.py` — enrutado del menú.
45+
- `Inicio.py` — página de bienvenida.
46+
- `Reservas.py` — orquestación del formulario y guardado.
47+
- `Juegos.py` — funciones que devuelven un dict de recursos por rama (`Juegos_mesa`, `Consolas`, `Computadora`).
48+
- `Validaciones.py` — validaciones centralizadas (`Validar_nombre`, `Ver_hora`, `Recursos_jm`, `Recursos_con`, `Recursos_pc`).
49+
- `Calendario.py` — tabla + delega en `Eliminar`.
50+
- `Eliminar_evento.py` — borrado autenticado.
51+
52+
El patrón "cada función de `Juegos.py` devuelve un dict que `Reservas.py` compone" (`Juegos.py:11`, `Reservas.py:43`) es un buen instinto de diseño. Nombres de funciones descriptivos. Puntos mejorables: alias de import poco legibles (`re_jm`, `re_con`, `re_pc`, `vh`, `vn` en `Reservas.py:6`); el bloque de apertura de `Fecha.json` con `try/except` se repite en 5 sitios (`Main.py:9`, `Reservas.py:11`, `Eliminar_evento.py:5`, `Validaciones.py:5,61,136,206`) y podría ser una sola función auxiliar; y `data` en `Main.py:9-13` se carga pero no se usa (es código muerto, la carga real está dentro de `Reservas()`).
53+
54+
## Dimensión 3 — Corrección funcional (ejecución real)
55+
56+
Ver "Ejecución dinámica". Resumen: **arranca y funciona**. Las tres páginas renderizan sin excepción; las tres ramas de reserva operan; validación de horario, capacidad, exclusividad de juegos por consola (`Validaciones.py:167-180`) y compatibilidad juego↔gama de PC (`Validaciones.py:247-262`) están implementadas y se disparan; una reserva válida persiste y una inválida se bloquea. Coincide con lo que promete el issue.
57+
58+
Defectos concretos:
59+
- **Bug real (borde):** `Ver_hora` (`Validaciones.py:31-37`) parsea la hora por posiciones fijas (`h1[:2]`, `h1[3:5]`, `h1[6:]`); con una cadena no cero-rellenada (`"9:00:00"`) lanza `ValueError`. Inalcanzable desde la UI, pero frágil. Solución: `datetime.time.fromisoformat(h1)` o `map(int, h1.split(":"))`.
60+
- **Chequeo de solapamiento parcial:** `Recursos_jm/con/pc` sólo detectan conflicto cuando la reserva existente **cubre completamente** el horario nuevo (`hora_j1 <= hora_h1 and hora_j2 >= hora_h2`, `Validaciones.py:84,161,230`). Dos reservas que se solapan parcialmente (p.ej. 10–12 y 11–13) **no** se detectan como conflicto. El propio informe reconoce esta simplificación; para 1er año es aceptable, pero conviene señalarla.
61+
- **Falta advertencia bloqueante:** en `Recursos_jm:102-103`, cuando hay <2 personas para un juego que no es D&D se muestra un `warning` pero **no** se hace `return False`, así que no bloquea la reserva. Inconsistente con el resto.
62+
- El informe menciona `st.experimental_rerun()` tras eliminar, pero **no aparece en el código** (`Eliminar_evento.py` no re-ejecuta); la tabla se refresca sólo al recargar.
63+
64+
## Dimensión 4 — Buenas prácticas de Python (nivel principiante)
65+
66+
Sólidas para el nivel. Indentación consistente; uso idiomático de `f-strings` (`Validaciones.py:57,103`); `try/except (FileNotFoundError, JSONDecodeError)` para lectura robusta del JSON; escritura con `indent=4` y `ensure_ascii=False` en el borrado (`Eliminar_evento.py:39`). Puntos a pulir:
67+
- Duplicación evidente del bloque de carga de `Fecha.json` (5+ veces) — extraer a una función.
68+
- Aliases crípticos en imports (`Reservas.py:6`).
69+
- En `Eliminar_evento.py:40-42` se llama `st.success("Reserva eliminada correctamente")` **dos veces seguidas** (línea duplicada).
70+
- Modificar la lista `data` mientras se itera sobre ella con `data.remove(i)` dentro del `for i in data` (`Eliminar_evento.py:33-37`) es un antipatrón; aquí no rompe porque hace `return` inmediatamente tras remover, pero es un hábito a corregir.
71+
- Al guardar en `Reservas.py:64` no usa `ensure_ascii=False`, por eso `Fecha.json` guarda `ñ` escapado (mientras el borrado sí lo desescapa): inconsistencia menor de codificación.
72+
73+
## Dimensión 5 — Datos y persistencia
74+
75+
Razonable. Estado en una **lista de diccionarios** serializada a `Fecha.json` (`Reservas.py:64`), estructura adecuada para el dominio. Persiste correctamente: verifiqué en ejecución que una reserva nueva se añade y una eliminada desaparece del archivo. También usa `st.session_state` para conservar reservas entre recargas (`Reservas.py:17`). Detalle: la clave es la hora truncada a la hora entera (`int(h1[:2])`) para los chequeos de conflicto, perdiendo minutos; funciona para el modelo simple pero limita la precisión.
76+
77+
## Dimensión 6 — Informe (`report.md`)
78+
79+
El repo trae el informe en un archivo llamado `README` (sin extensión), no `report.md`. Es **extenso, bien redactado y en general fiel** al código: describe correctamente las tres áreas, las validaciones, el doble password de borrado y la persistencia en JSON. Discrepancias detectadas:
80+
- **Nombre del entry point:** el informe dice ejecutar `streamlit run app.py`, pero el archivo se llama `Main.py`. Un profesor que siga el informe al pie no arrancaría la app.
81+
- **`st.experimental_rerun()`** se describe como implementado tras eliminar, pero no está en el código.
82+
- El informe presenta el chequeo de solapamiento como resuelto con lógica de intervalos `[inicio, fin]`, pero el código real sólo cubre el caso de contención total (más simple de lo narrado). Es una leve **sobreestimación**, aunque el propio texto luego admite la simplificación.
83+
84+
En conjunto el informe describe de verdad lo que hace el programa, explica diseño/uso/dificultades con honestidad y sólo sobreestima en detalles menores.
85+
86+
## Síntesis
87+
88+
Trabajo **notable para un primer proyecto de 1er año**. El estudiante fue más allá de la consola pedida y entregó una app web funcional, modular y con una capa de validación de reglas de negocio genuinamente rica (exclusivos por consola, gamas de PC, capacidades de mesa, D&D). Ejecutada de verdad, arranca y hace lo que promete. Las debilidades son de robustez y consistencia (parseo frágil de horas, solapamiento parcial no detectado, duplicaciones), todas normales al nivel y con arreglos claros. Principal fortaleza: alcance y organización. Principal mejora: robustez del parseo/validación y limpiar duplicaciones.

0 commit comments

Comments
 (0)