Implementados 3 módulos con agent swarm: 1. SISTEMA DE TORNEOS - Tipos: Eliminación, Round Robin, Suizo, Consolación - Categorías: Masculina, Femenina, Mixta - Inscripciones con validación de niveles - Gestión de pagos y estados 2. CUADROS Y PARTIDOS - Generación automática de cuadros - Algoritmos: Circle method (Round Robin), Swiss pairing - Avance automático de ganadores - Asignación de canchas y horarios - Registro y confirmación de resultados 3. LIGAS POR EQUIPOS - Creación de equipos con capitán - Calendario round-robin automático - Tabla de clasificación con desempates - Estadísticas por equipo Modelos DB: - Tournament, TournamentParticipant, TournamentMatch - League, LeagueTeam, LeagueTeamMember, LeagueMatch, LeagueStanding Nuevos endpoints: - /tournaments/* - Gestión de torneos - /tournaments/:id/draw/* - Cuadros - /tournaments/:id/matches/* - Partidos de torneo - /leagues/* - Ligas - /league-teams/* - Equipos - /league-schedule/* - Calendario - /league-standings/* - Clasificación - /league-matches/* - Partidos de liga Datos de prueba: - Torneo de Verano 2024 (Eliminatoria) - Liga de Invierno (Round Robin) - Liga de Club 2024
147 lines
4.0 KiB
TypeScript
147 lines
4.0 KiB
TypeScript
import { Router } from 'express';
|
|
import { TournamentMatchController } from '../controllers/tournamentMatch.controller';
|
|
import { authenticate, authorize } from '../middleware/auth';
|
|
import { validate, validateQuery } from '../middleware/validate';
|
|
import { UserRole, TournamentMatchStatus } from '../utils/constants';
|
|
import { z } from 'zod';
|
|
|
|
const router = Router({ mergeParams: true });
|
|
|
|
// Schema para query params de filtros
|
|
const matchFiltersSchema = z.object({
|
|
round: z.string().regex(/^\d+$/).optional().transform(Number),
|
|
status: z.enum([
|
|
TournamentMatchStatus.PENDING,
|
|
TournamentMatchStatus.SCHEDULED,
|
|
TournamentMatchStatus.IN_PROGRESS,
|
|
TournamentMatchStatus.FINISHED,
|
|
TournamentMatchStatus.CANCELLED,
|
|
TournamentMatchStatus.BYE,
|
|
]).optional(),
|
|
courtId: z.string().uuid().optional(),
|
|
playerId: z.string().uuid().optional(),
|
|
fromDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
|
|
toDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
|
|
});
|
|
|
|
// Schema para actualizar partido
|
|
const updateMatchSchema = z.object({
|
|
courtId: z.string().uuid().optional(),
|
|
scheduledDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
|
|
scheduledTime: z.string().regex(/^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/).optional(),
|
|
status: z.enum([
|
|
TournamentMatchStatus.PENDING,
|
|
TournamentMatchStatus.SCHEDULED,
|
|
TournamentMatchStatus.IN_PROGRESS,
|
|
TournamentMatchStatus.CANCELLED,
|
|
]).optional(),
|
|
notes: z.string().optional(),
|
|
});
|
|
|
|
// Schema para asignar cancha
|
|
const assignCourtSchema = z.object({
|
|
courtId: z.string().uuid('ID de cancha inválido'),
|
|
date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Fecha debe ser YYYY-MM-DD'),
|
|
time: z.string().regex(/^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/, 'Hora debe ser HH:MM'),
|
|
});
|
|
|
|
// Schema para registrar resultado
|
|
const recordResultSchema = z.object({
|
|
team1Score: z.number().int().min(0, 'El puntaje no puede ser negativo'),
|
|
team2Score: z.number().int().min(0, 'El puntaje no puede ser negativo'),
|
|
});
|
|
|
|
// Schema para cancelar partido
|
|
const cancelMatchSchema = z.object({
|
|
reason: z.string().optional(),
|
|
});
|
|
|
|
// Schema para params de IDs
|
|
const matchIdSchema = z.object({
|
|
matchId: z.string().uuid('ID de partido inválido'),
|
|
});
|
|
|
|
// Listar partidos del torneo
|
|
router.get(
|
|
'/matches',
|
|
authenticate,
|
|
validateQuery(matchFiltersSchema),
|
|
TournamentMatchController.getMatches
|
|
);
|
|
|
|
// Obtener mis partidos en el torneo
|
|
router.get(
|
|
'/my-matches',
|
|
authenticate,
|
|
TournamentMatchController.getMyMatches
|
|
);
|
|
|
|
// Obtener partidos de un participante específico
|
|
router.get(
|
|
'/participants/:participantId/matches',
|
|
authenticate,
|
|
TournamentMatchController.getParticipantMatches
|
|
);
|
|
|
|
// Obtener un partido específico
|
|
router.get(
|
|
'/matches/:matchId',
|
|
authenticate,
|
|
validate(z.object({ matchId: z.string().uuid() })),
|
|
TournamentMatchController.getMatch
|
|
);
|
|
|
|
// Actualizar partido (solo admins)
|
|
router.put(
|
|
'/matches/:matchId',
|
|
authenticate,
|
|
authorize(UserRole.ADMIN, UserRole.SUPERADMIN),
|
|
validate(updateMatchSchema),
|
|
TournamentMatchController.updateMatch
|
|
);
|
|
|
|
// Asignar cancha (solo admins)
|
|
router.put(
|
|
'/matches/:matchId/assign-court',
|
|
authenticate,
|
|
authorize(UserRole.ADMIN, UserRole.SUPERADMIN),
|
|
validate(assignCourtSchema),
|
|
TournamentMatchController.assignCourt
|
|
);
|
|
|
|
// Iniciar partido (solo admins)
|
|
router.put(
|
|
'/matches/:matchId/start',
|
|
authenticate,
|
|
authorize(UserRole.ADMIN, UserRole.SUPERADMIN),
|
|
validate(matchIdSchema),
|
|
TournamentMatchController.startMatch
|
|
);
|
|
|
|
// Cancelar partido (solo admins)
|
|
router.put(
|
|
'/matches/:matchId/cancel',
|
|
authenticate,
|
|
authorize(UserRole.ADMIN, UserRole.SUPERADMIN),
|
|
validate(cancelMatchSchema),
|
|
TournamentMatchController.cancelMatch
|
|
);
|
|
|
|
// Registrar resultado (jugadores o admins)
|
|
router.put(
|
|
'/matches/:matchId/result',
|
|
authenticate,
|
|
validate(recordResultSchema),
|
|
TournamentMatchController.recordResult
|
|
);
|
|
|
|
// Confirmar resultado (jugadores)
|
|
router.put(
|
|
'/matches/:matchId/confirm',
|
|
authenticate,
|
|
validate(matchIdSchema),
|
|
TournamentMatchController.confirmResult
|
|
);
|
|
|
|
export default router;
|