73 lines
1.8 KiB
Go
73 lines
1.8 KiB
Go
package site
|
|
|
|
import (
|
|
"math"
|
|
"net/http"
|
|
"slices"
|
|
"strings"
|
|
|
|
"github.com/delaneyj/toolbelt"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-faker/faker/v4"
|
|
"github.com/lithammer/fuzzysearch/fuzzy"
|
|
datastar "github.com/starfederation/datastar/sdk/go"
|
|
)
|
|
|
|
func setupExamplesActiveSearch(examplesRouter chi.Router) error {
|
|
|
|
users := make([]*ActiveSearchUser, 256)
|
|
for i := range users {
|
|
u := &ActiveSearchUser{
|
|
ID: faker.UUIDHyphenated(),
|
|
FirstName: faker.FirstName(),
|
|
LastName: faker.LastName(),
|
|
Email: faker.Email(),
|
|
}
|
|
users[i] = u
|
|
}
|
|
|
|
examplesRouter.Get("/active_search/updates", func(w http.ResponseWriter, r *http.Request) {
|
|
signals := &ActiveSearchSignals{}
|
|
if err := datastar.ReadSignals(r, signals); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
scores := map[string]float64{}
|
|
s := strings.ToLower(signals.Search)
|
|
minScore, maxScore := math.MaxFloat64, -math.MaxFloat64
|
|
for _, u := range users {
|
|
fn := strings.ToLower(u.FirstName)
|
|
ln := strings.ToLower(u.LastName)
|
|
e := strings.ToLower(u.Email)
|
|
|
|
fnd := fuzzy.LevenshteinDistance(s, fn)
|
|
lnd := fuzzy.LevenshteinDistance(s, ln)
|
|
ed := fuzzy.LevenshteinDistance(s, e)
|
|
|
|
dist := float64(fnd + lnd + ed)
|
|
scores[u.ID] = dist
|
|
|
|
minScore = min(minScore, dist)
|
|
maxScore = max(maxScore, dist)
|
|
}
|
|
|
|
for id, score := range scores {
|
|
scores[id] = toolbelt.Fit(score, minScore, maxScore, 100, 0)
|
|
}
|
|
|
|
// copy users
|
|
filteredUsers := make([]*ActiveSearchUser, len(users))
|
|
copy(filteredUsers, users)
|
|
|
|
// sort users by score
|
|
slices.SortFunc(filteredUsers, func(a, b *ActiveSearchUser) int {
|
|
return int(10000 * (scores[b.ID] - scores[a.ID]))
|
|
})
|
|
|
|
datastar.NewSSE(w, r).MergeFragmentTempl(ActiveSearchComponent(filteredUsers, scores, signals))
|
|
})
|
|
|
|
return nil
|
|
}
|