50 Commits

Author SHA1 Message Date
margarita 1c3fbf2f90 separar código para segur MVC 2026-10-02 11:01:56 +02:00
Juanjo cd53cba69e Actualizar mysqulito/triviagmagicoDEFINITIVO.sql 2026-10-02 10:45:46 +02:00
jorge 5f407ce8f4 Merge pull request 'Arreglado categorias' (#38) from corregir_categorias into main
Reviewed-on: #38
2026-10-02 10:43:55 +02:00
Isaac d20b1fa7d7 Arreglado categorias 2026-10-02 10:42:45 +02:00
jorge 02e725e0f3 Merge pull request 'Add sincronizacion de jugadores en partida' (#37) from sincronizacion_jugadores into main
Reviewed-on: #37
2026-10-02 10:41:50 +02:00
alexis 3856db81ef Add sincronizacion de jugadores en partida 2026-10-02 10:40:01 +02:00
jorge bdc7bef169 Merge pull request 'Ahora se actualiza el nombre y la imagen nueva de forma dinámica' (#36) from perfil_cabecera into main
Reviewed-on: #36
2026-10-02 10:34:47 +02:00
v.rodriguezcamacho 963ab50f37 Ahora se actualiza el nombre y la imagen nueva de forma dinámica 2026-10-02 09:58:03 +02:00
jorge 9488d7cee7 Merge pull request 'Añadir tiempoRespuesta' (#33) from controlador_juego into main
Reviewed-on: #33
2026-10-02 09:42:55 +02:00
Isaac 0b8045544b Arreglado head de cabecera 2026-10-02 09:27:31 +02:00
jorge d67e4d76e2 Corregida cabecera.js 2026-10-02 09:21:23 +02:00
jorge 20131bbe7f Editar cabecera.html (antes de dominio correo) 2026-10-02 09:20:39 +02:00
jorge c624f06b88 Eliminacion includes en buscadorSala 2026-10-02 08:52:52 +02:00
jorge e879a92ac2 Modificación perfil para cabecera mvc 2026-10-02 08:52:00 +02:00
jorge c18576e97d Modificación header index e inclusión cabecera mvc 2026-10-02 08:50:57 +02:00
jorge fd4301d741 Modificación buscadorsala para cabecera mvc 2026-10-02 08:49:36 +02:00
jorge afff6cfb4a Modificación cabecera.js 2026-10-02 08:48:16 +02:00
jorge 46bfb7ea62 Merge pull request 'Ahora pide el @ a la hora de registrar el correo electronico' (#28) from dominio_correo into main
Reviewed-on: #28
2026-10-01 14:15:47 +02:00
Juanjo cbdbd8bc4b Añadir tiempoRespuesta 2026-10-01 14:12:36 +02:00
jorge 8bea83460b Merge pull request 'Ajustado CSS de resultados.php para consistencia con el proyecto.' (#30) from css_resultados into main
Reviewed-on: #30
2026-10-01 14:10:46 +02:00
jorge 554cf5c52f Merge pull request 'Add actualizacion de jugadores dentro de sala cada 5 segundos' (#29) from lobby into main
Reviewed-on: #29
2026-10-01 14:09:14 +02:00
alexis c0207197fb Add se actualizan las salas sin pestañeo 2026-10-01 14:05:02 +02:00
alexis 5113b960d2 Add se actualizan las salas automaticamente 2026-10-01 13:52:36 +02:00
v.rodriguezcamacho 83b1ae90c6 Cambio pasado a cabecera.html y cabecera.php ha sido eliminado 2026-10-01 13:47:21 +02:00
Isaac d994f09f7d Ajustado CSS de resultados.php para consistencia con el proyecto.
Importante: He cambiado la ruta del "Volver al inicio" a $_ENV['urlBase']
2026-10-01 13:46:40 +02:00
alexis 8453735727 Dividido buscadorSala.js en dos archivos para facilitar la modificacion 2026-10-01 13:42:48 +02:00
v.rodriguezcamacho 90a2ad1256 Ahora pide el @ a la hora de registrar el correo electronico 2026-10-01 13:18:12 +02:00
alexis fdd1ba8272 Add actualizacion de jugadores dentro de sala cada 5 segundos 2026-10-01 13:18:11 +02:00
jorge befc6a7cc1 Merge pull request 'add tiempo de respuesta' (#26) from add_tiempo into main
Reviewed-on: #26
2026-10-01 13:03:54 +02:00
alexis e9cf7c8fcf add tiempo de respuesta 2026-10-01 12:53:45 +02:00
dbvictor2002 111a101037 Subir archivos a "js" 2026-10-01 12:42:03 +02:00
dbvictor2002 71b7337dba Subir archivos a "controladores" 2026-10-01 12:39:45 +02:00
jorge dc5c04b693 Merge branch 'main' of https://git.desarrolloalcala.com/jorge/triviagmatico 2026-10-01 12:37:29 +02:00
dbvictor2002 29eb70b626 Subir archivos a "/" 2026-10-01 12:33:57 +02:00
margarita 5bf5b7a3bc triviagmatico 30/09/26 a 13:30 2026-10-01 12:07:47 +02:00
jorge e8accf949e revert 7f70112f63
revert Merge pull request 'Fix inicia partida todos los usuarios' (#21) from partida into main

Reviewed-on: #21
2026-10-01 11:16:36 +02:00
jorge fa883cde39 revert eed77db62f
revert Subir archivos a "controladores"
2026-10-01 11:16:20 +02:00
jorge ae213a3d12 revert a66ac7086d
revert Subir archivos a "js"
2026-10-01 11:16:14 +02:00
jorge cd0685f41c revert 71fb45b94c
revert Merge branch 'main' of https://git.desarrolloalcala.com/jorge/triviagmatico
2026-10-01 11:15:10 +02:00
jorge e3395a017c revert 8d5d7da615
revert Merge pull request 'Resultados victor' (#25) from resultados_victor into main

Reviewed-on: #25
2026-10-01 11:13:07 +02:00
jorge 396aca8b03 revert c6db380ef9
revert Merge branch 'main' of https://git.desarrolloalcala.com/jorge/triviagmatico
2026-10-01 11:12:58 +02:00
jorge c6db380ef9 Merge branch 'main' of https://git.desarrolloalcala.com/jorge/triviagmatico 2026-10-01 10:53:03 +02:00
jorge 8d5d7da615 Merge pull request 'Resultados victor' (#25) from resultados_victor into main
Reviewed-on: #25
2026-10-01 10:52:42 +02:00
jorge 7f70112f63 Merge pull request 'Fix inicia partida todos los usuarios' (#21) from partida into main
Reviewed-on: #21
2026-10-01 10:49:10 +02:00
dbvictor2002 a66ac7086d Subir archivos a "js" 2026-10-01 10:47:05 +02:00
dbvictor2002 eed77db62f Subir archivos a "controladores" 2026-10-01 10:46:36 +02:00
dbvictor2002 83545152bb Subir archivos a "/" 2026-10-01 10:46:12 +02:00
jorge 71fb45b94c Merge branch 'main' of https://git.desarrolloalcala.com/jorge/triviagmatico 2026-10-01 08:58:45 +02:00
jorge 2531ef321a cabecera mvc modificada 2026-09-30 11:08:09 +02:00
dbvictor2002 5446352cf9 Fix inicia partida todos los usuarios 2026-09-30 10:21:43 +02:00
23 changed files with 3543 additions and 2201 deletions
+6 -2
View File
@@ -10,11 +10,12 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="css/index.css"> <link rel="stylesheet" href="css/index.css">
<link rel="stylesheet" href="css/buscadorSala.css"> <link rel="stylesheet" href="css/buscadorSala.css">
<script src="js/jquery-4.0.0.min.js"></script>
</head> </head>
<body> <body>
<?php include_once("cabecera.php"); ?> <header id="cabecera-container"></header>
<main class="container py-4"> <main class="container py-4">
@@ -99,8 +100,11 @@
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="js/jquery-4.0.0.min.js"></script> <script src="js/sala.js"></script>
<script src="js/buscadorSala.js"></script> <script src="js/buscadorSala.js"></script>
<script src="js/cabecera.js"></script>
</body> </body>
</html> </html>
+110
View File
@@ -0,0 +1,110 @@
<head>
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- FontAwesome para iconos -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
<!-- Google Fonts para estilo Kahoot -->
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<!-- cabecera.html -->
<nav class="navbar navbar-expand-lg navbar-kahoot py-3 mb-4">
<div class="container">
<a class="navbar-brand" href="index.php">
<img src="img/favicon/favicon.svg" alt="TRIVIAGMÁTICO" class="me-2" style="height: 35px;">
TRIVIAGMÁTICO
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarContent">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0"></ul>
<!-- Contenedor dinámico de usuario/botones -->
<div class="d-flex align-items-center gap-3" id="contenedorUsuarioCabecera"></div>
</div>
</div>
</nav>
<!-- MODAL DE LOGIN -->
<div class="modal fade" id="modalLogin" tabindex="-1" aria-labelledby="loginModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-dark">
<div class="modal-header">
<h1 class="modal-title fs-5 fw-bold" id="loginModalLabel">
<i class="fa-solid fa-right-to-bracket text-primary me-2"></i>Iniciar sesión
</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
</div>
<div class="modal-body">
<form id="formLogin">
<div class="form-floating mb-3">
<input type="email" class="form-control border-dark" id="loginEmail" name="email" placeholder="Correo electrónico" required>
<label for="loginEmail">Correo electrónico</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control border-dark" id="loginPassword" name="contrasena" placeholder="Contraseña" required>
<label for="loginPassword">Contraseña</label>
</div>
<div class="form-check">
<input class="form-check-input" id="recordar" name="recordar" type="checkbox" />
<label for="recordar" class="small">Recuérdeme durante 10 días</label>
</div>
<input type="hidden" name="orden" value="validar">
</form>
<div id="errorLogin" class="text-danger fw-bold mt-2"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary rounded-pill px-3" data-bs-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-primary rounded-pill px-4" id="botonAceptarLogin">Entrar</button>
</div>
</div>
</div>
</div>
<!-- MODAL DE REGISTRO -->
<div class="modal fade" id="modalRegistro" tabindex="-1" aria-labelledby="registroModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-dark">
<div class="modal-header">
<h1 class="modal-title fs-5 fw-bold" id="registroModalLabel">
<i class="fa-solid fa-user-plus text-success me-2"></i>Registrarse
</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
</div>
<div class="modal-body">
<form id="formRegistro">
<div class="form-floating mb-3">
<input type="text" class="form-control border-dark" id="regNombre" name="nombreUsuario" placeholder="Nombre" required>
<label for="regNombre">Nombre</label>
</div>
<div class="form-floating mb-3">
<input type="email" class="form-control border-dark" id="regEmail" name="email" placeholder="Correo electrónico" required>
<label for="regEmail">Correo electrónico</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control border-dark" id="regPassword" name="contrasena" placeholder="Contraseña" required>
<label for="regPassword">Contraseña</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control border-dark" id="regPasswordConfirm" name="contrasenaConfirm" placeholder="Confirmar contraseña" required>
<label for="regPasswordConfirm">Confirmar contraseña</label>
</div>
<input type="hidden" name="orden" value="registrar">
</form>
<div id="errorRegistro" class="text-danger fw-bold mt-2"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary rounded-pill px-3" data-bs-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-success rounded-pill px-4" id="botonAceptarRegistro">Registrarse</button>
</div>
</div>
</div>
</div>
</body>
-108
View File
@@ -1,108 +0,0 @@
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- FontAwesome para iconos -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
<!-- Google Fonts para estilo Kahoot -->
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/index.css">
<script src="js/jquery-4.0.0.min.js"></script>
<nav class="navbar navbar-expand-lg navbar-kahoot py-3 mb-4">
<div class="container">
<a class="navbar-brand" href="index.php">
<img src="img/favicon/favicon.svg" alt="TRIVIAGMÁTICO" class="me-2" style="height: 35px;">
TRIVIAGMÁTICO
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarContent">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0"></ul>
<!-- Contenedor dinámico de usuario/botones -->
<div class="d-flex align-items-center gap-3" id="contenedorUsuarioCabecera">
</div>
</div>
</div>
</nav>
<!-- MODAL DE LOGIN -->
<div class="modal fade" id="modalLogin" tabindex="-1" aria-labelledby="loginModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-dark">
<div class="modal-header">
<h1 class="modal-title fs-5 fw-bold" id="loginModalLabel">
<i class="fa-solid fa-right-to-bracket text-primary me-2"></i>Iniciar sesión
</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
</div>
<div class="modal-body">
<form id="formLogin">
<div class="form-floating mb-3">
<input type="email" class="form-control border-dark" id="loginEmail" name="email" placeholder="Correo electrónico" required>
<label for="loginEmail">Correo electrónico</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control border-dark" id="loginPassword" name="contrasena" placeholder="Contraseña" required>
<label for="loginPassword">Contraseña</label>
</div>
<div class="form-check">
<input class="form-check-input" id="recordar" name="recordar" type="checkbox" />
<label for="recordar" class="small">Recuérdeme durante 10 días</label>
</div>
<input type="hidden" name="orden" value="validar">
</form>
<div id="errorLogin" class="text-danger fw-bold mt-2"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary rounded-pill px-3" data-bs-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-primary rounded-pill px-4" id="botonAceptarLogin">Entrar</button>
</div>
</div>
</div>
</div>
<!-- MODAL DE REGISTRO -->
<div class="modal fade" id="modalRegistro" tabindex="-1" aria-labelledby="registroModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-dark">
<div class="modal-header">
<h1 class="modal-title fs-5 fw-bold" id="registroModalLabel">
<i class="fa-solid fa-user-plus text-success me-2"></i>Registrarse
</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
</div>
<div class="modal-body">
<form id="formRegistro">
<div class="form-floating mb-3">
<input type="text" class="form-control border-dark" id="regNombre" name="nombreUsuario" placeholder="Nombre" required>
<label for="regNombre">Nombre</label>
</div>
<div class="form-floating mb-3">
<input type="email" class="form-control border-dark" id="regEmail" name="email" placeholder="Correo electrónico" required>
<label for="regEmail">Correo electrónico</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control border-dark" id="regPassword" name="contrasena" placeholder="Contraseña" required>
<label for="regPassword">Contraseña</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control border-dark" id="regPasswordConfirm" name="contrasenaConfirm" placeholder="Confirmar contraseña" required>
<label for="regPasswordConfirm">Confirmar contraseña</label>
</div>
<input type="hidden" name="orden" value="registrar">
</form>
<div id="errorRegistro" class="text-danger fw-bold mt-2"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary rounded-pill px-3" data-bs-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-success rounded-pill px-4" id="botonAceptarRegistro">Registrarse</button>
</div>
</div>
</div>
</div>
<script src="js/cabecera.js"></script>
+1 -1
View File
@@ -1,6 +1,6 @@
<?php <?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/triviagmatico/includes/conexionBD.php';
require_once __DIR__ . '/../includes/conexionBD.php';
class Categoria{ class Categoria{
+9 -2
View File
@@ -229,7 +229,13 @@ class Juego
* - la respuesta pertenece a esa pregunta * - la respuesta pertenece a esa pregunta
* - el usuario no ha respondido ya esa pregunta * - el usuario no ha respondido ya esa pregunta
*/ */
public static function registrarRespuesta($idPartida, $idUsuario, $idPartidaxPregunta, $idRespuesta) public static function registrarRespuesta(
$idPartida,
$idUsuario,
$idPartidaxPregunta,
$idRespuesta,
$tiempoRespuesta
)
{ {
$conexion = conexionBD(); $conexion = conexionBD();
if (is_array($conexion)) { if (is_array($conexion)) {
@@ -298,7 +304,8 @@ class Juego
null, null,
$idPartidaxPregunta, $idPartidaxPregunta,
$idUsuario, $idUsuario,
$idRespuesta $idRespuesta,
$tiempoRespuesta
); );
$guardado = $almacenada->guardarRespuesta(); $guardado = $almacenada->guardarRespuesta();
+21 -5
View File
@@ -132,23 +132,39 @@ class Partida
} }
public function iniciarPartida(){ public function iniciarPartida()
{
$conexion = conexionBD(); $conexion = conexionBD();
if (is_array($conexion)) { if (is_array($conexion)) {
return $conexion; return $conexion;
} }
try { try {
$consulta = $conexion->prepare("UPDATE partida SET fechaInicio=NOW() WHERE idPartida=:idPartida AND fechaInicio IS NULL");
$consulta->bindParam(":idPartida", $this->idPartida); $consulta = $conexion->prepare("
UPDATE partida
SET fechaInicio = NOW()
WHERE idPartida = :idPartida
AND fechaInicio IS NULL
");
$consulta->bindParam(
":idPartida",
$this->idPartida
);
$consulta->execute(); $consulta->execute();
return [ return [
"exito" => "La partida ha comenzado.", "exito" => "La partida ha comenzado.",
"exito_tecnico" => $this->idPartida "exito_tecnico" => $this->idPartida
]; ];
} catch (PDOException $error) { } catch (PDOException $error) {
return [ return [
"error" => "Ocurrió un error al iniciar la partida.", "error" => "ERROR REAL: " . $error->getMessage()
'error_tecnico' => $error->getMessage()
]; ];
} }
} }
+2
View File
@@ -24,6 +24,8 @@ class Respuesta{
$consulta->bindParam(':idPregunta', $this->idPregunta); $consulta->bindParam(':idPregunta', $this->idPregunta);
$consulta->bindParam(':nombreRespuesta', $this->nombreRespuesta); $consulta->bindParam(':nombreRespuesta', $this->nombreRespuesta);
$consulta->bindParam(':correcta', $this->correcta); $consulta->bindParam(':correcta', $this->correcta);
$consulta->execute(); $consulta->execute();
$respuesta = [ $respuesta = [
'exito' => 'La respuesta se guardó correctamente.', 'exito' => 'La respuesta se guardó correctamente.',
+17 -7
View File
@@ -7,12 +7,14 @@ class RespuestaAlmacenada {
public $idPartidaxPregunta; public $idPartidaxPregunta;
public $idUsuario; public $idUsuario;
public $idRespuesta; public $idRespuesta;
public $tiempoRespuesta;
public function __construct($idRespuestaAlmacenada = null, $idPartidaxPregunta = null, $idUsuario = null, $idRespuesta = null) { public function __construct($idRespuestaAlmacenada = null, $idPartidaxPregunta = null, $idUsuario = null, $idRespuesta = null, $tiempoRespuesta = null) {
$this->idRespuestaAlmacenada = $idRespuestaAlmacenada; $this->idRespuestaAlmacenada = $idRespuestaAlmacenada;
$this->idPartidaxPregunta = $idPartidaxPregunta; $this->idPartidaxPregunta = $idPartidaxPregunta;
$this->idUsuario = $idUsuario; $this->idUsuario = $idUsuario;
$this->idRespuesta = $idRespuesta; $this->idRespuesta = $idRespuesta;
$this->tiempoRespuesta = $tiempoRespuesta;
} }
/** /**
@@ -20,25 +22,33 @@ class RespuestaAlmacenada {
*/ */
public function guardarRespuesta() { public function guardarRespuesta() {
$conexion = conexionBD(); $conexion = conexionBD();
if (is_array($conexion)) return $conexion;
if (is_array($conexion)) {
return $conexion;
}
try { try {
$sql = "INSERT INTO respuestaalmacenada (idPartidaxPregunta, idUsuario, idRespuesta) $sql = "INSERT INTO respuestaalmacenada
VALUES (:idPartidaxPregunta, :idUsuario, :idRespuesta)"; (idPartidaxPregunta, idUsuario, idRespuesta, tiempoRespuesta)
VALUES
(:idPartidaxPregunta, :idUsuario, :idRespuesta, :tiempoRespuesta)";
$consulta = $conexion->prepare($sql); $consulta = $conexion->prepare($sql);
$consulta->bindParam(':idPartidaxPregunta', $this->idPartidaxPregunta); $consulta->bindParam(':idPartidaxPregunta', $this->idPartidaxPregunta);
$consulta->bindParam(':idUsuario', $this->idUsuario); $consulta->bindParam(':idUsuario', $this->idUsuario);
$consulta->bindParam(':idRespuesta', $this->idRespuesta); $consulta->bindParam(':idRespuesta', $this->idRespuesta);
$consulta->bindParam(':tiempoRespuesta', $this->tiempoRespuesta);
$consulta->execute(); $consulta->execute();
return [ return [
'exito' => 'Respuesta del usuario almacenada correctamente.', 'exito' => 'Respuesta almacenada correctamente.'
'exito_tecnico' => $conexion->lastInsertId()
]; ];
} catch (PDOException $error) { } catch (PDOException $error) {
return [ return [
'error' => 'Ocurrió un error al guardar la respuesta del jugador.', 'error' => 'Ocurrió un error al guardar la respuesta.',
'error_tecnico' => $error->getMessage() 'error_tecnico' => $error->getMessage()
]; ];
} }
+20 -7
View File
@@ -74,20 +74,27 @@ switch ($orden) {
case 'responder': case 'responder':
if (!isset($_POST['idPartidaxPregunta']) || !isset($_POST['idRespuesta'])){ if (
!isset($_POST['idPartidaxPregunta']) ||
!isset($_POST['idRespuesta']) ||
!isset($_POST['tiempoRespuesta'])
) {
echo json_encode([ echo json_encode([
'error' => 'Faltan datos para registrar la respuesta.' 'error' => 'Faltan datos para registrar la respuestfdfa.'
]); ]);
break; break;
} }
$idPartidaxPregunta = intval($_POST['idPartidaxPregunta']); $idPartidaxPregunta = intval($_POST['idPartidaxPregunta']);
$idRespuesta = intval($_POST['idRespuesta']); $idRespuesta = intval($_POST['idRespuesta']);
$tiempoRespuesta = intval($_POST['tiempoRespuesta']);
if ($idPartidaxPregunta <= 0 || $idRespuesta <= 0){ if (
$idPartidaxPregunta <= 0 ||
$idRespuesta <= 0 ||
$tiempoRespuesta < 0
) {
echo json_encode([ echo json_encode([
'error' => 'Los datos de la respuesta no son válidos.' 'error' => 'Los datos de la respuesta no son válidos.'
]); ]);
@@ -95,9 +102,15 @@ switch ($orden) {
break; break;
} }
// Registramos la respuesta del usuario // Registramos la respuesta del usuario junto con su tiempo de respuesta
$resultado = Juego::registrarRespuesta($idPartida, $idUsuario, $idPartidaxPregunta, $idRespuesta); $resultado = Juego::registrarRespuesta(
$idPartida,
$idUsuario,
$idPartidaxPregunta,
$idRespuesta,
$tiempoRespuesta
);
echo json_encode($resultado); echo json_encode($resultado);
+36 -2
View File
@@ -795,13 +795,47 @@ switch ($_POST['orden']) {
*/ */
$resultado = $partida->iniciar(); $resultado = $partida->iniciarPartida();
echo json_encode($resultado); echo json_encode($resultado);
break; break;
case 'comprobarInicio':
if (!isset($_POST['idPartida'])) {
echo json_encode([
'error' => 'No se ha indicado la partida.'
]);
break;
}
$partida = new Partida();
$partida->idPartida =
intval($_POST['idPartida']);
$datosPartida = $partida->buscar();
if (!$datosPartida || isset($datosPartida['error'])) {
echo json_encode([
'error' => 'La partida no existe.'
]);
break;
}
echo json_encode([
'iniciada' => $datosPartida['fechaInicio'] !== null
]);
break;
// OBTENER LA PREGUNTA ACTUAL // OBTENER LA PREGUNTA ACTUAL
@@ -933,7 +967,7 @@ switch ($_POST['orden']) {
) { ) {
echo json_encode([ echo json_encode([
'error' => 'Faltan datos para registrar la respuesta.' 'error' => 'Faltan datos para registrar la respuestadd.'
]); ]);
break; break;
+84 -16
View File
@@ -1,6 +1,6 @@
<?php <?php
session_start(); session_start();
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/conexionBD.php'; require_once __DIR__ . '/../includes/conexionBD.php';
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
@@ -26,7 +26,7 @@ if (is_array($conexion)) {
switch ($orden) { switch ($orden) {
case 'comprobarEstado': case 'comprobarEstado':
try { try {
// Contar jugadores totales apuntados en los equipos de esta partida // 1. Contar cuántos jugadores hay asignados en esta partida
$stmt = $conexion->prepare(" $stmt = $conexion->prepare("
SELECT COUNT(exu.idUsuario) AS total_jugadores SELECT COUNT(exu.idUsuario) AS total_jugadores
FROM equipoxpartida exp FROM equipoxpartida exp
@@ -38,7 +38,7 @@ switch ($orden) {
$preguntasTotalesEsperadas = $totalJugadores * 10; $preguntasTotalesEsperadas = $totalJugadores * 10;
// Contar respuestas dadas en la partida // 2. Contar cuántas respuestas reales se han guardado
$stmtRespuestas = $conexion->prepare(" $stmtRespuestas = $conexion->prepare("
SELECT COUNT(*) SELECT COUNT(*)
FROM respuestaalmacenada ra FROM respuestaalmacenada ra
@@ -50,17 +50,16 @@ switch ($orden) {
$terminada = ($respuestasRespondidas >= $preguntasTotalesEsperadas && $preguntasTotalesEsperadas > 0); $terminada = ($respuestasRespondidas >= $preguntasTotalesEsperadas && $preguntasTotalesEsperadas > 0);
// Cuando la partida finaliza, se actualizan los históricos // 3. Si ha terminado, guardamos los datos históricos una sola vez
if ($terminada && !isset($_SESSION['partidas_procesadas'][$idPartida])) { if ($terminada && !isset($_SESSION['partidas_procesadas'][$idPartida])) {
$conexion->beginTransaction(); $conexion->beginTransaction();
// CÁLCULO DE VELOCIDAD PREGUNTA A PREGUNTA EN SESIÓN // --- CÁLCULO DE VELOCIDAD ---
if (!isset($_SESSION['primeros_en_acertar'][$idPartida])) { if (!isset($_SESSION['primeros_en_acertar'][$idPartida])) {
$_SESSION['primeros_en_acertar'][$idPartida] = []; $_SESSION['primeros_en_acertar'][$idPartida] = [];
} }
// Vemos quién fue el primero
$stmtVelocidad = $conexion->prepare(" $stmtVelocidad = $conexion->prepare("
SELECT ra.idPartidaxPregunta, ra.idUsuario SELECT ra.idPartidaxPregunta, ra.idUsuario
FROM respuestaalmacenada ra FROM respuestaalmacenada ra
@@ -81,8 +80,7 @@ switch ($orden) {
} }
} }
// Actualizamos la base de datos // Consulta de aciertos
// Buscamos los aciertos de cada jugador en la partida actual
$stmtAciertos = $conexion->prepare(" $stmtAciertos = $conexion->prepare("
SELECT ra.idUsuario, exu.idEquipo, COUNT(*) as aciertos_partida SELECT ra.idUsuario, exu.idEquipo, COUNT(*) as aciertos_partida
FROM respuestaalmacenada ra FROM respuestaalmacenada ra
@@ -90,12 +88,12 @@ switch ($orden) {
INNER JOIN respuesta r ON ra.idRespuesta = r.idRespuesta INNER JOIN respuesta r ON ra.idRespuesta = r.idRespuesta
INNER JOIN equipoxusuario exu ON ra.idUsuario = exu.idUsuario INNER JOIN equipoxusuario exu ON ra.idUsuario = exu.idUsuario
WHERE pxp.idPartida = :idPartida AND r.correcta = 1 WHERE pxp.idPartida = :idPartida AND r.correcta = 1
GROUP BY ra.idUsuario GROUP BY ra.idUsuario, exu.idEquipo
"); ");
$stmtAciertos->execute([':idPartida' => $idPartida]); $stmtAciertos->execute([':idPartida' => $idPartida]);
$jugadoresPartida = $stmtAciertos->fetchAll(PDO::FETCH_ASSOC); $jugadoresPartida = $stmtAciertos->fetchAll(PDO::FETCH_ASSOC);
$updateAciertosGlobales = $conexion->prepare(" $updateAciertos = $conexion->prepare("
UPDATE usuario UPDATE usuario
SET aciertos = aciertos + :nuevos_aciertos SET aciertos = aciertos + :nuevos_aciertos
WHERE idUsuario = :idUsuario WHERE idUsuario = :idUsuario
@@ -107,7 +105,6 @@ switch ($orden) {
$idE = (int)$jp['idEquipo']; $idE = (int)$jp['idEquipo'];
$nuevosAciertos = (int)$jp['aciertos_partida']; $nuevosAciertos = (int)$jp['aciertos_partida'];
// Sumamos los aciertos al perfil del usuario
$updateAciertos->execute([ $updateAciertos->execute([
':nuevos_aciertos' => $nuevosAciertos, ':nuevos_aciertos' => $nuevosAciertos,
':idUsuario' => $idU ':idUsuario' => $idU
@@ -119,11 +116,10 @@ switch ($orden) {
$puntosEquipos[$idE] += $nuevosAciertos; $puntosEquipos[$idE] += $nuevosAciertos;
} }
// Determinamos qué equipo ha obtenido más aciertos en la partida if (!empty($puntosEquipos)) {
arsort($puntosEquipos); arsort($puntosEquipos);
$idEquipoGanador = key($puntosEquipos); $idEquipoGanador = key($puntosEquipos);
// Obtenemos todos los usuarios de la partida para asignar victorias/derrotas
$stmtMiembros = $conexion->prepare(" $stmtMiembros = $conexion->prepare("
SELECT exu.idUsuario, exu.idEquipo SELECT exu.idUsuario, exu.idEquipo
FROM equipoxpartida exp FROM equipoxpartida exp
@@ -146,6 +142,15 @@ switch ($orden) {
$updateDerrota->execute([':idUsuario' => $idU]); $updateDerrota->execute([':idUsuario' => $idU]);
} }
} }
}
// 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->execute([':idPartida' => $idPartida]);
$conexion->commit(); $conexion->commit();
$_SESSION['partidas_procesadas'][$idPartida] = true; $_SESSION['partidas_procesadas'][$idPartida] = true;
@@ -160,7 +165,70 @@ switch ($orden) {
} }
break; break;
default: case 'registrarSalidaUsuario':
echo json_encode(['error' => 'Acción no permitida']); try {
break; $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
INNER JOIN equipoxusuario exu ON exp.idEquipo = exu.idEquipo
WHERE exp.idPartida = :idPartida
");
$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
WHERE pxp.idPartida = :idPartida
");
$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]);
}
$conexion->commit();
echo json_encode(['exito' => true, 'usuarios_quedan' => $jugadoresRestantes]);
} catch (PDOException $e) {
if ($conexion->inTransaction()) {
$conexion->rollBack();
}
echo json_encode(['error' => $e->getMessage()]);
}
break;
} }
+1
View File
@@ -121,6 +121,7 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 15px; gap: 15px;
text-decoration: none;
} }
.btn-play-kahoot:hover { .btn-play-kahoot:hover {
+385 -122
View File
@@ -1,179 +1,442 @@
/* ========================================================================== /* ==========================================================================
ESTILOS GENERALES Y FONDO VARIABLES DEL PROYECTO
========================================================================== */ ========================================================================== */
:root {
--kahoot-purple: #46178f;
--kahoot-purple-dark: #35116f;
--kahoot-blue: #1368ce;
--kahoot-blue-dark: #0c4891;
--kahoot-red: #e21b3c;
--kahoot-yellow: #ffa602;
--kahoot-yellow-dark: #d88900;
--kahoot-green: #26890c;
--kahoot-green-hover: #1f6f09;
--background: #f2f2f2;
--text-dark: #333333;
--text-muted: #666666;
--white: #ffffff;
}
/* ==========================================================================
ESTILOS GENERALES
========================================================================== */
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
box-shadow: none;
box-sizing: border-box; box-sizing: border-box;
} }
body { body {
font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; font-family: 'Fredoka', sans-serif;
background-color: #f0f4f8; background-color: var(--background);
color: #2c3e50; color: var(--text-dark);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh; min-height: 100vh;
padding: 20px; padding: 30px 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) CONTENEDOR PRINCIPAL
========================================================================== */ ========================================================================== */
#pantalla-espera {
padding: 60px 20px; .contenedor {
width: 100%;
max-width: 1000px;
margin: 0 auto;
background-color: var(--white);
border-radius: 20px;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.10);
overflow: hidden;
} }
/* ==========================================================================
PANTALLA DE ESPERA
========================================================================== */
#pantalla-espera {
padding: 70px 30px;
text-align: center;
}
#pantalla-espera h2 {
color: var(--kahoot-purple);
font-size: 2rem;
font-weight: 700;
margin-bottom: 15px;
}
#pantalla-espera p {
color: var(--text-muted);
font-size: 1.1rem;
margin-bottom: 35px;
}
/* ==========================================================================
LOADER
========================================================================== */
.loader { .loader {
width: 60px; width: 65px;
height: 60px; height: 65px;
border: 6px solid #e2e8f0;
border-top: 6px solid #3182ce;
border-radius: 50%;
margin: 0 auto; margin: 0 auto;
animation: spin 1.2s linear infinite;
border: 7px solid #e5e5e5;
border-top-color: var(--kahoot-purple);
border-radius: 50%;
animation: spin 1s linear infinite;
} }
@keyframes spin { @keyframes spin {
0% { transform: rotate(0deg); } from {
100% { transform: rotate(360deg); } transform: rotate(0deg);
} }
to {
transform: rotate(360deg);
}
}
/* ========================================================================== /* ==========================================================================
TABLAS DE CLASIFICACIÓN (RANKING) CABECERA DE RESULTADOS
========================================================================== */ ========================================================================== */
.tabla-ranking {
width: 100%; #pantalla-resultados {
border-collapse: collapse; padding: 40px;
margin-bottom: 20px;
font-size: 1.05rem;
} }
.tabla-ranking th, #pantalla-resultados h1 {
.tabla-ranking td { text-align: center;
padding: 16px 20px; color: var(--kahoot-yellow);
font-size: 2.6rem;
font-weight: 700;
margin-bottom: 35px;
text-shadow: 2px 2px 0 rgba(70, 23, 143, 0.10);
}
#pantalla-resultados h2 {
display: flex;
align-items: center;
gap: 10px;
font-size: 1.5rem;
font-weight: 700;
margin-top: 35px;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 3px solid #eee;
}
/* ==========================================================================
TABLAS
========================================================================== */
.tabla-ranking {
width: 100%;
border-collapse: separate;
border-spacing: 0;
overflow: hidden;
background-color: #fff;
border: 2px solid #eeeeee;
border-radius: 15px;
margin-bottom: 30px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.06);
}
/* Cabecera */
.tabla-ranking thead th {
background-color: var(--kahoot-purple);
color: white;
padding: 15px 18px;
font-size: 0.95rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.3px;
text-align: left; text-align: left;
} }
.tabla-ranking th { .tabla-ranking thead th:first-child {
background-color: #2d3748; border-top-left-radius: 12px;
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 thead th:last-child {
.tabla-ranking th:last-child, border-top-right-radius: 12px;
.tabla-ranking td:last-child {
text-align: right;
} }
.tabla-ranking tr {
border-bottom: 1px solid #e2e8f0; /* Celdas */
transition: background-color 0.2s;
.tabla-ranking tbody td {
padding: 16px 18px;
font-size: 1rem;
font-weight: 500;
border-bottom: 1px solid #eeeeee;
color: var(--text-dark);
}
/* Última fila */
.tabla-ranking tbody tr:last-child td {
border-bottom: none;
}
/* Hover */
.tabla-ranking tbody tr {
transition:
transform 0.15s ease,
background-color 0.15s ease;
} }
.tabla-ranking tbody tr:hover { .tabla-ranking tbody tr:hover {
background-color: #f7fafc; background-color: #f7f3ff;
} }
/* ========================================================================== /* ==========================================================================
RESALTADO DE GANADORES (1º PUESTO) COLUMNA DE POSICIÓN
========================================================================== */ ========================================================================== */
/* Fila del Equipo Ganador y Jugador Ganador */
.tabla-ranking tr.top-team, .tabla-ranking tbody td:first-child {
.tabla-ranking tr.top-player { font-weight: 700;
background-color: #fefcbf !important; /* Amarillo suave */ color: var(--kahoot-purple);
font-weight: bold; width: 100px;
} }
/* Cambiar el color del texto del puesto #1 a dorado/corona */
/* ==========================================================================
PUNTOS
========================================================================== */
.tabla-ranking td strong {
color: var(--kahoot-green);
font-size: 1.15rem;
font-weight: 700;
}
/* ==========================================================================
EQUIPO / JUGADOR GANADOR
========================================================================== */
.tabla-ranking tr.top-team,
.tabla-ranking tr.top-player {
background-color: #fff7df !important;
font-weight: 700;
}
/* Línea lateral amarilla */
.tabla-ranking tr.top-team td:first-child, .tabla-ranking tr.top-team td:first-child,
.tabla-ranking tr.top-player td:first-child { .tabla-ranking tr.top-player td:first-child {
color: #b7791f; color: var(--kahoot-yellow-dark);
font-size: 1.2rem; font-size: 1.15rem;
}
/* Puntos del ganador */
.tabla-ranking tr.top-team td strong,
.tabla-ranking tr.top-player td strong {
color: var(--kahoot-green);
}
/* ==========================================================================
BOTÓN VOLVER AL INICIO
========================================================================== */
.contenedor-boton {
display: flex;
justify-content: center;
align-items: center;
margin-top: 40px;
padding-top: 10px;
}
/* Botón */
.btn-inicio {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
min-width: 240px;
padding: 15px 28px;
background-color: var(--kahoot-blue);
color: white;
border: none;
border-bottom: 5px solid var(--kahoot-blue-dark);
border-radius: 12px;
font-family: 'Fredoka', sans-serif;
font-size: 1.1rem;
font-weight: 700;
text-decoration: none;
box-shadow: 0 5px 10px rgba(19, 104, 206, 0.25);
transition: all 0.15s ease;
}
/* Hover */
.btn-inicio:hover {
background-color: #0f56ab;
color: white;
transform: translateY(-3px);
box-shadow: 0 8px 15px rgba(19, 104, 206, 0.30);
}
/* Click */
.btn-inicio:active {
transform: translateY(3px);
border-bottom-width: 2px;
box-shadow: 0 3px 6px rgba(19, 104, 206, 0.20);
}
/* ==========================================================================
RESPONSIVE
========================================================================== */
@media (max-width: 768px) {
body {
padding: 15px 10px;
}
#pantalla-resultados {
padding: 25px 15px;
}
#pantalla-resultados h1 {
font-size: 2rem;
margin-bottom: 25px;
}
#pantalla-resultados h2 {
font-size: 1.3rem;
}
.tabla-ranking {
font-size: 0.9rem;
}
.tabla-ranking thead th,
.tabla-ranking tbody td {
padding: 12px 10px;
}
.tabla-ranking thead th {
font-size: 0.75rem;
}
.tabla-ranking tbody td {
font-size: 0.9rem;
} }
.tabla-ranking td strong { .tabla-ranking td strong {
color: #2f855a; /* Verde para destacar los aciertos conseguidos */ font-size: 1rem;
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 { .btn-inicio {
display: inline-block; width: 100%;
background-color: #3182ce; /* Azul corporativo */ min-width: 0;
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); MÓVILES PEQUEÑOS
transform: translateY(-2px); /* Pequeño salto hacia arriba */ ========================================================================== */
@media (max-width: 500px) {
body {
padding: 10px 5px;
} }
.btn-inicio:active { #pantalla-espera {
transform: translateY(0); /* Vuelve a su posición normal al pulsar */ padding: 50px 20px;
box-shadow: 0 2px 4px rgba(43, 108, 176, 0.2); }
#pantalla-espera h2 {
font-size: 1.5rem;
}
#pantalla-espera p {
font-size: 0.95rem;
}
#pantalla-resultados {
padding: 20px 10px;
}
#pantalla-resultados h1 {
font-size: 1.7rem;
}
#pantalla-resultados h2 {
font-size: 1.15rem;
}
.tabla-ranking {
display: block;
overflow-x: auto;
white-space: nowrap;
}
.tabla-ranking thead th,
.tabla-ranking tbody td {
padding: 10px 8px;
}
.contenedor-boton {
margin-top: 25px;
}
} }
+10 -2
View File
@@ -4,13 +4,20 @@
<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>Triviagmático</title>
<link rel="icon" type="image/svg+xml" href="img/favicon/favicon.svg"> <link rel="icon" type="image/svg+xml" href="img/favicon/favicon.svg">
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- FontAwesome para iconos -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
<!-- Google Fonts para estilo Kahoot -->
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/index.css">
<script src="js/jquery-4.0.0.min.js"></script>
</head> </head>
<body> <body>
<?php include 'cabecera.php'; ?> <header id="cabecera-container"></header>
<div class="container my-5"> <div class="container my-5">
<div class="row justify-content-center align-items-center g-4"> <div class="row justify-content-center align-items-center g-4">
@@ -46,6 +53,7 @@
<!-- JS de Bootstrap --> <!-- JS de Bootstrap -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="js/index.js"></script> <script src="js/index.js"></script>
<script src="js/cabecera.js"></script>
</body> </body>
</html> </html>
+353 -279
View File
@@ -1,435 +1,509 @@
let usuarioYaEstaEnEquipo = false; let intervaloBuscadorSalas = null;
let cargandoSalas = false;
$(document).ready(function () { function iniciarActualizacionSalas() {
comprobarSalaUsuario(); if (intervaloBuscadorSalas) {
}); clearInterval(intervaloBuscadorSalas);
// 1. Comprobar si el usuario actual ya pertenece a una sala
function comprobarSalaUsuario() {
$("#cargandoSalas").remove();
$.ajax({
url: "controladores/controladorEquipoxUsuario.php",
type: "POST",
dataType: "json",
data: { orden: "obtenerSalaUsuario" },
success: function (respuesta) {
if (respuesta.error || !respuesta.asociado) {
usuarioYaEstaEnEquipo = false;
$("#contenedorCrearSala").show();
cargarSalas();
} else {
usuarioYaEstaEnEquipo = true;
$("#contenedorCrearSala").hide(); // Ocultar "Crear Sala" si ya pertenece a una
cargarSalaUsuario(respuesta.idPartida);
}
},
error: function (xhr, status, error) {
console.error("Error al comprobar la sala del usuario:", error);
usuarioYaEstaEnEquipo = false;
cargarSalas();
},
});
} }
// 2. Cargar únicamente la sala en la que está metido el usuario cargarSalas();
function cargarSalaUsuario(idPartida) {
$.ajax({ intervaloBuscadorSalas = setInterval(function () {
url: "controladores/controladorPartida.php", if (!usuarioYaEstaEnEquipo) {
type: "POST", cargarSalas();
dataType: "json", }
data: { orden: "buscar", idPartida: idPartida }, }, 5000);
success: function (partida) { }
if (partida.error) {
console.error(partida.error); function cargarSalas() {
if (cargandoSalas) {
return; return;
} }
$("#contenedorSalas").empty();
cargarInformacionSala(partida);
},
error: function (xhr, status, error) {
console.error("Error al obtener la sala del usuario:", error);
},
});
}
// 3. Cargar la lista completa de todas las salas cargandoSalas = true;
function cargarSalas() {
$.ajax({ $.ajax({
url: "controladores/controladorPartida.php", url: "controladores/controladorPartida.php",
type: "POST", type: "POST",
dataType: "json", dataType: "json",
data: { orden: "listar" }, data: {
orden: "listar",
},
success: function (partidas) { success: function (partidas) {
const contenedor = $("#contenedorSalas"); const contenedor = $("#contenedorSalas");
contenedor.empty();
if (!Array.isArray(partidas) || partidas.length === 0) { if (!Array.isArray(partidas) || partidas.length === 0) {
contenedor.html(` $(".sala-item").remove();
<div class="col-12 text-center">
<p class="text-muted">No hay salas disponibles actualmente.</p> if ($("#mensajeSinSalas").length === 0) {
contenedor.append(`
<div
id="mensajeSinSalas"
class="col-12 text-center">
<p class="text-muted">
No hay salas disponibles actualmente.
</p>
</div> </div>
`); `);
}
return; return;
} }
$("#mensajeSinSalas").remove();
const idsPartidas = partidas.map(function (partida) {
return String(partida.idPartida);
});
$(".sala-item").each(function () {
const idPartida = String($(this).data("id-partida"));
if (!idsPartidas.includes(idPartida)) {
$(this).remove();
}
});
partidas.forEach(function (partida) { partidas.forEach(function (partida) {
cargarInformacionSala(partida); cargarSalaBuscador(partida);
}); });
}, },
error: function (xhr, status, error) { error: function (xhr, status, error) {
console.error("Error al obtener las partidas:", error); console.error(
"Error al obtener las partidas:",
error
);
},
complete: function () {
cargandoSalas = false;
}, },
}); });
} }
// 4. Obtener equipos y jugadores asociados a una sala concreta function cargarSalaBuscador(partida) {
function cargarInformacionSala(partida) {
$.ajax({ $.ajax({
url: "controladores/controladorPartida.php", url: "controladores/controladorPartida.php",
type: "POST", type: "POST",
dataType: "json", dataType: "json",
data: { orden: "getEquipos", idPartida: partida.idPartida }, data: {
orden: "getEquipos",
idPartida: partida.idPartida,
},
success: function (equipos) { success: function (equipos) {
$.ajax({ $.ajax({
url: "controladores/controladorPartida.php", url: "controladores/controladorPartida.php",
type: "POST", type: "POST",
dataType: "json", dataType: "json",
data: { orden: "getJugadores", idPartida: partida.idPartida }, data: {
success: function (jugadores) { orden: "getJugadores",
mostrarSala(partida, equipos, jugadores); idPartida: partida.idPartida,
}, },
success: function (jugadores) {
if (
!Array.isArray(jugadores) ||
jugadores.length === 0
) {
$(
`.sala-item[data-id-partida="${partida.idPartida}"]`
).remove();
comprobarSiNoHaySalas();
return;
}
actualizarSalaBuscador(
partida,
equipos,
jugadores
);
},
error: function (xhr, status, error) { error: function (xhr, status, error) {
console.error("Error al obtener jugadores:", error); console.error(
"Error al obtener jugadores:",
error
);
}, },
}); });
}, },
error: function (xhr, status, error) { error: function (xhr, status, error) {
console.error("Error al obtener equipos:", error); console.error(
"Error al obtener equipos:",
error
);
}, },
}); });
} }
// 5. Renderizar el HTML de la sala y botones según estado function comprobarSiNoHaySalas() {
function mostrarSala(partida, equipos, jugadores) { if ($(".sala-item").length === 0) {
const contenedor = $("#contenedorSalas"); if ($("#mensajeSinSalas").length === 0) {
$("#contenedorSalas").append(`
<div
id="mensajeSinSalas"
class="col-12 text-center">
<p class="text-muted">
No hay salas disponibles actualmente.
</p>
</div>
`);
}
}
}
function actualizarSalaBuscador(
partida,
equipos,
jugadores
) {
$("#mensajeSinSalas").remove();
const selectorSala =
`.sala-item[data-id-partida="${partida.idPartida}"]`;
const salaExistente = $(selectorSala);
if (salaExistente.length === 0) {
crearSalaBuscador(
partida,
equipos,
jugadores
);
return;
}
const equiposHTML =
generarEquiposHTML(
partida,
equipos,
jugadores
);
salaExistente
.find(".equipos")
.html(equiposHTML);
}
function crearSalaBuscador(
partida,
equipos,
jugadores
) {
$("#mensajeSinSalas").remove();
const equiposHTML =
generarEquiposHTML(
partida,
equipos,
jugadores
);
const salaHTML = `
<div
class="col-12 col-md-10 col-lg-8 sala-item"
data-id-partida="${partida.idPartida}">
<div class="sala card p-3 shadow-sm mb-4">
<div
class="sala-header h4 text-center mb-3 text-white">
${escapeHTML(partida.nombrePartida)}
</div>
<div class="sala-body">
<div class="equipos d-flex justify-content-around">
${equiposHTML}
</div>
</div>
</div>
</div>
`;
$("#contenedorSalas").append(salaHTML);
}
function generarEquiposHTML(
partida,
equipos,
jugadores
) {
let equiposHTML = ""; let equiposHTML = "";
equipos.forEach(function (equipo) { equipos.forEach(function (equipo) {
const jugadoresEquipo = jugadores.filter(function (jugador) { const jugadoresEquipo =
return jugador.idEquipo == equipo.idEquipo; jugadores.filter(function (jugador) {
return (
jugador.idEquipo ==
equipo.idEquipo
);
}); });
let jugadoresHTML = ""; let jugadoresHTML = "";
if (jugadoresEquipo.length > 0) { if (jugadoresEquipo.length > 0) {
jugadoresEquipo.forEach(function (jugador) { jugadoresEquipo.forEach(function (jugador) {
const esHost = jugador.idUsuario == partida.idUsuario; const esHost =
jugador.idUsuario ==
partida.idUsuario;
jugadoresHTML += ` jugadoresHTML += `
<div class="jugador border border-2 d-flex align-items-center justify-content-between ${ <div
esHost ? "jugador-host" : "" class="jugador border border-2 d-flex align-items-center justify-content-between">
}">
<div> <div>
<span class="avatar">${esHost ? '<i class="bi bi-award-fill"></i>' : '<i class="bi bi-person-fill"></i>'}</span>
${escapeHTML(jugador.nombreUsuario)} <span class="avatar">
${
esHost
? '<i class="bi bi-award-fill"></i>'
: '<i class="bi bi-person-fill"></i>'
}
</span>
${escapeHTML(
jugador.nombreUsuario
)}
</div> </div>
${ ${
esHost esHost
? `<span class="badge bg-warning text-dark ms-2">HOST</span>` ? `
<span
class="badge bg-warning text-dark ms-2">
HOST
</span>
`
: "" : ""
} }
</div> </div>
`; `;
}); });
} else { } else {
jugadoresHTML = `<div class="text-muted small">Sin jugadores</div>`; jugadoresHTML = `
<div class="text-muted small">
Sin jugadores
</div>
`;
} }
// Botón "Unirse" solo visible si NO pertenece a ningún equipo
let botonUnirseHTML = ""; let botonUnirseHTML = "";
if (!usuarioYaEstaEnEquipo) { if (!usuarioYaEstaEnEquipo) {
botonUnirseHTML = ` botonUnirseHTML = `
<button type="button" class="btn-unirse w-100 btn-unirse-equipo mt-2" <button
type="button"
class="btn-unirse w-100 btn-unirse-equipo mt-2"
data-id-partida="${partida.idPartida}" data-id-partida="${partida.idPartida}"
data-id-equipo="${equipo.idEquipo}"> data-id-equipo="${equipo.idEquipo}">
Unirse Unirse
</button> </button>
`; `;
} }
equiposHTML += ` equiposHTML += `
<div class="equipo me-2 ms-2 p-3 border rounded"> <div
<h6>${escapeHTML(equipo.nombreEquipo)}</h6> class="equipo me-2 ms-2 p-3 border rounded">
<h6>
${escapeHTML(
equipo.nombreEquipo
)}
</h6>
<div class="jugadores mb-2"> <div class="jugadores mb-2">
${jugadoresHTML} ${jugadoresHTML}
</div> </div>
${botonUnirseHTML} ${botonUnirseHTML}
</div>
`;
});
// Acciones disponibles si el usuario YA ESTÁ dentro de esta sala
// Acciones disponibles si el usuario YA ESTÁ dentro de esta sala
let accionesSalaHTML = "";
if (usuarioYaEstaEnEquipo) {
const esHost = partida.idUsuario == idUsuarioSesion;
let botonIniciarHTML = "";
// Solo el host puede iniciar la partida
if (esHost) {
botonIniciarHTML = `
<a href="juego.php?idPartida=${partida.idPartida}"
class="btn btn-success btn-lg px-4">
<i class="bi bi-controller"></i> ¡Iniciar Partida!
</a>
`;
}
accionesSalaHTML = `
<div class="sala-acciones text-center mt-4 pt-3 border-top d-flex justify-content-center gap-3">
<button type="button"
class="btn btn-outline-danger btn-abandonar-sala"
data-id-partida="${partida.idPartida}"
data-es-host="${esHost}">
Abandonar sala
</button>
${botonIniciarHTML}
</div> </div>
`; `;
}
const salaHTML = `
<div class="col-12 col-md-10 col-lg-8">
<div class="sala card p-3 shadow-sm mb-4">
<div class="sala-header h4 text-center mb-3 text-white">
${escapeHTML(partida.nombrePartida)}
</div>
<div class="sala-body">
<div class="equipos d-flex justify-content-around">
${equiposHTML}
</div>
${accionesSalaHTML}
</div>
</div>
</div>
`;
contenedor.append(salaHTML);
}
// 6. Evento: Unirse a un Equipo
$(document).on("click", ".btn-unirse-equipo", function () {
const boton = $(this);
const idEquipo = boton.data("id-equipo");
const idPartida = boton.data("id-partida");
boton.prop("disabled", true).text("Uniéndose...");
$.ajax({
url: "controladores/controladorEquipoxUsuario.php",
type: "POST",
dataType: "json",
data: {
orden: "registrarUsuarioEnEquipo",
idEquipo: idEquipo,
},
success: function (respuesta) {
if (respuesta.error) {
alert(respuesta.error);
boton.prop("disabled", false).text("Unirse");
return;
}
usuarioYaEstaEnEquipo = true;
$("#contenedorCrearSala").hide();
$("#contenedorSalas").empty();
cargarSalaUsuario(idPartida);
},
error: function (xhr, status, error) {
console.error("Error al unirse al equipo:", error);
alert("No se ha podido unir al equipo.");
boton.prop("disabled", false).text("Unirse");
},
});
}); });
// 7. Evento: Abandonar Sala return equiposHTML;
// Guardamos temporalmente el botón presionado
let botonAbandonarReferencia = null;
// A. Al hacer clic en el botón "Abandonar sala" de la tarjeta, abrimos el modal
$(document).on("click", ".btn-abandonar-sala", function () {
botonAbandonarReferencia = $(this);
const esHost = $(this).data("es-host") === true || $(this).data("es-host") === "true";
const titulo = $("#modalAbandonarSalaLabel");
const mensaje = $("#modalAbandonarSalaMensaje");
const botonConfirmar = $("#btnConfirmarAbandonar");
if (esHost) {
titulo.text("¿Abandonar la sala?");
mensaje.text(
"Si abandonas la sala como anfitrión, la partida terminará para todos los jugadores.",
);
botonConfirmar.text("Sí, terminar partida");
} else {
titulo.text("¿Abandonar la sala?");
mensaje.text(
"Si sales de la sala, perderás tu lugar en el equipo.",
);
botonConfirmar.text("Sí, salir");
} }
const modal = new bootstrap.Modal(
document.getElementById("modalAbandonarSala"),
);
modal.show();
});
// B. Al hacer clic en "Sí, salir" dentro del modal Kahoot
$(document).on("click", "#btnConfirmarAbandonar", function () {
const modalEl = document.getElementById("modalAbandonarSala");
const modalInstance = bootstrap.Modal.getInstance(modalEl);
const btnConfirmar = $(this);
btnConfirmar.prop("disabled", true).text("Saliendo...");
$.ajax({
url: "controladores/controladorEquipoxUsuario.php",
type: "POST",
dataType: "json",
data: { orden: "salirDeSala" },
success: function (respuesta) {
btnConfirmar.prop("disabled", false).text("Sí, salir");
if (modalInstance) {
modalInstance.hide();
}
if (respuesta.error) {
alert(respuesta.error);
return;
}
// Restablecemos la interfaz a la lista completa de salas
usuarioYaEstaEnEquipo = false;
$("#contenedorCrearSala").show();
cargarSalas();
},
error: function (xhr, status, error) {
console.error("Error al salir de la sala:", error);
alert("No se pudo salir de la sala.");
btnConfirmar.prop("disabled", false).text("Sí, salir");
if (modalInstance) {
modalInstance.hide();
}
},
});
});
// 8. Evento: Crear Sala
$("#btnCrearSala").on("click", function () { $("#btnCrearSala").on("click", function () {
const nombreSala = $("#nombreSala").val().trim(); const nombreSala =
const nombreEquipo1 = $("#nombreEquipo1").val().trim(); $("#nombreSala").val().trim();
const nombreEquipo2 = $("#nombreEquipo2").val().trim();
const nombreEquipo1 =
$("#nombreEquipo1").val().trim();
const nombreEquipo2 =
$("#nombreEquipo2").val().trim();
let valido = true; let valido = true;
$(".mensaje-error-sala").remove();
$(".input-kahoot").removeClass("is-invalid");
if (nombreSala === "" || nombreSala.length < 3) { $(".mensaje-error-sala").remove();
$(".input-kahoot")
.removeClass("is-invalid");
if (
nombreSala === "" ||
nombreSala.length < 3
) {
mostrarError( mostrarError(
"#nombreSala", "#nombreSala",
"El nombre de la sala debe tener al menos 3 caracteres.", "El nombre de la sala debe tener al menos 3 caracteres."
); );
valido = false; valido = false;
} }
if (nombreEquipo1 === "" || nombreEquipo1.length < 2) { if (
nombreEquipo1 === "" ||
nombreEquipo1.length < 2
) {
mostrarError( mostrarError(
"#nombreEquipo1", "#nombreEquipo1",
"El nombre del equipo debe tener al menos 2 caracteres.", "El nombre del equipo debe tener al menos 2 caracteres."
); );
valido = false; valido = false;
} }
if (nombreEquipo2 === "" || nombreEquipo2.length < 2) { if (
nombreEquipo2 === "" ||
nombreEquipo2.length < 2
) {
mostrarError( mostrarError(
"#nombreEquipo2", "#nombreEquipo2",
"El nombre del equipo debe tener al menos 2 caracteres.", "El nombre del equipo debe tener al menos 2 caracteres."
); );
valido = false; valido = false;
} }
if ( if (
nombreEquipo1 !== "" && nombreEquipo1 !== "" &&
nombreEquipo2 !== "" && nombreEquipo2 !== "" &&
nombreEquipo1.toLowerCase() === nombreEquipo2.toLowerCase() nombreEquipo1.toLowerCase() ===
nombreEquipo2.toLowerCase()
) { ) {
mostrarError( mostrarError(
"#nombreEquipo2", "#nombreEquipo2",
"Los dos equipos deben tener nombres diferentes.", "Los dos equipos deben tener nombres diferentes."
); );
valido = false; valido = false;
} }
if (!valido) return; if (!valido) {
return;
}
const boton = $("#btnCrearSala"); const boton = $("#btnCrearSala");
boton.prop("disabled", true).text("Creando sala...");
boton
.prop("disabled", true)
.text("Creando sala...");
$.ajax({ $.ajax({
url: "controladores/controladorPartida.php", url: "controladores/controladorPartida.php",
type: "POST", type: "POST",
dataType: "json", dataType: "json",
data: { data: {
orden: "crear", orden: "crear",
nombrePartida: nombreSala, nombrePartida: nombreSala,
nombreEquipo1: nombreEquipo1, nombreEquipo1: nombreEquipo1,
nombreEquipo2: nombreEquipo2, nombreEquipo2: nombreEquipo2,
}, },
success: function (respuesta) { success: function (respuesta) {
if (respuesta.error) { if (respuesta.error) {
alert(respuesta.error); alert(respuesta.error);
boton.prop("disabled", false).text("Crear sala");
boton
.prop("disabled", false)
.text("Crear sala");
return; return;
} }
if (respuesta.exito) { if (respuesta.exito) {
$("#modalCrearSala").modal("hide"); $("#modalCrearSala").modal("hide");
location.reload(); location.reload();
} }
}, },
error: function (xhr, status, error) { error: function (xhr, status, error) {
console.error("Error al crear la sala:", error); console.error(
alert("No se ha podido crear la sala."); "Error al crear la sala:",
boton.prop("disabled", false).text("Crear sala"); error
);
alert(
"No se ha podido crear la sala."
);
boton
.prop("disabled", false)
.text("Crear sala");
}, },
}); });
}); });
// Auxiliares function mostrarError(
function escapeHTML(texto) { selector,
return $("<div>") mensaje
.text(texto ?? "") ) {
.html();
}
function mostrarError(selector, mensaje) {
const input = $(selector); const input = $(selector);
input.addClass("is-invalid"); input.addClass("is-invalid");
input.after(
`<div class="mensaje-error-sala text-danger mt-1 small">${mensaje}</div>`, input.after(`
); <div
class="mensaje-error-sala text-danger mt-1 small">
${mensaje}
</div>
`);
} }
$(document).on("input", ".input-kahoot", function () { $(document).on(
$(this).removeClass("is-invalid"); "input",
$(this).next(".mensaje-error-sala").remove(); ".input-kahoot",
}); function () {
$(this)
.removeClass("is-invalid");
$(this)
.next(".mensaje-error-sala")
.remove();
}
);
+78 -63
View File
@@ -1,14 +1,19 @@
let idUsuarioSesion = null; let idUsuarioSesion = null;
$(document).ready(function () { $(document).ready(function () {
// Cargar la cabecera HTML e iniciar comprobación de sesión SOLO al terminar de cargar
$("#cabecera-container").load("cabecera.html", function (response, status, xhr) {
if (status === "error") {
console.error("Error al cargar cabecera.html:", xhr.status, xhr.statusText);
} else {
comprobarSesion(); comprobarSesion();
}
});
}); });
// Función auxiliar para escapar texto HTML // Función auxiliar para escapar texto HTML
function escapeHTML(str) { function escapeHTML(str) {
return $("<div>") return $("<div>").text(str ?? "").html();
.text(str ?? "")
.html();
} }
// Comprobar estado de sesión al cargar la página // Comprobar estado de sesión al cargar la página
@@ -16,24 +21,21 @@ function comprobarSesion() {
$.ajax({ $.ajax({
method: "POST", method: "POST",
url: "controladores/controladorUsuario.php", url: "controladores/controladorUsuario.php",
dataType: "json",
data: { orden: "comprobarSesion" }, data: { orden: "comprobarSesion" },
}).done(function (respuesta) { })
try { .done(function (respuesta) {
if (typeof respuesta === "string") {
respuesta = JSON.parse(respuesta);
}
const contenedor = $("#contenedorUsuarioCabecera"); const contenedor = $("#contenedorUsuarioCabecera");
if (!contenedor.length) return; // Si aún no existe el contenedor en HTML, cancelamos
contenedor.empty(); contenedor.empty();
if (respuesta.activa && respuesta.usuario) { if (respuesta && respuesta.activa && respuesta.usuario) {
// Recogemos el idUsuario de la sesion en una variable para usarlo (no me lo volváis a borrar por favor os lo pido) // Guardar idUsuario globalmente
idUsuarioSesion = respuesta.usuario.idUsuario; idUsuarioSesion = respuesta.usuario.idUsuario;
// Obtenemos la ruta del avatar o la de por defecto const avatarUrl = respuesta.usuario.avatar || "img/avatars/defaultProfile.jpeg";
const avatarUrl =
respuesta.usuario.avatar || "img/avatars/defaultProfile.jpeg";
// Usuario autenticado: Mostrar Menú Dropdown con el avatar // Usuario autenticado: Menú desplegable
const htmlUsuario = ` const htmlUsuario = `
<div class="dropdown"> <div class="dropdown">
<button class="btn user-dropdown-btn dropdown-toggle d-flex align-items-center gap-2" <button class="btn user-dropdown-btn dropdown-toggle d-flex align-items-center gap-2"
@@ -58,15 +60,26 @@ function comprobarSesion() {
`; `;
contenedor.html(htmlUsuario); contenedor.html(htmlUsuario);
// Si estamos en la página de perfil, rellenamos nombre y foto
if ($("#nombre").length) {
$("#nombre").text(respuesta.usuario.nombreUsuario);
// ?t= evita que el navegador enseñe la foto antigua en caché
$("#fotoPerfil").attr("src", avatarUrl + "?t=" + new Date().getTime());
}
// Si estamos en la página principal, mostramos el botón JUGAR // Si estamos en la página principal, mostramos el botón JUGAR
if ($("#colBotonJugar").length) { if ($("#colBotonJugar").length) {
$("#colBotonJugar").removeClass("d-none"); $("#colBotonJugar").removeClass("d-none");
$("#colRanking") $("#colRanking").removeClass("col-lg-8").addClass("col-lg-7 col-xl-8");
.removeClass("col-lg-8")
.addClass("col-lg-7 col-xl-8");
} }
} else { } else {
// No hay sesión: Mostrar botones de Login y Registro // Si estamos en el perfil y no hay sesión, volvemos al inicio
if ($("#nombre").length) {
window.location.href = "index.php";
return;
}
// No hay sesión: Botones de Login y Registro
const htmlInvitado = ` const htmlInvitado = `
<button type="button" class="btn btn-kahoot-login rounded-pill px-4" data-bs-toggle="modal" data-bs-target="#modalLogin"> <button type="button" class="btn btn-kahoot-login rounded-pill px-4" 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
@@ -77,22 +90,19 @@ function comprobarSesion() {
`; `;
contenedor.html(htmlInvitado); contenedor.html(htmlInvitado);
// Si estamos en la página principal, ocultamos el botón JUGAR
if ($("#colBotonJugar").length) { if ($("#colBotonJugar").length) {
$("#colBotonJugar").addClass("d-none"); $("#colBotonJugar").addClass("d-none");
$("#colRanking") $("#colRanking").removeClass("col-lg-7 col-xl-8").addClass("col-lg-8");
.removeClass("col-lg-7 col-xl-8")
.addClass("col-lg-8");
} }
} }
} catch (e) { })
console.error("Error al procesar la respuesta de la sesión:", e); .fail(function (xhr, status, error) {
} console.error("Error en comprobarSesion AJAX:", error, xhr.responseText);
}); });
} }
// Registro // Registro de usuario
$("#botonAceptarRegistro").click(function (event) { $(document).on("click", "#botonAceptarRegistro", function (event) {
event.preventDefault(); event.preventDefault();
let nombreUsuario = $("#regNombre").val().trim(); let nombreUsuario = $("#regNombre").val().trim();
@@ -100,61 +110,64 @@ $("#botonAceptarRegistro").click(function (event) {
let contrasena = $("#regPassword").val(); let contrasena = $("#regPassword").val();
let contrasenaConfirmacion = $("#regPasswordConfirm").val(); let contrasenaConfirmacion = $("#regPasswordConfirm").val();
$("#regNombre").removeClass("is-invalid"); // Resetear estados visuales
$("#regEmail").removeClass("is-invalid"); $("#regNombre, #regEmail, #regPassword, #regPasswordConfirm").removeClass("is-invalid");
$("#regPassword").removeClass("is-invalid"); $("#errorRegistro").removeClass("text-danger text-success").text("").show();
$("#regPasswordConfirm").removeClass("is-invalid");
$("#errorRegistro").text("");
if (contrasena !== contrasenaConfirmacion) { if (contrasena !== contrasenaConfirmacion) {
$("#regPassword").addClass("is-invalid"); $("#regPassword, #regPasswordConfirm").addClass("is-invalid");
$("#regPasswordConfirm").addClass("is-invalid"); $("#errorRegistro").addClass("text-danger").text("Las contraseñas no coinciden.");
$("#errorRegistro").text("Las contraseñas no coinciden.");
return; return;
} }
$.ajax({ $.ajax({
method: "POST", method: "POST",
url: "controladores/controladorUsuario.php", url: "controladores/controladorUsuario.php",
dataType: "json",
data: { data: {
nombreUsuario: nombreUsuario, nombreUsuario: nombreUsuario,
email: email, email: email,
contrasena: contrasena, contrasena: contrasena,
orden: "registrarUsuario", orden: "registrarUsuario",
}, },
}).done(function (respuesta) { })
if (typeof respuesta === "string") respuesta = JSON.parse(respuesta); .done(function (respuesta) {
if (respuesta.error) { if (respuesta.error) {
$("#errorRegistro").text(respuesta.error); $("#errorRegistro").addClass("text-danger").text(respuesta.error);
$("#regNombre").addClass("is-invalid"); $("#regNombre, #regEmail").addClass("is-invalid");
$("#regEmail").addClass("is-invalid");
} else { } else {
// Mostrar mensaje de confirmación
$("#errorRegistro") $("#errorRegistro")
.removeClass("text-danger") .removeClass("text-danger")
.addClass("text-success") .addClass("text-success fw-bold")
.text(respuesta.exito); .text(respuesta.exito || "¡Registro completado con éxito!");
if ($("#formRegistro").length) {
$("#formRegistro")[0].reset(); $("#formRegistro")[0].reset();
}
// Recargar para iniciar sesión tras 1.5 segundos
setTimeout(function () { setTimeout(function () {
location.reload(); location.reload();
}, 1000); }, 1500);
} }
})
.fail(function (xhr, status, error) {
console.error("Error en el registro:", error, xhr.responseText);
$("#errorRegistro").addClass("text-danger").text("Error de conexión con el servidor.");
}); });
}); });
// Login // Login de usuario
$("#botonAceptarLogin").click(function (event) { $(document).on("click", "#botonAceptarLogin", function (event) {
event.preventDefault(); event.preventDefault();
let email = $("#loginEmail").val().trim(); let email = $("#loginEmail").val().trim();
let contrasena = $("#loginPassword").val(); let contrasena = $("#loginPassword").val();
let recuerdame = $("#recordar").is(":checked"); let recuerdame = $("#recordar").is(":checked");
$("#loginEmail").removeClass("is-invalid"); $("#loginEmail, #loginPassword").removeClass("is-invalid");
$("#loginPassword").removeClass("is-invalid"); $("#errorLogin").removeClass("text-success").addClass("text-danger").text("").show();
$("#errorLogin").text("");
if (email === "" || contrasena === "") { if (email === "" || contrasena === "") {
$("#errorLogin").text("Todos los campos son obligatorios."); $("#errorLogin").text("Todos los campos son obligatorios.");
@@ -166,22 +179,26 @@ $("#botonAceptarLogin").click(function (event) {
$.ajax({ $.ajax({
method: "POST", method: "POST",
url: "controladores/controladorUsuario.php", url: "controladores/controladorUsuario.php",
dataType: "json",
data: { data: {
email: email, email: email,
contrasena: contrasena, contrasena: contrasena,
recuerdame: recuerdame, recuerdame: recuerdame,
orden: "comprobarUsuario", orden: "comprobarUsuario",
}, },
}).done(function (respuesta) { })
if (typeof respuesta === "string") respuesta = JSON.parse(respuesta); .done(function (respuesta) {
if (respuesta.error) { if (respuesta.error) {
$("#loginEmail").addClass("is-invalid"); $("#loginEmail, #loginPassword").addClass("is-invalid");
$("#loginPassword").addClass("is-invalid");
$("#errorLogin").text(respuesta.error); $("#errorLogin").text(respuesta.error);
} else { } else {
// Login correcto: Recargar la vista
location.reload(); location.reload();
} }
})
.fail(function (xhr, status, error) {
console.error("Error en el login:", error, xhr.responseText);
$("#errorLogin").text("Error de conexión o respuesta no válida del servidor.");
}); });
}); });
@@ -192,15 +209,13 @@ $(document).on("click", "#botonCerrarSesion", function (event) {
$.ajax({ $.ajax({
method: "POST", method: "POST",
url: "controladores/controladorUsuario.php", url: "controladores/controladorUsuario.php",
dataType: "json",
data: { orden: "cerrarSesion" }, data: { orden: "cerrarSesion" },
}).done(function (respuesta) { })
if (typeof respuesta === "string") respuesta = JSON.parse(respuesta); .done(function (respuesta) {
window.location.href = "index.php";
if (respuesta.error) { })
console.log(respuesta.error); .fail(function () {
} else {
window.location.href = "index.php"; window.location.href = "index.php";
}
}); });
}); });
+97 -10
View File
@@ -18,9 +18,10 @@ let preguntas = [];
let indice = 0; // pregunta que se está mostrando let indice = 0; // pregunta que se está mostrando
let bloqueado = false; // true mientras se envía una respuesta o se ve el feedback let bloqueado = false; // true mientras se envía una respuesta o se ve el feedback
let numeroAciertos = 0; // número de aciertos del jugador let numeroAciertos = 0; // número de aciertos del jugador
let tiempoRespuesta = 0;
let intervaloTiempo;
$(document).ready(function () { $(document).ready(function () {
// Obtenemos el idPartida de la URL // Obtenemos el idPartida de la URL
// Ejemplo: juego.php?idPartida=3 // Ejemplo: juego.php?idPartida=3
@@ -83,6 +84,11 @@ function cargarPreguntas() {
function mostrarPregunta() { function mostrarPregunta() {
const pregunta = preguntas[indice]; const pregunta = preguntas[indice];
tiempoRespuesta = 0;
intervaloTiempo = setInterval(function () {
tiempoRespuesta++;
}, 100);
bloqueado = false; bloqueado = false;
$("#textoPregunta").text(pregunta.nombrePregunta); $("#textoPregunta").text(pregunta.nombrePregunta);
@@ -111,6 +117,14 @@ function mostrarPregunta() {
// 3. El usuario pulsa una respuesta: se guarda y se enseña si ha acertado // 3. El usuario pulsa una respuesta: se guarda y se enseña si ha acertado
function responder($botonPulsado) { function responder($botonPulsado) {
clearInterval(intervaloTiempo);
console.log(
"Tiempo de respuesta: " +
tiempoRespuesta / 10 +
" segundos"
);
if (bloqueado) { if (bloqueado) {
return; return;
} }
@@ -118,7 +132,29 @@ function responder($botonPulsado) {
bloqueado = true; bloqueado = true;
const pregunta = preguntas[indice]; const pregunta = preguntas[indice];
const idRespuesta = parseInt($botonPulsado.attr("data-id-respuesta"), 10);
const idRespuesta = parseInt(
$botonPulsado.attr("data-id-respuesta"),
10
);
console.log("PREGUNTA ACTUAL:", pregunta);
console.log(
"idPartidaxPregunta:",
pregunta.idPartidaxPregunta
);
console.log(
"idRespuesta:",
idRespuesta
);
console.log(
"tiempoRespuesta:",
tiempoRespuesta
);
console.log(
"idPartida:",
idPartida
);
$("#respuestas").addClass("bloqueado"); $("#respuestas").addClass("bloqueado");
@@ -126,45 +162,96 @@ function responder($botonPulsado) {
url: URL_CONTROLADOR, url: URL_CONTROLADOR,
type: "POST", type: "POST",
dataType: "json", dataType: "json",
data: { data: {
orden: "responder", orden: "responder",
idPartida: idPartida, idPartida: idPartida,
idPartidaxPregunta: pregunta.idPartidaxPregunta, idPartidaxPregunta: pregunta.idPartidaxPregunta,
idRespuesta: idRespuesta, idRespuesta: idRespuesta,
tiempoRespuesta: tiempoRespuesta
}, },
success: function (datos) { success: function (datos) {
console.log("RESPUESTA DEL SERVIDOR:", datos);
if (datos.error) { if (datos.error) {
// No se guardó: dejamos que vuelva a intentarlo
$("#feedback").text(datos.error).removeClass("ok").addClass("ko"); $("#feedback")
.text(datos.error)
.removeClass("ok")
.addClass("ko");
$("#respuestas").removeClass("bloqueado"); $("#respuestas").removeClass("bloqueado");
bloqueado = false; bloqueado = false;
return; return;
} }
pregunta.respondida = true; pregunta.respondida = true;
mostrarFeedback($botonPulsado, datos);
mostrarFeedback(
$botonPulsado,
datos
);
setTimeout(function () { setTimeout(function () {
if (datos.terminada || indice >= preguntas.length - 1) {
if (
datos.terminada ||
indice >= preguntas.length - 1
) {
terminar(); terminar();
} else { } else {
indice++; indice++;
$("#respuestas").removeClass("bloqueado");
$("#respuestas")
.removeClass("bloqueado");
mostrarPregunta(); mostrarPregunta();
} }
}, PAUSA_FEEDBACK); }, PAUSA_FEEDBACK);
}, },
error: function () {
error: function (xhr, status, error) {
console.error(
"ERROR AJAX RESPONDER"
);
console.error(
"HTTP:",
xhr.status
);
console.error(
"ERROR:",
error
);
console.error(
"RESPUESTA:",
xhr.responseText
);
$("#feedback") $("#feedback")
.text("No se pudo guardar la respuesta. Inténtalo de nuevo.") .text(
"No se pudo guardar la respuesta. Inténtalo de nuevo."
)
.removeClass("ok") .removeClass("ok")
.addClass("ko"); .addClass("ko");
$("#respuestas").removeClass("bloqueado"); $("#respuestas").removeClass("bloqueado");
bloqueado = false; bloqueado = false;
}, }
}); });
} }
// Marca la respuesta correcta en verde y atenúa el resto // Marca la respuesta correcta en verde y atenúa el resto
function mostrarFeedback($botonPulsado, datos) { function mostrarFeedback($botonPulsado, datos) {
$("#respuestas .btn-answer").each(function () { $("#respuestas .btn-answer").each(function () {
+6 -6
View File
@@ -50,10 +50,9 @@ function cambiarNombre() {
$("#nuevoNombre").val(""); $("#nuevoNombre").val("");
if (typeof comprobarEstadoSesion === "function") { comprobarSesion();
comprobarEstadoSesion();
}
} }
}); });
} }
@@ -71,6 +70,7 @@ function borrarNombre() {
function seleccionarFoto() { function seleccionarFoto() {
$("#inputFoto").click(); $("#inputFoto").click();
} }
$("#inputFoto").change(function () { $("#inputFoto").change(function () {
@@ -80,6 +80,7 @@ $("#inputFoto").change(function () {
return; return;
} }
// 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.");
@@ -110,9 +111,8 @@ $("#inputFoto").change(function () {
); );
// Actualizamos también el avatar superior en la cabecera // Actualizamos también el avatar superior en la cabecera
if (typeof comprobarEstadoSesion === "function") {
comprobarEstadoSesion(); comprobarSesion();
}
} }
}); });
}); });
+52 -10
View File
@@ -1,5 +1,7 @@
$(document).ready(function () { $(document).ready(function () {
const idPartida = $("body").data("id-partida"); // Captura segura del ID de la partida desde el body de la página
const idPartida =
$("body").attr("data-id-partida") || $("body").data("id-partida");
comprobarEstadoPartida(idPartida); comprobarEstadoPartida(idPartida);
@@ -9,30 +11,70 @@ $(document).ready(function () {
}); });
function comprobarEstadoPartida(idPartida, intervalo = null) { function comprobarEstadoPartida(idPartida, intervalo = null) {
if (!idPartida || idPartida <= 0) return;
$.ajax({ $.ajax({
url: "controladores/controladorResultados.php", url: "controladores/controladorResultados.php",
type: "POST", type: "POST",
dataType: "json", dataType: "json",
data: { data: {
orden: "comprobarEstado", orden: "comprobarEstado",
idPartida: idPartida idPartida: idPartida,
}, },
success: function (respuesta) { success: function (respuesta) {
if (respuesta.error) { if (respuesta.error) {
console.error("Error:", respuesta.error); console.error("Error del controlador:", respuesta.error);
return; return;
} }
if (respuesta.terminada) { if (respuesta.terminada === true || respuesta.terminada === "true") {
if (intervalo !== null) clearInterval(intervalo); if (intervalo !== null) {
clearInterval(intervalo);
}
$("#pantalla-espera").fadeOut(400, function() { $("#pantalla-espera").hide();
location.reload(); $("#pantalla-resultados").show();
});
} }
}, },
error: function () { error: function () {
console.log("Error de comunicación con el controlador."); console.log("Esperando conexión con el servidor del Trivial...");
} },
}); });
} }
// INTERCEPTOR DE SALIDA: Saca al usuario y destruye la sala en cascada
$(document).on("click", "#btnVolverInicio", function (e) {
e.preventDefault(); // Congelamos un instante la redirección
const urlDestino = $(this).attr("href");
// Leemos el ID de forma científica directamente desde el botón pulsado
const idPartida = $(this).attr("data-id");
if (!idPartida) {
window.location.href = urlDestino;
return;
}
$.ajax({
url: "controladores/controladorResultados.php",
type: "POST",
dataType: "json",
data: {
orden: "registrarSalidaUsuario",
idPartida: idPartida,
},
success: function (response) {
console.log(
"Servidor procesó la salida. Usuarios restantes: " +
response.usuarios_quedan,
);
},
error: function (error) {
console.error("Error técnico al salir de la sala:", error);
},
complete: function () {
// Rompemos la pausa y mandamos al jugador al menú de inicio limpio
window.location.href = urlDestino;
},
});
});
+619
View File
@@ -0,0 +1,619 @@
let usuarioYaEstaEnEquipo = false;
let intervaloSala = null;
let botonAbandonarReferencia = null;
$(document).ready(function () {
comprobarSalaUsuario();
});
function comprobarSalaUsuario() {
$("#cargandoSalas").remove();
$.ajax({
url: "controladores/controladorEquipoxUsuario.php",
type: "POST",
dataType: "json",
data: {
orden: "obtenerSalaUsuario",
},
success: function (respuesta) {
if (respuesta.error || !respuesta.asociado) {
usuarioYaEstaEnEquipo = false;
$("#contenedorCrearSala").show();
iniciarActualizacionSalas();
} else {
usuarioYaEstaEnEquipo = true;
$("#contenedorCrearSala").hide();
cargarSalaUsuario(respuesta.idPartida);
}
},
error: function (xhr, status, error) {
usuarioYaEstaEnEquipo = false;
if (intervaloSala) {
clearInterval(intervaloSala);
intervaloSala = null;
}
$("#contenedorSalas").empty();
$("#contenedorCrearSala").show();
iniciarActualizacionSalas();
},
});
}
function cargarSalaUsuario(idPartida) {
cargarSalaCompleta(idPartida);
if (intervaloSala) {
clearInterval(intervaloSala);
}
intervaloSala = setInterval(function () {
actualizarSalaUsuario(idPartida);
}, 5000);
}
function cargarSalaCompleta(idPartida) {
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: {
orden: "buscar",
idPartida: idPartida,
},
success: function (partida) {
if (partida.error) {
console.error(partida.error);
return;
}
cargarInformacionSalaCompleta(partida);
},
error: function (xhr, status, error) {
console.error("Error al obtener la sala:", error);
},
});
}
function cargarInformacionSalaCompleta(partida) {
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: {
orden: "getEquipos",
idPartida: partida.idPartida,
},
success: function (equipos) {
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: {
orden: "getJugadores",
idPartida: partida.idPartida,
},
success: function (jugadores) {
mostrarSala(partida, equipos, jugadores);
},
error: function (xhr, status, error) {
console.error("Error al obtener jugadores:", error);
},
});
},
error: function (xhr, status, error) {
console.error("Error al obtener equipos:", error);
},
});
}
function actualizarSalaUsuario(idPartida) {
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: {
orden: "buscar",
idPartida: idPartida,
},
success: function (partida) {
if (partida.error) {
console.error(partida.error);
return;
}
cargarInformacionSala(partida);
},
error: function (xhr, status, error) {
console.error("Error al actualizar la sala:", error);
},
});
}
function cargarInformacionSala(partida) {
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: {
orden: "getEquipos",
idPartida: partida.idPartida,
},
success: function (equipos) {
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: {
orden: "getJugadores",
idPartida: partida.idPartida,
},
success: function (jugadores) {
mostrarEquipos(partida, equipos, jugadores);
},
error: function (xhr, status, error) {
console.error("Error al obtener jugadores:", error);
},
});
},
error: function (xhr, status, error) {
console.error("Error al obtener equipos:", error);
},
});
}
function mostrarSala(partida, equipos, jugadores) {
const contenedor = $("#contenedorSalas");
let equiposHTML = "";
equipos.forEach(function (equipo) {
const jugadoresEquipo = jugadores.filter(function (jugador) {
return jugador.idEquipo == equipo.idEquipo;
});
let jugadoresHTML = "";
if (jugadoresEquipo.length > 0) {
jugadoresEquipo.forEach(function (jugador) {
const esHost = jugador.idUsuario == partida.idUsuario;
jugadoresHTML += `
<div class="jugador border border-2 d-flex align-items-center justify-content-between ${
esHost ? "jugador-host" : ""
}">
<div>
<span class="avatar">
${
esHost
? '<i class="bi bi-award-fill"></i>'
: '<i class="bi bi-person-fill"></i>'
}
</span>
${escapeHTML(jugador.nombreUsuario)}
</div>
${
esHost
? `<span class="badge bg-warning text-dark ms-2">
HOST
</span>`
: ""
}
</div>
`;
});
} else {
jugadoresHTML = `
<div class="text-muted small">
Sin jugadores
</div>
`;
}
equiposHTML += `
<div class="equipo me-2 ms-2 p-3 border rounded">
<h6>
${escapeHTML(equipo.nombreEquipo)}
</h6>
<div class="jugadores mb-2">
${jugadoresHTML}
</div>
</div>
`;
});
const esHost = partida.idUsuario == idUsuarioSesion;
let botonIniciarHTML = "";
if (esHost) {
botonIniciarHTML = `
<button
type="button"
class="btn btn-success btn-lg px-4 btn-iniciar-partida"
data-id-partida="${partida.idPartida}">
<i class="bi bi-controller"></i>
¡Iniciar Partida!
</button>
`;
}
const salaHTML = `
<div class="col-12 col-md-10 col-lg-8">
<div class="sala card p-3 shadow-sm mb-4">
<div class="sala-header h4 text-center mb-3 text-white">
${escapeHTML(partida.nombrePartida)}
</div>
<div class="sala-body">
<div class="equipos d-flex justify-content-around">
${equiposHTML}
</div>
<div class="sala-acciones text-center mt-4 pt-3 border-top d-flex justify-content-center gap-3">
<button
type="button"
class="btn btn-outline-danger btn-abandonar-sala"
data-id-partida="${partida.idPartida}"
data-es-host="${esHost}">
Abandonar sala
</button>
${esHost ? botonIniciarHTML : ""}
</div>
</div>
</div>
</div>
`;
contenedor.html(salaHTML);
if (!partida.fechaInicio) {
iniciarComprobacionPartida(partida.idPartida);
}
}
let intervaloComprobarPartida = null;
function iniciarComprobacionPartida(idPartida) {
if (intervaloComprobarPartida) {
clearInterval(intervaloComprobarPartida);
}
intervaloComprobarPartida = setInterval(function () {
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: {
orden: "comprobarInicio",
idPartida: idPartida,
},
success: function (respuesta) {
if (respuesta.iniciada) {
clearInterval(intervaloComprobarPartida);
window.location.href = "juego.php?idPartida=" + idPartida;
}
},
});
}, 1000);
}
$(document).on("click", ".btn-iniciar-partida", function () {
const boton = $(this);
const idPartida = boton.data("id-partida");
boton.prop("disabled", true);
boton.html(`
<span class="spinner-border spinner-border-sm"></span>
Iniciando...
`);
$.ajax({
url: "controladores/controladorPartida.php",
type: "POST",
dataType: "json",
data: {
orden: "iniciar",
idPartida: idPartida,
},
success: function (respuesta) {
if (respuesta.error) {
alert(respuesta.error);
boton.prop("disabled", false);
boton.html(`
<i class="bi bi-controller"></i>
¡Iniciar Partida!
`);
return;
}
// El host entra directamente
window.location.href = "juego.php?idPartida=" + idPartida;
},
error: function () {
alert("Ocurrió un error al iniciar la partida.");
boton.prop("disabled", false);
boton.html(`
<i class="bi bi-controller"></i>
¡Iniciar Partida!
`);
},
});
});
$(document).on("click", ".btn-unirse-equipo", function () {
const boton = $(this);
const idEquipo = boton.data("id-equipo");
const idPartida = boton.data("id-partida");
boton.prop("disabled", true).text("Uniéndose...");
$.ajax({
url: "controladores/controladorEquipoxUsuario.php",
type: "POST",
dataType: "json",
data: {
orden: "registrarUsuarioEnEquipo",
idEquipo: idEquipo,
},
success: function (respuesta) {
if (respuesta.error) {
alert(respuesta.error);
boton.prop("disabled", false).text("Unirse");
return;
}
usuarioYaEstaEnEquipo = true;
$("#contenedorCrearSala").hide();
$("#contenedorSalas").empty();
cargarSalaUsuario(idPartida);
},
error: function (xhr, status, error) {
console.error("Error al unirse al equipo:", error);
alert("No se ha podido unir al equipo.");
boton.prop("disabled", false).text("Unirse");
},
});
});
$(document).on("click", ".btn-abandonar-sala", function () {
botonAbandonarReferencia = $(this);
const esHost =
$(this).data("es-host") === true || $(this).data("es-host") === "true";
const titulo = $("#modalAbandonarSalaLabel");
const mensaje = $("#modalAbandonarSalaMensaje");
const botonConfirmar = $("#btnConfirmarAbandonar");
if (esHost) {
titulo.text("¿Abandonar la sala?");
mensaje.text(
"Si abandonas la sala como anfitrión, la partida terminará para todos los jugadores.",
);
botonConfirmar.text("Sí, terminar partida");
} else {
titulo.text("¿Abandonar la sala?");
mensaje.text("Si sales de la sala, perderás tu lugar en el equipo.");
botonConfirmar.text("Sí, salir");
}
const modal = new bootstrap.Modal(
document.getElementById("modalAbandonarSala"),
);
modal.show();
});
$(document).on("click", "#btnConfirmarAbandonar", function () {
const modalEl = document.getElementById("modalAbandonarSala");
const modalInstance = bootstrap.Modal.getInstance(modalEl);
const btnConfirmar = $(this);
btnConfirmar.prop("disabled", true).text("Saliendo...");
$.ajax({
url: "controladores/controladorEquipoxUsuario.php",
type: "POST",
dataType: "json",
data: {
orden: "salirDeSala",
},
success: function (respuesta) {
btnConfirmar.prop("disabled", false).text("Sí, salir");
if (modalInstance) {
modalInstance.hide();
}
if (respuesta.error) {
alert(respuesta.error);
return;
}
usuarioYaEstaEnEquipo = false;
if (intervaloSala) {
clearInterval(intervaloSala);
intervaloSala = null;
}
$("#contenedorSalas").empty();
$("#contenedorCrearSala").show();
iniciarActualizacionSalas();
},
error: function (xhr, status, error) {
console.error("Error al salir de la sala:", error);
alert("No se pudo salir de la sala.");
btnConfirmar.prop("disabled", false).text("Sí, salir");
if (modalInstance) {
modalInstance.hide();
}
},
});
});
function escapeHTML(texto) {
return $("<div>")
.text(texto ?? "")
.html();
}
function mostrarEquipos(partida, equipos, jugadores) {
let equiposHTML = "";
equipos.forEach(function (equipo) {
const jugadoresEquipo = jugadores.filter(function (jugador) {
return jugador.idEquipo == equipo.idEquipo;
});
let jugadoresHTML = "";
if (jugadoresEquipo.length > 0) {
jugadoresEquipo.forEach(function (jugador) {
const esHost = jugador.idUsuario == partida.idUsuario;
jugadoresHTML += `
<div class="jugador border border-2 d-flex align-items-center justify-content-between ${
esHost ? "jugador-host" : ""
}">
<div>
<span class="avatar">
${
esHost
? '<i class="bi bi-award-fill"></i>'
: '<i class="bi bi-person-fill"></i>'
}
</span>
${escapeHTML(jugador.nombreUsuario)}
</div>
${
esHost
? `<span class="badge bg-warning text-dark ms-2">
HOST
</span>`
: ""
}
</div>
`;
});
} else {
jugadoresHTML = `
<div class="text-muted small">
Sin jugadores
</div>
`;
}
equiposHTML += `
<div class="equipo me-2 ms-2 p-3 border rounded">
<h6>
${escapeHTML(equipo.nombreEquipo)}
</h6>
<div class="jugadores mb-2">
${jugadoresHTML}
</div>
</div>
`;
});
$("#contenedorSalas .equipos").html(equiposHTML);
}
+293 -205
View File
@@ -1,42 +1,42 @@
/*M!999999\- enable the sandbox mode */ -- phpMyAdmin SQL Dump
-- MariaDB dump 10.19-11.7.2-MariaDB, for Win64 (AMD64) -- version 5.2.3
-- https://www.phpmyadmin.net/
-- --
-- Host: localhost Database: triviagmatico -- Host: localhost:3306
-- ------------------------------------------------------ -- Generation Time: Oct 02, 2026 at 08:40 AM
-- Server version 10.4.32-MariaDB -- Server version: 8.4.3
-- PHP Version: 8.3.30
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */; /*!40101 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */; --
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -- Database: `triviagmatico`
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; --
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*M!100616 SET @OLD_NOTE_VERBOSITY=@@NOTE_VERBOSITY, NOTE_VERBOSITY=0 */; -- --------------------------------------------------------
-- --
-- Table structure for table `categoria` -- Table structure for table `categoria`
-- --
DROP TABLE IF EXISTS `categoria`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `categoria` ( CREATE TABLE `categoria` (
`idCategoria` int(11) NOT NULL AUTO_INCREMENT, `idCategoria` int NOT NULL,
`nombreCategoria` varchar(50) NOT NULL, `nombreCategoria` varchar(50) COLLATE utf8mb4_spanish_ci NOT NULL
PRIMARY KEY (`idCategoria`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `categoria` -- Dumping data for table `categoria`
-- --
LOCK TABLES `categoria` WRITE; INSERT INTO `categoria` (`idCategoria`, `nombreCategoria`) VALUES
/*!40000 ALTER TABLE `categoria` DISABLE KEYS */;
INSERT INTO `categoria` VALUES
(4, 'Historia'), (4, 'Historia'),
(5, 'Geografía'), (5, 'Geografía'),
(6, 'Ciencia'), (6, 'Ciencia'),
@@ -50,98 +50,69 @@ INSERT INTO `categoria` VALUES
(14, 'Tecnología'), (14, 'Tecnología'),
(15, 'Cultura'), (15, 'Cultura'),
(16, 'Gastronomía'); (16, 'Gastronomía');
/*!40000 ALTER TABLE `categoria` ENABLE KEYS */;
UNLOCK TABLES; -- --------------------------------------------------------
-- --
-- Table structure for table `equipo` -- Table structure for table `equipo`
-- --
DROP TABLE IF EXISTS `equipo`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `equipo` ( CREATE TABLE `equipo` (
`idEquipo` int(11) NOT NULL AUTO_INCREMENT, `idEquipo` int NOT NULL,
`nombreEquipo` varchar(50) NOT NULL, `nombreEquipo` varchar(50) COLLATE utf8mb4_spanish_ci NOT NULL
PRIMARY KEY (`idEquipo`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `equipo` -- Dumping data for table `equipo`
-- --
LOCK TABLES `equipo` WRITE; INSERT INTO `equipo` (`idEquipo`, `nombreEquipo`) VALUES
/*!40000 ALTER TABLE `equipo` DISABLE KEYS */;
INSERT INTO `equipo` VALUES
(1, 'Los Trivialistas'), (1, 'Los Trivialistas'),
(2, 'Los Cerebritos'), (2, 'Los Cerebritos'),
(3, 'Los Sabios'), (3, 'Los Sabios'),
(4, 'Los Exploradores'); (4, 'Los Exploradores');
/*!40000 ALTER TABLE `equipo` ENABLE KEYS */;
UNLOCK TABLES; -- --------------------------------------------------------
-- --
-- Table structure for table `equipoxpartida` -- Table structure for table `equipoxpartida`
-- --
DROP TABLE IF EXISTS `equipoxpartida`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `equipoxpartida` ( CREATE TABLE `equipoxpartida` (
`idEquipoxPartida` int(11) NOT NULL AUTO_INCREMENT, `idEquipoxPartida` int NOT NULL,
`idPartida` int(11) DEFAULT NULL, `idPartida` int DEFAULT NULL,
`idEquipo` int(11) DEFAULT NULL, `idEquipo` int DEFAULT NULL
PRIMARY KEY (`idEquipoxPartida`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
KEY `FK idEquipo tabla equipo` (`idEquipo`),
KEY `FK idPartida tabla partida` (`idPartida`),
CONSTRAINT `FK idEquipo tabla equipo` FOREIGN KEY (`idEquipo`) REFERENCES `equipo` (`idEquipo`),
CONSTRAINT `FK idPartida tabla partida` FOREIGN KEY (`idPartida`) REFERENCES `partida` (`idPartida`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `equipoxpartida` -- Dumping data for table `equipoxpartida`
-- --
LOCK TABLES `equipoxpartida` WRITE; INSERT INTO `equipoxpartida` (`idEquipoxPartida`, `idPartida`, `idEquipo`) VALUES
/*!40000 ALTER TABLE `equipoxpartida` DISABLE KEYS */;
INSERT INTO `equipoxpartida` VALUES
(1, 1, 1), (1, 1, 1),
(2, 1, 2), (2, 1, 2),
(3, 2, 2), (3, 2, 2),
(4, 2, 3), (4, 2, 3),
(5, 3, 3), (5, 3, 3),
(6, 3, 4); (6, 3, 4);
/*!40000 ALTER TABLE `equipoxpartida` ENABLE KEYS */;
UNLOCK TABLES; -- --------------------------------------------------------
-- --
-- Table structure for table `equipoxusuario` -- Table structure for table `equipoxusuario`
-- --
DROP TABLE IF EXISTS `equipoxusuario`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `equipoxusuario` ( CREATE TABLE `equipoxusuario` (
`idEquipoxUsuario` int(11) NOT NULL AUTO_INCREMENT, `idEquipoxUsuario` int NOT NULL,
`idUsuario` int(11) NOT NULL, `idUsuario` int NOT NULL,
`idEquipo` int(11) NOT NULL, `idEquipo` int NOT NULL
PRIMARY KEY (`idEquipoxUsuario`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
KEY `idUsuario` (`idUsuario`),
KEY `idEquipo` (`idEquipo`),
CONSTRAINT `equipoxusuario_ibfk_1` FOREIGN KEY (`idUsuario`) REFERENCES `usuario` (`idUsuario`),
CONSTRAINT `equipoxusuario_ibfk_2` FOREIGN KEY (`idEquipo`) REFERENCES `equipo` (`idEquipo`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `equipoxusuario` -- Dumping data for table `equipoxusuario`
-- --
LOCK TABLES `equipoxusuario` WRITE; INSERT INTO `equipoxusuario` (`idEquipoxUsuario`, `idUsuario`, `idEquipo`) VALUES
/*!40000 ALTER TABLE `equipoxusuario` DISABLE KEYS */;
INSERT INTO `equipoxusuario` VALUES
(1, 1, 1), (1, 1, 1),
(2, 2, 1), (2, 2, 1),
(3, 3, 1), (3, 3, 1),
@@ -152,68 +123,48 @@ INSERT INTO `equipoxusuario` VALUES
(8, 8, 3), (8, 8, 3),
(9, 9, 4), (9, 9, 4),
(10, 10, 4); (10, 10, 4);
/*!40000 ALTER TABLE `equipoxusuario` ENABLE KEYS */;
UNLOCK TABLES; -- --------------------------------------------------------
-- --
-- Table structure for table `partida` -- Table structure for table `partida`
-- --
DROP TABLE IF EXISTS `partida`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `partida` ( CREATE TABLE `partida` (
`idPartida` int(11) NOT NULL AUTO_INCREMENT, `idPartida` int NOT NULL,
`nombrePartida` varchar(100) NOT NULL, `nombrePartida` varchar(100) COLLATE utf8mb4_spanish_ci NOT NULL,
`idUsuario` int(11) NOT NULL, `idUsuario` int NOT NULL,
`fechaCreacion` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `fechaCreacion` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`fechaInicio` DATETIME NULL, `fechaInicio` datetime DEFAULT NULL,
`fechaFin` DATETIME NULL, `fechaFin` datetime DEFAULT NULL
PRIMARY KEY (`idPartida`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
KEY `FK idUsuario tabla usuario` (`idUsuario`),
CONSTRAINT `FK idUsuario tabla usuario` FOREIGN KEY (`idUsuario`) REFERENCES `usuario` (`idUsuario`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `partida` -- Dumping data for table `partida`
-- --
LOCK TABLES `partida` WRITE; INSERT INTO `partida` (`idPartida`, `nombrePartida`, `idUsuario`, `fechaCreacion`, `fechaInicio`, `fechaFin`) VALUES
/*!40000 ALTER TABLE `partida` DISABLE KEYS */; (1, 'Partida de prueba 1', 1, '2026-10-01 09:03:18', NULL, NULL),
INSERT INTO `partida` (idPartida, nombrePartida, idUsuario, fechaInicio, fechaFin) VALUES (2, 'Partida de prueba 2', 4, '2026-10-01 09:03:18', NULL, NULL),
(1,'Partida de prueba 1',1, NULL, NULL), (3, 'Partida de prueba 3', 9, '2026-10-01 09:03:18', NULL, NULL);
(2,'Partida de prueba 2',4, NULL, NULL),
(3,'Partida de prueba 3',9, NULL, NULL); -- --------------------------------------------------------
/*!40000 ALTER TABLE `partida` ENABLE KEYS */;
UNLOCK TABLES;
-- --
-- Table structure for table `partidaxpregunta` -- Table structure for table `partidaxpregunta`
-- --
DROP TABLE IF EXISTS `partidaxpregunta`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `partidaxpregunta` ( CREATE TABLE `partidaxpregunta` (
`idPartidaxPregunta` int(11) NOT NULL AUTO_INCREMENT, `idPartidaxPregunta` int NOT NULL,
`idPartida` int(11) NOT NULL, `idPartida` int NOT NULL,
`idPregunta` int(11) NOT NULL, `idPregunta` int NOT NULL
PRIMARY KEY (`idPartidaxPregunta`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
KEY `idPartida` (`idPartida`),
KEY `idPregunta` (`idPregunta`),
CONSTRAINT `partidaxpregunta_ibfk_1` FOREIGN KEY (`idPartida`) REFERENCES `partida` (`idPartida`),
CONSTRAINT `partidaxpregunta_ibfk_2` FOREIGN KEY (`idPregunta`) REFERENCES `pregunta` (`idPregunta`)
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `partidaxpregunta` -- Dumping data for table `partidaxpregunta`
-- --
LOCK TABLES `partidaxpregunta` WRITE; INSERT INTO `partidaxpregunta` (`idPartidaxPregunta`, `idPartida`, `idPregunta`) VALUES
/*!40000 ALTER TABLE `partidaxpregunta` DISABLE KEYS */;
INSERT INTO `partidaxpregunta` VALUES
(1, 1, 2140), (1, 1, 2140),
(2, 1, 2141), (2, 1, 2141),
(3, 1, 2142), (3, 1, 2142),
@@ -234,34 +185,24 @@ INSERT INTO `partidaxpregunta` VALUES
(18, 2, 2158), (18, 2, 2158),
(19, 2, 2159), (19, 2, 2159),
(20, 2, 2160); (20, 2, 2160);
/*!40000 ALTER TABLE `partidaxpregunta` ENABLE KEYS */;
UNLOCK TABLES; -- --------------------------------------------------------
-- --
-- Table structure for table `pregunta` -- Table structure for table `pregunta`
-- --
DROP TABLE IF EXISTS `pregunta`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `pregunta` ( CREATE TABLE `pregunta` (
`idPregunta` int(11) NOT NULL AUTO_INCREMENT, `idPregunta` int NOT NULL,
`idCategoria` int(11) NOT NULL, `idCategoria` int NOT NULL,
`nombrePregunta` varchar(255) NOT NULL, `nombrePregunta` varchar(255) COLLATE utf8mb4_spanish_ci NOT NULL
PRIMARY KEY (`idPregunta`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
UNIQUE KEY `nombrePregunta` (`nombrePregunta`),
KEY `idCategoria` (`idCategoria`),
CONSTRAINT `pregunta_ibfk_1` FOREIGN KEY (`idCategoria`) REFERENCES `categoria` (`idCategoria`)
) ENGINE=InnoDB AUTO_INCREMENT=2535 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `pregunta` -- Dumping data for table `pregunta`
-- --
LOCK TABLES `pregunta` WRITE; INSERT INTO `pregunta` (`idPregunta`, `idCategoria`, `nombrePregunta`) VALUES
/*!40000 ALTER TABLE `pregunta` DISABLE KEYS */;
INSERT INTO `pregunta` VALUES
(2140, 4, '¿En qué año llegó Cristóbal Colón a América?'), (2140, 4, '¿En qué año llegó Cristóbal Colón a América?'),
(2141, 5, '¿Cuál es la capital de España?'), (2141, 5, '¿Cuál es la capital de España?'),
(2142, 6, '¿Qué planeta es conocido como el planeta rojo?'), (2142, 6, '¿Qué planeta es conocido como el planeta rojo?'),
@@ -487,42 +428,29 @@ INSERT INTO `pregunta` VALUES
(2525, 6, '¿Qué científico estudió la electricidad y los rayos con una cometa?'), (2525, 6, '¿Qué científico estudió la electricidad y los rayos con una cometa?'),
(2531, 14, '¿Qué unidad se utiliza normalmente para medir almacenamiento digital?'), (2531, 14, '¿Qué unidad se utiliza normalmente para medir almacenamiento digital?'),
(2534, 16, '¿Qué dulce español se consume tradicionalmente en Navidad?'); (2534, 16, '¿Qué dulce español se consume tradicionalmente en Navidad?');
/*!40000 ALTER TABLE `pregunta` ENABLE KEYS */;
UNLOCK TABLES; -- --------------------------------------------------------
-- --
-- Table structure for table `respuesta` -- Table structure for table `respuesta`
-- --
DROP TABLE IF EXISTS `respuesta`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `respuesta` ( CREATE TABLE `respuesta` (
`idRespuesta` int(11) NOT NULL AUTO_INCREMENT, `idRespuesta` int NOT NULL,
`idPregunta` int(11) NOT NULL, `idPregunta` int NOT NULL,
`nombreRespuesta` varchar(255) NOT NULL, `nombreRespuesta` varchar(255) COLLATE utf8mb4_spanish_ci NOT NULL,
`correcta` tinyint(1) DEFAULT 0, `correcta` tinyint(1) DEFAULT '0'
PRIMARY KEY (`idRespuesta`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
KEY `idPregunta` (`idPregunta`),
CONSTRAINT `respuesta_ibfk_1` FOREIGN KEY (`idPregunta`) REFERENCES `pregunta` (`idPregunta`)
) ENGINE=InnoDB AUTO_INCREMENT=4935 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `respuesta` -- Dumping data for table `respuesta`
-- --
LOCK TABLES `respuesta` WRITE; INSERT INTO `respuesta` (`idRespuesta`, `idPregunta`, `nombreRespuesta`, `correcta`) VALUES
/*!40000 ALTER TABLE `respuesta` DISABLE KEYS */;
INSERT INTO `respuesta` VALUES
(3355, 2140, '1492', 1), (3355, 2140, '1492', 1),
(3356, 2140, '1512', 0), (3356, 2140, '1512', 0),
(3357, 2140, '1453', 0), (3357, 2140, '1453', 0),
(3358, 2140, '1600', 0), (3358, 2140, '1600', 0),
(3399,2141,'Madrid',1),
(3400,2141,'Barcelona',0),
(3401,2141,'Sevilla',0),
(3402,2141,'Valencia',0),
(3363, 2142, 'Marte', 1), (3363, 2142, 'Marte', 1),
(3364, 2142, 'Venus', 0), (3364, 2142, 'Venus', 0),
(3365, 2142, 'Júpiter', 0), (3365, 2142, 'Júpiter', 0),
@@ -559,6 +487,10 @@ INSERT INTO `respuesta` VALUES
(3396, 2150, 'Julio César', 0), (3396, 2150, 'Julio César', 0),
(3397, 2150, 'Nerón', 0), (3397, 2150, 'Nerón', 0),
(3398, 2150, 'Trajano', 0), (3398, 2150, 'Trajano', 0),
(3399, 2141, 'Madrid', 1),
(3400, 2141, 'Barcelona', 0),
(3401, 2141, 'Sevilla', 0),
(3402, 2141, 'Valencia', 0),
(3403, 2152, 'Oxígeno', 1), (3403, 2152, 'Oxígeno', 1),
(3404, 2152, 'Helio', 0), (3404, 2152, 'Helio', 0),
(3405, 2152, 'Hidrógeno', 0), (3405, 2152, 'Hidrógeno', 0),
@@ -1415,70 +1347,44 @@ INSERT INTO `respuesta` VALUES
(4932, 2534, 'Croissant', 0), (4932, 2534, 'Croissant', 0),
(4933, 2534, 'Brownie', 0), (4933, 2534, 'Brownie', 0),
(4934, 2534, 'Tiramisú', 0); (4934, 2534, 'Tiramisú', 0);
/*!40000 ALTER TABLE `respuesta` ENABLE KEYS */;
UNLOCK TABLES; -- --------------------------------------------------------
-- --
-- Table structure for table `respuestaalmacenada` -- Table structure for table `respuestaalmacenada`
-- --
DROP TABLE IF EXISTS `respuestaalmacenada`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `respuestaalmacenada` ( CREATE TABLE `respuestaalmacenada` (
`idRespuestaAlmacenada` int(11) NOT NULL AUTO_INCREMENT, `idRespuestaAlmacenada` int NOT NULL,
`idPartidaxPregunta` int(11) NOT NULL, `idPartidaxPregunta` int NOT NULL,
`idUsuario` int(11) NOT NULL, `idUsuario` int NOT NULL,
`idRespuesta` int(11) NOT NULL, `idRespuesta` int NOT NULL,
`primero` tinyint(1) DEFAULT 0, `tiempoRespuesta` int NOT NULL
PRIMARY KEY (`idRespuestaAlmacenada`),
KEY `idPartidaxPregunta` (`idPartidaxPregunta`),
KEY `idUsuario` (`idUsuario`),
KEY `idRespuesta` (`idRespuesta`),
CONSTRAINT `respuestaalmacenada_ibfk_1` FOREIGN KEY (`idPartidaxPregunta`) REFERENCES `partidaxpregunta` (`idPartidaxPregunta`) ON DELETE CASCADE,
CONSTRAINT `respuestaalmacenada_ibfk_2` FOREIGN KEY (`idUsuario`) REFERENCES `usuario` (`idUsuario`) ON DELETE CASCADE,
CONSTRAINT `respuestaalmacenada_ibfk_3` FOREIGN KEY (`idRespuesta`) REFERENCES `respuesta` (`idRespuesta`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- -- --------------------------------------------------------
-- Dumping data for table `respuestaalmacenada`
--
LOCK TABLES `respuestaalmacenada` WRITE;
/*!40000 ALTER TABLE `respuestaalmacenada` DISABLE KEYS */;
/*!40000 ALTER TABLE `respuestaalmacenada` ENABLE KEYS */;
UNLOCK TABLES;
-- --
-- Table structure for table `usuario` -- Table structure for table `usuario`
-- --
DROP TABLE IF EXISTS `usuario`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `usuario` ( CREATE TABLE `usuario` (
`idUsuario` int(11) NOT NULL AUTO_INCREMENT, `idUsuario` int NOT NULL,
`nombreUsuario` varchar(50) NOT NULL, `nombreUsuario` varchar(50) COLLATE utf8mb4_spanish_ci NOT NULL,
`contrasena` varchar(100) NOT NULL, `contrasena` varchar(100) COLLATE utf8mb4_spanish_ci NOT NULL,
`email` varchar(50) NOT NULL, `email` varchar(50) COLLATE utf8mb4_spanish_ci NOT NULL,
`avatar` varchar(200) DEFAULT NULL, `avatar` varchar(200) COLLATE utf8mb4_spanish_ci DEFAULT NULL,
`cookie` varchar(200) DEFAULT NULL, `cookie` varchar(200) COLLATE utf8mb4_spanish_ci DEFAULT NULL,
`aciertos` int(11) NOT NULL, `aciertos` int NOT NULL,
`victorias` int(11) NOT NULL, `victorias` int NOT NULL,
`derrotas` int(11) NOT NULL, `derrotas` int NOT NULL
PRIMARY KEY (`idUsuario`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `usuario` -- Dumping data for table `usuario`
-- --
LOCK TABLES `usuario` WRITE; INSERT INTO `usuario` (`idUsuario`, `nombreUsuario`, `contrasena`, `email`, `avatar`, `cookie`, `aciertos`, `victorias`, `derrotas`) VALUES
/*!40000 ALTER TABLE `usuario` DISABLE KEYS */;
INSERT INTO `usuario` VALUES
(1, 'Carlos', '1234', 'carlos@test.com', NULL, NULL, 125, 18, 7), (1, 'Carlos', '1234', 'carlos@test.com', NULL, NULL, 125, 18, 7),
(2, 'Lucia', '1234', 'lucia@test.com', NULL, NULL, 98, 14, 9), (2, 'Lucia', '1234', 'lucia@test.com', NULL, NULL, 98, 14, 9),
(3, 'Miguel', 'abcd', 'miguel@test.com', NULL, NULL, 210, 32, 5), (3, 'Miguel', 'abcd', 'miguel@test.com', NULL, NULL, 210, 32, 5),
@@ -1488,21 +1394,203 @@ INSERT INTO `usuario` VALUES
(7, 'Javier', '1234', 'javier@test.com', NULL, NULL, 185, 27, 8), (7, 'Javier', '1234', 'javier@test.com', NULL, NULL, 185, 27, 8),
(8, 'Marta', 'qwer', 'marta@test.com', NULL, NULL, 67, 9, 13), (8, 'Marta', 'qwer', 'marta@test.com', NULL, NULL, 67, 9, 13),
(9, 'Alejandro', 'qwer', 'alejandro@test.com', NULL, NULL, 240, 41, 4), (9, 'Alejandro', 'qwer', 'alejandro@test.com', NULL, NULL, 240, 41, 4),
(10,'Elena','hola','elena@test.com',NULL,NULL,112,16,10); (10, 'Elena', 'hola', 'elena@test.com', NULL, NULL, 112, 16, 10),
/*!40000 ALTER TABLE `usuario` ENABLE KEYS */; (11, 'papa', '$2y$10$tj.YXSaXhMbh63zYuwbnSuc8bVNzIHI3zZHs1cCmS.iNN25fRbZ5u', 'pepe', 'img/avatars/defaultProfile.jpeg', NULL, 13, 6, 0);
UNLOCK TABLES;
-- --
-- Dumping routines for database 'triviagmatico' -- Indexes for dumped tables
-- --
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; --
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -- Indexes for table `categoria`
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; --
ALTER TABLE `categoria`
ADD PRIMARY KEY (`idCategoria`);
--
-- Indexes for table `equipo`
--
ALTER TABLE `equipo`
ADD PRIMARY KEY (`idEquipo`);
--
-- Indexes for table `equipoxpartida`
--
ALTER TABLE `equipoxpartida`
ADD PRIMARY KEY (`idEquipoxPartida`),
ADD KEY `FK idEquipo tabla equipo` (`idEquipo`),
ADD KEY `FK idPartida tabla partida` (`idPartida`);
--
-- Indexes for table `equipoxusuario`
--
ALTER TABLE `equipoxusuario`
ADD PRIMARY KEY (`idEquipoxUsuario`),
ADD KEY `idUsuario` (`idUsuario`),
ADD KEY `idEquipo` (`idEquipo`);
--
-- Indexes for table `partida`
--
ALTER TABLE `partida`
ADD PRIMARY KEY (`idPartida`),
ADD KEY `FK idUsuario tabla usuario` (`idUsuario`);
--
-- Indexes for table `partidaxpregunta`
--
ALTER TABLE `partidaxpregunta`
ADD PRIMARY KEY (`idPartidaxPregunta`),
ADD KEY `idPartida` (`idPartida`),
ADD KEY `idPregunta` (`idPregunta`);
--
-- Indexes for table `pregunta`
--
ALTER TABLE `pregunta`
ADD PRIMARY KEY (`idPregunta`),
ADD UNIQUE KEY `nombrePregunta` (`nombrePregunta`),
ADD KEY `idCategoria` (`idCategoria`);
--
-- Indexes for table `respuesta`
--
ALTER TABLE `respuesta`
ADD PRIMARY KEY (`idRespuesta`),
ADD KEY `idPregunta` (`idPregunta`);
--
-- Indexes for table `respuestaalmacenada`
--
ALTER TABLE `respuestaalmacenada`
ADD PRIMARY KEY (`idRespuestaAlmacenada`),
ADD KEY `idPartidaxPregunta` (`idPartidaxPregunta`),
ADD KEY `idUsuario` (`idUsuario`),
ADD KEY `idRespuesta` (`idRespuesta`);
--
-- Indexes for table `usuario`
--
ALTER TABLE `usuario`
ADD PRIMARY KEY (`idUsuario`),
ADD UNIQUE KEY `email` (`email`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `categoria`
--
ALTER TABLE `categoria`
MODIFY `idCategoria` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=17;
--
-- AUTO_INCREMENT for table `equipo`
--
ALTER TABLE `equipo`
MODIFY `idEquipo` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=19;
--
-- AUTO_INCREMENT for table `equipoxpartida`
--
ALTER TABLE `equipoxpartida`
MODIFY `idEquipoxPartida` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=21;
--
-- AUTO_INCREMENT for table `equipoxusuario`
--
ALTER TABLE `equipoxusuario`
MODIFY `idEquipoxUsuario` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=19;
--
-- AUTO_INCREMENT for table `partida`
--
ALTER TABLE `partida`
MODIFY `idPartida` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11;
--
-- AUTO_INCREMENT for table `partidaxpregunta`
--
ALTER TABLE `partidaxpregunta`
MODIFY `idPartidaxPregunta` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=101;
--
-- AUTO_INCREMENT for table `pregunta`
--
ALTER TABLE `pregunta`
MODIFY `idPregunta` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2535;
--
-- AUTO_INCREMENT for table `respuesta`
--
ALTER TABLE `respuesta`
MODIFY `idRespuesta` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4935;
--
-- AUTO_INCREMENT for table `respuestaalmacenada`
--
ALTER TABLE `respuestaalmacenada`
MODIFY `idRespuestaAlmacenada` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=51;
--
-- AUTO_INCREMENT for table `usuario`
--
ALTER TABLE `usuario`
MODIFY `idUsuario` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `equipoxpartida`
--
ALTER TABLE `equipoxpartida`
ADD CONSTRAINT `FK idEquipo tabla equipo` FOREIGN KEY (`idEquipo`) REFERENCES `equipo` (`idEquipo`),
ADD CONSTRAINT `FK idPartida tabla partida` FOREIGN KEY (`idPartida`) REFERENCES `partida` (`idPartida`);
--
-- Constraints for table `equipoxusuario`
--
ALTER TABLE `equipoxusuario`
ADD CONSTRAINT `equipoxusuario_ibfk_1` FOREIGN KEY (`idUsuario`) REFERENCES `usuario` (`idUsuario`),
ADD CONSTRAINT `equipoxusuario_ibfk_2` FOREIGN KEY (`idEquipo`) REFERENCES `equipo` (`idEquipo`);
--
-- Constraints for table `partida`
--
ALTER TABLE `partida`
ADD CONSTRAINT `FK idUsuario tabla usuario` FOREIGN KEY (`idUsuario`) REFERENCES `usuario` (`idUsuario`);
--
-- Constraints for table `partidaxpregunta`
--
ALTER TABLE `partidaxpregunta`
ADD CONSTRAINT `partidaxpregunta_ibfk_1` FOREIGN KEY (`idPartida`) REFERENCES `partida` (`idPartida`),
ADD CONSTRAINT `partidaxpregunta_ibfk_2` FOREIGN KEY (`idPregunta`) REFERENCES `pregunta` (`idPregunta`);
--
-- Constraints for table `pregunta`
--
ALTER TABLE `pregunta`
ADD CONSTRAINT `pregunta_ibfk_1` FOREIGN KEY (`idCategoria`) REFERENCES `categoria` (`idCategoria`);
--
-- Constraints for table `respuesta`
--
ALTER TABLE `respuesta`
ADD CONSTRAINT `respuesta_ibfk_1` FOREIGN KEY (`idPregunta`) REFERENCES `pregunta` (`idPregunta`);
--
-- Constraints for table `respuestaalmacenada`
--
ALTER TABLE `respuestaalmacenada`
ADD CONSTRAINT `respuestaalmacenada_ibfk_1` FOREIGN KEY (`idPartidaxPregunta`) REFERENCES `partidaxpregunta` (`idPartidaxPregunta`) ON DELETE CASCADE,
ADD CONSTRAINT `respuestaalmacenada_ibfk_2` FOREIGN KEY (`idUsuario`) REFERENCES `usuario` (`idUsuario`) ON DELETE CASCADE,
ADD CONSTRAINT `respuestaalmacenada_ibfk_3` FOREIGN KEY (`idRespuesta`) REFERENCES `respuesta` (`idRespuesta`) ON DELETE CASCADE;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*M!100616 SET NOTE_VERBOSITY=@OLD_NOTE_VERBOSITY */;
-- Dump completed on 2026-09-25 10:00:41
+4 -20
View File
@@ -1,17 +1,3 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
// Redirección si el usuario no ha iniciado sesión
if (!isset($_SESSION['idUsuario'])) {
header('Location: login.php');
exit();
}
$nombreUsuario = htmlspecialchars($_SESSION['nombreUsuario'] ?? 'Usuario');
$avatarUsuario = htmlspecialchars($_SESSION['avatar'] ?? 'img/avatars/defaultProfile.jpeg');
?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="es"> <html lang="es">
@@ -41,7 +27,7 @@ $avatarUsuario = htmlspecialchars($_SESSION['avatar'] ?? 'img/avatars/defaultPro
<body> <body>
<?php include_once 'cabecera.php'; ?> <header id="cabecera-container"></header>
<div class="perfil-container"> <div class="perfil-container">
@@ -61,15 +47,13 @@ $avatarUsuario = htmlspecialchars($_SESSION['avatar'] ?? 'img/avatars/defaultPro
<div class="col-md-6 text-center"> <div class="col-md-6 text-center">
<!-- Nombre --> <!-- Nombre -->
<h1 id="nombre" class="nombre"> <h1 id="nombre" class="nombre"></h1>
<?= $nombreUsuario ?>
</h1>
<!-- FOTO DE PERFIL --> <!-- FOTO DE PERFIL -->
<div class="foto-container"> <div class="foto-container">
<img id="fotoPerfil" <img id="fotoPerfil"
src="<?= $avatarUsuario ?>" src="img/avatars/defaultProfile.jpeg"
alt="Foto de perfil" alt="Foto de perfil"
class="avatar rounded-circle"> class="avatar rounded-circle">
@@ -310,7 +294,7 @@ $avatarUsuario = htmlspecialchars($_SESSION['avatar'] ?? 'img/avatars/defaultPro
<!-- Tu JavaScript --> <!-- Tu JavaScript -->
<script src="js/perfil.js"></script> <script src="js/perfil.js"></script>
<script src="js/cabecera.js"></script>
</body> </body>
</html> </html>
+13 -8
View File
@@ -1,6 +1,6 @@
<?php <?php
session_start(); session_start();
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/conexionBD.php'; require_once __DIR__ . '/includes/conexionBD.php';
$idPartida = intval($_GET['idPartida'] ?? 0); $idPartida = intval($_GET['idPartida'] ?? 0);
if ($idPartida <= 0) { if ($idPartida <= 0) {
@@ -29,7 +29,7 @@ $primerosEnAcertar = $_SESSION['primeros_en_acertar'][$idPartida] ?? [];
$jugadoresFinales = []; $jugadoresFinales = [];
$equiposFinales = []; $equiposFinales = [];
// Respuestas de velocidad (+2 o +1) // Respuestas de velocidad (+2 o +1) procesadas en la capa de la vista
foreach ($listaJugadoresRaw as $jugador) { foreach ($listaJugadoresRaw as $jugador) {
$idU = (int)$jugador['idUsuario']; $idU = (int)$jugador['idUsuario'];
$idE = (int)$jugador['idEquipo']; $idE = (int)$jugador['idEquipo'];
@@ -52,7 +52,6 @@ foreach ($listaJugadoresRaw as $jugador) {
$aciertos++; $aciertos++;
$idPxp = $resp['idPartidaxPregunta']; $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) { if (isset($primerosEnAcertar[$idPxp]) && $primerosEnAcertar[$idPxp] === $idU) {
$puntosTotalesJugador += 2; $puntosTotalesJugador += 2;
} else { } else {
@@ -77,7 +76,6 @@ foreach ($listaJugadoresRaw as $jugador) {
$equiposFinales[$idE]['puntos'] += $puntosTotalesJugador; $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($jugadoresFinales, function($a, $b) { return $b['puntos'] <=> $a['puntos']; });
usort($equiposFinales, function($a, $b) { return $b['puntos'] <=> $a['puntos']; }); usort($equiposFinales, function($a, $b) { return $b['puntos'] <=> $a['puntos']; });
?> ?>
@@ -88,19 +86,24 @@ usort($equiposFinales, function($a, $b) { return $b['puntos'] <=> $a['puntos'];
<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>Resultados - Trivial</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="css/index.css">
<link rel="stylesheet" href="css/resultados.css"> <link rel="stylesheet" href="css/resultados.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@4.0.0/dist/jquery.min.js"></script> <script src="js/jquery-4.0.0.min.js"></script>
</head> </head>
<body data-id-partida="<?php echo $idPartida; ?>"> <body data-id-partida="<?php echo $idPartida; ?>">
<div id="pantalla-espera" class="contenedor"> <div id="pantalla-espera" class="contenedor">
<h2>⌛ Esperando a que todos los jugadores terminen...</h2> <h2> <i class="bi bi-hourglass"></i> Esperando a que todos los jugadores terminen...</h2>
<p>Calculando estadísticas de velocidad y actualizando perfiles históricos en el servidor.</p> <p>Calculando estadísticas de velocidad y actualizando perfiles históricos en el servidor.</p>
<div class="loader"></div> <div class="loader"></div>
</div> </div>
<div id="pantalla-resultados" class="contenedor" style="display:none;"> <div id="pantalla-resultados" class="contenedor" style="display:none;">
<h1>🏆 Resultados de la Partida 🏆</h1> <h1> <i class="bi bi-trophy-fill"></i> Resultados de la Partida <i class="bi bi-trophy-fill"></i> </h1>
<h2>Clasificación por Equipos</h2> <h2>Clasificación por Equipos</h2>
<table class="tabla-ranking"> <table class="tabla-ranking">
@@ -146,9 +149,11 @@ usort($equiposFinales, function($a, $b) { return $b['puntos'] <=> $a['puntos'];
</tbody> </tbody>
</table> </table>
<div class="contenedor-boton"> <div class="contenedor-boton">
<a href="/triviagmatico/buscadorSala.php" class="btn-inicio">Volver al Inicio 🏠</a> <a href="<?= $_ENV['urlBase'] ?>/" id="btnVolverInicio" data-id="<?php echo $idPartida; ?>" class="btn btn-play-kahoot"> <i class="bi bi-arrow-left"></i> Volver al Inicio <i class="bi bi-house-fill"></i> </a>
</div> </div>
</div> </div>
<script src="js/resultados.js"></script> <script src="js/resultados.js"></script>