5 Commits

Author SHA1 Message Date
dbvictor2002 7ae1b14e6e Subir archivos a "js" 2026-09-29 13:19:26 +02:00
dbvictor2002 e64761400d Subir archivos a "css" 2026-09-29 13:18:57 +02:00
dbvictor2002 00e1c04868 Subir archivos a "controladores" 2026-09-29 13:18:33 +02:00
dbvictor2002 8e1ccc6718 Subir archivos a "/" 2026-09-29 13:18:16 +02:00
jorge 3cc0dfb122 Corregido cambiar avatar en cabecera 2026-09-28 13:29:57 +02:00
7 changed files with 590 additions and 349 deletions
+166
View File
@@ -0,0 +1,166 @@
<?php
session_start();
require_once $_SERVER['DOCUMENT_ROOT'] . '/triviagmatico/includes/conexionBD.php';
header('Content-Type: application/json; charset=utf-8');
if (!isset($_SESSION['idUsuario'])) {
echo json_encode(['error' => '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;
}
+5 -3
View File
@@ -55,10 +55,11 @@ switch ($_POST['orden']) {
if ($resultado instanceof Usuario) { if ($resultado instanceof Usuario) {
// === AÑADIR ESTAS LÍNEAS PARA GUARDAR EN SESIÓN === // === GUARDAR EN SESIÓN (incluido avatar)===
$_SESSION['idUsuario'] = $resultado->getIdUsuario(); $_SESSION['idUsuario'] = $resultado->getIdUsuario();
$_SESSION['nombreUsuario'] = $resultado->getNombreUsuario(); $_SESSION['nombreUsuario'] = $resultado->getNombreUsuario();
$_SESSION['email'] = $resultado->getEmail(); $_SESSION['email'] = $resultado->getEmail();
$_SESSION['avatar'] = $resultado->getAvatar();
// ================================================= // =================================================
echo json_encode([ echo json_encode([
@@ -83,6 +84,7 @@ switch ($_POST['orden']) {
unset($_SESSION['idUsuario']); unset($_SESSION['idUsuario']);
unset($_SESSION['email']); unset($_SESSION['email']);
unset($_SESSION['nombreUsuario']); unset($_SESSION['nombreUsuario']);
unset($_SESSION['avatar']);
// Destruimos la sesión // Destruimos la sesión
session_destroy(); session_destroy();
@@ -92,7 +94,6 @@ switch ($_POST['orden']) {
]); ]);
break; break;
case 'mostrarEstadisticas': case 'mostrarEstadisticas':
$usuario = Usuario::buscarPorId($_SESSION['idUsuario']); $usuario = Usuario::buscarPorId($_SESSION['idUsuario']);
@@ -242,7 +243,8 @@ switch ($_POST['orden']) {
'activa' => true, 'activa' => true,
'usuario' => [ 'usuario' => [
'idUsuario' => $_SESSION['idUsuario'], 'idUsuario' => $_SESSION['idUsuario'],
'nombreUsuario' => $_SESSION['nombreUsuario'] ?? '' 'nombreUsuario' => $_SESSION['nombreUsuario'] ?? '',
'avatar' => $_SESSION['avatar'] ?? ''
] ]
]); ]);
} else { } else {
+179
View File
@@ -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);
}
+15 -17
View File
@@ -26,7 +26,7 @@ $(document).ready(function () {
}); });
/** /**
* Comprueba con el servidor si existe una sesión PHP activa. * Comprueba con el servidor si existe una sesión PHP
*/ */
function comprobarEstadoSesion() { function comprobarEstadoSesion() {
$.ajax({ $.ajax({
@@ -37,7 +37,6 @@ function comprobarEstadoSesion() {
success: function (respuesta) { success: function (respuesta) {
if (respuesta.activa) { if (respuesta.activa) {
renderizarCabeceraConSesion(respuesta.usuario); renderizarCabeceraConSesion(respuesta.usuario);
// Si existe el contenedor del botón Jugar en index, lo mostramos
$('#colBotonJugar').removeClass('d-none'); $('#colBotonJugar').removeClass('d-none');
} else { } else {
renderizarCabeceraSinSesion(); renderizarCabeceraSinSesion();
@@ -79,13 +78,8 @@ function ejecutarLogin() {
$('#modalLogin').modal('hide'); $('#modalLogin').modal('hide');
$('#formLogin')[0].reset(); $('#formLogin')[0].reset();
renderizarCabeceraConSesion({ // Cargar datos de la sesión actualizados
idUsuario: respuesta.idUsuario, comprobarEstadoSesion();
nombreUsuario: respuesta.nombreUsuario,
avatar: respuesta.avatar
});
$('#colBotonJugar').removeClass('d-none');
} }
}, },
error: function () { error: function () {
@@ -132,7 +126,7 @@ function ejecutarRegistro() {
$('#modalRegistro').modal('hide'); $('#modalRegistro').modal('hide');
$('#formRegistro')[0].reset(); $('#formRegistro')[0].reset();
// Autologin // Autologin tras registrarse
$('#loginEmail').val(email); $('#loginEmail').val(email);
$('#loginPassword').val(pass); $('#loginPassword').val(pass);
ejecutarLogin(); ejecutarLogin();
@@ -165,15 +159,21 @@ function cerrarSesion() {
} }
/** /**
* Renderiza la cabecera cuando HAY sesión iniciada (Menú Perfil + Avatar) * Renderiza la cabecera cuando HAY sesión iniciada
*/ */
function renderizarCabeceraConSesion(usuario) { function renderizarCabeceraConSesion(usuario) {
let avatarImg = usuario.avatar ? usuario.avatar : 'img/avatars/defaultProfile.jpeg'; //Mete el avatar en cabecera
let avatarImg = (usuario.avatar && usuario.avatar !== '')
? usuario.avatar
: 'img/avatars/defaultProfile.jpeg';
// Refrescar avatar si se cambia
let avatarConCacheBuster = avatarImg + '?v=' + new Date().getTime();
let html = ` let html = `
<div class="dropdown"> <div class="dropdown">
<button class="btn btn-outline-light dropdown-toggle d-flex align-items-center gap-2 rounded-pill px-3 py-1 fw-bold" type="button" id="userMenu" data-bs-toggle="dropdown" aria-expanded="false"> <button class="btn btn-outline-light dropdown-toggle d-flex align-items-center gap-2 rounded-pill px-3 py-1 fw-bold" type="button" id="userMenu" data-bs-toggle="dropdown" aria-expanded="false">
<img src="${avatarImg}" alt="Avatar" class="rounded-circle border" style="width: 32px; height: 32px; object-fit: cover;"> <img src="${avatarConCacheBuster}" alt="Avatar" class="rounded-circle border" style="width: 32px; height: 32px; object-fit: cover;">
<span>${escapeHtml(usuario.nombreUsuario)}</span> <span>${escapeHtml(usuario.nombreUsuario)}</span>
</button> </button>
<ul class="dropdown-menu dropdown-menu-end shadow border-0 mt-2" aria-labelledby="userMenu"> <ul class="dropdown-menu dropdown-menu-end shadow border-0 mt-2" aria-labelledby="userMenu">
@@ -195,13 +195,11 @@ function renderizarCabeceraConSesion(usuario) {
} }
/** /**
* Renderiza los botones originales: * Renderiza los botones en la cabecera cuando NO hay sesión (Iniciar sesión azul)
* - "Iniciar Sesión" (Rojo -> btn-danger)
* - "Registrarse" (Verde -> btn-success)
*/ */
function renderizarCabeceraSinSesion() { function renderizarCabeceraSinSesion() {
let html = ` let html = `
<button class="btn btn-danger rounded-pill px-4 fw-bold shadow-sm" data-bs-toggle="modal" data-bs-target="#modalLogin"> <button class="btn btn-primary rounded-pill px-4 fw-bold shadow-sm" data-bs-toggle="modal" data-bs-target="#modalLogin">
<i class="fa-solid fa-right-to-bracket me-1"></i> Iniciar sesión <i class="fa-solid fa-right-to-bracket me-1"></i> Iniciar sesión
</button> </button>
<button class="btn btn-success rounded-pill px-4 fw-bold shadow-sm" data-bs-toggle="modal" data-bs-target="#modalRegistro"> <button class="btn btn-success rounded-pill px-4 fw-bold shadow-sm" data-bs-toggle="modal" data-bs-target="#modalRegistro">
+20 -27
View File
@@ -26,6 +26,10 @@ $.ajax({
function cambiarNombre() { function cambiarNombre() {
let nuevoNombre = $("#nuevoNombre").val().trim(); let nuevoNombre = $("#nuevoNombre").val().trim();
if (nuevoNombre === "") {
return;
}
$.ajax({ $.ajax({
method: "POST", method: "POST",
url: "controladores/controladorUsuario.php", url: "controladores/controladorUsuario.php",
@@ -42,8 +46,13 @@ function cambiarNombre() {
// Actualizamos el nombre mostrado en la página // Actualizamos el nombre mostrado en la página
$("#nombre").text(respuesta.nombreUsuario); $("#nombre").text(respuesta.nombreUsuario);
// Limpiamos el input
$("#nuevoNombre").val(""); $("#nuevoNombre").val("");
if (typeof comprobarEstadoSesion === "function") {
comprobarEstadoSesion();
}
} }
}); });
} }
@@ -74,14 +83,11 @@ $("#inputFoto").change(function () {
// Comprobamos que sea una imagen // Comprobamos que sea una imagen
if (!archivo.type.startsWith("image/")) { if (!archivo.type.startsWith("image/")) {
alert("El archivo seleccionado no es una imagen."); alert("El archivo seleccionado no es una imagen.");
$("#inputFoto").val(""); $("#inputFoto").val("");
return; return;
} }
let datos = new FormData(); let datos = new FormData();
datos.append("avatar", archivo); datos.append("avatar", archivo);
datos.append("orden", "cambiarAvatar"); datos.append("orden", "cambiarAvatar");
@@ -97,18 +103,23 @@ $("#inputFoto").change(function () {
if (respuesta.error) { if (respuesta.error) {
alert(respuesta.error); alert(respuesta.error);
} else { } else {
// Actualizamos la imagen sin recargar la página // Actualizamos la imagen en la página de perfil sin recargar
$("#fotoPerfil").attr( $("#fotoPerfil").attr(
"src", "src",
respuesta.avatar + "?t=" + new Date().getTime(), respuesta.avatar + "?t=" + new Date().getTime()
); );
// Actualizamos también el avatar superior en la cabecera
if (typeof comprobarEstadoSesion === "function") {
comprobarEstadoSesion();
}
} }
}); });
}); });
// ========================= // =========================
// RECOGER CATEGORIAS // RECOGER CATEGORIAS
// ==== // =========================
$("#modalCrearPregunta").on("show.bs.modal", function () { $("#modalCrearPregunta").on("show.bs.modal", function () {
const selectCategoria = $("#idCategoria"); const selectCategoria = $("#idCategoria");
@@ -141,16 +152,14 @@ $("#modalCrearPregunta").on("show.bs.modal", function () {
$("<option>", { $("<option>", {
value: categoria.idCategoria, value: categoria.idCategoria,
text: categoria.nombreCategoria, text: categoria.nombreCategoria,
}), })
); );
}); });
}, },
error: function (xhr, status, error) { error: function (xhr, status, error) {
console.error("Error al cargar las categorías:", error); console.error("Error al cargar las categorías:", error);
console.error("Respuesta del servidor:", xhr.responseText); console.error("Respuesta del servidor:", xhr.responseText);
alert("No se han podido cargar las categorías."); alert("No se han podido cargar las categorías.");
}, },
}); });
@@ -158,7 +167,7 @@ $("#modalCrearPregunta").on("show.bs.modal", function () {
// ========================= // =========================
// CREAR PREGUNTA // CREAR PREGUNTA
// ==== // =========================
$("#formCrearPregunta").on("submit", function (e) { $("#formCrearPregunta").on("submit", function (e) {
e.preventDefault(); e.preventDefault();
@@ -188,24 +197,15 @@ $("#formCrearPregunta").on("submit", function (e) {
$.ajax({ $.ajax({
url: "controladores/controladorPregunta.php", url: "controladores/controladorPregunta.php",
type: "POST", type: "POST",
dataType: "json", dataType: "json",
data: { data: {
orden: "crearPregunta", orden: "crearPregunta",
idCategoria: $("#idCategoria").val(), idCategoria: $("#idCategoria").val(),
nombrePregunta: pregunta, nombrePregunta: pregunta,
respuestaCorrecta: respuestaCorrecta, respuestaCorrecta: respuestaCorrecta,
respuestaIncorrecta1: respuestaIncorrecta1, respuestaIncorrecta1: respuestaIncorrecta1,
respuestaIncorrecta2: respuestaIncorrecta2, respuestaIncorrecta2: respuestaIncorrecta2,
respuestaIncorrecta3: respuestaIncorrecta3, respuestaIncorrecta3: respuestaIncorrecta3,
}, },
@@ -214,10 +214,8 @@ $("#formCrearPregunta").on("submit", function (e) {
if (respuesta.error) { if (respuesta.error) {
alert(respuesta.error); alert(respuesta.error);
boton.prop("disabled", false); boton.prop("disabled", false);
boton.text("Crear pregunta"); boton.text("Crear pregunta");
return; return;
} }
@@ -233,17 +231,12 @@ $("#formCrearPregunta").on("submit", function (e) {
// Volvemos a activar el botón // Volvemos a activar el botón
boton.prop("disabled", false); boton.prop("disabled", false);
boton.text("Crear pregunta"); boton.text("Crear pregunta");
// Si tienes que actualizar la lista de preguntas:
// cargarPreguntas();
} }
}, },
error: function (xhr, status, error) { error: function (xhr, status, error) {
console.error("Error al crear la pregunta:", error); console.error("Error al crear la pregunta:", error);
console.error("Respuesta del servidor:", xhr.responseText); console.error("Respuesta del servidor:", xhr.responseText);
alert("No se ha podido crear la pregunta."); alert("No se ha podido crear la pregunta.");
boton.prop("disabled", false); boton.prop("disabled", false);
+38
View File
@@ -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.");
}
});
}
+141 -276
View File
@@ -1,291 +1,156 @@
<?php
session_start();
require_once $_SERVER['DOCUMENT_ROOT'] . '/triviagmatico/includes/conexionBD.php';
$idPartida = intval($_GET['idPartida'] ?? 0);
if ($idPartida <= 0) {
die("Partida no válida.");
}
$conexion = conexionBD();
if (is_array($conexion)) {
die("Error de conexión a la base de datos.");
}
// Obtener listado de jugadores y sus equipos en esta partida
$stmt = $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]);
$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']; });
?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="es"> <html lang="es">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Resultados - Trivial</title>
<title>Trivial - Resultado final</title> <link rel="stylesheet" href="css/resultados.css">
<script src="https://jquery.com"></script>
<link rel="icon" type="image/svg+xml" href="img/favicon/favicon.svg">
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet">
<!-- Bootstrap Icons -->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link
href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap"
rel="stylesheet">
<link rel="stylesheet" href="css/index.css">
</head> </head>
<body data-id-partida="<?php echo $idPartida; ?>">
<body> <div id="pantalla-espera" class="contenedor">
<h2>⌛ Esperando a que todos los jugadores terminen...</h2>
<?php <p>Calculando estadísticas de velocidad y actualizando perfiles históricos en el servidor.</p>
include_once("cabecera.php"); <div class="loader"></div>
?>
<main class="container py-5">
<!-- Título -->
<div class="text-center mb-5">
<div class="trophy-icon">
<i class="bi bi-trophy-fill"></i>
</div> </div>
<h1 class="fw-bold"> <div id="pantalla-resultados" class="contenedor" style="display:none;">
¡Trivial terminado! <h1>🏆 Resultados de la Partida 🏆</h1>
</h1>
<p class="text-muted fs-5 mb-0"> <h2>Clasificación por Equipos</h2>
Estos son los resultados finales <table class="tabla-ranking">
</p> <thead>
<tr>
<th>Posición</th>
<th>Equipo</th>
<th>Puntos Totales</th>
</tr>
</thead>
<tbody>
<?php foreach ($equiposFinales as $index => $eq): ?>
<tr class="<?php echo $index === 0 ? 'top-team' : ''; ?>">
<td>#<?php echo $index + 1; ?></td>
<td><?php echo htmlspecialchars($eq['nombre']); ?></td>
<td><strong><?php echo $eq['puntos']; ?> pts</strong></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<h2>Rendimiento Individual</h2>
<table class="tabla-ranking">
<thead>
<tr>
<th>Posición</th>
<th>Jugador</th>
<th>Equipo</th>
<th>Aciertos</th>
<th>Puntos Logrados</th>
</tr>
</thead>
<tbody>
<?php foreach ($jugadoresFinales as $index => $jug): ?>
<tr class="<?php echo $index === 0 ? 'top-player' : ''; ?>">
<td>#<?php echo $index + 1; ?></td>
<td><?php echo htmlspecialchars($jug['nombre']); ?></td>
<td><?php echo htmlspecialchars($jug['equipo']); ?></td>
<td><?php echo $jug['aciertos']; ?> / 10</td>
<td><strong><?php echo $jug['puntos']; ?> pts</strong></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="contenedor-boton">
<a href="/triviagmatico/buscadorSala.php" class="btn-inicio">Volver al Inicio 🏠</a>
</div>
</div> </div>
<script src="js/resultados.js"></script>
<!-- Equipo ganador -->
<section class="row justify-content-center mb-5">
<div class="col-12 col-lg-8">
<div class="ranking-card">
<div class="ranking-header text-center">
<i class="bi bi-trophy-fill me-2"></i>
Equipo ganador
</div>
<div class="card-body text-center p-4">
<h2 class="fw-bold mb-2">
Los Cerebritos
</h2>
<div class="display-3 fw-bold mb-3">
850
<span class="fs-4 text-muted">
puntos
</span>
</div>
<p class="text-muted mb-0">
<i class="bi bi-stars me-1"></i>
¡Enhorabuena por la victoria!
</p>
</div>
</div>
</div>
</section>
<!-- Resultados de los dos equipos -->
<section class="row justify-content-center g-4">
<!-- EQUIPO GANADOR -->
<div class="col-12 col-lg-6">
<div class="ranking-card h-100">
<div class="ranking-header d-flex justify-content-between align-items-center">
<span>
Los Cerebritos
</span>
<span>
<i class="bi bi-trophy-fill"></i>
</span>
</div>
<div class="card-body p-4">
<div class="text-center mb-4">
<div class="fs-1 fw-bold">
850
</div>
<div class="text-muted">
puntos
</div>
</div>
<h5 class="fw-bold mb-3">
<i class="bi bi-people-fill me-2"></i>
Jugadores
</h5>
<ul class="list-group">
<li class="list-group-item">
1. Carlos
</li>
<li class="list-group-item">
2. Marta
</li>
<li class="list-group-item">
3. Pablo
</li>
<li class="list-group-item">
4. Laura
</li>
<li class="list-group-item">
5. David
</li>
<li class="list-group-item">
6. Ana
</li>
<li class="list-group-item">
7. Sergio
</li>
<li class="list-group-item">
8. Lucía
</li>
<li class="list-group-item">
9. Miguel
</li>
<li class="list-group-item">
10. Elena
</li>
</ul>
</div>
</div>
</div>
<!-- EQUIPO PERDEDOR -->
<div class="col-12 col-lg-6">
<div class="ranking-card h-100">
<!-- Cabecera plateada -->
<div
class="ranking-header d-flex justify-content-between align-items-center"
style="background-color: #c0c0c0;">
<span>
Los Campeones
</span>
<span>
<i class="bi bi-award-fill"></i>
</span>
</div>
<div class="card-body p-4">
<div class="text-center mb-4">
<div class="fs-1 fw-bold">
720
</div>
<div class="text-muted">
puntos
</div>
</div>
<h5 class="fw-bold mb-3">
<i class="bi bi-people-fill me-2"></i>
Jugadores
</h5>
<ul class="list-group">
<li class="list-group-item">
1. Javier
</li>
<li class="list-group-item">
2. Sofía
</li>
<li class="list-group-item">
3. Diego
</li>
<li class="list-group-item">
4. María
</li>
<li class="list-group-item">
5. Alejandro
</li>
<li class="list-group-item">
6. Paula
</li>
<li class="list-group-item">
7. Álvaro
</li>
<li class="list-group-item">
8. Carmen
</li>
</ul>
</div>
</div>
</div>
</section>
<!-- Volver al buscador -->
<div class="text-center mt-5">
<a
href="buscadorSala.php"
class="btn btn-play-kahoot">
<i class="bi bi-arrow-left-circle-fill"></i>
Volver al buscador de salas
</a>
</div>
</main>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js">
</script>
</body> </body>
</html> </html>