143 lines
4.6 KiB
Dart
143 lines
4.6 KiB
Dart
import 'dart:convert';
|
|
import 'dart:math';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:farolero/l10n/generated/app_localizations.dart';
|
|
|
|
/// Categorías disponibles en el banco de palabras
|
|
class BancoPalabras {
|
|
final Map<String, List<String>> categorias;
|
|
|
|
BancoPalabras(this.categorias);
|
|
|
|
static final Map<String, BancoPalabras> _instancias = {};
|
|
|
|
static Future<BancoPalabras> cargar({String idioma = 'es'}) async {
|
|
if (_instancias.containsKey(idioma)) return _instancias[idioma]!;
|
|
|
|
// Intentar cargar el banco del idioma solicitado, fallback a castellano
|
|
String jsonStr;
|
|
try {
|
|
final archivo = idioma == 'es'
|
|
? 'assets/palabras.json'
|
|
: 'assets/palabras_$idioma.json';
|
|
jsonStr = await rootBundle.loadString(archivo);
|
|
} catch (_) {
|
|
// Fallback a castellano si no existe el banco para ese idioma
|
|
if (idioma != 'es') {
|
|
return cargar(idioma: 'es');
|
|
}
|
|
rethrow;
|
|
}
|
|
|
|
final data = json.decode(jsonStr) as Map<String, dynamic>;
|
|
final cats = data['categorias'] as Map<String, dynamic>;
|
|
final mapa = <String, List<String>>{};
|
|
for (final entrada in cats.entries) {
|
|
mapa[entrada.key] = List<String>.from(entrada.value);
|
|
}
|
|
_instancias[idioma] = BancoPalabras(mapa);
|
|
return _instancias[idioma]!;
|
|
}
|
|
|
|
List<String> get nombresCategorias => categorias.keys.toList();
|
|
|
|
/// Obtiene una palabra aleatoria de la categoría dada (o de todas si es null)
|
|
String palabraAleatoria(String? categoria) {
|
|
final rng = Random();
|
|
if (categoria == null || categoria == 'todas') {
|
|
final todasPalabras = categorias.values.expand((l) => l).toList();
|
|
return todasPalabras[rng.nextInt(todasPalabras.length)];
|
|
}
|
|
final lista = categorias[categoria]!;
|
|
return lista[rng.nextInt(lista.length)];
|
|
}
|
|
|
|
/// Devuelve la categoría a la que pertenece una palabra
|
|
String? categoriaDepalabra(String palabra) {
|
|
for (final entrada in categorias.entries) {
|
|
if (entrada.value.contains(palabra)) return entrada.key;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// Devuelve el nombre localizado de la categoría usando AppLocalizations
|
|
static String nombreBonitoCategoria(String clave, [AppLocalizations? l10n]) {
|
|
if (l10n != null) {
|
|
final nombres = {
|
|
'todas': l10n.categoryAll,
|
|
'animales': l10n.categoryAnimals,
|
|
'comida': l10n.categoryFood,
|
|
'paises': l10n.categoryCountries,
|
|
'deportes': l10n.categorySports,
|
|
'profesiones': l10n.categoryProfessions,
|
|
'objetos': l10n.categoryObjects,
|
|
'lugares': l10n.categoryPlaces,
|
|
'peliculas': l10n.categoryMovies,
|
|
'musica': l10n.categoryMusic,
|
|
'tecnologia': l10n.categoryTechnology,
|
|
};
|
|
return nombres[clave] ?? clave;
|
|
}
|
|
// Fallback a castellano si no hay l10n
|
|
const nombres = {
|
|
'todas': 'Todas',
|
|
'animales': 'Animales',
|
|
'comida': 'Comida',
|
|
'paises': 'Países',
|
|
'deportes': 'Deportes',
|
|
'profesiones': 'Profesiones',
|
|
'objetos': 'Objetos',
|
|
'lugares': 'Lugares',
|
|
'peliculas': 'Películas',
|
|
'musica': 'Música',
|
|
'tecnologia': 'Tecnología',
|
|
};
|
|
return nombres[clave] ?? clave;
|
|
}
|
|
}
|
|
|
|
class EntradaPalabraTraducida {
|
|
final String palabra;
|
|
final Map<String, String> traducciones;
|
|
|
|
const EntradaPalabraTraducida({
|
|
required this.palabra,
|
|
required this.traducciones,
|
|
});
|
|
}
|
|
|
|
class BancoPalabrasTraducidas {
|
|
final Map<String, List<EntradaPalabraTraducida>> categorias;
|
|
|
|
const BancoPalabrasTraducidas(this.categorias);
|
|
|
|
static BancoPalabrasTraducidas? _instancia;
|
|
|
|
static Future<BancoPalabrasTraducidas> cargar() async {
|
|
if (_instancia != null) return _instancia!;
|
|
|
|
final jsonStr = await rootBundle.loadString('assets/palabras_i18n.json');
|
|
final data = json.decode(jsonStr) as Map<String, dynamic>;
|
|
final cats = data['categorias'] as Map<String, dynamic>;
|
|
final mapa = <String, List<EntradaPalabraTraducida>>{};
|
|
|
|
for (final categoria in cats.entries) {
|
|
final entradas = categoria.value as List<dynamic>;
|
|
mapa[categoria.key] = entradas.map((entradaRaw) {
|
|
final entrada = entradaRaw as Map<String, dynamic>;
|
|
final traduccionesRaw =
|
|
entrada['traducciones'] as Map<String, dynamic>? ?? {};
|
|
return EntradaPalabraTraducida(
|
|
palabra: entrada['es'] as String,
|
|
traducciones: traduccionesRaw.map(
|
|
(idioma, valor) => MapEntry(idioma, valor?.toString() ?? ''),
|
|
)..removeWhere((_, valor) => valor.isEmpty),
|
|
);
|
|
}).toList();
|
|
}
|
|
|
|
_instancia = BancoPalabrasTraducidas(mapa);
|
|
return _instancia!;
|
|
}
|
|
}
|