better autocomplete

This commit is contained in:
2026-01-22 22:24:24 -05:00
parent 950662e0b9
commit f3698f0fc6
4 changed files with 33 additions and 14 deletions

View File

@@ -7,4 +7,4 @@ Production instance is named Zenno Rob Roy, because she has read all about Umamu
## Running ## Running
The bot always uses the Gateway API. The bot always uses the Gateway API.
If the `-http` argument is provided, it will also use the HTTP API, and `-token` must also be provided. If the `-http` argument is provided, it will also use the HTTP API, and `-key` must also be provided.

View File

@@ -111,3 +111,12 @@ func inorder(a, b string) bool {
} }
return true return true
} }
// Metrics gets the number of buckets in the autocomplete set and the length
// of the longest bucket.
func (s *Set) Metrics() (buckets, longest int) {
for _, b := range s.keys {
longest = max(longest, len(b))
}
return len(s.keys), longest
}

22
main.go
View File

@@ -9,7 +9,6 @@ import (
"os" "os"
"os/signal" "os/signal"
"strconv" "strconv"
"strings"
"time" "time"
"git.sunturtle.xyz/zephyr/horse/horse" "git.sunturtle.xyz/zephyr/horse/horse"
@@ -110,6 +109,13 @@ func main() {
stop() stop()
} }
slog.Info("ready") slog.Info("ready")
go func() {
// Preload autocomplete in a separate goroutine.
slog.Info("begin computing skill autocomplete")
set := skillGlobalAuto()
buckets, longest := set.Metrics()
slog.Info("done computing skill autocomplete", slog.Int("buckets", buckets), slog.Int("longest", longest))
}()
<-ctx.Done() <-ctx.Done()
stop() stop()
@@ -162,15 +168,11 @@ func skillHandler(data discord.SlashCommandInteractionData, e *handler.CommandEv
} }
func skillAutocomplete(e *handler.AutocompleteEvent) error { func skillAutocomplete(e *handler.AutocompleteEvent) error {
q := strings.ToLower(e.Data.String("query")) q := e.Data.String("query")
r := make([]discord.AutocompleteChoice, 0, 25) opts := skillGlobalAuto().Find(nil, q)
for k, _ := range global.SkillNameToID { r := make([]discord.AutocompleteChoice, min(len(opts), 25))
if strings.HasPrefix(strings.ToLower(k), q) { for i, k := range opts[:min(len(opts), len(r))] {
r = append(r, discord.AutocompleteChoiceString{Name: k, Value: k}) r[i] = discord.AutocompleteChoiceString{Name: k, Value: k}
if len(r) == cap(r) {
break
}
}
} }
return e.AutocompleteResult(r) return e.AutocompleteResult(r)
} }

View File

@@ -3,8 +3,11 @@ package main
import ( import (
"fmt" "fmt"
"strings" "strings"
"sync"
"git.sunturtle.xyz/zephyr/horse/horse" "git.sunturtle.xyz/zephyr/horse/horse"
"git.sunturtle.xyz/zephyr/horse/horse/global"
"git.sunturtle.xyz/zephyr/horsebot/autocomplete"
"github.com/disgoorg/disgo/discord" "github.com/disgoorg/disgo/discord"
) )
@@ -115,6 +118,11 @@ func isDebuff(s horse.Skill) bool {
return false return false
} }
// TODO(zeph): autocomplete var skillGlobalAuto = sync.OnceValue(func() *autocomplete.Set {
// if we want to backgroundify construction of an autocomplete map, var set autocomplete.Set
// use sync.OnceValue and launch a goroutine in main to get the value and discard it for _, id := range global.OrderedSkills {
s := global.AllSkills[id]
set.Add(s.Name, s.Name)
}
return &set
})