feat(manga): implémenter la page Découvrir avec recommandations MangaDex
- Endpoint GET /api/manga-discover via DiscoverMangaStateProvider + DiscoverMangaHandler
- Algorithme : top 5 manga de la collection → appel /manga/{id}/recommendation
par source → agrégation avec système de votes (multi-sources = plus pertinent)
- Filtrage : tags exclus (Oneshot, Doujinshi, Self-Published), contentRating,
et suppression des manga déjà en bibliothèque
- Page Vue DiscoverPage.vue : chargement auto au montage, bouton Actualiser,
modal détail, ajout à la bibliothèque
- Adapteurs InMemory de test mis à jour (discover + getMangaRecommendations)
This commit is contained in:
parent
65453c87e5
commit
814fe46ce5
@@ -135,6 +135,55 @@ readonly class MangadexProvider implements MangaProviderInterface
|
||||
}
|
||||
}
|
||||
|
||||
public function discover(array $sourceExternalIds): MangaCollection
|
||||
{
|
||||
if (empty($sourceExternalIds)) {
|
||||
return new MangaCollection([]);
|
||||
}
|
||||
|
||||
// Compter les votes : un manga recommandé par plusieurs sources est plus pertinent.
|
||||
// On conserve aussi la position d'apparition pour départager les ex-aequo.
|
||||
$votes = [];
|
||||
$firstPosition = [];
|
||||
$resultsById = [];
|
||||
$position = 0;
|
||||
|
||||
foreach ($sourceExternalIds as $externalId) {
|
||||
try {
|
||||
$response = $this->client->getMangaRecommendations($externalId);
|
||||
foreach ($response['data'] ?? [] as $result) {
|
||||
$id = $result['id'];
|
||||
$votes[$id] = ($votes[$id] ?? 0) + 1;
|
||||
if (!isset($firstPosition[$id])) {
|
||||
$firstPosition[$id] = $position++;
|
||||
$resultsById[$id] = $result;
|
||||
}
|
||||
}
|
||||
} catch (\Exception) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($resultsById)) {
|
||||
return new MangaCollection([]);
|
||||
}
|
||||
|
||||
// Trier : votes décroissants (multi-sources = plus pertinent), puis position croissante (score API)
|
||||
uksort($resultsById, function (string $a, string $b) use ($votes, $firstPosition): int {
|
||||
$voteDiff = $votes[$b] - $votes[$a];
|
||||
if ($voteDiff !== 0) {
|
||||
return $voteDiff;
|
||||
}
|
||||
|
||||
return $firstPosition[$a] <=> $firstPosition[$b];
|
||||
});
|
||||
|
||||
$mangas = $this->createMangasFromResults(array_values($resultsById));
|
||||
$this->enrichWithRatings($mangas);
|
||||
|
||||
return new MangaCollection($mangas);
|
||||
}
|
||||
|
||||
public function findByExternalId(ExternalId $externalId): ?Manga
|
||||
{
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user