dorfylegends/backend/server/search.go
2022-05-03 19:39:00 +00:00

125 lines
4.1 KiB
Go

package server
import (
"encoding/json"
"fmt"
"net/http"
"sort"
"strings"
"github.com/robertjanetzko/LegendsBrowser2/backend/model"
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
)
type searchHandler struct {
server *DfServer
}
type SearchResult struct {
Label string `json:"label"`
Value string `json:"value"`
}
func (h searchHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if h.server.context.world == nil {
h.server.renderLoading(w, r)
return
}
term := r.URL.Query().Get("term")
world := h.server.context.world
if term != "" {
var results []SearchResult
results = searchMap(term, world.HistoricalFigures, results, "/hf")
results = searchMap(term, world.Entities, results, "/entity")
results = searchMap(term, world.Sites, results, "/site")
for _, site := range world.Sites {
results = searchMap(term, site.Structures, results, fmt.Sprintf("/site/%d/structure", site.Id_))
}
results = searchMap(term, world.Regions, results, "/region")
results = searchMap(term, world.Artifacts, results, "/artifavt")
results = searchMap(term, world.WorldConstructions, results, "/worldconstruction")
results = searchMap(term, world.DanceForms, results, "/danceform")
results = searchMap(term, world.MusicalForms, results, "/musicalform")
results = searchMap(term, world.PoeticForms, results, "/poeticform")
results = searchMap(term, world.WrittenContents, results, "/writtencontent")
results = searchMap(term, world.Landmasses, results, "/landmass")
results = searchMap(term, world.MountainPeaks, results, "/mountain")
sort.Slice(results, func(i, j int) bool { return results[i].Label < results[j].Label })
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(results)
} else {
term = r.URL.Query().Get("search")
var structures []*model.Structure
for _, site := range world.Sites {
structures = search(term, site.Structures, structures)
}
results := struct {
Term string
HistoricalFigures []*model.HistoricalFigure
Entities []*model.Entity
Sites []*model.Site
Structures []*model.Structure
Regions []*model.Region
Artifacts []*model.Artifact
WorldConstructions []*model.WorldConstruction
DanceForms []*model.DanceForm
MusicalForms []*model.MusicalForm
PoeticForms []*model.PoeticForm
WrittenContents []*model.WrittenContent
Landmasses []*model.Landmass
MountainPeaks []*model.MountainPeak
}{
Term: term,
HistoricalFigures: search(term, world.HistoricalFigures, nil),
Entities: search(term, world.Entities, nil),
Sites: search(term, world.Sites, nil),
Structures: structures,
Regions: search(term, world.Regions, nil),
Artifacts: search(term, world.Artifacts, nil),
WorldConstructions: search(term, world.WorldConstructions, nil),
DanceForms: search(term, world.DanceForms, nil),
MusicalForms: search(term, world.MusicalForms, nil),
PoeticForms: search(term, world.PoeticForms, nil),
WrittenContents: search(term, world.WrittenContents, nil),
Landmasses: search(term, world.Landmasses, nil),
MountainPeaks: search(term, world.MountainPeaks, nil),
}
err := h.server.templates.Render(w, "search.html", results)
if err != nil {
httpError(w, err)
}
}
}
func searchMap[T model.Named](s string, input map[int]T, output []SearchResult, baseUrl string) []SearchResult {
s = strings.ToLower(s)
for id, v := range input {
if strings.Contains(strings.ToLower(v.Name()), s) {
output = append(output, SearchResult{
Label: util.Title(v.Name()),
Value: fmt.Sprintf("%s/%d", baseUrl, id),
})
}
}
return output
}
func search[T model.Named](s string, input map[int]T, output []T) []T {
s = strings.ToLower(s)
for _, v := range input {
if strings.Contains(strings.ToLower(v.Name()), s) {
output = append(output, v)
}
}
sort.Slice(output, func(i, j int) bool { return output[i].Name() < output[j].Name() })
return output
}