quel-est-ce-pokemon/lib/data/dto/pokemon_dto.dart

134 lines
4.3 KiB
Dart

import '../../domain/entities/pokemon.dart';
/// Conversion JSON <-> entité Pokemon. Unique endroit de parsing.
class PokemonDto {
PokemonDto._();
static PokemonType _frenchTypeToEnum(String type) {
const map = {
'Normal': PokemonType.normal,
'Combat': PokemonType.fighting,
'Vol': PokemonType.flying,
'Poison': PokemonType.poison,
'Sol': PokemonType.ground,
'Roche': PokemonType.rock,
'Insecte': PokemonType.bug,
'Spectre': PokemonType.ghost,
'Acier': PokemonType.steel,
'Feu': PokemonType.fire,
'Eau': PokemonType.water,
'Plante': PokemonType.grass,
'Électrik': PokemonType.electric,
'Psy': PokemonType.psychic,
'Glace': PokemonType.ice,
'Dragon': PokemonType.dragon,
'Ténèbres': PokemonType.dark,
'Fée': PokemonType.fairy,
};
return map[type] ?? PokemonType.unknown;
}
// Tyradex always returns type names in French regardless of endpoint language.
static PokemonType _typeToEnum(String typeName, String languageCode) {
return _frenchTypeToEnum(typeName);
}
/// Construit une entité depuis la réponse Tyradex.
/// [languageCode] détermine quelle langue utiliser pour [name] ('fr' ou 'en').
static Pokemon fromTyradexJson(
Map<String, dynamic> json, {
int? fallbackId,
String languageCode = 'fr',
}) {
final id = (json['pokedex_id'] as int?) ??
fallbackId ??
(throw ArgumentError('pokedex_id absent et fallbackId non fourni'));
final nameMap = json['name'] as Map<String, dynamic>?;
final nameFr = nameMap?['fr'] as String? ?? 'unknown';
final nameEn = nameMap?['en'] as String? ?? nameFr;
final name = languageCode == 'en' ? nameEn : nameFr;
final List types = json['types'] ?? [];
// Tyradex retourne toujours les types dans la langue du endpoint (fr ou en).
final type1 = types.isNotEmpty
? _typeToEnum(types[0]['name'] as String, languageCode)
: PokemonType.unknown;
final type2 = types.length > 1
? _typeToEnum(types[1]['name'] as String, languageCode)
: null;
final Map<String, dynamic>? stats = json['stats'];
// Tyradex expose 'category' (FR) et parfois 'category_en' (EN).
final descFr = json['category'] as String?;
final descEn = (json['category_en'] ?? json['category']) as String?;
return Pokemon(
name: name,
nameFr: nameFr,
nameEn: nameEn,
id: id,
type1: type1,
type2: type2,
hp: stats?['hp'] ?? 0,
atk: stats?['atk'] ?? 0,
def: stats?['def'] ?? 0,
spd: stats?['vit'] ?? 0,
description: descFr,
descriptionEn: descEn,
);
}
/// Sérialise pour SQLite (stocke les deux noms et descriptions).
static Map<String, dynamic> toDb(Pokemon p) {
return {
'name': p.name,
'name_fr': p.nameFr ?? p.name,
'name_en': p.nameEn ?? p.name,
'id': p.id,
'type1': p.type1.name,
'type2': p.type2?.name,
'hp': p.hp,
'atk': p.atk,
'def': p.def,
'spd': p.spd,
'description': p.description,
'description_en': p.descriptionEn,
'isCaught': p.isCaught ? 1 : 0,
'isSeen': p.isSeen ? 1 : 0,
};
}
/// Reconstruit depuis une ligne SQLite.
/// [languageCode] détermine quel nom afficher.
static Pokemon fromDb(Map<String, dynamic> row, {String languageCode = 'fr'}) {
final nameFr = row['name_fr'] as String? ?? row['name'] as String;
final nameEn = row['name_en'] as String? ?? nameFr;
final name = languageCode == 'en' ? nameEn : nameFr;
return Pokemon(
name: name,
nameFr: nameFr,
nameEn: nameEn,
id: row['id'],
type1: PokemonType.values.firstWhere(
(e) => e.name == row['type1'],
orElse: () => PokemonType.unknown,
),
type2: row['type2'] != null
? PokemonType.values.firstWhere(
(e) => e.name == row['type2'],
orElse: () => PokemonType.unknown,
)
: null,
hp: row['hp'] ?? 0,
atk: row['atk'] ?? 0,
def: row['def'] ?? 0,
spd: row['spd'] ?? 0,
description: row['description'],
descriptionEn: row['description_en'] as String?,
isCaught: row['isCaught'] == 1 || row['isCaught'] == true,
isSeen: row['isSeen'] == 1 || row['isSeen'] == true,
);
}
}