WIP ranking of search results
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/deluan/sanitize"
|
||||||
"github.com/dweymouth/go-subsonic/subsonic"
|
"github.com/dweymouth/go-subsonic/subsonic"
|
||||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||||
"github.com/dweymouth/supersonic/sharedutil"
|
"github.com/dweymouth/supersonic/sharedutil"
|
||||||
@@ -34,14 +35,14 @@ func (s *subsonicMediaProvider) SearchAll(searchQuery string, maxResults int) ([
|
|||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
queryLowerWords := strings.Fields(strings.ToLower(searchQuery))
|
queryLowerWords := strings.Fields(strings.ToLower(sanitize.Accents(searchQuery)))
|
||||||
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
p, e := s.client.GetPlaylists(nil)
|
p, e := s.client.GetPlaylists(nil)
|
||||||
if e == nil {
|
if e == nil {
|
||||||
playlists = sharedutil.FilterSlice(p, func(p *subsonic.Playlist) bool {
|
playlists = sharedutil.FilterSlice(p, func(p *subsonic.Playlist) bool {
|
||||||
return allTermsMatch(strings.ToLower(p.Name), queryLowerWords)
|
return allTermsMatch(strings.ToLower(sanitize.Accents(p.Name)), queryLowerWords)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
@@ -52,7 +53,7 @@ func (s *subsonicMediaProvider) SearchAll(searchQuery string, maxResults int) ([
|
|||||||
g, e := s.client.GetGenres()
|
g, e := s.client.GetGenres()
|
||||||
if e == nil {
|
if e == nil {
|
||||||
genres = sharedutil.FilterSlice(g, func(g *subsonic.Genre) bool {
|
genres = sharedutil.FilterSlice(g, func(g *subsonic.Genre) bool {
|
||||||
return allTermsMatch(strings.ToLower(g.Name), queryLowerWords)
|
return allTermsMatch(strings.ToLower(sanitize.Accents(g.Name)), queryLowerWords)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
@@ -64,7 +65,7 @@ func (s *subsonicMediaProvider) SearchAll(searchQuery string, maxResults int) ([
|
|||||||
}
|
}
|
||||||
|
|
||||||
results := mergeResults(result, playlists, genres)
|
results := mergeResults(result, playlists, genres)
|
||||||
//rankResults(results, queryLowerWords) // TODO
|
rankResults(results, queryLowerWords)
|
||||||
if len(results) > maxResults {
|
if len(results) > maxResults {
|
||||||
results = results[:maxResults]
|
results = results[:maxResults]
|
||||||
}
|
}
|
||||||
@@ -143,9 +144,42 @@ func mergeResults(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func rankResults(results []*mediaprovider.SearchResult, queryTerms []string) {
|
func rankResults(results []*mediaprovider.SearchResult, queryTerms []string) {
|
||||||
// TODO
|
if len(queryTerms) == 0 || len(results) < 2 {
|
||||||
sort.Slice(results, func(a, b int) bool {
|
return
|
||||||
return false
|
}
|
||||||
|
|
||||||
|
sanitizeMemo := make([]string, len(results))
|
||||||
|
sanitized := func(s string, i int) string {
|
||||||
|
if x := sanitizeMemo[i]; x != "" {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
x := strings.ToLower(sanitize.Accents(s))
|
||||||
|
sanitizeMemo[i] = x
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(results, func(i, j int) bool {
|
||||||
|
// Compare by search query terms
|
||||||
|
a, b := results[i], results[j]
|
||||||
|
aName := sanitized(a.Name, i)
|
||||||
|
bName := sanitized(b.Name, j)
|
||||||
|
|
||||||
|
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
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ go 1.19
|
|||||||
require (
|
require (
|
||||||
fyne.io/fyne/v2 v2.4.1
|
fyne.io/fyne/v2 v2.4.1
|
||||||
github.com/20after4/configdir v0.1.1
|
github.com/20after4/configdir v0.1.1
|
||||||
|
github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1
|
||||||
github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee
|
github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee
|
||||||
github.com/dweymouth/go-subsonic v0.0.0-20231105161622-54b5aec28363
|
github.com/dweymouth/go-subsonic v0.0.0-20231105161622-54b5aec28363
|
||||||
github.com/fsnotify/fsnotify v1.6.0
|
github.com/fsnotify/fsnotify v1.6.0
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7h
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1 h1:mGvOb3zxl4vCLv+dbf7JA6CAaM2UH/AGP1KX4DsJmTI=
|
||||||
|
github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1/go.mod h1:ZNCLJfehvEf34B7BbLKjgpsL9lyW7q938w/GY1XgV4E=
|
||||||
github.com/dweymouth/fyne/v2 v2.3.0-rc1.0.20231104060932-f124004dd651 h1:szaOWq1a8gthqA55qq1egRj660DQM3Pp0nkrmjUwR48=
|
github.com/dweymouth/fyne/v2 v2.3.0-rc1.0.20231104060932-f124004dd651 h1:szaOWq1a8gthqA55qq1egRj660DQM3Pp0nkrmjUwR48=
|
||||||
github.com/dweymouth/fyne/v2 v2.3.0-rc1.0.20231104060932-f124004dd651/go.mod h1:AWM1iPM2YfliduZ4u/kQzP9E6ARIWm0gg+57GpYzWro=
|
github.com/dweymouth/fyne/v2 v2.3.0-rc1.0.20231104060932-f124004dd651/go.mod h1:AWM1iPM2YfliduZ4u/kQzP9E6ARIWm0gg+57GpYzWro=
|
||||||
github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee h1:ZGyJ6wp7CAfT31BugypcF/TPKEy2RrGR9JFq1JOjOpY=
|
github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee h1:ZGyJ6wp7CAfT31BugypcF/TPKEy2RrGR9JFq1JOjOpY=
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ func (q *QuickSearch) onSearched(query string) {
|
|||||||
q.resultsMutex.Unlock()
|
q.resultsMutex.Unlock()
|
||||||
q.list.Refresh()
|
q.list.Refresh()
|
||||||
q.list.ScrollToTop()
|
q.list.ScrollToTop()
|
||||||
|
q.selectedIndex = 0
|
||||||
q.list.Select(0)
|
q.list.Select(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user