first commit
This commit is contained in:
20
src/app.module.ts
Normal file
20
src/app.module.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { join } from 'path';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ServeStaticModule } from '@nestjs/serve-static';
|
||||
import { LoginModule } from './login/login.module';
|
||||
import { SalaChatModule } from './sala-chat/sala-chat.module';
|
||||
import { BatallaModule } from './batalla/batalla.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ServeStaticModule.forRoot({
|
||||
rootPath: join(__dirname, '..', 'public'),
|
||||
}),
|
||||
LoginModule,
|
||||
SalaChatModule,
|
||||
BatallaModule,
|
||||
],
|
||||
controllers: [],
|
||||
providers: []
|
||||
})
|
||||
export class AppModule {}
|
||||
19
src/batalla/batalla.gateway.ts
Normal file
19
src/batalla/batalla.gateway.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { OnGatewayConnection, OnGatewayDisconnect, WebSocketGateway } from '@nestjs/websockets';
|
||||
import { BatallaService } from './batalla.service';
|
||||
import { Socket } from 'socket.io';
|
||||
|
||||
@WebSocketGateway({ namespace: 'batalla' })
|
||||
export class BatallaGateway implements OnGatewayConnection, OnGatewayDisconnect {
|
||||
constructor(private readonly batallaService: BatallaService) {}
|
||||
|
||||
handleConnection(client: Socket) {
|
||||
const {userId,gameId}=client.handshake.auth
|
||||
|
||||
}
|
||||
|
||||
|
||||
handleDisconnect(client: Socket) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
8
src/batalla/batalla.module.ts
Normal file
8
src/batalla/batalla.module.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { BatallaService } from './batalla.service';
|
||||
import { BatallaGateway } from './batalla.gateway';
|
||||
|
||||
@Module({
|
||||
providers: [BatallaGateway, BatallaService],
|
||||
})
|
||||
export class BatallaModule {}
|
||||
4
src/batalla/batalla.service.ts
Normal file
4
src/batalla/batalla.service.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class BatallaService {}
|
||||
29
src/battleship/barco.ts
Normal file
29
src/battleship/barco.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
export const BarcoTipo = Object.freeze({
|
||||
FRAGATA: 1,
|
||||
DESTRUCTOR: 2,
|
||||
ACORAZADO: 3,
|
||||
PORTAAVIONES: 4,
|
||||
});
|
||||
|
||||
export default class Barco {
|
||||
constructor(
|
||||
public id: number,
|
||||
public x: number,
|
||||
public y: number,
|
||||
public longitud: number,
|
||||
public orientacion: string,
|
||||
public impactos: number = 0,
|
||||
public destruido = false,
|
||||
) {}
|
||||
|
||||
recibirImpacto() {
|
||||
this.impactos++;
|
||||
if (this.impactos >= this.longitud) {
|
||||
this.destruido = true;
|
||||
}
|
||||
}
|
||||
|
||||
haSidoDestruido(): boolean {
|
||||
return this.destruido;
|
||||
}
|
||||
}
|
||||
57
src/battleship/battleship.ts
Normal file
57
src/battleship/battleship.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import Jugador from './jugador';
|
||||
|
||||
export default class BattleshipGame{
|
||||
public jugadorA: Jugador;
|
||||
public jugadorB: Jugador;
|
||||
|
||||
turnoActual: Jugador | null;
|
||||
|
||||
constructor(
|
||||
public idPartida: string,
|
||||
) {
|
||||
this.turnoActual = null;
|
||||
}
|
||||
|
||||
setJugadorA(jugador:Jugador){
|
||||
this.jugadorA=jugador;
|
||||
}
|
||||
|
||||
setJugadorB(jugador:Jugador){
|
||||
this.jugadorB=jugador;
|
||||
}
|
||||
|
||||
iniciaPartida() {
|
||||
this.turnoActual = this.jugadorA;
|
||||
// Iniciar el primer turno
|
||||
this.realizarTurno();
|
||||
}
|
||||
realizarTurno() {
|
||||
// Realizar las acciones correspondientes al turno actual
|
||||
// Por ejemplo, mostrar el mapa del turno actual, solicitar un disparo, etc.
|
||||
// Implementa esta parte según sea necesario
|
||||
|
||||
// Luego, alternar el turno al otro jugador
|
||||
this.turnoActual =
|
||||
this.turnoActual === this.jugadorA ? this.jugadorB : this.jugadorA;
|
||||
|
||||
// Verificar si se ha alcanzado el final del juego
|
||||
if (this.haFinalizado()) {
|
||||
this.finalizaPartida();
|
||||
} else {
|
||||
// Si no ha finalizado, continuar con el próximo turno
|
||||
this.realizarTurno();
|
||||
}
|
||||
}
|
||||
haFinalizado(): boolean {
|
||||
// Aquí debes implementar la lógica para verificar si el juego ha finalizado
|
||||
// Por ejemplo, si todos los barcos de uno de los jugadores han sido destruidos
|
||||
// Devuelve true si el juego ha finalizado, de lo contrario, devuelve false
|
||||
// Implementa esta parte según sea necesario
|
||||
return false;
|
||||
}
|
||||
finalizaPartida() {
|
||||
// Aquí debes implementar la lógica para finalizar el juego
|
||||
// Por ejemplo, mostrar el resultado (quién ganó, etc.)
|
||||
// Implementa esta parte según sea necesario
|
||||
}
|
||||
}
|
||||
49
src/battleship/jugador.ts
Normal file
49
src/battleship/jugador.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import Barco, { BarcoTipo } from './barco';
|
||||
import Mapa, { EstadoCelda } from './mapa';
|
||||
|
||||
export default class Jugador {
|
||||
public mapaFlota: Mapa = new Mapa();
|
||||
public mapaDeAtaques: Mapa = new Mapa();
|
||||
|
||||
public jugadorPreparado: boolean = false;
|
||||
|
||||
public barcos: Barco[] = [
|
||||
new Barco(1, 0, 0, BarcoTipo.PORTAAVIONES, 'VERTICAL'),
|
||||
new Barco(2, 1, 0, BarcoTipo.ACORAZADO, 'VERTICAL'),
|
||||
new Barco(3, 2, 0, BarcoTipo.ACORAZADO, 'VERTICAL'),
|
||||
new Barco(4, 3, 0, BarcoTipo.ACORAZADO, 'VERTICAL'),
|
||||
new Barco(5, 4, 0, BarcoTipo.DESTRUCTOR, 'VERTICAL'),
|
||||
new Barco(6, 5, 0, BarcoTipo.DESTRUCTOR, 'VERTICAL'),
|
||||
new Barco(7, 6, 0, BarcoTipo.DESTRUCTOR, 'VERTICAL'),
|
||||
new Barco(8, 7, 0, BarcoTipo.FRAGATA, 'VERTICAL'),
|
||||
new Barco(9, 8, 0, BarcoTipo.FRAGATA, 'VERTICAL'),
|
||||
];
|
||||
|
||||
constructor(public nickname: string) {}
|
||||
|
||||
prepararFlota(barcos: Barco[]) {
|
||||
this.barcos = barcos;
|
||||
this.mapaFlota.setBarcos(this.barcos);
|
||||
this.jugadorPreparado = true;
|
||||
}
|
||||
|
||||
setBarcos(barcos: Barco[]) {
|
||||
this.mapaFlota.setBarcos(barcos);
|
||||
}
|
||||
|
||||
realizarDisparo(x: number, y: number, rival: Jugador): boolean {
|
||||
const acierto = rival.mapaFlota.verificaDisparo(x, y);
|
||||
this.mapaDeAtaques.marcaDisparo(x,y,acierto ? EstadoCelda.Golpe : EstadoCelda.Agua);
|
||||
return acierto;
|
||||
}
|
||||
|
||||
haPerdido(): boolean {
|
||||
for (const barco of this.barcos) {
|
||||
if (!barco.destruido) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
68
src/battleship/mapa.ts
Normal file
68
src/battleship/mapa.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import Barco, { BarcoTipo } from './barco';
|
||||
|
||||
export enum EstadoCelda {
|
||||
Vacio = 0,
|
||||
Agua = -1,
|
||||
Golpe = -2,
|
||||
}
|
||||
|
||||
export default class Mapa {
|
||||
celdas: number[][] = [];
|
||||
barcosMapa: Map<number, Barco> = new Map<number, Barco>();
|
||||
constructor() {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
this.celdas[i] = [];
|
||||
for (let j = 0; j < 10; j++) {
|
||||
this.celdas[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setBarcos(barcos: Barco | Barco[]) {
|
||||
const barcosArray = Array.isArray(barcos) ? barcos : [barcos];
|
||||
for (const barco of barcosArray) {
|
||||
const incFila = barco.orientacion === 'VERTICAL' ? 1 : 0;
|
||||
const incColumna = barco.orientacion === 'HORIZONTAL' ? 1 : 0;
|
||||
for (let i = 0; i < barco.longitud; i++) {
|
||||
const fila = barco.y + i * incFila;
|
||||
const columna = barco.x + i * incColumna;
|
||||
this.celdas[fila][columna] = barco.id;
|
||||
}
|
||||
this.barcosMapa.set(barco.id, barco);
|
||||
}
|
||||
}
|
||||
|
||||
getEstadoCelda(x: number, y: number): EstadoCelda {
|
||||
return this.celdas[x][y];
|
||||
}
|
||||
|
||||
getBarcoEnCelda(x: number, y: number): Barco | null {
|
||||
const barcoId = this.celdas[x][y];
|
||||
if (barcoId > 0) {
|
||||
return this.barcosMapa.get(barcoId) || null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
marcaDisparo(x:number,y:number,valor:number){
|
||||
this.celdas[x][y]=valor;
|
||||
}
|
||||
|
||||
getInformacionBarcos(): Barco[] {
|
||||
return Array.from(this.barcosMapa.values());
|
||||
}
|
||||
|
||||
verificaDisparo(x: number, y: number): boolean {
|
||||
if (this.celdas[x][y] > 0) {
|
||||
const barco = this.getBarcoEnCelda(x,y);
|
||||
if (barco) {
|
||||
barco.recibirImpacto();
|
||||
this.celdas[x][y] = EstadoCelda.Golpe;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
this.celdas[x][y] = EstadoCelda.Agua;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
18
src/login/login.gateway.ts
Normal file
18
src/login/login.gateway.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit, SubscribeMessage, WebSocketGateway } from '@nestjs/websockets';
|
||||
import { LoginService } from './login.service';
|
||||
import { Socket } from 'socket.io';
|
||||
|
||||
@WebSocketGateway({namespace:'login'})
|
||||
export class LoginGateway implements OnGatewayConnection, OnGatewayDisconnect{
|
||||
constructor(private readonly loginService: LoginService) {}
|
||||
|
||||
handleConnection(client: any, ...args: any[]) {
|
||||
}
|
||||
handleDisconnect(client: any) {
|
||||
}
|
||||
|
||||
@SubscribeMessage('login')
|
||||
handleLogin(client: Socket, nick: string){
|
||||
return this.loginService.login(nick);
|
||||
}
|
||||
}
|
||||
12
src/login/login.module.ts
Normal file
12
src/login/login.module.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { LoginService } from './login.service';
|
||||
import { LoginGateway } from './login.gateway';
|
||||
import { SharedModule } from 'src/shared/shared.module';
|
||||
|
||||
|
||||
|
||||
@Module({
|
||||
imports:[SharedModule],
|
||||
providers: [LoginGateway,LoginService],
|
||||
})
|
||||
export class LoginModule {}
|
||||
18
src/login/login.service.ts
Normal file
18
src/login/login.service.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { UsuariosService } from 'src/shared/usuarios.service';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class LoginService {
|
||||
constructor(private readonly usuariosService: UsuariosService){}
|
||||
|
||||
login(nickname:string){
|
||||
const usuario=this.usuariosService.obtenerUsuarioPorNickname(nickname);
|
||||
if (usuario){
|
||||
return usuario.uuid
|
||||
} else {
|
||||
return this.usuariosService.creaUsuario(nickname);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
8
src/main.ts
Normal file
8
src/main.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
await app.listen(3000);
|
||||
}
|
||||
bootstrap();
|
||||
61
src/sala-chat/sala-chat.gateway.ts
Normal file
61
src/sala-chat/sala-chat.gateway.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import {
|
||||
OnGatewayConnection,
|
||||
OnGatewayDisconnect,
|
||||
SubscribeMessage,
|
||||
WebSocketGateway,
|
||||
WebSocketServer,
|
||||
} from '@nestjs/websockets';
|
||||
import { SalaChatService } from './sala-chat.service';
|
||||
import { Server, Socket } from 'socket.io';
|
||||
|
||||
@WebSocketGateway({ namespace: 'salachat' })
|
||||
export class SalaChatGateway
|
||||
implements OnGatewayConnection, OnGatewayDisconnect
|
||||
{
|
||||
@WebSocketServer()
|
||||
server: Server;
|
||||
constructor(private readonly salaChatService: SalaChatService) {}
|
||||
|
||||
handleConnection(client: Socket) {
|
||||
const userId = client.handshake.auth.userId;
|
||||
const userConectado = this.salaChatService.conectaUsuarioUUID(userId);
|
||||
if (userConectado){
|
||||
client.join('chat_general');
|
||||
client.emit('onConnectRoom',this.salaChatService.listaUsuariosSinPartidas);
|
||||
client.broadcast.to('chat_general').emit('onUserConnectRoom',userConectado);
|
||||
}else{
|
||||
client.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
handleDisconnect(client: Socket) {
|
||||
const userId = client.handshake.auth.userId;
|
||||
const userDesconectado = this.salaChatService.desconectaUsuarioUUID(userId);
|
||||
if (userDesconectado){
|
||||
client.broadcast.to('chat_general').emit('onUserDisconnectRoom',userDesconectado);
|
||||
}
|
||||
client.leave('chat_general');
|
||||
}
|
||||
|
||||
@SubscribeMessage('chatMsg')
|
||||
handleMsg(client: Socket, msg: string) {
|
||||
const userId = client.handshake.auth.userId;
|
||||
const user = this.salaChatService.getUsuarioUUID(userId);
|
||||
if (user) {
|
||||
this.server.to('chat_general').emit('chatMsg', { uuid:userId, msg });
|
||||
} else {
|
||||
client.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
sendBroadcastMsg(msg:string){
|
||||
this.server.to('chat_general').emit('broadcastMsg',msg);
|
||||
}
|
||||
|
||||
@SubscribeMessage('creaPartida')
|
||||
handleCreaPartida(client: Socket) {
|
||||
const userId = client.handshake.auth.userId;
|
||||
const partida= this.salaChatService.creaPartida(userId);
|
||||
this.server.to('chat_general').emit('on_create_partida',partida);
|
||||
}
|
||||
}
|
||||
11
src/sala-chat/sala-chat.module.ts
Normal file
11
src/sala-chat/sala-chat.module.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { SalaChatService } from './sala-chat.service';
|
||||
import { SalaChatGateway } from './sala-chat.gateway';
|
||||
import { SharedModule } from 'src/shared/shared.module';
|
||||
|
||||
|
||||
@Module({
|
||||
imports:[SharedModule],
|
||||
providers: [SalaChatGateway, SalaChatService],
|
||||
})
|
||||
export class SalaChatModule {}
|
||||
58
src/sala-chat/sala-chat.service.ts
Normal file
58
src/sala-chat/sala-chat.service.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Partida, PartidasService } from 'src/shared/partidas.service';
|
||||
import { UsuariosService } from 'src/shared/usuarios.service';
|
||||
|
||||
@Injectable()
|
||||
export class SalaChatService {
|
||||
constructor(
|
||||
private readonly usuariosService: UsuariosService,
|
||||
private readonly partidasService: PartidasService,
|
||||
) {}
|
||||
|
||||
get listaUsuariosSinPartidas() {
|
||||
return Array.from(this.usuariosService.usuarios.values()).map(
|
||||
({ uuid, nickname, conectado }) => ({
|
||||
uuid,
|
||||
nickname,
|
||||
conectado,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
getUsuarioUUID(uuid: string) {
|
||||
return this.usuariosService.getUsuarioByUUID(uuid);
|
||||
}
|
||||
conectaUsuarioUUID(uuid: string) {
|
||||
const user = this.usuariosService.getUsuarioByUUID(uuid);
|
||||
if (user) {
|
||||
user.conectado = true;
|
||||
return {
|
||||
uuid: user.uuid,
|
||||
nickname: user.nickname,
|
||||
conectado: user.conectado,
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
desconectaUsuarioUUID(uuid: string) {
|
||||
const user = this.usuariosService.getUsuarioByUUID(uuid);
|
||||
if (user) {
|
||||
user.conectado = false;
|
||||
return {
|
||||
uuid: user.uuid,
|
||||
nickname: user.nickname,
|
||||
conectado: user.conectado,
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
creaPartida(uuidJugadorCreador: string) {
|
||||
const partida = this.partidasService.creaPartida(uuidJugadorCreador);
|
||||
this.usuariosService.addPartidaToUsuario(uuidJugadorCreador, partida);
|
||||
return partida;
|
||||
}
|
||||
}
|
||||
35
src/shared/partidas.service.ts
Normal file
35
src/shared/partidas.service.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { UsuariosService } from './usuarios.service';
|
||||
|
||||
export class Partida {
|
||||
constructor(
|
||||
public uuid: string,
|
||||
public uuidJugadorA: string,
|
||||
public nickJugadorA: string = '',
|
||||
public uuidJugadorB: string = null,
|
||||
public nickJugadorB: string = null,
|
||||
public abierta: boolean = true,
|
||||
) {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class PartidasService {
|
||||
private _partidas: Map<string, Partida> = new Map<string, Partida>();
|
||||
|
||||
constructor(private readonly usuariosService: UsuariosService) {}
|
||||
|
||||
get partidasAbiertas(): Partida[] {
|
||||
return Array.from(this._partidas.values()).filter(
|
||||
(partida) => partida.abierta,
|
||||
);
|
||||
}
|
||||
|
||||
creaPartida(uuidJugadorA: string) {
|
||||
const uuid = uuidv4();
|
||||
const nickJugadorA=this.usuariosService.usuarios.get(uuidJugadorA).nickname;
|
||||
const partida = new Partida(uuid, uuidJugadorA,nickJugadorA);
|
||||
this._partidas.set(uuid, partida);
|
||||
return partida;
|
||||
}
|
||||
}
|
||||
9
src/shared/shared.module.ts
Normal file
9
src/shared/shared.module.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { UsuariosService } from './usuarios.service';
|
||||
import { PartidasService } from './partidas.service';
|
||||
|
||||
@Module({
|
||||
providers:[UsuariosService, PartidasService],
|
||||
exports:[UsuariosService, PartidasService]
|
||||
})
|
||||
export class SharedModule {}
|
||||
49
src/shared/usuarios.service.ts
Normal file
49
src/shared/usuarios.service.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { Injectable, Scope } from '@nestjs/common';
|
||||
import { Partida } from './partidas.service';
|
||||
|
||||
class Usuario {
|
||||
partidas: Partida[] = [];
|
||||
constructor(
|
||||
public uuid: string,
|
||||
public nickname: string,
|
||||
public conectado: boolean = false,
|
||||
) {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class UsuariosService {
|
||||
private _usuarios: Map<string, Usuario> = new Map<string, Usuario>();
|
||||
|
||||
get usuarios() {
|
||||
return this._usuarios;
|
||||
}
|
||||
|
||||
getUsuarioByUUID(uuid: string) {
|
||||
return this._usuarios.get(uuid) ? this._usuarios.get(uuid) : undefined;
|
||||
}
|
||||
|
||||
creaUsuario(nickname: string) {
|
||||
const uuid = uuidv4();
|
||||
const usuario = new Usuario(uuid, nickname);
|
||||
this._usuarios.set(uuid, usuario);
|
||||
return usuario.uuid;
|
||||
}
|
||||
|
||||
obtenerUsuarioPorNickname(nickname: string): Usuario | undefined {
|
||||
for (const usuario of this._usuarios.values()) {
|
||||
if (usuario.nickname === nickname) {
|
||||
return usuario;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
addPartidaToUsuario(uuid: string, partida: Partida) {
|
||||
this._usuarios.get(uuid).partidas.push(partida);
|
||||
}
|
||||
|
||||
getPartidasUsuario(uuid: string) {
|
||||
return this._usuarios.get(uuid).partidas;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user