diff --git a/controladores/ControladorReusltados.php b/controladores/ControladorReusltados.php
new file mode 100644
index 0000000..de401f7
--- /dev/null
+++ b/controladores/ControladorReusltados.php
@@ -0,0 +1,166 @@
+ 'Sesión no iniciada']);
+ exit;
+}
+
+$idPartida = intval($_POST['idPartida'] ?? 0);
+$orden = $_POST['orden'] ?? '';
+
+if ($idPartida <= 0) {
+ echo json_encode(['error' => 'Partida no válida']);
+ exit;
+}
+
+$conexion = conexionBD();
+if (is_array($conexion)) {
+ echo json_encode($conexion);
+ exit;
+}
+
+switch ($orden) {
+ case 'comprobarEstado':
+ try {
+ // Contar jugadores totales apuntados en los equipos de esta partida
+ $stmt = $conexion->prepare("
+ SELECT COUNT(exu.idUsuario) AS total_jugadores
+ FROM equipoxpartida exp
+ INNER JOIN equipoxusuario exu ON exp.idEquipo = exu.idEquipo
+ WHERE exp.idPartida = :idPartida
+ ");
+ $stmt->execute([':idPartida' => $idPartida]);
+ $totalJugadores = (int)$stmt->fetchColumn();
+
+ $preguntasTotalesEsperadas = $totalJugadores * 10;
+
+ // Contar respuestas dadas en la partida
+ $stmtRespuestas = $conexion->prepare("
+ SELECT COUNT(*)
+ FROM respuestaalmacenada ra
+ INNER JOIN partidaxpregunta pxp ON ra.idPartidaxPregunta = pxp.idPartidaxPregunta
+ WHERE pxp.idPartida = :idPartida
+ ");
+ $stmtRespuestas->execute([':idPartida' => $idPartida]);
+ $respuestasRespondidas = (int)$stmtRespuestas->fetchColumn();
+
+ $terminada = ($respuestasRespondidas >= $preguntasTotalesEsperadas && $preguntasTotalesEsperadas > 0);
+
+ // Cuando la partida finaliza, se actualizan los históricos
+ if ($terminada && !isset($_SESSION['partidas_procesadas'][$idPartida])) {
+
+ $conexion->beginTransaction();
+
+ // CÁLCULO DE VELOCIDAD PREGUNTA A PREGUNTA EN SESIÓN
+ if (!isset($_SESSION['primeros_en_acertar'][$idPartida])) {
+ $_SESSION['primeros_en_acertar'][$idPartida] = [];
+ }
+
+ // Vemos quién fue el primero
+ $stmtVelocidad = $conexion->prepare("
+ SELECT ra.idPartidaxPregunta, ra.idUsuario
+ 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 r.correcta = 1
+ ORDER BY ra.idRespuestaAlmacenada ASC
+ ");
+ $stmtVelocidad->execute([':idPartida' => $idPartida]);
+ $todosLosAciertos = $stmtVelocidad->fetchAll(PDO::FETCH_ASSOC);
+
+ 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;
+ }
+ }
+
+ // Actualizamos la base de datos
+ // Buscamos los aciertos de cada jugador en la partida actual
+ $stmtAciertos = $conexion->prepare("
+ SELECT ra.idUsuario, exu.idEquipo, COUNT(*) as aciertos_partida
+ FROM respuestaalmacenada ra
+ INNER JOIN partidaxpregunta pxp ON ra.idPartidaxPregunta = pxp.idPartidaxPregunta
+ INNER JOIN respuesta r ON ra.idRespuesta = r.idRespuesta
+ INNER JOIN equipoxusuario exu ON ra.idUsuario = exu.idUsuario
+ WHERE pxp.idPartida = :idPartida AND r.correcta = 1
+ GROUP BY ra.idUsuario
+ ");
+ $stmtAciertos->execute([':idPartida' => $idPartida]);
+ $jugadoresPartida = $stmtAciertos->fetchAll(PDO::FETCH_ASSOC);
+
+ $updateAciertosGlobales = $conexion->prepare("
+ UPDATE usuario
+ SET aciertos = aciertos + :nuevos_aciertos
+ WHERE idUsuario = :idUsuario
+ ");
+
+ $puntosEquipos = [];
+ foreach ($jugadoresPartida as $jp) {
+ $idU = (int)$jp['idUsuario'];
+ $idE = (int)$jp['idEquipo'];
+ $nuevosAciertos = (int)$jp['aciertos_partida'];
+
+ // Sumamos los aciertos al perfil del usuario
+ $updateAciertos->execute([
+ ':nuevos_aciertos' => $nuevosAciertos,
+ ':idUsuario' => $idU
+ ]);
+
+ if (!isset($puntosEquipos[$idE])) {
+ $puntosEquipos[$idE] = 0;
+ }
+ $puntosEquipos[$idE] += $nuevosAciertos;
+ }
+
+ // Determinamos qué equipo ha obtenido más aciertos en la partida
+ arsort($puntosEquipos);
+ $idEquipoGanador = key($puntosEquipos);
+
+ // Obtenemos todos los usuarios de la partida para asignar victorias/derrotas
+ $stmtMiembros = $conexion->prepare("
+ SELECT exu.idUsuario, exu.idEquipo
+ FROM equipoxpartida exp
+ INNER JOIN equipoxusuario exu ON exp.idEquipo = exu.idEquipo
+ WHERE exp.idPartida = :idPartida
+ ");
+ $stmtMiembros->execute([':idPartida' => $idPartida]);
+ $todosLosMiembros = $stmtMiembros->fetchAll(PDO::FETCH_ASSOC);
+
+ $updateVictoria = $conexion->prepare("UPDATE usuario SET victorias = victorias + 1 WHERE idUsuario = :idUsuario");
+ $updateDerrota = $conexion->prepare("UPDATE usuario SET derrotas = derrotas + 1 WHERE idUsuario = :idUsuario");
+
+ foreach ($todosLosMiembros as $miembro) {
+ $idU = (int)$miembro['idUsuario'];
+ $idE = (int)$miembro['idEquipo'];
+
+ if ($idE === $idEquipoGanador) {
+ $updateVictoria->execute([':idUsuario' => $idU]);
+ } else {
+ $updateDerrota->execute([':idUsuario' => $idU]);
+ }
+ }
+
+ $conexion->commit();
+ $_SESSION['partidas_procesadas'][$idPartida] = true;
+ }
+
+ echo json_encode(['terminada' => $terminada]);
+ } catch (PDOException $e) {
+ if ($conexion->inTransaction()) {
+ $conexion->rollBack();
+ }
+ echo json_encode(['error' => $e->getMessage()]);
+ }
+ break;
+
+ default:
+ echo json_encode(['error' => 'Acción no permitida']);
+ break;
+}
\ No newline at end of file
diff --git a/css/resultados.css b/css/resultados.css
new file mode 100644
index 0000000..006a439
--- /dev/null
+++ b/css/resultados.css
@@ -0,0 +1,179 @@
+/* ==========================================================================
+ ESTILOS GENERALES Y FONDO
+ ========================================================================== */
+* {
+ margin: 0;
+ padding: 0;
+ box-shadow: none;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
+ background-color: #f0f4f8;
+ color: #2c3e50;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-height: 100vh;
+ padding: 20px;
+}
+
+/* Contenedor principal estilo tarjeta */
+.contenedor {
+ width: 100%;
+ max-width: 900px;
+ background: #ffffff;
+ padding: 40px;
+ border-radius: 16px;
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
+ text-align: center;
+ animation: fadeIn 0.5s ease-in-out;
+}
+
+h1 {
+ font-size: 2.5rem;
+ color: #1a365d;
+ margin-bottom: 30px;
+}
+
+h2 {
+ font-size: 1.6rem;
+ color: #2b6cb0;
+ margin-top: 30px;
+ margin-bottom: 15px;
+ text-align: left;
+ border-bottom: 2px solid #e2e8f0;
+ padding-bottom: 8px;
+}
+
+p {
+ font-size: 1.1rem;
+ color: #718096;
+ margin-bottom: 30px;
+}
+
+/* ==========================================================================
+ PANTALLA DE ESPERA Y ANIMACIÓN DE CARGA (LOADER)
+ ========================================================================== */
+#pantalla-espera {
+ padding: 60px 20px;
+}
+
+.loader {
+ width: 60px;
+ height: 60px;
+ border: 6px solid #e2e8f0;
+ border-top: 6px solid #3182ce;
+ border-radius: 50%;
+ margin: 0 auto;
+ animation: spin 1.2s linear infinite;
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+/* ==========================================================================
+ TABLAS DE CLASIFICACIÓN (RANKING)
+ ========================================================================== */
+.tabla-ranking {
+ width: 100%;
+ border-collapse: collapse;
+ margin-bottom: 20px;
+ font-size: 1.05rem;
+}
+
+.tabla-ranking th,
+.tabla-ranking td {
+ padding: 16px 20px;
+ text-align: left;
+}
+
+.tabla-ranking th {
+ background-color: #2d3748;
+ color: #ffffff;
+ font-weight: 600;
+ text-transform: uppercase;
+ font-size: 0.9rem;
+ letter-spacing: 0.5px;
+}
+
+/* Alinear los puntos y aciertos a la derecha para mejor lectura numérica */
+.tabla-ranking th:last-child,
+.tabla-ranking td:last-child {
+ text-align: right;
+}
+
+.tabla-ranking tr {
+ border-bottom: 1px solid #e2e8f0;
+ transition: background-color 0.2s;
+}
+
+.tabla-ranking tbody tr:hover {
+ background-color: #f7fafc;
+}
+
+/* ==========================================================================
+ RESALTADO DE GANADORES (1º PUESTO)
+ ========================================================================== */
+/* Fila del Equipo Ganador y Jugador Ganador */
+.tabla-ranking tr.top-team,
+.tabla-ranking tr.top-player {
+ background-color: #fefcbf !important; /* Amarillo suave */
+ font-weight: bold;
+}
+
+/* Cambiar el color del texto del puesto #1 a dorado/corona */
+.tabla-ranking tr.top-team td:first-child,
+.tabla-ranking tr.top-player td:first-child {
+ color: #b7791f;
+ font-size: 1.2rem;
+}
+
+.tabla-ranking td strong {
+ color: #2f855a; /* Verde para destacar los aciertos conseguidos */
+ font-size: 1.1rem;
+}
+
+/* ==========================================================================
+ EFECTOS VISUALES SUAVES
+ ========================================================================== */
+@keyframes fadeIn {
+ from { opacity: 0; transform: translateY(10px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+/* ==========================================================================
+ ESTILOS DEL BOTÓN DE RETORNO A INICIO
+ ========================================================================== */
+.contenedor-boton {
+ margin-top: 40px;
+ padding-top: 20px;
+ text-align: center;
+}
+
+.btn-inicio {
+ display: inline-block;
+ background-color: #3182ce; /* Azul corporativo */
+ color: #ffffff;
+ padding: 14px 28px;
+ font-size: 1.1rem;
+ font-weight: 600;
+ text-decoration: none;
+ border-radius: 8px;
+ box-shadow: 0 4px 6px rgba(49, 130, 206, 0.2);
+ transition: background-color 0.2s, transform 0.2s, box-shadow 0.2s;
+}
+
+.btn-inicio:hover {
+ background-color: #2b6cb0; /* Azul ligeramente más oscuro al pasar el cursor */
+ box-shadow: 0 6px 12px rgba(43, 108, 176, 0.3);
+ transform: translateY(-2px); /* Pequeño salto hacia arriba */
+}
+
+.btn-inicio:active {
+ transform: translateY(0); /* Vuelve a su posición normal al pulsar */
+ box-shadow: 0 2px 4px rgba(43, 108, 176, 0.2);
+}
diff --git a/js/resultados.js b/js/resultados.js
new file mode 100644
index 0000000..4ecd202
--- /dev/null
+++ b/js/resultados.js
@@ -0,0 +1,38 @@
+$(document).ready(function () {
+ const idPartida = $("body").data("id-partida");
+
+ comprobarEstadoPartida(idPartida);
+
+ const intervalo = setInterval(function () {
+ comprobarEstadoPartida(idPartida, intervalo);
+ }, 3000);
+});
+
+function comprobarEstadoPartida(idPartida, intervalo = null) {
+ $.ajax({
+ url: "controladores/ControladorResultados.php",
+ type: "POST",
+ dataType: "json",
+ data: {
+ orden: "comprobarEstado",
+ idPartida: idPartida
+ },
+ success: function (respuesta) {
+ if (respuesta.error) {
+ console.error("Error:", respuesta.error);
+ return;
+ }
+
+ if (respuesta.terminada) {
+ if (intervalo !== null) clearInterval(intervalo);
+
+ $("#pantalla-espera").fadeOut(400, function() {
+ location.reload();
+ });
+ }
+ },
+ error: function () {
+ console.log("Error de comunicación con el controlador.");
+ }
+ });
+}
diff --git a/resultados.php b/resultados.php
index d15f529..3cf48c6 100644
--- a/resultados.php
+++ b/resultados.php
@@ -1,291 +1,156 @@
-
-
-
-
-
-
-
- Trivial - Resultado final
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ¡Trivial terminado!
-
-
-
- Estos son los resultados finales
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Los Cerebritos
-
-
-
- 850
-
- puntos
-
-
-
-
-
- ¡Enhorabuena por la victoria!
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 850
-
-
-
- puntos
-
-
-
-
-
-
- Jugadores
-
-
-
-
- -
- 1. Carlos
-
-
- -
- 2. Marta
-
-
- -
- 3. Pablo
-
-
- -
- 4. Laura
-
-
- -
- 5. David
-
-
- -
- 6. Ana
-
-
- -
- 7. Sergio
-
-
- -
- 8. Lucía
-
-
- -
- 9. Miguel
-
-
- -
- 10. Elena
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 720
-
-
-
- puntos
-
-
-
-
-
-
- Jugadores
-
-
-
-
- -
- 1. Javier
-
-
- -
- 2. Sofía
-
-
- -
- 3. Diego
-
-
- -
- 4. María
-
-
- -
- 5. Alejandro
-
-
- -
- 6. Paula
-
-
- -
- 7. Álvaro
-
-
- -
- 8. Carmen
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+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);
+
+$primerosEnAcertar = $_SESSION['primeros_en_acertar'][$idPartida] ?? [];
+
+$jugadoresFinales = [];
+$equiposFinales = [];
+
+// Respuestas de velocidad (+2 o +1)
+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);
+
+ $aciertos = 0;
+ $puntosTotalesJugador = 0;
+
+ foreach ($respuestasUsuario as $resp) {
+ if ((int)$resp['correcta'] === 1) {
+ $aciertos++;
+ $idPxp = $resp['idPartidaxPregunta'];
+
+ // Si el ID de usuario coincide con el primero guardado de esa pregunta se lleva 2 puntos
+ if (isset($primerosEnAcertar[$idPxp]) && $primerosEnAcertar[$idPxp] === $idU) {
+ $puntosTotalesJugador += 2;
+ } else {
+ $puntosTotalesJugador += 1;
+ }
+ }
+ }
+
+ $jugadoresFinales[] = [
+ 'nombre' => $jugador['nombreUsuario'],
+ 'equipo' => $jugador['nombreEquipo'],
+ 'aciertos' => $aciertos,
+ 'puntos' => $puntosTotalesJugador
+ ];
+
+ if (!isset($equiposFinales[$idE])) {
+ $equiposFinales[$idE] = [
+ 'nombre' => $jugador['nombreEquipo'],
+ 'puntos' => 0
+ ];
+ }
+ $equiposFinales[$idE]['puntos'] += $puntosTotalesJugador;
+}
+
+// Ordenar según la puntuación final de mayor a menor
+usort($jugadoresFinales, function($a, $b) { return $b['puntos'] <=> $a['puntos']; });
+usort($equiposFinales, function($a, $b) { return $b['puntos'] <=> $a['puntos']; });
+?>
+
+
+
+
+
+
+ Resultados - Trivial
+
+
+
+
+
+
+
⌛ Esperando a que todos los jugadores terminen...
+
Calculando estadísticas de velocidad y actualizando perfiles históricos en el servidor.
+
+
+
+
+
🏆 Resultados de la Partida 🏆
+
+
Clasificación por Equipos
+
+
+
+ | Posición |
+ Equipo |
+ Puntos Totales |
+
+
+
+ $eq): ?>
+
+ | # |
+ |
+ pts |
+
+
+
+
+
+
Rendimiento Individual
+
+
+
+ | Posición |
+ Jugador |
+ Equipo |
+ Aciertos |
+ Puntos Logrados |
+
+
+
+ $jug): ?>
+
+ | # |
+ |
+ |
+ / 10 |
+ pts |
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file