Sistema de cronometraje digital para carreras 5K de la Universidad Nacional de Loja
RASC-UNL (Registro Atlético de Salida por Carrera - Universidad Nacional de Loja) es un sistema completo de cronometraje digital diseñado para gestionar competencias atléticas de 5 kilómetros. El sistema reemplaza el cronometraje manual con una solución tecnológica que permite a jueces registrar tiempos desde dispositivos móviles, sincronizarlos con un servidor central y visualizar resultados en tiempo real desde una interfaz web pública.
El sistema fue desarrollado para el evento deportivo institucional "Actívate UNL" organizado por la Universidad Nacional de Loja, en el cual participan equipos de estudiantes e interfacultades.
| Funcionalidad | Descripción |
|---|---|
| Gestión de Competencias | Crear, programar, iniciar y detener competencias 5K desde el panel administrativo |
| Registro de Jueces | Administración de jueces con credenciales seguras (contraseñas hasheadas) |
| Asignación de Equipos | Asignar equipos a jueces y competencias con dorsales únicos |
| Cronometraje Móvil | App Android para que cada juez registre los 15 tiempos de su equipo asignado |
| Sincronización HTTP | Envío atómico de los 15 registros por HTTP POST con idempotencia UUID |
| WebSocket en Tiempo Real | Notificaciones instantáneas de inicio/fin de competencia y actualizaciones de registros |
| Resultados en Vivo | Interfaz web pública con tabla de posiciones actualizada en tiempo real |
| Panel Administrativo | Django Admin personalizado con botones de acción, cronómetro inline y gestión completa |
| Base de Datos Local | SQLite en el móvil para resiliencia offline (offline-first) |
| Categorías | Soporte para categorías: Estudiantes por Equipos e Interfacultades por Equipos |
┌─────────────────────────────────────────────────────────┐
│ ADMINISTRADOR │
│ • Crea competencias, jueces y equipos │
│ • Inicia/detiene competencias desde Django Admin │
│ • Visualiza todos los registros y resultados │
└───────────────────────┬─────────────────────────────────┘
│
┌───────▼───────┐
│ SERVIDOR │
│ (Server-5K) │
└───┬───────┬───┘
│ │
┌───────────▼┐ ┌──▼────────────┐
│ JUECES (N) │ │ PÚBLICO │
│ App Móvil │ │ Interfaz Web │
│ (Movil-5K) │ │ (Resultados) │
└────────────┘ └───────────────┘
- Administrador: Gestiona todo desde Django Admin (competencias, jueces, equipos, resultados)
- Jueces: Usan la app móvil para cronometrar los 15 participantes de sus equipos asignados
- Público: Visualiza resultados en tiempo real desde cualquier navegador web
┌──────────────────┐ HTTP POST (Registros) ┌──────────────────────┐
│ │ ──────────────────────────────▶│ │
│ APP MÓVIL │ HTTP GET (Login, Equipos) │ SERVIDOR │
│ (Flutter) │ ──────────────────────────────▶│ (Django + DRF) │
│ │ │ │
│ • Cronómetro │◀────── WebSocket ─────────────▶│ • API REST │
│ • SQLite local │ (Notificaciones RT) │ • WebSocket │
│ • Offline-first│ │ • Django Admin │
└──────────────────┘ │ • Interfaz Web │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ INFRAESTRUCTURA │
│ • PostgreSQL 16 │
│ • Redis 7 │
│ • Daphne (ASGI) │
│ • Docker Compose │
└──────────────────────┘
| Componente | Tecnología | Versión |
|---|---|---|
| App Móvil | Flutter / Dart | SDK ^3.8.1 |
| Backend | Django + Django REST Framework | 6.0 / 3.16.1 |
| Servidor ASGI | Daphne (Twisted) | 4.2.1 |
| WebSocket | Django Channels + Channels Redis | 4.3.2 / 4.3.0 |
| Base de Datos | PostgreSQL (prod) / SQLite (dev) | 16 |
| Cache/Pub-Sub | Redis | 7 |
| Autenticación | JWT (SimpleJWT) | 5.5.1 |
| Documentación API | drf-spectacular (Swagger/ReDoc) | 0.29.0 |
| Contenedores | Docker + Docker Compose | - |
| Archivos Estáticos | WhiteNoise | 6.11.0 |
- Crear una Competencia con nombre y fecha/hora
- Crear los Jueces con credenciales de acceso
- Crear los Equipos con dorsal, nombre y categoría
- Asignar cada equipo a un juez y a la competencia
- Los jueces inician sesión en la app móvil con sus credenciales
- La app se conecta por WebSocket y queda en espera
- El administrador inicia la competencia desde Django Admin
- Los jueces reciben notificación de inicio vía WebSocket
- El cronómetro se activa automáticamente en la app de cada juez
- Cada juez registra los tiempos de los 15 participantes de su equipo
- Los registros se guardan primero en SQLite local (resiliencia)
- Al completar los 15 registros, se envían por HTTP POST al servidor
- El servidor valida, guarda atómicamente y notifica por WebSocket
- La interfaz web pública se actualiza en tiempo real vía WebSocket
- Se muestra tabla de posiciones con tiempo total por equipo
- Equipos con participantes ausentes (tiempo = 0) se marcan como descalificados
- Filtros por categoría disponibles
RASC-UNL/
├── Movil-5K/ # Aplicación móvil Flutter (Android)
│ ├── lib/ # Código fuente Dart
│ ├── android/ # Configuración nativa Android
│ ├── assets/ # Recursos (imágenes, datos)
│ ├── pubspec.yaml # Dependencias Flutter
│ └── README.md # Documentación de la app móvil
│
├── Server-5K/ # Servidor backend Django
│ ├── app/ # Aplicación Django principal
│ ├── server/ # Configuración del proyecto Django
│ ├── templates/ # Templates HTML
│ ├── static/ # Archivos estáticos
│ ├── Dockerfile # Imagen Docker
│ ├── docker-compose.yml
│ └── README.md # Documentación del servidor
│
└── README.md # Este archivo (documentación general)
- Autenticación JWT: Tokens de acceso (60 min) y refresh (7 días) con claims personalizados (
juez_id) - Modelo Juez independiente: Los jueces NO son usuarios de Django; tienen su propio modelo con contraseñas hasheadas
- Validación WebSocket: Token JWT en query string, verificación de identidad y pertenencia a competencia activa
- Idempotencia: Registros con UUID como clave primaria +
bulk_create(ignore_conflicts=True)para evitar duplicados - Transacciones atómicas:
SELECT ... FOR UPDATE+transaction.atomic()para integridad de datos - CORS configurado: Orígenes permitidos por variable de entorno
- HTTPS opcional: Configuración HSTS, cookies seguras y SSL redirect habilitables
El sistema se despliega con Docker Compose con tres servicios:
| Servicio | Contenedor | Puerto |
|---|---|---|
| PostgreSQL 16 | server5k-postgres |
5432 |
| Redis 7 | server5k-redis |
6379 |
| Django + Daphne | server5k-web |
8000 |
# 1. Configurar variables de entorno
cp .env.example .env
# Editar .env con valores reales
# 2. Levantar servicios
docker compose up -d
# 3. Crear superusuario (primera vez)
docker compose exec web python manage.py createsuperuser- 📱 README de la App Móvil (Movil-5K) — Arquitectura, pantallas, servicios y flujo de la aplicación Flutter
- 🖥️ README del Servidor (Server-5K) — API REST, WebSocket, modelos, servicios y despliegue del backend Django
- Institución: Universidad Nacional de Loja (UNL)
- Evento: Actívate UNL — Carrera 5K
- Modalidad: Competencia por equipos (15 integrantes por equipo)
- Categorías: Estudiantes por Equipos / Interfacultades por Equipos
- Zona horaria: America/Guayaquil (UTC-5)
- Idioma: Español (Ecuador)
Proyecto desarrollado para uso interno de la Universidad Nacional de Loja.