Lista de partidas

This commit is contained in:
Marklogo 2024-04-05 02:00:23 +02:00
parent c27de6f4f0
commit ab6068d578
9 changed files with 309 additions and 161 deletions

View File

@ -18,10 +18,10 @@
</div> </div>
<form id="login-form" onsubmit=""> <form id="login-form" onsubmit="">
<div class="container_col" style="min-width: 20rem;"> <div class="container_col" style="min-width: 20rem;">
<label for="username">Introduce tu nick de batalla</label> <label for="login-input">Introduce tu nick de batalla</label>
<input id="login-input" name="nick" type="text" autocomplete="off" autocorrect="off" autocapitalize="none" <input id="login-input" name="nick" type="text" autocomplete="off" autocorrect="off" autocapitalize="none"
spellcheck="false" placeholder="Nick..." required> spellcheck="false" placeholder="Nick..." required>
<input type="submit" value="Conectar"> <input type="submit" class="button button-orange" value="Conectar">
</div> </div>
</form> </form>
</div> </div>

View File

@ -1,27 +1,27 @@
export const cardGamePropia = (nickname, game_id) => { export const cardGamePropia = (nickname, game_id,eliminarPartidaCallback) => {
var cardGameDiv = document.createElement('div'); var cardGameDiv = document.createElement('div');
cardGameDiv.classList.add('cardGame'); cardGameDiv.classList.add('cardGame');
cardGameDiv.innerHTML = `<span>${nickname}</span> cardGameDiv.innerHTML = `<span>${nickname}</span>
<span class="parpadea">Esperando rival...</span> <span class="parpadea">Esperando rival...</span>
<button class="cancel-game-btn">Cancelar</button> <button class="cancel-game-btn button button-orange">Cancelar</button>
`; `;
const cancelGameBtn = cardGameDiv.querySelector('.cancel-game-btn'); const cancelGameBtn = cardGameDiv.querySelector('.cancel-game-btn');
cancelGameBtn.addEventListener('click', () => { cancelGameBtn.addEventListener('click', () => {
eliminarPartida(game_id); eliminarPartidaCallback(game_id);
}); });
return cardGameDiv; return cardGameDiv;
}; };
export const cardGameGeneral = (nickname, game_id) => { export const cardGameGeneral = (nickname, game_id,unirsePartidaCallback) => {
var cardGameDiv = document.createElement('div'); var cardGameDiv = document.createElement('div');
cardGameDiv.classList.add('cardGame'); cardGameDiv.classList.add('cardGame');
cardGameDiv.innerHTML = `<span>${nickname}</span> cardGameDiv.innerHTML = `<span>${nickname}</span>
<span>VS</span> <span>VS</span>
<button class="join-game-btn">Unirse</button> <button class="join-game-btn button button-green">Unirse</button>
`; `;
const joinGameBtn = cardGameDiv.querySelector('.join-game-btn'); const joinGameBtn = cardGameDiv.querySelector('.join-game-btn');
joinGameBtn.addEventListener('click', () => { joinGameBtn.addEventListener('click', () => {
unirsePartida(game_id); unirsePartidaCallback(game_id);
}); });
return cardGameDiv; return cardGameDiv;
}; };

View File

@ -1,25 +1,26 @@
export class ListaPartidas { export class ListaPartidas {
_partidas = []; _partidas = [];
constructor(partidas) { constructor(partidas) {
this._partidas = partidas; this._partidas = partidas;
} }
agregarPartida(partida) { agregarPartida(partida) {
this._partidas.push(partida); this._partidas.push(partida);
} }
eliminaPartida(uuid){ actualizarPartida(partidaActualizada) {
const index = this._partidas.findIndex((partida) => partida.uuid === uuid); const index = this._partidas.findIndex(
if (index !== -1) { (partida) => partida.uuid === partidaActualizada.uuid,
this._partidas.splice(index, 1); );
} if (index !== -1) {
} this._partidas[index] = partidaActualizada;
get partidasAbiertas() {
return this._partidas.filter((partida) => partida.abierta);
}
getPartidasEnCurso(uuid) {
return this._partidas.filter((partida) => partida.uuid === uuid && !partida.abierta);
}
obtenerPartidaPorUuid(uuid) {
return this._partidas.find((partida) => partida.uuid === uuid);
} }
} }
eliminarPartida(uuid) {
const index = this._partidas.findIndex((partida) => partida.uuid === uuid);
if (index !== -1) {
this._partidas.splice(index, 1);
}
}
get partidas() {
return this._partidas;
}
}

