From 8e1ccc671834ec34339d1b5811424a8714d3ce11 Mon Sep 17 00:00:00 2001 From: dbvictor2002 Date: Tue, 29 Sep 2026 13:18:16 +0200 Subject: [PATCH 1/4] Subir archivos a "/" --- resultados.php | 445 +++++++++++++++++-------------------------------- 1 file changed, 155 insertions(+), 290 deletions(-) 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 -

- -
- - - -
- -
- -
- -
- - Equipo ganador -
- -
- -

- Los Cerebritos -

- -
- 850 - - puntos - -
- -

- - ¡Enhorabuena por la victoria! -

- -
- -
- -
- -
- - - -
- - -
- -
- -
- - - Los Cerebritos - - - - - - -
- -
- -
- -
- 850 -
- -
- puntos -
- -
- -
- - Jugadores -
- -
    - -
  • - 1. Carlos -
  • - -
  • - 2. Marta -
  • - -
  • - 3. Pablo -
  • - -
  • - 4. Laura -
  • - -
  • - 5. David -
  • - -
  • - 6. Ana -
  • - -
  • - 7. Sergio -
  • - -
  • - 8. Lucía -
  • - -
  • - 9. Miguel -
  • - -
  • - 10. Elena -
  • - -
- -
- -
- -
- - - -
- -
- - -
- - - Los Campeones - - - - - - -
- -
- -
- -
- 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.

+
+
+ + + + + \ No newline at end of file -- 2.47.3 From 00e1c04868cb4195fa4297cc7f7816d8d60a93a5 Mon Sep 17 00:00:00 2001 From: dbvictor2002 Date: Tue, 29 Sep 2026 13:18:33 +0200 Subject: [PATCH 2/4] Subir archivos a "controladores" --- controladores/ControladorReusltados.php | 166 ++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 controladores/ControladorReusltados.php 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 -- 2.47.3 From e64761400d6b6a5accb3c359187b50bc8494ff27 Mon Sep 17 00:00:00 2001 From: dbvictor2002 Date: Tue, 29 Sep 2026 13:18:57 +0200 Subject: [PATCH 3/4] Subir archivos a "css" --- css/resultados.css | 179 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 css/resultados.css 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); +} -- 2.47.3 From 7ae1b14e6e659929c5f50379547d7a8419402989 Mon Sep 17 00:00:00 2001 From: dbvictor2002 Date: Tue, 29 Sep 2026 13:19:26 +0200 Subject: [PATCH 4/4] Subir archivos a "js" --- js/resultados.js | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 js/resultados.js 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."); + } + }); +} -- 2.47.3