Skip to content

Commit 77fbbb3

Browse files
Simplified code for related anime search and potentially fixed bug in which related anime search didn't return some expected entries
1 parent 4ffcd43 commit 77fbbb3

File tree

7 files changed

+47
-117
lines changed

7 files changed

+47
-117
lines changed

manami-app/src/main/kotlin/io/github/manamiproject/manami/app/relatedanime/DefaultRelatedAnimeHandler.kt

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import io.github.manamiproject.manami.app.state.State
1414
import io.github.manamiproject.modb.core.logging.LoggerDelegate
1515
import io.github.manamiproject.modb.core.models.Anime
1616
import java.net.URI
17-
import java.util.*
1817

1918
internal class DefaultRelatedAnimeHandler(
2019
private val cache: AnimeCache = DefaultAnimeCache.instance,
@@ -33,49 +32,33 @@ internal class DefaultRelatedAnimeHandler(
3332
}
3433

3534
private fun findRelatedAnime(eventListType: EventListType, initialSources: Collection<URI>) {
36-
var numberOfEntriesToBeChecked: Int
37-
val entriesToCheck = Stack<URI>()
35+
val entriesToCheck = HashSet<URI>()
36+
var lastSize = 0
3837

3938
val initialRelatedAnime = initialSources.map { cache.fetch(it) }
4039
.filterIsInstance<PresentValue<Anime>>()
4140
.flatMap { it.value.relatedAnime }
4241
initialSources.union(initialRelatedAnime).forEach { entriesToCheck.add(it) }
43-
numberOfEntriesToBeChecked = entriesToCheck.size
4442

4543
val animeList = state.animeList().map { it.link }.filterIsInstance<Link>().map { it.uri }.toSet()
4644
val watchList = state.watchList().map { it.link.uri }.toSet()
4745
val ignoreList = state.ignoreList().map { it.link.uri }.toSet()
4846

49-
val checkedEntries = mutableSetOf<URI>()
50-
5147
log.info { "Initializing search for [$eventListType] related anime is done." }
5248

53-
while (entriesToCheck.isNotEmpty()) {
54-
log.trace { "Checking ${checkedEntries.size+1}/$numberOfEntriesToBeChecked for [$eventListType] related anime" }
55-
val currentEntry = entriesToCheck.pop()
56-
57-
if (!checkedEntries.contains(currentEntry)) {
58-
val entry = cache.fetch(currentEntry)
59-
if (entry is PresentValue<Anime>) {
60-
entry.value.relatedAnime.filterNot { checkedEntries.contains(it) }
61-
.filterNot { entriesToCheck.contains(it) }
62-
.forEach {
63-
entriesToCheck.push(it)
64-
numberOfEntriesToBeChecked++
65-
}
66-
67-
val entrySource = entry.value.sources.first()
68-
if (!animeList.contains(entrySource) && !watchList.contains(entrySource) && !ignoreList.contains(entrySource)) {
69-
eventBus.post(RelatedAnimeFoundEvent(eventListType, entry.value))
70-
}
71-
}
72-
}
73-
74-
checkedEntries.add(currentEntry)
75-
eventBus.post(RelatedAnimeStatusEvent(eventListType, checkedEntries.size, numberOfEntriesToBeChecked))
49+
while (entriesToCheck.size != lastSize) {
50+
lastSize = entriesToCheck.size
51+
entriesToCheck.map { cache.fetch(it) }
52+
.filterIsInstance<PresentValue<Anime>>()
53+
.flatMap { it.value.relatedAnime }
54+
.forEach { entriesToCheck.add(it) }
7655
}
7756

78-
eventBus.post(RelatedAnimeFinishedEvent(eventListType))
57+
entriesToCheck.removeAll(animeList)
58+
entriesToCheck.removeAll(watchList)
59+
entriesToCheck.removeAll(ignoreList)
60+
61+
eventBus.post(RelatedAnimeFinishedEvent(eventListType, entriesToCheck.map { cache.fetch(it) }.filterIsInstance<PresentValue<Anime>>().map { it.value }))
7962
log.info { "Finished searching for [$eventListType] related anime" }
8063
}
8164

manami-app/src/main/kotlin/io/github/manamiproject/manami/app/relatedanime/RelatedAnimeEvents.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,4 @@ import io.github.manamiproject.manami.app.events.Event
44
import io.github.manamiproject.manami.app.events.EventListType
55
import io.github.manamiproject.modb.core.models.Anime
66

7-
data class RelatedAnimeFoundEvent(val listType: EventListType, val anime: Anime): Event
8-
data class RelatedAnimeStatusEvent(val listType: EventListType, val finishedChecking: Int, val toBeChecked: Int): Event
9-
data class RelatedAnimeFinishedEvent(val listType: EventListType): Event
7+
data class RelatedAnimeFinishedEvent(val listType: EventListType, val resultList: List<Anime>): Event

manami-app/src/test/kotlin/io/github/manamiproject/manami/app/relatedanime/DefaultRelatedAnimeHandlerTest.kt

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ internal class DefaultRelatedAnimeHandlerTest {
8787
defaultRelatedAnimeHandler.findRelatedAnimeForAnimeList()
8888

8989
// then
90-
val animeFoundEvents = receivedEvents.filterIsInstance<RelatedAnimeFoundEvent>()
91-
assertThat(animeFoundEvents).hasSize(6)
90+
val animeFoundEvents = receivedEvents.filterIsInstance<RelatedAnimeFinishedEvent>()
91+
assertThat(animeFoundEvents).hasSize(1)
9292
assertThat(animeFoundEvents.map { it.listType }.distinct()).containsExactly(ANIME_LIST)
9393

94-
val foundEntries = animeFoundEvents.map { it.anime.sources.first() }
94+
val foundEntries = animeFoundEvents.flatMap { it.resultList.map { anime -> anime.sources.first() } }
9595
assertThat(foundEntries).containsExactlyInAnyOrder(
9696
anime1.sources.first(),
9797
anime3.sources.first(),
@@ -100,13 +100,6 @@ internal class DefaultRelatedAnimeHandlerTest {
100100
anime6.sources.first(),
101101
anime7.sources.first(),
102102
)
103-
104-
val statusEvents = receivedEvents.filterIsInstance<RelatedAnimeStatusEvent>()
105-
assertThat(statusEvents).hasSize(7)
106-
assertThat(statusEvents.map { it.listType }.distinct()).containsExactly(ANIME_LIST)
107-
108-
assertThat(receivedEvents.last()).isInstanceOf(RelatedAnimeFinishedEvent::class.java)
109-
assertThat((receivedEvents.last() as RelatedAnimeFinishedEvent).listType).isEqualTo(ANIME_LIST)
110103
}
111104
}
112105

@@ -162,10 +155,10 @@ internal class DefaultRelatedAnimeHandlerTest {
162155
defaultRelatedAnimeHandler.findRelatedAnimeForAnimeList()
163156

164157
// then
165-
val animeFoundEvents = receivedEvents.filterIsInstance<RelatedAnimeFoundEvent>()
166-
assertThat(animeFoundEvents).hasSize(4)
158+
val animeFoundEvents = receivedEvents.filterIsInstance<RelatedAnimeFinishedEvent>()
159+
assertThat(animeFoundEvents).hasSize(1)
167160

168-
val foundEntries = animeFoundEvents.map { it.anime.sources.first() }
161+
val foundEntries = animeFoundEvents.flatMap { it.resultList.map { anime -> anime.sources.first() } }
169162
assertThat(foundEntries).containsExactlyInAnyOrder(
170163
anime1.sources.first(),
171164
anime3.sources.first(),
@@ -227,10 +220,10 @@ internal class DefaultRelatedAnimeHandlerTest {
227220
defaultRelatedAnimeHandler.findRelatedAnimeForAnimeList()
228221

229222
// then
230-
val animeFoundEvents = receivedEvents.filterIsInstance<RelatedAnimeFoundEvent>()
231-
assertThat(animeFoundEvents).hasSize(4)
223+
val animeFoundEvents = receivedEvents.filterIsInstance<RelatedAnimeFinishedEvent>()
224+
assertThat(animeFoundEvents).hasSize(1)
232225

233-
val foundEntries = animeFoundEvents.map { it.anime.sources.first() }
226+
val foundEntries = animeFoundEvents.flatMap { it.resultList.map { anime -> anime.sources.first() } }
234227
assertThat(foundEntries).containsExactlyInAnyOrder(
235228
anime1.sources.first(),
236229
anime5.sources.first(),
@@ -285,11 +278,11 @@ internal class DefaultRelatedAnimeHandlerTest {
285278
defaultRelatedAnimeHandler.findRelatedAnimeForIgnoreList()
286279

287280
// then
288-
val animeFoundEvents = receivedEvents.filterIsInstance<RelatedAnimeFoundEvent>()
289-
assertThat(animeFoundEvents).hasSize(6)
281+
val animeFoundEvents = receivedEvents.filterIsInstance<RelatedAnimeFinishedEvent>()
282+
assertThat(animeFoundEvents).hasSize(1)
290283
assertThat(animeFoundEvents.map { it.listType }.distinct()).containsExactly(IGNORE_LIST)
291284

292-
val foundEntries = animeFoundEvents.map { it.anime.sources.first() }
285+
val foundEntries = animeFoundEvents.flatMap { it.resultList.map { anime -> anime.sources.first() } }
293286
assertThat(foundEntries).containsExactlyInAnyOrder(
294287
anime1.sources.first(),
295288
anime3.sources.first(),
@@ -298,13 +291,6 @@ internal class DefaultRelatedAnimeHandlerTest {
298291
anime6.sources.first(),
299292
anime7.sources.first(),
300293
)
301-
302-
val statusEvents = receivedEvents.filterIsInstance<RelatedAnimeStatusEvent>()
303-
assertThat(statusEvents).hasSize(7)
304-
assertThat(statusEvents.map { it.listType }.distinct()).containsExactly(IGNORE_LIST)
305-
306-
assertThat(receivedEvents.last()).isInstanceOf(RelatedAnimeFinishedEvent::class.java)
307-
assertThat((receivedEvents.last() as RelatedAnimeFinishedEvent).listType).isEqualTo(IGNORE_LIST)
308294
}
309295

310296
@Test
@@ -348,10 +334,10 @@ internal class DefaultRelatedAnimeHandlerTest {
348334
defaultRelatedAnimeHandler.findRelatedAnimeForIgnoreList()
349335

350336
// then
351-
val animeFoundEvents = receivedEvents.filterIsInstance<RelatedAnimeFoundEvent>()
352-
assertThat(animeFoundEvents).hasSize(4)
337+
val animeFoundEvents = receivedEvents.filterIsInstance<RelatedAnimeFinishedEvent>()
338+
assertThat(animeFoundEvents).hasSize(1)
353339

354-
val foundEntries = animeFoundEvents.map { it.anime.sources.first() }
340+
val foundEntries = animeFoundEvents.flatMap { it.resultList.map { anime -> anime.sources.first() } }
355341
assertThat(foundEntries).containsExactlyInAnyOrder(
356342
anime1.sources.first(),
357343
anime3.sources.first(),
@@ -420,10 +406,10 @@ internal class DefaultRelatedAnimeHandlerTest {
420406
defaultRelatedAnimeHandler.findRelatedAnimeForIgnoreList()
421407

422408
// then
423-
val animeFoundEvents = receivedEvents.filterIsInstance<RelatedAnimeFoundEvent>()
424-
assertThat(animeFoundEvents).hasSize(4)
409+
val animeFoundEvents = receivedEvents.filterIsInstance<RelatedAnimeFinishedEvent>()
410+
assertThat(animeFoundEvents).hasSize(1)
425411

426-
val foundEntries = animeFoundEvents.map { it.anime.sources.first() }
412+
val foundEntries = animeFoundEvents.flatMap { it.resultList.map { anime -> anime.sources.first() } }
427413
assertThat(foundEntries).containsExactlyInAnyOrder(
428414
anime1.sources.first(),
429415
anime5.sources.first(),

manami-gui/src/main/kotlin/io/github/manamiproject/manami/gui/ManamiAccess.kt

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ import io.github.manamiproject.manami.app.lists.ListChangedEvent.EventType.REMOV
1919
import io.github.manamiproject.manami.app.lists.ignorelist.AddIgnoreListStatusUpdateEvent
2020
import io.github.manamiproject.manami.app.lists.watchlist.AddWatchListStatusUpdateEvent
2121
import io.github.manamiproject.manami.app.relatedanime.RelatedAnimeFinishedEvent
22-
import io.github.manamiproject.manami.app.relatedanime.RelatedAnimeFoundEvent
23-
import io.github.manamiproject.manami.app.relatedanime.RelatedAnimeStatusEvent
2422
import io.github.manamiproject.manami.app.search.FileSearchAnimeListResultsEvent
2523
import io.github.manamiproject.manami.app.search.FileSearchIgnoreListResultsEvent
2624
import io.github.manamiproject.manami.app.search.FileSearchWatchListResultsEvent
@@ -34,6 +32,7 @@ import io.github.manamiproject.manami.app.commands.history.FileSavedStatusChange
3432
import io.github.manamiproject.manami.app.commands.history.UndoRedoStatusEvent
3533
import io.github.manamiproject.manami.app.events.EventListType.*
3634
import io.github.manamiproject.manami.app.inconsistencies.animelist.episodes.AnimeListEpisodesInconsistenciesResultEvent
35+
import io.github.manamiproject.manami.app.lists.ignorelist.IgnoreListEntry
3736
import io.github.manamiproject.manami.app.migration.MetaDataMigrationProgressEvent
3837
import io.github.manamiproject.manami.app.migration.MetaDataMigrationResultEvent
3938
import io.github.manamiproject.manami.app.search.similaranime.SimilarAnimeFoundEvent
@@ -55,8 +54,6 @@ class ManamiAccess(private val manami: ManamiApp = manamiInstance) : Controller(
5554
is AddIgnoreListStatusUpdateEvent -> AddIgnoreListStatusUpdateGuiEvent(this.finishedTasks, this.tasks)
5655
is FileSavedStatusChangedEvent -> FileSavedStatusChangedGuiEvent(this.isFileSaved)
5756
is UndoRedoStatusEvent -> UndoRedoStatusGuiEvent(this.isUndoPossible, this.isRedoPossible)
58-
is RelatedAnimeFoundEvent -> mapRelatedAnimeFoundEvent(this)
59-
is RelatedAnimeStatusEvent -> mapRelatedAnimeStatusEvent(this)
6057
is RelatedAnimeFinishedEvent -> mapRelatedAnimeFinsihedEvent(this)
6158
is AnimeSeasonEntryFoundEvent -> AnimeSeasonEntryFoundGuiEvent(this.anime)
6259
is AnimeSeasonSearchFinishedEvent -> AnimeSeasonSearchFinishedGuiEvent
@@ -105,27 +102,11 @@ class ManamiAccess(private val manami: ManamiApp = manamiInstance) : Controller(
105102
}
106103
}
107104

108-
private fun mapRelatedAnimeFoundEvent(event: RelatedAnimeFoundEvent): GuiEvent {
109-
return when(event.listType) {
110-
ANIME_LIST -> AnimeListRelatedAnimeFoundGuiEvent(event.anime)
111-
WATCH_LIST -> throw IllegalStateException("Unsupported list type")
112-
IGNORE_LIST -> IgnoreListRelatedAnimeFoundGuiEvent(event.anime)
113-
}
114-
}
115-
116-
private fun mapRelatedAnimeStatusEvent(event: RelatedAnimeStatusEvent): GuiEvent {
117-
return when(event.listType) {
118-
ANIME_LIST -> AnimeListRelatedAnimeStatusGuiEvent(event.finishedChecking, event.toBeChecked)
119-
WATCH_LIST -> throw IllegalStateException("Unsupported list type")
120-
IGNORE_LIST -> IgnoreListRelatedAnimeStatusGuiEvent(event.finishedChecking, event.toBeChecked)
121-
}
122-
}
123-
124105
private fun mapRelatedAnimeFinsihedEvent(event: RelatedAnimeFinishedEvent): GuiEvent {
125106
return when(event.listType) {
126-
ANIME_LIST -> AnimeListRelatedAnimeFinishedGuiEvent
107+
ANIME_LIST -> AnimeListRelatedAnimeFinishedGuiEvent(event.resultList)
127108
WATCH_LIST -> throw IllegalStateException("Unsupported list type")
128-
IGNORE_LIST -> IgnoreListRelatedAnimeFinishedGuiEvent
109+
IGNORE_LIST -> IgnoreListRelatedAnimeFinishedGuiEvent(event.resultList.map { IgnoreListEntry(it) })
129110
}
130111
}
131112

manami-gui/src/main/kotlin/io/github/manamiproject/manami/gui/events/GuiEvents.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,10 @@ data class RemoveIgnoreListEntryGuiEvent(val entries: Set<IgnoreListEntry>) : Gu
3939
data class AddIgnoreListStatusUpdateGuiEvent(val finishedTasks: Int, val tasks: Int): GuiEvent()
4040

4141
// Related Anime
42-
data class AnimeListRelatedAnimeFoundGuiEvent(val anime: Anime): GuiEvent()
43-
data class AnimeListRelatedAnimeStatusGuiEvent(val finishedChecking: Int, val toBeChecked: Int): GuiEvent()
44-
data object AnimeListRelatedAnimeFinishedGuiEvent: GuiEvent()
42+
data class AnimeListRelatedAnimeFinishedGuiEvent(val result: List<Anime>): GuiEvent()
4543

4644
// IgnoreList Search
47-
data class IgnoreListRelatedAnimeFoundGuiEvent(val anime: Anime): GuiEvent()
48-
data class IgnoreListRelatedAnimeStatusGuiEvent(val finishedChecking: Int, val toBeChecked: Int): GuiEvent()
49-
data object IgnoreListRelatedAnimeFinishedGuiEvent: GuiEvent()
45+
data class IgnoreListRelatedAnimeFinishedGuiEvent(val result: List<IgnoreListEntry>): GuiEvent()
5046

5147
// Anime Season
5248
data class AnimeSeasonEntryFoundGuiEvent(val anime: Anime): GuiEvent()

manami-gui/src/main/kotlin/io/github/manamiproject/manami/gui/ignorelist/IgnoreListView.kt

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,11 @@ class IgnoreListView : View() {
3636
finishedAddingEntriesTasks.set(event.finishedTasks)
3737
addingEntriesTasks.set(event.tasks)
3838
}
39-
subscribe<IgnoreListRelatedAnimeFoundGuiEvent> { event ->
40-
entries.value.add(IgnoreListEntry(event.anime))
41-
}
42-
subscribe<IgnoreListRelatedAnimeStatusGuiEvent> { event ->
43-
finishedRelatedAnimeTasks.set(event.finishedChecking)
44-
relatedAnimeTasks.set(event.toBeChecked)
45-
46-
if (event.finishedChecking == 1) {
47-
entries.get().clear()
48-
}
49-
}
50-
subscribe<IgnoreListRelatedAnimeFinishedGuiEvent> {
39+
subscribe<IgnoreListRelatedAnimeFinishedGuiEvent> { event ->
40+
finishedRelatedAnimeTasks.set(1)
41+
relatedAnimeTasks.set(1)
42+
entries.get().clear()
43+
event.result.forEach {entries.value.add(it) }
5144
isRelatedAnimeProgressIndicatorVisible.set(false)
5245
}
5346
subscribe<AddAnimeListEntryGuiEvent> { event ->

manami-gui/src/main/kotlin/io/github/manamiproject/manami/gui/relatedanime/RelatedAnimeView.kt

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,11 @@ class RelatedAnimeView : View() {
2626
)
2727

2828
init {
29-
subscribe<AnimeListRelatedAnimeFoundGuiEvent> { event ->
30-
entries.value.add(BigPicturedAnimeEntry(event.anime))
31-
}
32-
subscribe<AnimeListRelatedAnimeStatusGuiEvent> { event ->
33-
finishedTasks.set(event.finishedChecking)
34-
tasks.set(event.toBeChecked)
35-
36-
if (event.finishedChecking == 1) {
37-
entries.get().clear()
38-
}
39-
}
40-
subscribe<AnimeListRelatedAnimeFinishedGuiEvent> {
29+
subscribe<AnimeListRelatedAnimeFinishedGuiEvent> { event ->
30+
finishedTasks.set(1)
31+
tasks.set(1)
32+
entries.get().clear()
33+
event.result.forEach { entries.value.add(BigPicturedAnimeEntry(it)) }
4134
isRelatedAnimeProgressIndicatorVisible.set(false)
4235
}
4336
subscribe<AddAnimeListEntryGuiEvent> { event ->

0 commit comments

Comments
 (0)