View File

@ -11,125 +11,164 @@ const chat = document.querySelector('#logchat');
const userId = localStorage.getItem('userId'); const userId = localStorage.getItem('userId');
const socket = io('/salachat', { closeOnBeforeunload: true, auth: { userId } }); const socket = io('/salachat', { closeOnBeforeunload: true, auth: { userId } });
document.querySelector('#btnCerrar').addEventListener('click', () => {
cerrarSesion('buttonClick');
});
document.querySelector('#btnCrearPartida').addEventListener('click', () => {
crearPartida();
});
document.querySelector('#chatinput').addEventListener('keyup', (event) => {
enviarMensaje(event);
});
let listaUsuarios; let listaUsuarios;
let listaPartidas; let listaPartidasAbiertas;
// Funciones que modifican el DOM // Función para generar elementos de lista de usuarios
function agregarUsuarioToLista(usuario, listaElemento, claseCSS) { function generarElementoListaUsuario(usuario, claseCSS) {
const liUsuario = document.createElement('li'); const liUsuario = document.createElement('li');
liUsuario.innerHTML = usuario.nickname; liUsuario.textContent = usuario.nickname;
liUsuario.classList.add(claseCSS); liUsuario.classList.add(claseCSS);
listaElemento.appendChild(liUsuario); return liUsuario;
} }
function listarUsuarios() { // Función para actualizar la lista de usuarios
function actualizarListaUsuarios() {
usersConnectUlEl.innerHTML = ''; usersConnectUlEl.innerHTML = '';
usersDisconnectUlEl.innerHTML = ''; usersDisconnectUlEl.innerHTML = '';
const miUsuario = listaUsuarios.usuario; const miUsuario = listaUsuarios.usuario;
agregarUsuarioToLista(miUsuario, usersConnectUlEl, 'spanNickPropio'); usersConnectUlEl.appendChild(
const usuariosConectados = listaUsuarios.usuariosConectados; generarElementoListaUsuario(miUsuario, 'spanNickPropio'),
usuariosConectados.forEach((usuario) => { );
agregarUsuarioToLista(usuario, usersConnectUlEl, 'spanNick');
listaUsuarios.usuariosConectados.forEach((usuario) => {
usersConnectUlEl.appendChild(
generarElementoListaUsuario(usuario, 'spanNick'),
);
}); });
const usuariosDesconectados = listaUsuarios.usuariosDesconectados;
usuariosDesconectados.forEach((usuario) => { listaUsuarios.usuariosDesconectados.forEach((usuario) => {
agregarUsuarioToLista(usuario, usersDisconnectUlEl, 'spanNickOffline'); usersDisconnectUlEl.appendChild(
generarElementoListaUsuario(usuario, 'spanNickOffline'),
);
}); });
} }
function listarPartidasAbiertas() { // Función para generar elementos de la lista de partidas
partidasAbiertasEl.innerHTML = ''; function generarElementoListaPartida(partida) {
listaPartidas.partidasAbiertas.forEach((partida) => { const cardGame =
const cardGame = userId === partida.uuidJugadorA
userId === partida.uuidJugadorA ? cardGamePropia(
? cardGamePropia(partida.nickJugadorA, partida.uuid) partida.nickJugadorA,
: cardGameGeneral(partida.nickJugadorA, partida.uuid); partida.uuid,
partidasAbiertasEl.appendChild(cardGame); onClickEliminarPartida,
)
: cardGameGeneral(
partida.nickJugadorA,
partida.uuid,
onClickUnirsePartida,
);
return cardGame;
}
// Función para actualizar la lista de partidas abiertas
function actualizarListaPartidasAbiertas() {
partidasAbiertasEl.innerHTML = '<legend>Partidas abiertas</legend>';
partidasProcesoEl.innerHTML = '<legend>Tus partidas</legend>';
listaPartidasAbiertas.partidas.forEach((partida) => {
const cardGame = generarElementoListaPartida(partida);
userId === partida.uuidJugadorA || userId === partida.uuidJugadorB
? partidasProcesoEl.appendChild(cardGame)
: partidasAbiertasEl.appendChild(cardGame);
}); });
} }
function agregaMsg({ uuid, msg }) { // Función para agregar un mensaje al chat
function agregarMensajeAlChat({ uuid, msg }) {
const spanUser = document.createElement('span'); const spanUser = document.createElement('span');
spanUser.textContent =
userId === uuid
? 'Tú: '
: `${listaUsuarios.obtenerUsuarioPorUuid(uuid).nickname}: `;
spanUser.classList.add(userId === uuid ? 'spanNickPropio' : 'spanNick');
const spanMsg = document.createElement('span'); const spanMsg = document.createElement('span');
if (userId === uuid) { spanMsg.textContent = msg;
spanUser.classList.add('spanNickPropio');
spanUser.textContent = `Tú: `;
spanMsg.textContent = msg;
} else {
spanUser.classList.add('spanNick');
spanUser.textContent = `${listaUsuarios.obtenerUsuarioPorUuid(uuid).nickname}: `;
spanMsg.textContent = msg;
}
const linea = document.createElement('p'); const linea = document.createElement('p');
linea.appendChild(spanUser); linea.appendChild(spanUser);
linea.appendChild(spanMsg); linea.appendChild(spanMsg);
chat.appendChild(linea); chat.appendChild(linea);
logchat.scrollTop = logchat.scrollHeight; logchat.scrollTop = logchat.scrollHeight;
} }
function agregaMsgBroadcast(msg) { // Función para agregar un mensaje de transmisión al chat
function agregarMensajeDeTransmisionAlChat(msg) {
const spanMsg = document.createElement('span'); const spanMsg = document.createElement('span');
spanMsg.textContent = msg; spanMsg.textContent = msg;
spanMsg.classList.add('broadcastMsg'); spanMsg.classList.add('broadcastMsg');
const linea = document.createElement('p'); const linea = document.createElement('p');
linea.appendChild(spanMsg); linea.appendChild(spanMsg);
chat.appendChild(linea); chat.appendChild(linea);
logchat.scrollTop = logchat.scrollHeight; logchat.scrollTop = logchat.scrollHeight;
} }
// Logica de negocio de la aplicacion const handlers = {
const entraSala = ({ usuarios, partidas }) => { onConnectRoom: ({ usuarios, partidas }) => {
listaUsuarios = new ListaUsuarios(userId, usuarios); listaUsuarios = new ListaUsuarios(userId, usuarios);
listaPartidas = new ListaPartidas(partidas); listaPartidasAbiertas = new ListaPartidas(partidas);
listarUsuarios(); actualizarListaUsuarios();
listarPartidasAbiertas(); actualizarListaPartidasAbiertas();
}; },
const actualizaUsuarios = (usuario) => { onUserChangeStatus: (usuario) => {
listaUsuarios.actualizaUsuario(usuario); listaUsuarios.actualizaUsuario(usuario);
listarUsuarios(); actualizarListaUsuarios();
usuario.conectado const mensaje = usuario.conectado
? agregaMsgBroadcast(`${usuario.nickname} se ha conectado`) ? `${usuario.nickname} se ha conectado`
: agregaMsgBroadcast(`${usuario.nickname} se ha desconectado`); : `${usuario.nickname} se ha desconectado`;
}; agregarMensajeDeTransmisionAlChat(mensaje);
const agregarPartida = (partida) => { },
listaPartidas.agregarPartida(partida); onMsgChat: (mensaje) => {
listarPartidasAbiertas(); agregarMensajeAlChat(mensaje);
},
onCreatePartida: (partida) => {
listaPartidasAbiertas.agregarPartida(partida);
actualizarListaPartidasAbiertas();
},
onJoinPartida: (partida) => {
listaPartidasAbiertas.eliminarPartida(partida);
actualizarListaPartidasAbiertas();
},
onCancelPartida: (uuid) => {
listaPartidasAbiertas.eliminarPartida(uuid);
actualizarListaPartidasAbiertas();
},
disconnect: (reason) => {
if (reason === 'io server disconnect' || reason === 'buttonClick') {
localStorage.removeItem('userId');
window.location.replace('/');
}
},
}; };
// Cerrar sesión Object.entries(handlers).forEach(([event, handler]) => {
const cerrarSesion = (reason) => { socket.on(event, handler);
if (reason === 'io server disconnect' || reason === 'buttonClick') { });
localStorage.removeItem('userId');
window.location.replace('/'); document.querySelector('#btnCerrar').addEventListener('click', () => {
} handlers.disconnect('buttonClick');
}; });
// Enviar mensaje
function enviarMensaje(event) { document.querySelector('#btnCrearPartida').addEventListener('click', () => {
socket.emit('createPartida', handlers.onCreatePartida);
});
document.querySelector('#chatinput').addEventListener('keyup', (event) => {
if (event.key === 'Enter') { if (event.key === 'Enter') {
const mensaje = event.target.value.trim(); const mensaje = event.target.value.trim();
if (mensaje != '') { if (mensaje != '') {
socket.emit('chatMsg', mensaje, agregaMsg); socket.emit('msgChat', mensaje, agregarMensajeAlChat);
} }
event.target.value = ''; event.target.value = '';
} }
} });
function crearPartida() {
socket.emit('creaPartida');
}
// Manejadores de eventos del socket
socket.on('onConnectRoom', entraSala);
socket.on('onUserConnectRoom', actualizaUsuarios);
socket.on('chatMsg', agregaMsg);
socket.on('onCrearPartida', agregarPartida);
socket.on('onUserDisconnectRoom', actualizaUsuarios);
socket.on('disconnect', cerrarSesion);
// // const url = '/batalla.html?game_id=' + encodeURIComponent(partida.uuid); // // const url = '/batalla.html?game_id=' + encodeURIComponent(partida.uuid);
// // window.open(url, '_blank'); // // window.open(url, '_blank');
function onClickEliminarPartida(game_id) {
socket.emit('cancelPartida', game_id, handlers.onCancelPartida);
}
function onClickUnirsePartida(game_id) {
socket.emit('joinPartida', game_id, handlers.onJoinPartida);
}

