feat: Implement multiplayer game session management
- Add models for managing player assignments and game session initialization in `inicio_partida_multijugador.dart`. - Create a multiplayer room state management system in `sala_multijugador.dart`, including user registration, selection, and session validation. - Develop a UI screen for displaying player words sequentially in `pantalla_palabras_cliente.dart`. - Implement unit tests for the multiplayer session management and player assignment logic in `inicio_partida_multijugador_test.dart` and `sala_multijugador_test.dart`.
This commit is contained in:
77
test/modelos/inicio_partida_multijugador_test.dart
Normal file
77
test/modelos/inicio_partida_multijugador_test.dart
Normal file
@@ -0,0 +1,77 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:farolero/modelos/inicio_partida_multijugador.dart';
|
||||
|
||||
void main() {
|
||||
group('InicioPartidaMultijugador', () {
|
||||
test('agrupa varios jugadores controlados por el mismo cliente', () {
|
||||
final asignaciones = [
|
||||
const AsignacionJugador(
|
||||
jugadorId: 'ana',
|
||||
nombre: 'Ana',
|
||||
clientId: 'host',
|
||||
endpointId: null,
|
||||
),
|
||||
const AsignacionJugador(
|
||||
jugadorId: 'juan',
|
||||
nombre: 'Juan',
|
||||
clientId: 'host',
|
||||
endpointId: null,
|
||||
),
|
||||
const AsignacionJugador(
|
||||
jugadorId: 'sofia',
|
||||
nombre: 'Sofía',
|
||||
clientId: 'cliente-sofia',
|
||||
endpointId: 'endpoint-2',
|
||||
),
|
||||
];
|
||||
final impostores = {'juan': true};
|
||||
|
||||
final payloads = InicioPartidaMultijugador.crearPayloadsPorCliente(
|
||||
asignaciones: asignaciones,
|
||||
palabraSecreta: 'mate',
|
||||
categoria: 'objetos',
|
||||
impostoresPorJugadorId: impostores,
|
||||
);
|
||||
|
||||
expect(payloads['host']?.jugadores.map((j) => j.jugadorId), [
|
||||
'ana',
|
||||
'juan',
|
||||
]);
|
||||
expect(payloads['host']?.jugadores.first.palabra, 'mate');
|
||||
expect(payloads['host']?.jugadores.last.esImpostor, isTrue);
|
||||
expect(payloads['host']?.jugadores.last.palabra, isNull);
|
||||
expect(payloads['cliente-sofia']?.endpointId, 'endpoint-2');
|
||||
expect(payloads['cliente-sofia']?.jugadores.single.nombre, 'Sofía');
|
||||
});
|
||||
|
||||
test('restaura payload completo desde json', () {
|
||||
final payload = InicioPartidaCliente(
|
||||
clientId: 'cliente-sofia',
|
||||
endpointId: 'endpoint-2',
|
||||
categoria: 'todas',
|
||||
jugadores: const [
|
||||
JugadorInicioPartida(
|
||||
jugadorId: 'sofia',
|
||||
nombre: 'Sofía',
|
||||
esImpostor: false,
|
||||
palabra: 'luna',
|
||||
),
|
||||
JugadorInicioPartida(
|
||||
jugadorId: 'helena',
|
||||
nombre: 'Helena',
|
||||
esImpostor: true,
|
||||
palabra: null,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final restaurado = InicioPartidaCliente.fromJson(payload.toJson());
|
||||
|
||||
expect(restaurado.clientId, 'cliente-sofia');
|
||||
expect(restaurado.endpointId, 'endpoint-2');
|
||||
expect(restaurado.jugadores.length, 2);
|
||||
expect(restaurado.jugadores.first.palabra, 'luna');
|
||||
expect(restaurado.jugadores.last.esImpostor, isTrue);
|
||||
});
|
||||
});
|
||||
}
|
||||
156
test/modelos/sala_multijugador_test.dart
Normal file
156
test/modelos/sala_multijugador_test.dart
Normal file
@@ -0,0 +1,156 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:farolero/modelos/sala_multijugador.dart';
|
||||
import 'package:farolero/modelos/usuario.dart';
|
||||
|
||||
void main() {
|
||||
group('EstadoSalaMultijugador', () {
|
||||
late EstadoSalaMultijugador sala;
|
||||
|
||||
setUp(() {
|
||||
sala = EstadoSalaMultijugador.crear(
|
||||
roomId: 'room-1',
|
||||
nombreSala: 'Ana - Farolero',
|
||||
hostClientId: 'host',
|
||||
hostNombre: 'Ana',
|
||||
);
|
||||
});
|
||||
|
||||
test('registra al host como cliente conectado de la sala', () {
|
||||
expect(sala.hostClientId, 'host');
|
||||
expect(sala.clientes['host']?.esHost, isTrue);
|
||||
expect(sala.clientes['host']?.conectado, isTrue);
|
||||
});
|
||||
|
||||
test('permite seleccionar varios usuarios para un mismo cliente', () {
|
||||
sala.crearUsuario(Usuario(id: 'ana', nombre: 'Ana'));
|
||||
sala.crearUsuario(Usuario(id: 'juan', nombre: 'Juan'));
|
||||
|
||||
final seleccionAna = sala.seleccionarUsuario(
|
||||
usuarioId: 'ana',
|
||||
clienteId: 'host',
|
||||
);
|
||||
final seleccionJuan = sala.seleccionarUsuario(
|
||||
usuarioId: 'juan',
|
||||
clienteId: 'host',
|
||||
);
|
||||
|
||||
expect(seleccionAna.exitoso, isTrue);
|
||||
expect(seleccionJuan.exitoso, isTrue);
|
||||
expect(sala.usuariosPorCliente('host').map((u) => u.nombre), [
|
||||
'Ana',
|
||||
'Juan',
|
||||
]);
|
||||
});
|
||||
|
||||
test('impide que dos clientes seleccionen el mismo usuario', () {
|
||||
sala.registrarCliente(
|
||||
const ClienteSala(
|
||||
clientId: 'cliente-jorge',
|
||||
endpointId: 'endpoint-1',
|
||||
nombre: 'Jorge',
|
||||
),
|
||||
);
|
||||
sala.crearUsuario(Usuario(id: 'sofia', nombre: 'Sofía'));
|
||||
|
||||
final primeraSeleccion = sala.seleccionarUsuario(
|
||||
usuarioId: 'sofia',
|
||||
clienteId: 'host',
|
||||
);
|
||||
final segundaSeleccion = sala.seleccionarUsuario(
|
||||
usuarioId: 'sofia',
|
||||
clienteId: 'cliente-jorge',
|
||||
);
|
||||
|
||||
expect(primeraSeleccion.exitoso, isTrue);
|
||||
expect(segundaSeleccion.exitoso, isFalse);
|
||||
expect(segundaSeleccion.codigo, 'usuario_ya_seleccionado');
|
||||
expect(sala.usuarios['sofia']?.clienteIdSeleccionado, 'host');
|
||||
});
|
||||
|
||||
test('solo permite eliminar usuarios no seleccionados y por el host', () {
|
||||
sala.registrarCliente(
|
||||
const ClienteSala(
|
||||
clientId: 'cliente-jorge',
|
||||
endpointId: 'endpoint-1',
|
||||
nombre: 'Jorge',
|
||||
),
|
||||
);
|
||||
sala.crearUsuario(Usuario(id: 'ana', nombre: 'Ana'));
|
||||
sala.crearUsuario(Usuario(id: 'javier', nombre: 'Javier'));
|
||||
sala.seleccionarUsuario(usuarioId: 'ana', clienteId: 'host');
|
||||
|
||||
final clienteElimina = sala.eliminarUsuario(
|
||||
usuarioId: 'javier',
|
||||
solicitanteClientId: 'cliente-jorge',
|
||||
);
|
||||
final hostEliminaSeleccionado = sala.eliminarUsuario(
|
||||
usuarioId: 'ana',
|
||||
solicitanteClientId: 'host',
|
||||
);
|
||||
final hostEliminaLibre = sala.eliminarUsuario(
|
||||
usuarioId: 'javier',
|
||||
solicitanteClientId: 'host',
|
||||
);
|
||||
|
||||
expect(clienteElimina.exitoso, isFalse);
|
||||
expect(clienteElimina.codigo, 'solo_host');
|
||||
expect(hostEliminaSeleccionado.exitoso, isFalse);
|
||||
expect(hostEliminaSeleccionado.codigo, 'usuario_seleccionado');
|
||||
expect(hostEliminaLibre.exitoso, isTrue);
|
||||
expect(sala.usuarios.containsKey('javier'), isFalse);
|
||||
});
|
||||
|
||||
test('valida inicio con minimo tres usuarios y host seleccionado', () {
|
||||
sala
|
||||
..crearUsuario(Usuario(id: 'ana', nombre: 'Ana'))
|
||||
..crearUsuario(Usuario(id: 'juan', nombre: 'Juan'))
|
||||
..crearUsuario(Usuario(id: 'sofia', nombre: 'Sofía'));
|
||||
|
||||
expect(sala.validarInicio().exitoso, isFalse);
|
||||
expect(sala.validarInicio().codigo, 'faltan_jugadores');
|
||||
|
||||
sala
|
||||
..seleccionarUsuario(usuarioId: 'ana', clienteId: 'host')
|
||||
..seleccionarUsuario(usuarioId: 'juan', clienteId: 'host')
|
||||
..seleccionarUsuario(usuarioId: 'sofia', clienteId: 'host');
|
||||
|
||||
expect(sala.validarInicio().exitoso, isTrue);
|
||||
expect(sala.iniciarPartida().exitoso, isTrue);
|
||||
expect(sala.fase, FaseSalaMultijugador.enPartida);
|
||||
});
|
||||
|
||||
test('libera usuarios de un cliente desconectado durante lobby', () {
|
||||
sala.registrarCliente(
|
||||
const ClienteSala(
|
||||
clientId: 'cliente-sofia',
|
||||
endpointId: 'endpoint-2',
|
||||
nombre: 'Sofía',
|
||||
),
|
||||
);
|
||||
sala
|
||||
..crearUsuario(Usuario(id: 'sofia', nombre: 'Sofía'))
|
||||
..crearUsuario(Usuario(id: 'helena', nombre: 'Helena'))
|
||||
..seleccionarUsuario(usuarioId: 'sofia', clienteId: 'cliente-sofia')
|
||||
..seleccionarUsuario(usuarioId: 'helena', clienteId: 'cliente-sofia');
|
||||
|
||||
sala.desconectarCliente('cliente-sofia');
|
||||
|
||||
expect(sala.clientes['cliente-sofia']?.conectado, isFalse);
|
||||
expect(sala.usuarios['sofia']?.estaDisponible, isTrue);
|
||||
expect(sala.usuarios['helena']?.estaDisponible, isTrue);
|
||||
});
|
||||
|
||||
test('serializa y restaura clientes y usuarios seleccionados', () {
|
||||
sala
|
||||
..crearUsuario(Usuario(id: 'ana', nombre: 'Ana'))
|
||||
..seleccionarUsuario(usuarioId: 'ana', clienteId: 'host');
|
||||
|
||||
final restaurada = EstadoSalaMultijugador.fromJson(sala.toJson());
|
||||
|
||||
expect(restaurada.roomId, 'room-1');
|
||||
expect(restaurada.clientes['host']?.esHost, isTrue);
|
||||
expect(restaurada.usuarios['ana']?.clienteIdSeleccionado, 'host');
|
||||
expect(restaurada.usuariosSeleccionados.single.nombre, 'Ana');
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user