68 lines
1.8 KiB
Go
68 lines
1.8 KiB
Go
package helpers
|
|
|
|
import (
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/deluan/sanitize"
|
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
|
)
|
|
|
|
// name and terms should be pre-converted to the same case
|
|
func AllTermsMatch(name string, terms []string) bool {
|
|
for _, t := range terms {
|
|
if !strings.Contains(name, t) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func RankSearchResults(results []*mediaprovider.SearchResult, fullQuery string, queryTerms []string) {
|
|
if len(queryTerms) == 0 || len(results) < 2 {
|
|
return
|
|
}
|
|
|
|
sanitizeMemo := make(map[string]string, len(results))
|
|
sanitized := func(s string) string {
|
|
if x, ok := sanitizeMemo[s]; ok {
|
|
return x
|
|
}
|
|
x := strings.ToLower(sanitize.Accents(s))
|
|
sanitizeMemo[s] = x
|
|
return x
|
|
}
|
|
|
|
sort.Slice(results, func(i, j int) bool {
|
|
a, b := results[i], results[j]
|
|
aName := sanitized(a.Name)
|
|
bName := sanitized(b.Name)
|
|
|
|
// Compare by entire query
|
|
matchesA, matchesB := strings.Contains(aName, fullQuery), strings.Contains(bName, fullQuery)
|
|
if matchesA && !matchesB {
|
|
return true // item A has a direct match with the full query and B does not
|
|
} else if matchesB && !matchesA {
|
|
return false // item B matches but not A
|
|
}
|
|
|
|
// Compare by search query terms
|
|
for _, term := range queryTerms {
|
|
firstTermIdxA, firstTermIdxB := strings.Index(aName, term), strings.Index(bName, term)
|
|
if firstTermIdxA >= 0 && firstTermIdxB < 0 {
|
|
return true // item A has a direct match with the query term and B does not
|
|
} else if firstTermIdxB >= 0 && firstTermIdxA < 0 {
|
|
return false // item B matches but not A
|
|
}
|
|
|
|
if firstTermIdxA < firstTermIdxB {
|
|
return true // item A matches the query term starting at an earlier position
|
|
} else if firstTermIdxB < firstTermIdxA {
|
|
return false // item B matches first
|
|
}
|
|
}
|
|
// Defer to item type for priority order
|
|
return a.Type < b.Type
|
|
})
|
|
}
|