package search import ( "sort" "strings" "github.com/animenotifier/notify.moe/arn" "github.com/animenotifier/notify.moe/arn/stringutils" ) // Anime searches all anime. func Anime(originalTerm string, maxLength int) []*arn.Anime { term := strings.ToLower(stringutils.RemoveSpecialCharacters(originalTerm)) results := make([]*Result, 0, maxLength) check := func(text string) float64 { if text == "" { return 0 } return stringutils.AdvancedStringSimilarity(term, strings.ToLower(stringutils.RemoveSpecialCharacters(text))) } add := func(anime *arn.Anime, similarity float64) { similarity += float64(anime.Popularity.Total()) * popularityDamping if anime.Type != "tv" && anime.Type != "movie" { similarity -= 0.3 } results = append(results, &Result{ obj: anime, similarity: similarity, }) } for anime := range arn.StreamAnime() { if anime.IsDraft { continue } if anime.ID == originalTerm { return []*arn.Anime{anime} } // Canonical title similarity := check(anime.Title.Canonical) if similarity >= MinStringSimilarity { add(anime, similarity) continue } // English similarity = check(anime.Title.English) if similarity >= MinStringSimilarity { add(anime, similarity) continue } // Romaji similarity = check(anime.Title.Romaji) if similarity >= MinStringSimilarity { add(anime, similarity) continue } // Synonyms for _, synonym := range anime.Title.Synonyms { similarity := check(synonym) if similarity >= MinStringSimilarity { add(anime, similarity) goto nextAnime } } // Japanese similarity = check(anime.Title.Japanese) if similarity >= MinStringSimilarity { add(anime, similarity) continue } nextAnime: } // Sort sort.Slice(results, func(i, j int) bool { return results[i].similarity > results[j].similarity }) // Limit if len(results) >= maxLength { results = results[:maxLength] } // Final list final := make([]*arn.Anime, len(results)) for i, result := range results { final[i] = result.obj.(*arn.Anime) } return final }