filenameAnalyzer->analyze($query->filename); $searchedTitle = $analyzedFilename->getTitle()->getValue(); $chapterNumber = $analyzedFilename->hasChapterNumber() ? $analyzedFilename->getChapterNumber()->getValue() : null; $volumeNumber = $analyzedFilename->hasVolumeNumber() ? $analyzedFilename->getVolumeNumber()->getValue() : null; // Rechercher les mangas correspondants $foundMangas = $this->mangaRepository->search($searchedTitle, 1, 10); $matches = []; foreach ($foundMangas as $manga) { $mangaId = $manga->getId()->getValue(); // Calculer un score de correspondance $matchScore = $this->calculateMatchScore( $manga, $searchedTitle ); $matches[] = new MangaMatchItem( id: $mangaId, title: $manga->getTitle()->getValue(), slug: $manga->getSlug()->getValue(), alternativeSlugs: $manga->getAlternativeSlugs(), thumbnailUrl: $manga->getImageUrls()->getThumbnail(), matchScore: $matchScore, chapterNumber: $chapterNumber, volumeNumber: $volumeNumber ); } // Trier les résultats par score de correspondance (du plus élevé au plus faible) usort($matches, fn ($a, $b) => $b->matchScore <=> $a->matchScore); return new MangaMatchResponse( matches: $matches, chapterNumber: $chapterNumber, volumeNumber: $volumeNumber, possibleTitles: [$searchedTitle] ); } /** * Calcule un score de correspondance entre le manga et le titre recherché * Score plus élevé = meilleure correspondance */ private function calculateMatchScore(Manga $manga, string $searchedTitle): int { $score = 0; $mangaTitle = $manga->getTitle()->getValue(); $mangaSlug = $manga->getSlug()->getValue(); // Correspondance exacte avec le titre if (strtolower($mangaTitle) === strtolower($searchedTitle)) { $score += 100; } // Correspondance exacte avec le slug if (strtolower($mangaSlug) === strtolower($searchedTitle)) { $score += 90; } // Correspondance avec les slugs alternatifs foreach ($manga->getAlternativeSlugs() as $altSlug) { if (strtolower($altSlug) === strtolower($searchedTitle)) { $score += 80; break; } } // Le titre du manga contient le terme recherché if (stripos($mangaTitle, $searchedTitle) !== false) { $score += 50; } // Le terme recherché contient le titre du manga if (stripos($searchedTitle, $mangaTitle) !== false) { $score += 40; } // Similarité de Levenshtein (pour les fautes de frappe) $levenshteinDistance = levenshtein( strtolower($mangaTitle), strtolower($searchedTitle) ); if ($levenshteinDistance <= 3) { $score += (3 - $levenshteinDistance) * 10; } return $score; } }