From d753761556890fd9693a8f67ec602c184ff68463 Mon Sep 17 00:00:00 2001 From: "ext.jeremy.guillot@maxicoffee.domains" Date: Fri, 20 Jun 2025 15:43:10 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20am=C3=A9lioration=20de=20l'harmonisatio?= =?UTF-8?q?n=20des=20volumes=20des=20chapitres=20en=20ajoutant=20une=20m?= =?UTF-8?q?=C3=A9thode=20pour=20remplir=20les=20trous=20de=20volumes=20man?= =?UTF-8?q?quants,=20et=20refactorisation=20de=20la=20cr=C3=A9ation=20de?= =?UTF-8?q?=20chapitres=20avec=20un=20nouveau=20volume.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FetchMangaChaptersHandler.php | 115 ++++++++++++++++-- 1 file changed, 103 insertions(+), 12 deletions(-) diff --git a/src/Domain/Manga/Application/CommandHandler/FetchMangaChaptersHandler.php b/src/Domain/Manga/Application/CommandHandler/FetchMangaChaptersHandler.php index 7149cba..a08e141 100644 --- a/src/Domain/Manga/Application/CommandHandler/FetchMangaChaptersHandler.php +++ b/src/Domain/Manga/Application/CommandHandler/FetchMangaChaptersHandler.php @@ -104,15 +104,17 @@ readonly class FetchMangaChaptersHandler * Harmonise les volumes des chapitres: * - Si le chapitre précédent et suivant ont un volume null, alors le chapitre actuel aussi * - Si le chapitre précédent et suivant ont le même volume, alors le chapitre actuel aura ce volume + * - Remplit les "trous" de volumes manquants dans une séquence */ private function harmonizeVolumes(array &$chaptersByNumber): void { // Trie les chapitres par numéro pour faciliter la recherche des adjacents - ksort($chaptersByNumber); + uksort($chaptersByNumber, fn($a, $b) => (float)$a <=> (float)$b); $chapterNumbers = array_keys($chaptersByNumber); $count = count($chapterNumbers); + // Première passe : harmonisation locale (chapitres adjacents) for ($i = 1; $i < $count - 1; $i++) { $prevChapterNum = $chapterNumbers[$i - 1]; $currentChapterNum = $chapterNumbers[$i]; @@ -137,18 +139,107 @@ readonly class FetchMangaChaptersHandler } if ($shouldUpdateVolume) { - // On doit créer un nouveau chapitre car les objets sont immuables - $chaptersByNumber[$currentChapterNum] = new Chapter( - id: new ChapterId($currentChapter->getId()), - mangaId: $currentChapter->getMangaId(), - number: $currentChapter->getNumber(), - title: $currentChapter->getTitle(), - volume: $newVolume, // On met à jour le volume - isVisible: $currentChapter->isVisible(), - isAvailable: $currentChapter->isAvailable(), - createdAt: $currentChapter->getCreatedAt() - ); + $chaptersByNumber[$currentChapterNum] = $this->createChapterWithNewVolume($currentChapter, $newVolume); + } + } + + // Deuxième passe : remplissage des trous de volumes + $this->fillVolumeGaps($chaptersByNumber); + } + + /** + * Remplit les "trous" de volumes dans une séquence de chapitres. + * Par exemple, si on a : Ch.317(Vol.34), Ch.318(Vol.34), Ch.319(null), Ch.320(null), Ch.321(Vol.34) + * Alors Ch.319 et Ch.320 seront assignés au Vol.34 + */ + private function fillVolumeGaps(array &$chaptersByNumber): void + { + $chapterNumbers = array_keys($chaptersByNumber); + $count = count($chapterNumbers); + + for ($i = 0; $i < $count; $i++) { + $currentChapterNum = $chapterNumbers[$i]; + $currentChapter = $chaptersByNumber[$currentChapterNum]; + + // Si le chapitre actuel n'a pas de volume, on cherche à le combler + if ($currentChapter->getVolume() === null) { + $volumeToAssign = $this->findVolumeForGap($chaptersByNumber, $chapterNumbers, $i); + + if ($volumeToAssign !== null) { + $chaptersByNumber[$currentChapterNum] = $this->createChapterWithNewVolume($currentChapter, $volumeToAssign); + } } } } + + /** + * Trouve le volume à assigner pour un chapitre sans volume en analysant son contexte + */ + private function findVolumeForGap(array $chaptersByNumber, array $chapterNumbers, int $currentIndex): ?int + { + $count = count($chapterNumbers); + + // Cherche le volume précédent non-null + $prevVolume = null; + for ($i = $currentIndex - 1; $i >= 0; $i--) { + $prevChapter = $chaptersByNumber[$chapterNumbers[$i]]; + if ($prevChapter->getVolume() !== null) { + $prevVolume = $prevChapter->getVolume(); + break; + } + } + + // Cherche le volume suivant non-null + $nextVolume = null; + for ($i = $currentIndex + 1; $i < $count; $i++) { + $nextChapter = $chaptersByNumber[$chapterNumbers[$i]]; + if ($nextChapter->getVolume() !== null) { + $nextVolume = $nextChapter->getVolume(); + break; + } + } + + // Si les volumes précédent et suivant sont identiques et non-null, on utilise ce volume + if ($prevVolume !== null && $prevVolume === $nextVolume) { + return $prevVolume; + } + + // Si on a seulement un volume précédent, on vérifie s'il est raisonnable de l'utiliser + // (pas plus de 10 chapitres d'écart pour éviter les erreurs) + if ($prevVolume !== null && $nextVolume === null) { + $currentChapterNumber = (float) $chapterNumbers[$currentIndex]; + + // Trouve le numéro du chapitre qui a ce volume précédent + for ($i = $currentIndex - 1; $i >= 0; $i--) { + $prevChapter = $chaptersByNumber[$chapterNumbers[$i]]; + if ($prevChapter->getVolume() === $prevVolume) { + $prevChapterNumber = (float) $chapterNumbers[$i]; + // Si l'écart est raisonnable (moins de 10 chapitres), on assigne le volume + if ($currentChapterNumber - $prevChapterNumber <= 10) { + return $prevVolume; + } + break; + } + } + } + + return null; + } + + /** + * Crée un nouveau chapitre avec un volume différent (les chapitres sont immuables) + */ + private function createChapterWithNewVolume(Chapter $chapter, ?int $newVolume): Chapter + { + return new Chapter( + id: new ChapterId($chapter->getId()), + mangaId: $chapter->getMangaId(), + number: $chapter->getNumber(), + title: $chapter->getTitle(), + volume: $newVolume, + isVisible: $chapter->isVisible(), + isAvailable: $chapter->isAvailable(), + createdAt: $chapter->getCreatedAt() + ); + } }