years
This commit is contained in:
parent
e5cd5bd3c2
commit
6380871358
10 changed files with 117 additions and 18 deletions
|
@ -85,6 +85,10 @@
|
|||
{
|
||||
"Name": "NecromancerSince",
|
||||
"Type": "int"
|
||||
},
|
||||
{
|
||||
"Name": "Kills",
|
||||
"Type": "[]int"
|
||||
}
|
||||
],
|
||||
"Entity": [
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
|
||||
"golang.org/x/exp/maps"
|
||||
)
|
||||
|
||||
func (w *DfWorld) AllEventTypes() []string {
|
||||
|
@ -63,6 +64,16 @@ func (w *DfWorld) SiteHistory(siteId int) []*HistoricalEvent {
|
|||
return list
|
||||
}
|
||||
|
||||
func (w *DfWorld) Races() []string {
|
||||
races := make(map[string]bool)
|
||||
for _, hf := range w.HistoricalFigures {
|
||||
races[hf.Race] = true
|
||||
}
|
||||
list := maps.Keys(races)
|
||||
sort.Strings(list)
|
||||
return list
|
||||
}
|
||||
|
||||
func (c *HistoricalEventCollection) Type() string {
|
||||
if c.Details == nil {
|
||||
return "unk"
|
||||
|
|
|
@ -19059,6 +19059,7 @@ type HistoricalFigure struct {
|
|||
Sphere []string `json:"sphere" legend:"base" related:""` // sphere
|
||||
UsedIdentityId []int `json:"usedIdentityId" legend:"base" related:""` // used_identity_id
|
||||
VagueRelationship []*VagueRelationship `json:"vagueRelationship" legend:"base" related:""` // vague_relationship
|
||||
Kills []int `json:"kills" legend:"add" related:""` // Kills
|
||||
Leader bool `json:"leader" legend:"add" related:""` // Leader
|
||||
Necromancer bool `json:"necromancer" legend:"add" related:""` // Necromancer
|
||||
NecromancerSince int `json:"necromancerSince" legend:"add" related:""` // NecromancerSince
|
||||
|
@ -19182,6 +19183,7 @@ func (x *HistoricalFigure) MarshalJSON() ([]byte, error) {
|
|||
d["sphere"] = x.Sphere
|
||||
d["usedIdentityId"] = x.UsedIdentityId
|
||||
d["vagueRelationship"] = x.VagueRelationship
|
||||
d["kills"] = x.Kills
|
||||
d["leader"] = x.Leader
|
||||
d["necromancer"] = x.Necromancer
|
||||
if x.NecromancerSince != -1 {
|
||||
|
|
|
@ -150,6 +150,10 @@ func (w *DfWorld) processEvents() {
|
|||
id.HistfigId = hf.Id_
|
||||
}
|
||||
}
|
||||
case *HistoricalEventHfDied:
|
||||
if hf, ok := w.HistoricalFigures[d.SlayerHfid]; ok {
|
||||
hf.Kills = append(hf.Kills, d.Hfid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/robertjanetzko/LegendsBrowser2/backend/model"
|
||||
"github.com/robertjanetzko/LegendsBrowser2/backend/templates"
|
||||
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
|
||||
"golang.org/x/exp/constraints"
|
||||
)
|
||||
|
||||
type DfServerContext struct {
|
||||
|
@ -119,6 +120,19 @@ func StartServer(config *Config, world *model.DfWorld, static embed.FS) error {
|
|||
srv.RegisterWorldResourcePage("/identity/{id}", "identity.html", func(id int) any { return srv.context.world.Identities[id] })
|
||||
srv.RegisterWorldResourcePage("/popover/identity/{id}", "popoverIdentity.html", func(id int) any { return srv.context.world.Identities[id] })
|
||||
|
||||
srv.RegisterWorldPage("/years", "years.html", func(p Parms) any {
|
||||
return groupBy(srv.context.world.HistoricalEvents,
|
||||
func(e *model.HistoricalEvent) int { return e.Year },
|
||||
func(e *model.HistoricalEvent) bool { return true },
|
||||
func(e *model.HistoricalEvent) int { return e.Id_ })
|
||||
})
|
||||
srv.RegisterWorldResourcePage("/year/{id}", "year.html", func(id int) any {
|
||||
return util.FilterMap(srv.context.world.HistoricalEvents,
|
||||
func(v *model.HistoricalEvent) bool { return v.Year == id },
|
||||
func(a, b *model.HistoricalEvent) bool { return a.Id_ < b.Id_ },
|
||||
)
|
||||
})
|
||||
|
||||
srv.RegisterWorldPage("/events", "eventTypes.html", func(p Parms) any { return srv.context.world.AllEventTypes() })
|
||||
srv.RegisterWorldPage("/events/{type}", "eventType.html", func(p Parms) any { return srv.context.world.EventsOfType(p["type"]) })
|
||||
srv.RegisterWorldResourcePage("/event/{id}", "event.html", func(id int) any { return srv.context.world.HistoricalEvents[id] })
|
||||
|
@ -236,7 +250,18 @@ func (srv *DfServer) searchHf(p Parms) any {
|
|||
list = append(list, hf)
|
||||
}
|
||||
|
||||
sort.Slice(list, func(i, j int) bool { return list[i].Name_ < list[j].Name_ })
|
||||
switch p["sort"] {
|
||||
case "race":
|
||||
sort.Slice(list, func(i, j int) bool { return list[i].Race < list[j].Race })
|
||||
case "birth":
|
||||
sort.Slice(list, func(i, j int) bool { return list[i].BirthYear < list[j].BirthYear })
|
||||
case "death":
|
||||
sort.Slice(list, func(i, j int) bool { return list[i].DeathYear < list[j].DeathYear })
|
||||
case "kills":
|
||||
sort.Slice(list, func(i, j int) bool { return len(list[i].Kills) > len(list[j].Kills) })
|
||||
default:
|
||||
sort.Slice(list, func(i, j int) bool { return list[i].Name_ < list[j].Name_ })
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"Params": p,
|
||||
|
@ -288,8 +313,8 @@ func groupByType[K comparable, T namedTyped](input map[K]T) map[string][]T {
|
|||
return groupBy(input, func(t T) string { return t.Type() }, func(t T) bool { return t.Name() != "" }, func(t T) string { return t.Name() })
|
||||
}
|
||||
|
||||
func groupBy[K comparable, T any](input map[K]T, mapper func(T) string, filter func(T) bool, sortMapper func(T) string) map[string][]T {
|
||||
output := make(map[string][]T)
|
||||
func groupBy[K comparable, N comparable, T any, S constraints.Ordered](input map[K]T, mapper func(T) N, filter func(T) bool, sortMapper func(T) S) map[N][]T {
|
||||
output := make(map[N][]T)
|
||||
|
||||
for _, v := range input {
|
||||
k := mapper(v)
|
||||
|
|
|
@ -90,12 +90,14 @@ func (srv *DfServer) LoadTemplates() {
|
|||
"html": func(value any) template.HTML {
|
||||
return template.HTML(fmt.Sprint(value))
|
||||
},
|
||||
"bytes": func(s int64) string { return humanize.Bytes(uint64(s)) },
|
||||
"first": util.FirstInMap,
|
||||
"ifFirst": func(m any, k string, r string) string { return util.If(util.FirstInMap(m, k), r, "") },
|
||||
"strip": util.Strip,
|
||||
"string": util.String,
|
||||
"capitalize": util.Capitalize,
|
||||
"bytes": func(s int64) string { return humanize.Bytes(uint64(s)) },
|
||||
"first": util.FirstInMap,
|
||||
"ifFirst": func(m any, k string, r string) string { return util.If(util.FirstInMap(m, k), r, "") },
|
||||
"strip": util.Strip,
|
||||
"string": util.String,
|
||||
"capitalize": util.Capitalize,
|
||||
"add": func(a, b int) int { return a + b },
|
||||
"breakYearColumn": func(c, m int) bool { return (c % ((m + 2) / 4)) == 0 },
|
||||
}
|
||||
srv.templates = templates.New(functions)
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<th>Name</th>
|
||||
<th>Race</th>
|
||||
<th>Lived</th>
|
||||
<th>Kills</th>
|
||||
</tr>
|
||||
{{- range .Hfs }}{{- if not (eq .Name "") }}
|
||||
<tr>
|
||||
|
@ -26,6 +27,7 @@
|
|||
from {{ .BirthYear }} till {{ .DeathYear }}
|
||||
{{- end }}
|
||||
</td>
|
||||
<td>{{ len .Kills }}</td>
|
||||
</tr>
|
||||
{{- end}}{{- end}}
|
||||
</table>
|
||||
|
@ -51,25 +53,26 @@
|
|||
}}checked{{end}}> Ghost</label></div>
|
||||
<div class="checkbox"><label><input class="filter" type="checkbox" name="adventurer" value="1" {{if eq .Params.adventurer "1"
|
||||
}}checked{{end}}> Adventurer</label></div>
|
||||
<div class="select form-group">
|
||||
<div class="select form-group mt-1 mb-3">
|
||||
<select class="form-control" name="race">
|
||||
<option class="text-muted" value="">Race</option>
|
||||
<option value="black bear">black bear</option>
|
||||
|
||||
{{- range world.Races -}}
|
||||
<option value="{{ . }}" {{if eq $.Params.race . }}selected{{end}}>{{ . }}</option>
|
||||
{{- end -}}
|
||||
</select>
|
||||
</div>
|
||||
<h4>Sorting</h4>
|
||||
<div class="select form-group">
|
||||
<select class="form-control" name="sort">
|
||||
<option value="">Default</option>
|
||||
<option value="name">Name</option>
|
||||
<option value="race">Race</option>
|
||||
<option value="birth">Birth</option>
|
||||
<option value="death">Death</option>
|
||||
<option value="kills">Kills</option>
|
||||
<option value="name" {{if eq .Params.sort "name" }}selected{{end}}>Name</option>
|
||||
<option value="race" {{if eq .Params.sort "race" }}selected{{end}}>Race</option>
|
||||
<option value="birth" {{if eq .Params.sort "birth" }}selected{{end}}>Birth</option>
|
||||
<option value="death" {{if eq .Params.sort "death" }}selected{{end}}>Death</option>
|
||||
<option value="kills" {{if eq .Params.sort "kills" }}selected{{end}}>Kills</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Refresh</button>
|
||||
<button type="submit" class="btn btn-primary mt-4">Refresh</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
12
backend/templates/year.html
Normal file
12
backend/templates/year.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
{{template "layout.html" .}}
|
||||
|
||||
{{define "title"}}Year {{(index . 0).Year}}{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
|
||||
<h3>Year {{(index . 0).Year}}</h3>
|
||||
|
||||
<h5>Events</h5>
|
||||
{{ template "events.html" events . }}
|
||||
|
||||
{{- end }}
|
25
backend/templates/years.html
Normal file
25
backend/templates/years.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
{{template "layout.html" .}}
|
||||
|
||||
{{define "title"}}Years{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<h3>Years</h3>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<ul>
|
||||
{{ $c := 0}}
|
||||
{{ range $y, $e := . }}
|
||||
{{ $c = add $c 1 }}
|
||||
{{ if breakYearColumn $c (len $) }}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<ul>
|
||||
{{end}}
|
||||
<li><a href="/year/{{ $y }}">Year {{ $y }}</a> ({{len $e}} events)</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{- end }}
|
|
@ -90,6 +90,17 @@ func Map[U, V any](list []U, mapper func(U) V) []V {
|
|||
return newList
|
||||
}
|
||||
|
||||
func FilterMap[K comparable, V any](input map[K]V, predicate func(V) bool, sorter func(V, V) bool) []V {
|
||||
var list []V
|
||||
for _, v := range input {
|
||||
if predicate(v) {
|
||||
list = append(list, v)
|
||||
}
|
||||
}
|
||||
sort.Slice(list, func(i, j int) bool { return sorter(list[i], list[j]) })
|
||||
return list
|
||||
}
|
||||
|
||||
type Identifiable interface {
|
||||
Id() int
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue