229 lines
10 KiB
Dart
229 lines
10 KiB
Dart
class MedallaUsuario {
|
|
final String id;
|
|
final String emoji;
|
|
final String assetPath;
|
|
final String nombre;
|
|
final String descripcion;
|
|
|
|
const MedallaUsuario({
|
|
required this.id,
|
|
required this.emoji,
|
|
required this.assetPath,
|
|
required this.nombre,
|
|
required this.descripcion,
|
|
});
|
|
}
|
|
|
|
class ResumenGamificacionUsuario {
|
|
final int fuego;
|
|
final List<String> medallas;
|
|
|
|
const ResumenGamificacionUsuario({
|
|
required this.fuego,
|
|
required this.medallas,
|
|
});
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
'fuego': fuego,
|
|
'medallas': medallas,
|
|
};
|
|
|
|
factory ResumenGamificacionUsuario.fromJson(Map<String, dynamic> json) {
|
|
return ResumenGamificacionUsuario(
|
|
fuego: (json['fuego'] as num?)?.toInt() ?? 0,
|
|
medallas: (json['medallas'] as List<dynamic>? ?? const [])
|
|
.map((valor) => valor.toString())
|
|
.toList(),
|
|
);
|
|
}
|
|
}
|
|
|
|
class ProgresoGamificacionUsuario {
|
|
final EstadisticasPerfilUsuario antes;
|
|
final EstadisticasPerfilUsuario despues;
|
|
final List<String> nuevasMedallas;
|
|
|
|
const ProgresoGamificacionUsuario({
|
|
required this.antes,
|
|
required this.despues,
|
|
required this.nuevasMedallas,
|
|
});
|
|
|
|
int get incrementoFuego => despues.fuego - antes.fuego;
|
|
}
|
|
|
|
class EstadisticasPerfilUsuario {
|
|
final int partidasJugadas;
|
|
final int partidasGanadas;
|
|
final int partidasPerdidas;
|
|
final int partidasComoImpostor;
|
|
final int victoriasComoImpostor;
|
|
final String? fechaUltimaPartidaIso;
|
|
final int partidasHoy;
|
|
final int subidaFuegoHoy;
|
|
final int fuego;
|
|
|
|
const EstadisticasPerfilUsuario({
|
|
this.partidasJugadas = 0,
|
|
this.partidasGanadas = 0,
|
|
this.partidasPerdidas = 0,
|
|
this.partidasComoImpostor = 0,
|
|
this.victoriasComoImpostor = 0,
|
|
this.fechaUltimaPartidaIso,
|
|
this.partidasHoy = 0,
|
|
this.subidaFuegoHoy = 0,
|
|
this.fuego = 0,
|
|
});
|
|
|
|
static const catalogoMedallas = <String, MedallaUsuario>{
|
|
'novato': MedallaUsuario(id: 'novato', emoji: '🎲', assetPath: 'assets/medals/novato.png', nombre: 'Novato', descripcion: 'Jugó su primera partida.'),
|
|
'habitual': MedallaUsuario(id: 'habitual', emoji: '🧭', assetPath: 'assets/medals/habitual.png', nombre: 'Habitual', descripcion: 'Jugó 10 partidas.'),
|
|
'veterano': MedallaUsuario(id: 'veterano', emoji: '🏛️', assetPath: 'assets/medals/veterano.png', nombre: 'Veterano', descripcion: 'Jugó 50 partidas.'),
|
|
'leyenda': MedallaUsuario(id: 'leyenda', emoji: '👑', assetPath: 'assets/medals/leyenda.png', nombre: 'Leyenda', descripcion: 'Jugó 100 partidas.'),
|
|
'primera_victoria': MedallaUsuario(id: 'primera_victoria', emoji: '🥉', assetPath: 'assets/medals/primera_victoria.png', nombre: 'Primera victoria', descripcion: 'Ganó una partida.'),
|
|
'diez_victorias': MedallaUsuario(id: 'diez_victorias', emoji: '🥈', assetPath: 'assets/medals/diez_victorias.png', nombre: 'Diez victorias', descripcion: 'Ganó 10 partidas.'),
|
|
'veinticinco_victorias': MedallaUsuario(id: 'veinticinco_victorias', emoji: '🥇', assetPath: 'assets/medals/veinticinco_victorias.png', nombre: 'Veinticinco victorias', descripcion: 'Ganó 25 partidas.'),
|
|
'cincuenta_victorias': MedallaUsuario(id: 'cincuenta_victorias', emoji: '💎', assetPath: 'assets/medals/cincuenta_victorias.png', nombre: 'Cincuenta victorias', descripcion: 'Ganó 50 partidas.'),
|
|
'primer_engano': MedallaUsuario(id: 'primer_engano', emoji: '🎭', assetPath: 'assets/medals/primer_engano.png', nombre: 'Primer engaño', descripcion: 'Ganó como impostor.'),
|
|
'impostor_habitual': MedallaUsuario(id: 'impostor_habitual', emoji: '🃏', assetPath: 'assets/medals/impostor_habitual.png', nombre: 'Impostor habitual', descripcion: 'Ganó 5 partidas como impostor.'),
|
|
'lobo_faroles': MedallaUsuario(id: 'lobo_faroles', emoji: '🐺', assetPath: 'assets/medals/lobo_faroles.png', nombre: 'Lobo entre faroles', descripcion: 'Ganó 15 partidas como impostor.'),
|
|
'brasa': MedallaUsuario(id: 'brasa', emoji: '♨️', assetPath: 'assets/medals/brasa.png', nombre: 'Brasa', descripcion: 'Mantiene algo de fuego reciente.'),
|
|
'llama_suave': MedallaUsuario(id: 'llama_suave', emoji: '🔥', assetPath: 'assets/medals/llama_suave.png', nombre: 'Llama suave', descripcion: 'Está jugando con cierta asiduidad.'),
|
|
'llama_fuerte': MedallaUsuario(id: 'llama_fuerte', emoji: '🔥', assetPath: 'assets/medals/llama_fuerte.png', nombre: 'Llama fuerte', descripcion: 'Tiene una asiduidad alta.'),
|
|
'incandescente': MedallaUsuario(id: 'incandescente', emoji: '🌋', assetPath: 'assets/medals/incandescente.png', nombre: 'Incandescente', descripcion: 'Tiene el fuego al máximo.'),
|
|
};
|
|
|
|
EstadisticasPerfilUsuario copiar({
|
|
int? partidasJugadas,
|
|
int? partidasGanadas,
|
|
int? partidasPerdidas,
|
|
int? partidasComoImpostor,
|
|
int? victoriasComoImpostor,
|
|
String? fechaUltimaPartidaIso,
|
|
bool limpiarFechaUltimaPartida = false,
|
|
int? partidasHoy,
|
|
int? subidaFuegoHoy,
|
|
int? fuego,
|
|
}) {
|
|
return EstadisticasPerfilUsuario(
|
|
partidasJugadas: partidasJugadas ?? this.partidasJugadas,
|
|
partidasGanadas: partidasGanadas ?? this.partidasGanadas,
|
|
partidasPerdidas: partidasPerdidas ?? this.partidasPerdidas,
|
|
partidasComoImpostor: partidasComoImpostor ?? this.partidasComoImpostor,
|
|
victoriasComoImpostor: victoriasComoImpostor ?? this.victoriasComoImpostor,
|
|
fechaUltimaPartidaIso: limpiarFechaUltimaPartida ? null : (fechaUltimaPartidaIso ?? this.fechaUltimaPartidaIso),
|
|
partidasHoy: partidasHoy ?? this.partidasHoy,
|
|
subidaFuegoHoy: subidaFuegoHoy ?? this.subidaFuegoHoy,
|
|
fuego: (fuego ?? this.fuego).clamp(0, 100).toInt(),
|
|
);
|
|
}
|
|
|
|
EstadisticasPerfilUsuario registrarPartida({
|
|
required bool victoria,
|
|
bool comoImpostor = false,
|
|
bool victoriaComoImpostor = false,
|
|
DateTime? fecha,
|
|
}) {
|
|
final momento = fecha ?? DateTime.now();
|
|
final normalizada = DateTime(momento.year, momento.month, momento.day);
|
|
final anterior = _aplicarPasoDeDias(normalizada);
|
|
final ganancia = anterior._gananciaFuegoSiguientePartida();
|
|
return anterior.copiar(
|
|
partidasJugadas: anterior.partidasJugadas + 1,
|
|
partidasGanadas: anterior.partidasGanadas + (victoria ? 1 : 0),
|
|
partidasPerdidas: anterior.partidasPerdidas + (victoria ? 0 : 1),
|
|
partidasComoImpostor: anterior.partidasComoImpostor + (comoImpostor ? 1 : 0),
|
|
victoriasComoImpostor: anterior.victoriasComoImpostor + (victoriaComoImpostor ? 1 : 0),
|
|
fechaUltimaPartidaIso: normalizada.toIso8601String(),
|
|
partidasHoy: anterior.partidasHoy + 1,
|
|
subidaFuegoHoy: anterior.subidaFuegoHoy + ganancia,
|
|
fuego: anterior.fuego + ganancia,
|
|
);
|
|
}
|
|
|
|
EstadisticasPerfilUsuario _aplicarPasoDeDias(DateTime hoy) {
|
|
final ultima = fechaUltimaPartidaIso == null ? null : DateTime.tryParse(fechaUltimaPartidaIso!);
|
|
if (ultima == null) return copiar(partidasHoy: 0, subidaFuegoHoy: 0);
|
|
final ultimoDia = DateTime(ultima.year, ultima.month, ultima.day);
|
|
final diferenciaDias = hoy.difference(ultimoDia).inDays;
|
|
if (diferenciaDias <= 0) return this;
|
|
final diasSinJugar = diferenciaDias - 1;
|
|
var fuegoActual = fuego;
|
|
for (var i = 1; i <= diasSinJugar; i++) {
|
|
fuegoActual -= i == 1 ? 3 : (i == 2 ? 5 : 7);
|
|
}
|
|
return copiar(partidasHoy: 0, subidaFuegoHoy: 0, fuego: fuegoActual);
|
|
}
|
|
|
|
int _gananciaFuegoSiguientePartida() {
|
|
final numeroPartidaDelDia = partidasHoy + 1;
|
|
final base = switch (numeroPartidaDelDia) { 1 => 6, 2 => 5, 3 => 4, 4 => 3, 5 => 2, _ => 1 };
|
|
final restanteHoy = (25 - subidaFuegoHoy).clamp(0, 25).toInt();
|
|
return base.clamp(0, restanteHoy).toInt();
|
|
}
|
|
|
|
List<String> get medallas {
|
|
final resultado = <String>[];
|
|
if (partidasJugadas >= 1) resultado.add('novato');
|
|
if (partidasJugadas >= 10) resultado.add('habitual');
|
|
if (partidasJugadas >= 50) resultado.add('veterano');
|
|
if (partidasJugadas >= 100) resultado.add('leyenda');
|
|
if (partidasGanadas >= 1) resultado.add('primera_victoria');
|
|
if (partidasGanadas >= 10) resultado.add('diez_victorias');
|
|
if (partidasGanadas >= 25) resultado.add('veinticinco_victorias');
|
|
if (partidasGanadas >= 50) resultado.add('cincuenta_victorias');
|
|
if (victoriasComoImpostor >= 1) resultado.add('primer_engano');
|
|
if (victoriasComoImpostor >= 5) resultado.add('impostor_habitual');
|
|
if (victoriasComoImpostor >= 15) resultado.add('lobo_faroles');
|
|
if (fuego >= 100) {
|
|
resultado.add('incandescente');
|
|
} else if (fuego >= 50) {
|
|
resultado.add('llama_fuerte');
|
|
} else if (fuego >= 25) {
|
|
resultado.add('llama_suave');
|
|
} else if (fuego > 0) {
|
|
resultado.add('brasa');
|
|
}
|
|
return resultado;
|
|
}
|
|
|
|
List<String> get medallasPrincipales {
|
|
final ids = medallas;
|
|
const prioridad = [
|
|
'incandescente', 'llama_fuerte', 'llama_suave', 'brasa',
|
|
'leyenda', 'veterano', 'habitual', 'novato',
|
|
'cincuenta_victorias', 'veinticinco_victorias', 'diez_victorias', 'primera_victoria',
|
|
'lobo_faroles', 'impostor_habitual', 'primer_engano',
|
|
];
|
|
return prioridad.where(ids.contains).take(3).toList();
|
|
}
|
|
|
|
ResumenGamificacionUsuario get resumen => ResumenGamificacionUsuario(fuego: fuego, medallas: medallasPrincipales);
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
'partidasJugadas': partidasJugadas,
|
|
'partidasGanadas': partidasGanadas,
|
|
'partidasPerdidas': partidasPerdidas,
|
|
'partidasComoImpostor': partidasComoImpostor,
|
|
'victoriasComoImpostor': victoriasComoImpostor,
|
|
if (fechaUltimaPartidaIso != null) 'fechaUltimaPartidaIso': fechaUltimaPartidaIso,
|
|
'partidasHoy': partidasHoy,
|
|
'subidaFuegoHoy': subidaFuegoHoy,
|
|
'fuego': fuego,
|
|
};
|
|
|
|
factory EstadisticasPerfilUsuario.fromJson(Map<String, dynamic> json) {
|
|
return EstadisticasPerfilUsuario(
|
|
partidasJugadas: (json['partidasJugadas'] as num?)?.toInt() ?? 0,
|
|
partidasGanadas: (json['partidasGanadas'] as num?)?.toInt() ?? 0,
|
|
partidasPerdidas: (json['partidasPerdidas'] as num?)?.toInt() ?? 0,
|
|
partidasComoImpostor: (json['partidasComoImpostor'] as num?)?.toInt() ?? 0,
|
|
victoriasComoImpostor: (json['victoriasComoImpostor'] as num?)?.toInt() ?? 0,
|
|
fechaUltimaPartidaIso: json['fechaUltimaPartidaIso'] as String?,
|
|
partidasHoy: (json['partidasHoy'] as num?)?.toInt() ?? 0,
|
|
subidaFuegoHoy: (json['subidaFuegoHoy'] as num?)?.toInt() ?? 0,
|
|
fuego: (json['fuego'] as num?)?.toInt() ?? 0,
|
|
);
|
|
}
|
|
}
|