diff --git a/PartidaModelo.php b/PartidaModelo.php new file mode 100644 index 0000000..0221972 --- /dev/null +++ b/PartidaModelo.php @@ -0,0 +1,37 @@ +conexion = $conexion; + } + + // Obtiene los jugadores mapeados en la partida actual + public function obtenerJugadoresPartida($idPartida) { + $stmt = $this->conexion->prepare(" + SELECT u.idUsuario, u.nombreUsuario, e.idEquipo, e.nombreEquipo + FROM equipoxpartida exp + INNER JOIN equipoxusuario exu ON exp.idEquipo = exu.idEquipo + INNER JOIN usuario u ON exu.idUsuario = u.idUsuario + INNER JOIN equipo e ON exu.idEquipo = e.idEquipo + WHERE exp.idPartida = :idPartida + "); + $stmt->execute([':idPartida' => $idPartida]); + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + // Obtiene las respuestas guardadas por un usuario específico + public function obtenerRespuestasUsuario($idPartida, $idUsuario) { + $stmtRespuestas = $this->conexion->prepare(" + SELECT ra.idPartidaxPregunta, r.correcta + FROM respuestaalmacenada ra + INNER JOIN respuesta r ON ra.idRespuesta = r.idRespuesta + INNER JOIN partidaxpregunta pxp ON ra.idPartidaxPregunta = pxp.idPartidaxPregunta + WHERE pxp.idPartida = :idPartida AND ra.idUsuario = :idUsuario + "); + $stmtRespuestas->execute([':idPartida' => $idPartida, ':idUsuario' => $idUsuario]); + return $stmtRespuestas->fetchAll(PDO::FETCH_ASSOC); + } +} diff --git a/controladores/controladorResultados.php b/controladores/controladorResultados.php index ec6071b..15cc24d 100644 --- a/controladores/controladorResultados.php +++ b/controladores/controladorResultados.php @@ -1,7 +1,7 @@ prepare(" SELECT COUNT(exu.idUsuario) AS total_jugadores FROM equipoxpartida exp @@ -38,7 +37,6 @@ switch ($orden) { $preguntasTotalesEsperadas = $totalJugadores * 10; - // 2. Contar cuántas respuestas reales se han guardado $stmtRespuestas = $conexion->prepare(" SELECT COUNT(*) FROM respuestaalmacenada ra @@ -50,12 +48,9 @@ switch ($orden) { $terminada = ($respuestasRespondidas >= $preguntasTotalesEsperadas && $preguntasTotalesEsperadas > 0); - // 3. Si ha terminado, guardamos los datos históricos una sola vez - if ($terminada && !isset($_SESSION['partidas_procesadas'][$idPartida])) { - + if ($terminada && !isset($_SESSION['partidas_processed'][$idPartida])) { $conexion->beginTransaction(); - // --- CÁLCULO DE VELOCIDAD --- if (!isset($_SESSION['primeros_en_acertar'][$idPartida])) { $_SESSION['primeros_en_acertar'][$idPartida] = []; } @@ -74,13 +69,11 @@ switch ($orden) { foreach ($todosLosAciertos as $acierto) { $idPxp = $acierto['idPartidaxPregunta']; $idU = $acierto['idUsuario']; - if (!isset($_SESSION['primeros_en_acertar'][$idPartida][$idPxp])) { $_SESSION['primeros_en_acertar'][$idPartida][$idPxp] = $idU; } } - // Consulta de aciertos $stmtAciertos = $conexion->prepare(" SELECT ra.idUsuario, exu.idEquipo, COUNT(*) as aciertos_partida FROM respuestaalmacenada ra @@ -93,11 +86,7 @@ switch ($orden) { $stmtAciertos->execute([':idPartida' => $idPartida]); $jugadoresPartida = $stmtAciertos->fetchAll(PDO::FETCH_ASSOC); - $updateAciertos = $conexion->prepare(" - UPDATE usuario - SET aciertos = aciertos + :nuevos_aciertos - WHERE idUsuario = :idUsuario - "); + $updateAciertos = $conexion->prepare("UPDATE usuario SET aciertos = aciertos + :nuevos_aciertos WHERE idUsuario = :idUsuario"); $puntosEquipos = []; foreach ($jugadoresPartida as $jp) { @@ -105,14 +94,9 @@ switch ($orden) { $idE = (int)$jp['idEquipo']; $nuevosAciertos = (int)$jp['aciertos_partida']; - $updateAciertos->execute([ - ':nuevos_aciertos' => $nuevosAciertos, - ':idUsuario' => $idU - ]); + $updateAciertos->execute([':nuevos_aciertos' => $nuevosAciertos, ':idUsuario' => $idU]); - if (!isset($puntosEquipos[$idE])) { - $puntosEquipos[$idE] = 0; - } + if (!isset($puntosEquipos[$idE])) { $puntosEquipos[$idE] = 0; } $puntosEquipos[$idE] += $nuevosAciertos; } @@ -135,7 +119,6 @@ switch ($orden) { foreach ($todosLosMiembros as $miembro) { $idU = (int)$miembro['idUsuario']; $idE = (int)$miembro['idEquipo']; - if ($idE === $idEquipoGanador) { $updateVictoria->execute([':idUsuario' => $idU]); } else { @@ -144,37 +127,27 @@ switch ($orden) { } } - // Marcar fecha fin de la partida para los históricos globales del grupo - $stmtFinalizar = $conexion->prepare(" - UPDATE partida - SET fechaFin = NOW() - WHERE idPartida = :idPartida AND fechaFin IS NULL - "); + $stmtFinalizar = $conexion->prepare("UPDATE partida SET fechaFin = NOW() WHERE idPartida = :idPartida AND fechaFin IS NULL"); $stmtFinalizar->execute([':idPartida' => $idPartida]); $conexion->commit(); $_SESSION['partidas_procesadas'][$idPartida] = true; } - echo json_encode(['terminada' => $terminada]); } catch (PDOException $e) { - if ($conexion->inTransaction()) { - $conexion->rollBack(); - } + if ($conexion->inTransaction()) { $conexion->rollBack(); } echo json_encode(['error' => $e->getMessage()]); } break; - case 'registrarSalidaUsuario': + case 'registrarSalidaUsuario': try { $idUsuario = (int)$_SESSION['idUsuario']; $conexion->beginTransaction(); - // A. LIBERACIÓN INMEDIATA DEL JUGADOR ACTUAL: Lo borramos de su equipo $stmtSalir = $conexion->prepare("DELETE FROM equipoxusuario WHERE idUsuario = :idUsuario"); $stmtSalir->execute([':idUsuario' => $idUsuario]); - // B. CONTADOR DE ALUMNOS QUEDAN: Contamos cuántas personas quedan en los equipos de esta partida $stmtContarQuedan = $conexion->prepare(" SELECT COUNT(exu.idUsuario) FROM equipoxpartida exp @@ -184,9 +157,7 @@ switch ($orden) { $stmtContarQuedan->execute([':idPartida' => $idPartida]); $jugadoresRestantes = (int)$stmtContarQuedan->fetchColumn(); - // C. DESTRUCCIÓN EN CADENA AUTOMÁTICA ATÓMICA (Si da 0, somos los últimos en salir) if ($jugadoresRestantes === 0) { - // 1. Limpiar las respuestas almacenadas $stmtBorrarRespuestas = $conexion->prepare(" DELETE ra FROM respuestaalmacenada ra INNER JOIN partidaxpregunta pxp ON ra.idPartidaxPregunta = pxp.idPartidaxPregunta @@ -194,29 +165,22 @@ switch ($orden) { "); $stmtBorrarRespuestas->execute([':idPartida' => $idPartida]); - // 2. Limpiar las preguntas vinculadas a la partida $stmtBorrarPreguntas = $conexion->prepare("DELETE FROM partidaxpregunta WHERE idPartida = :idPartida"); $stmtBorrarPreguntas->execute([':idPartida' => $idPartida]); - // 3. NUEVO: Obtener los IDs de los dos equipos que jugaban en esta partida antes de borrar la relación $stmtObtenerEquipos = $conexion->prepare("SELECT idEquipo FROM equipoxpartida WHERE idPartida = :idPartida"); $stmtObtenerEquipos->execute([':idPartida' => $idPartida]); $equiposDeLaPartida = $stmtObtenerEquipos->fetchAll(PDO::FETCH_COLUMN); - // 4. Limpiar la relación de equipos de la partida (tabla intermedia) - $stmtBorrarEquiposPartida = $conexion->prepare("DELETE FROM equipoxpartida WHERE idPartida = :idPartida"); $stmtBorrarEquiposPartida = $conexion->prepare("DELETE FROM equipoxpartida WHERE idPartida = :idPartida"); $stmtBorrarEquiposPartida->execute([':idPartida' => $idPartida]); - // 5. NUEVO: Borrar físicamente los equipos de la tabla 'equipo' si existen if (!empty($equiposDeLaPartida)) { - // Creamos los marcadores (?, ?) de forma dinámica según los equipos que devuelva $inQuery = implode(',', array_fill(0, count($equiposDeLaPartida), '?')); $stmtBorrarEquiposFisicos = $conexion->prepare("DELETE FROM equipo WHERE idEquipo IN ($inQuery)"); $stmtBorrarEquiposFisicos->execute($equiposDeLaPartida); } - // 6. Borrar físicamente la fila de la partida principal $stmtBorrarSala = $conexion->prepare("DELETE FROM partida WHERE idPartida = :idPartida"); $stmtBorrarSala->execute([':idPartida' => $idPartida]); } @@ -224,11 +188,8 @@ switch ($orden) { $conexion->commit(); echo json_encode(['exito' => true, 'usuarios_quedan' => $jugadoresRestantes]); } catch (PDOException $e) { - if ($conexion->inTransaction()) { - $conexion->rollBack(); - } + if ($conexion->inTransaction()) { $conexion->rollBack(); } echo json_encode(['error' => $e->getMessage()]); } break; - } diff --git a/resultados.php b/resultados.php index 1c82ba8..e9aa2c5 100644 --- a/resultados.php +++ b/resultados.php @@ -1,6 +1,8 @@ prepare(" - SELECT u.idUsuario, u.nombreUsuario, e.idEquipo, e.nombreEquipo - FROM equipoxpartida exp - INNER JOIN equipoxusuario exu ON exp.idEquipo = exu.idEquipo - INNER JOIN usuario u ON exu.idUsuario = u.idUsuario - INNER JOIN equipo e ON exu.idEquipo = e.idEquipo - WHERE exp.idPartida = :idPartida -"); -$stmt->execute([':idPartida' => $idPartida]); -$listaJugadoresRaw = $stmt->fetchAll(PDO::FETCH_ASSOC); +// Instanciamos el modelo +$modelo = new PartidaModelo($conexion); +// Obtenemos datos crudos del modelo +$listaJugadoresRaw = $modelo->obtenerJugadoresPartida($idPartida); $primerosEnAcertar = $_SESSION['primeros_en_acertar'][$idPartida] ?? []; $jugadoresFinales = []; $equiposFinales = []; -// Respuestas de velocidad (+2 o +1) procesadas en la capa de la vista +// Procesamiento de la lógica de negocio (puntos y velocidad) foreach ($listaJugadoresRaw as $jugador) { $idU = (int)$jugador['idUsuario']; $idE = (int)$jugador['idEquipo']; - $stmtRespuestas = $conexion->prepare(" - SELECT ra.idPartidaxPregunta, r.correcta - FROM respuestaalmacenada ra - INNER JOIN respuesta r ON ra.idRespuesta = r.idRespuesta - INNER JOIN partidaxpregunta pxp ON ra.idPartidaxPregunta = pxp.idPartidaxPregunta - WHERE pxp.idPartida = :idPartida AND ra.idUsuario = :idUsuario - "); - $stmtRespuestas->execute([':idPartida' => $idPartida, ':idUsuario' => $idU]); - $respuestasUsuario = $stmtRespuestas->fetchAll(PDO::FETCH_ASSOC); + $respuestasUsuario = $modelo->obtenerRespuestasUsuario($idPartida, $idU); $aciertos = 0; $puntosTotalesJugador = 0; @@ -52,6 +39,7 @@ foreach ($listaJugadoresRaw as $jugador) { $aciertos++; $idPxp = $resp['idPartidaxPregunta']; + // Regula si es el más rápido (+2) o normal (+1) if (isset($primerosEnAcertar[$idPxp]) && $primerosEnAcertar[$idPxp] === $idU) { $puntosTotalesJugador += 2; } else { @@ -76,86 +64,8 @@ foreach ($listaJugadoresRaw as $jugador) { $equiposFinales[$idE]['puntos'] += $puntosTotalesJugador; } +// Ordenaciones de rankings usort($jugadoresFinales, function($a, $b) { return $b['puntos'] <=> $a['puntos']; }); usort($equiposFinales, function($a, $b) { return $b['puntos'] <=> $a['puntos']; }); -?> - - -
- - -Calculando estadísticas de velocidad y actualizando perfiles históricos en el servidor.
- -Calculando estadísticas de velocidad y actualizando perfiles históricos en el servidor.
+ +