fix: multidispositivo - Random seguro + gestor host + reacción clientes
Some checks failed
Build & Deploy Farolero / Análisis de código (push) Has been cancelled
Build & Deploy Farolero / Build APK + AAB release (push) Has been cancelled

- Random.secure() para selección de impostores (no predecible)
- Random.secure() también en desempate de votación
- Nueva PantallaGestorHost para coordinación multi-device
- Navegación: host va a gestor tras iniciar, no a pantalla de palabra
- PantallaPalabraCliente: cada jugador ve su palabra en su móvil
- PantallaDebateCliente: debate con timer y botón solicitar votación
- PantallaVotacionCliente: voto desde el móvil del cliente
- PantallaUnirse: listener que reacciona a partidaInicio y cambia de fase
- Protocolo: listo/voto/solicitoVotacion via Nearby hacia el host
- Nuevas cadenas l10n ES
This commit is contained in:
ShanaiaBot
2026-04-15 02:09:05 +02:00
parent 302cdf6f1a
commit eb2662f561
27 changed files with 2282 additions and 60 deletions

View File

@@ -33,8 +33,6 @@ class EstadoJuego extends ChangeNotifier {
if (_banco == null) return;
if (nombresJugadores.length < 3) return;
final rng = Random();
// Seleccionar palabra
final palabra = _banco!.palabraAleatoria(config.categoria);
final categoriaReal =
@@ -42,19 +40,18 @@ class EstadoJuego extends ChangeNotifier {
// Crear jugadores
final jugadores = nombresJugadores.asMap().entries.map((e) {
return Jugador(
id: 'j${e.key}',
nombre: e.value,
);
return Jugador(id: 'j${e.key}', nombre: e.value);
}).toList();
// Asignar impostores aleatoriamente
final indices = List.generate(jugadores.length, (i) => i);
indices.shuffle(rng);
final numImpostores =
config.numImpostores.clamp(1, jugadores.length ~/ 3);
for (int i = 0; i < numImpostores; i++) {
jugadores[indices[i]].esImpostor = true;
// Asignar impostores usando Random seguro (no predecible)
final rng = Random.secure();
final numImpostores = config.numImpostores.clamp(1, jugadores.length ~/ 3);
final impostoresElegidos = <int>{};
while (impostoresElegidos.length < numImpostores) {
impostoresElegidos.add(rng.nextInt(jugadores.length));
}
for (final i in impostoresElegidos) {
jugadores[i].esImpostor = true;
}
// Asignar palabras
@@ -124,15 +121,17 @@ class EstadoJuego extends ChangeNotifier {
// Encontrar máximo
final maxVotos = conteo.values.reduce(max);
final masVotados =
conteo.entries.where((e) => e.value == maxVotos).toList();
final masVotados = conteo.entries
.where((e) => e.value == maxVotos)
.toList();
// En caso de empate, elegir aleatoriamente
final rng = Random();
final eliminadoId =
masVotados[rng.nextInt(masVotados.length)].key;
// En caso de empate, elegir aleatoriamente (usar Random.secure para consistencia)
final rng = Random.secure();
final eliminadoId = masVotados[rng.nextInt(masVotados.length)].key;
final eliminado = _partida!.jugadores.firstWhere((j) => j.id == eliminadoId);
final eliminado = _partida!.jugadores.firstWhere(
(j) => j.id == eliminadoId,
);
eliminado.eliminado = true;
final resultado = ResultadoVotacion(