diff --git a/pages/recommended/anime.go b/pages/recommended/anime.go index 4cca829e..0ae74fed 100644 --- a/pages/recommended/anime.go +++ b/pages/recommended/anime.go @@ -1,6 +1,8 @@ package recommended import ( + "fmt" + "math" "net/http" "sort" @@ -11,7 +13,9 @@ import ( ) const ( - maxRecommendations = 10 + maxRecommendations = 10 + bestGenreCount = 3 + genreBonusCompletedAnimeThreshold = 40 ) // Anime shows a list of recommended anime. @@ -25,6 +29,41 @@ func Anime(ctx *aero.Context) string { } animeList := viewUser.AnimeList() + completed := animeList.FilterStatus(arn.AnimeListStatusCompleted) + + // Genre affinity + genreItems := animeList.Genres() + genreAffinity := map[string]float64{} + bestGenres := []string{} + + for genre, animeListItems := range genreItems { + affinity := 0.0 + + for _, item := range animeListItems { + if item.Status != arn.AnimeListStatusCompleted { + continue + } + + if item.Rating.Overall != 0 { + affinity += item.Rating.Overall + } else { + affinity += 5.0 + } + } + + genreAffinity[genre] = affinity + bestGenres = append(bestGenres, genre) + } + + sort.Slice(bestGenres, func(i, j int) bool { + return genreAffinity[bestGenres[i]] > genreAffinity[bestGenres[j]] + }) + + if len(bestGenres) > bestGenreCount { + bestGenres = bestGenres[:bestGenreCount] + } + + fmt.Println(bestGenres) // Get all anime var tv []*arn.Anime @@ -65,18 +104,32 @@ func Anime(ctx *aero.Context) string { prequels := anime.Prequels() for _, prequel := range prequels { - item := animeList.Find(prequel.ID) + item := completed.Find(prequel.ID) // Filter out unimportant prequels if prequel.Score() < anime.Score()/2 { continue } - if item == nil || item.Status != arn.AnimeListStatusCompleted { + if item == nil { animeAffinity -= 20.0 } } + // Give favorite genre bonus if we have enough completed anime + if len(completed.Items) >= genreBonusCompletedAnimeThreshold { + bestGenreCount := 0 + + for _, genre := range anime.Genres { + if arn.Contains(bestGenres, genre) { + bestGenreCount++ + } + } + + // Use square root to dampen the bonus of additional best genres + animeAffinity += math.Sqrt(float64(bestGenreCount)) * 7.0 + } + affinity[anime.ID] = animeAffinity }