View File

@ -22,7 +22,7 @@
<ul id="users_disconnect"> <ul id="users_disconnect">
</ul> </ul>
</div> </div>
<button id="btnCerrar">Cerrar</button> <button id="btnCerrar" class="button button-orange">Cerrar</button>
</div> </div>
<div class="container_col" style="border: none;"> <div class="container_col" style="border: none;">
@ -32,17 +32,14 @@
<i style="font-size: 2rem;" class="ti ti-medal-2"></i> <i style="font-size: 2rem;" class="ti ti-medal-2"></i>
<i style="font-size: 2rem;" class="ti ti-medal-2"></i> <i style="font-size: 2rem;" class="ti ti-medal-2"></i>
</div> </div>
<button id="btnCrearPartida">Crear Partida</button> <button id="btnCrearPartida" class="button button-orange">Crear Partida</button>
</div> </div>
<fieldset id="tus_partidas" class="container_games">
<legend> Tus partidas</legend>
</fieldset>
<fieldset id="partidas_abiertas" class="container_games"> <fieldset id="partidas_abiertas" class="container_games">
<legend>Partidas abiertas</legend> <legend>Partidas abiertas</legend>
</fieldset> </fieldset>
<fieldset id="tus_partidas" class="container_games">
<legend>Partidas</legend>
</fieldset>
<div class="container_col" style="overflow-y: hidden;"> <div class="container_col" style="overflow-y: hidden;">
<div id="logchat" class="container_col" style="overflow-y: auto; border: none;"> <div id="logchat" class="container_col" style="overflow-y: auto; border: none;">
</div> </div>

