Reduced recommended anime function complexity
This commit is contained in:
parent
4f6078943c
commit
63c3ab894f
48
pages/recommended/affinity.go
Normal file
48
pages/recommended/affinity.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package recommended
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"github.com/animenotifier/arn"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getAnimeAffinity(anime *arn.Anime, animeListItem *arn.AnimeListItem, completed *arn.AnimeList, bestGenres []string) float64 {
|
||||||
|
animeAffinity := anime.Score()
|
||||||
|
|
||||||
|
// Planned anime go higher
|
||||||
|
if animeListItem != nil && animeListItem.Status == arn.AnimeListStatusPlanned {
|
||||||
|
animeAffinity += 10.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anime whose high-ranked prequel you did not see are lower ranked
|
||||||
|
prequels := anime.Prequels()
|
||||||
|
|
||||||
|
for _, prequel := range prequels {
|
||||||
|
item := completed.Find(prequel.ID)
|
||||||
|
|
||||||
|
// Filter out unimportant prequels
|
||||||
|
if prequel.Score() < anime.Score()/2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
return animeAffinity
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package recommended
|
package recommended
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
@ -31,36 +30,7 @@ func Anime(ctx *aero.Context) string {
|
|||||||
completed := animeList.FilterStatus(arn.AnimeListStatusCompleted)
|
completed := animeList.FilterStatus(arn.AnimeListStatusCompleted)
|
||||||
|
|
||||||
// Genre affinity
|
// Genre affinity
|
||||||
genreItems := animeList.Genres()
|
bestGenres := getBestGenres(animeList)
|
||||||
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]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all anime
|
// Get all anime
|
||||||
var tv []*arn.Anime
|
var tv []*arn.Anime
|
||||||
@ -81,6 +51,8 @@ func Anime(ctx *aero.Context) string {
|
|||||||
tv = append(tv, anime)
|
tv = append(tv, anime)
|
||||||
} else if anime.Type == "movie" {
|
} else if anime.Type == "movie" {
|
||||||
movies = append(movies, anime)
|
movies = append(movies, anime)
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip anime from my list (except planned anime)
|
// Skip anime from my list (except planned anime)
|
||||||
@ -90,44 +62,7 @@ func Anime(ctx *aero.Context) string {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
animeAffinity := anime.Score()
|
affinity[anime.ID] = getAnimeAffinity(anime, existing, completed, bestGenres)
|
||||||
|
|
||||||
// Planned anime go higher
|
|
||||||
if existing != nil && existing.Status == arn.AnimeListStatusPlanned {
|
|
||||||
animeAffinity += 10.0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anime whose high-ranked prequel you did not see are lower ranked
|
|
||||||
prequels := anime.Prequels()
|
|
||||||
|
|
||||||
for _, prequel := range prequels {
|
|
||||||
item := completed.Find(prequel.ID)
|
|
||||||
|
|
||||||
// Filter out unimportant prequels
|
|
||||||
if prequel.Score() < anime.Score()/2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort
|
// Sort
|
||||||
|
43
pages/recommended/bestgenres.go
Normal file
43
pages/recommended/bestgenres.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package recommended
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/animenotifier/arn"
|
||||||
|
)
|
||||||
|
|
||||||
|
// getBestGenres returns the most liked genres for the user's anime list.
|
||||||
|
func getBestGenres(animeList *arn.AnimeList) []string {
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestGenres
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user