View File

@ -77,26 +77,64 @@ body {
overflow-y: auto; overflow-y: auto;
} }
input[type='submit'], /* Estilo base para los botones */
button { .button {
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
font-size: 1rem; font-size: 1rem;
border: none; border: none;
border-radius: 0.4rem; border-radius: 0.4rem;
background-color: #ff5722; /* Color de fondo naranja */ color: white;
color: white; /* Color del texto blanco */ cursor: pointer;
cursor: pointer; /* Cambia el cursor al pasar sobre el botón */ transition: background-color 0.3s ease;
transition: background-color 0.3s ease; /* Transición suave al cambiar de color */
} }
input[type='submit']:hover,
button:hover { /* Estilo para el botón naranja */
background-color: #e64a19; /* Color de fondo naranja más oscuro al pasar el cursor */ .button-orange {
background-color: #ff5722;
} }
input[type='submit']:active,
button:active { /* Estilo para el botón naranja claro al pasar el cursor */
background-color: #bf360c; /* Color de fondo naranja más oscuro al hacer clic */ .button-orange:hover {
background-color: #e64a19;
} }
.cardGame button {
/* Estilo para el botón naranja oscuro al hacer clic */
.button-orange:active {
background-color: #bf360c;
}
/* Estilo para el botón azul */
.button-blue {
background-color: #2196f3;
}
/* Estilo para el botón azul claro al pasar el cursor */
.button-blue:hover {
background-color: #0d47a1;
}
/* Estilo para el botón azul oscuro al hacer clic */
.button-blue:active {
background-color: #002171;
}
/* Estilo para el botón verde */
.button-green {
background-color: #4caf50;
}
/* Estilo para el botón verde claro al pasar el cursor */
.button-green:hover {
background-color: #388e3c;
}
/* Estilo para el botón verde oscuro al hacer clic */
.button-green:active {
background-color: #1b5e20;
}
/* Estilo para el botón personalizado dentro de la clase .cardGame */
.cardGame .button {
padding: 0 0.4rem; padding: 0 0.4rem;
font-size: medium; font-size: medium;
width: 100%; width: 100%;
@ -167,26 +205,44 @@ button:active {
animation-duration: 2s; animation-duration: 2s;
animation-timing-function: linear; animation-timing-function: linear;
animation-iteration-count: infinite; animation-iteration-count: infinite;
-webkit-animation-name:parpadeo; -webkit-animation-name: parpadeo;
-webkit-animation-duration: 2s; -webkit-animation-duration: 2s;
-webkit-animation-timing-function: linear; -webkit-animation-timing-function: linear;
-webkit-animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite;
} }
@-moz-keyframes parpadeo{ @-moz-keyframes parpadeo {
0% { opacity: 1.0; } 0% {
50% { opacity: 0.0; } opacity: 1;
100% { opacity: 1.0; } }
50% {
opacity: 0;
}
100% {
opacity: 1;
}
} }
@-webkit-keyframes parpadeo { @-webkit-keyframes parpadeo {
0% { opacity: 1.0; } 0% {
50% { opacity: 0.0; } opacity: 1;
100% { opacity: 1.0; } }
50% {
opacity: 0;
}
100% {
opacity: 1;
}
} }
@keyframes parpadeo { @keyframes parpadeo {
0% { opacity: 1.0; } 0% {
50% { opacity: 0.0; } opacity: 1;
100% { opacity: 1.0; } }
} 50% {
opacity: 0;
}
100% {
opacity: 1;
}
}

View File

@ -28,7 +28,7 @@ export class SalaChatGateway
}); });
client.broadcast client.broadcast
.to('chat_general') .to('chat_general')
.emit('onUserConnectRoom', userConectado); .emit('onUserChangeStatus', userConectado);
} else { } else {
client.disconnect(); client.disconnect();
} }
@ -40,31 +40,52 @@ export class SalaChatGateway
if (userDesconectado) { if (userDesconectado) {
client.broadcast client.broadcast
.to('chat_general') .to('chat_general')
.emit('onUserDisconnectRoom', userDesconectado); .emit('onUserChangeStatus', userDesconectado);
} }
client.leave('chat_general'); client.leave('chat_general');
} }
@SubscribeMessage('chatMsg') @SubscribeMessage('msgChat')
handleMsg(client: Socket, msg: string) { handleMsg(client: Socket, msg: string) {
const userId = client.handshake.auth.userId; const userId = client.handshake.auth.userId;
const user = this.salaChatService.getUsuarioUUID(userId); const user = this.salaChatService.getUsuarioUUID(userId);
if (user) { client.broadcast
client.broadcast.to('chat_general').emit('chatMsg',{ uuid: userId, msg }); .to('chat_general')
return { uuid: userId, msg }; .emit('onMsgChat', { uuid: userId, msg });
} else { return { uuid: userId, msg };
client.disconnect();
}
} }
sendBroadcastMsg(msg: string) { sendBroadcastMsg(msg: string) {
this.server.to('chat_general').emit('broadcastMsg', msg); this.server.to('chat_general').emit('broadcastMsg', msg);
} }
@SubscribeMessage('creaPartida') @SubscribeMessage('createPartida')
handleCreaPartida(client: Socket) { handleCreatePartida(client: Socket) {
const userId = client.handshake.auth.userId; const userId = client.handshake.auth.userId;
const partida = this.salaChatService.creaPartida(userId); const partida = this.salaChatService.creaPartida(userId);
this.server.to('chat_general').emit('onCrearPartida', partida); client.broadcast.to('chat_general').emit('onCreatePartida', partida);
return partida;
} }
}
@SubscribeMessage('cancelPartida')
handleCancelPartida(client: Socket, uuidPartida: string) {
const userId = client.handshake.auth.userId;
const uuidPartidaEliminado = this.salaChatService.eliminarPartida(
userId,
uuidPartida,
);
if (uuidPartidaEliminado)
client.broadcast
.to('chat_general')
.emit('onCancelPartida', uuidPartidaEliminado);
return uuidPartidaEliminado;
}
@SubscribeMessage('joinPartida')
handleJoinPartida(client: Socket, uuidPartida: string) {
const userId = client.handshake.auth.userId;
const partida = this.salaChatService.unirsePartida(userId, uuidPartida);
client.broadcast.to('chat_general').emit('onJoinPartida', partida);
return partida;
}
}

View File

@ -59,4 +59,12 @@ export class SalaChatService {
const partida = this.partidasService.creaPartida(uuidJugadorCreador); const partida = this.partidasService.creaPartida(uuidJugadorCreador);
return partida; return partida;
} }
unirsePartida(uuidJugadorB:string,uuidPartida:string){
return this.partidasService.unirsePartida(uuidJugadorB,uuidPartida);
}
eliminarPartida(uuidJugador:string, uuidPartida:string){
return this.partidasService.eliminarPartida(uuidJugador,uuidPartida);
}
} }

View File

@ -27,9 +27,35 @@ export class PartidasService {
creaPartida(uuidJugadorA: string) { creaPartida(uuidJugadorA: string) {
const uuid = uuidv4(); const uuid = uuidv4();
const nickJugadorA=this.usuariosService.usuarios.get(uuidJugadorA).nickname; const nickJugadorA =
const partida = new Partida(uuid, uuidJugadorA,nickJugadorA); this.usuariosService.usuarios.get(uuidJugadorA).nickname;
const partida = new Partida(uuid, uuidJugadorA, nickJugadorA);
this._partidas.set(uuid, partida); this._partidas.set(uuid, partida);
return partida; return partida;
} }
unirsePartida(uuidJugadorB: string, uuidPartida: string){
const partida = this._partidas.get(uuidPartida);
const nickJugadorB = this.usuariosService.usuarios.get(uuidJugadorB)?.nickname;
partida.uuidJugadorB = uuidJugadorB;
partida.nickJugadorB = nickJugadorB;
partida.abierta = false;
return partida;
}
eliminarPartida(uuidJugador: string, uuidPartida: string) {
if (!this._partidas.has(uuidPartida)) {
return null;
}
const partida = this._partidas.get(uuidPartida);
if (
partida.uuidJugadorA !== uuidJugador &&
partida.uuidJugadorB !== uuidJugador
) {
return null;
}
this._partidas.delete(uuidPartida);
return uuidPartida;
}
} }