collections

This commit is contained in:
Robert Janetzko 2022-05-03 12:59:47 +00:00
parent edc4fe9b75
commit 0596601ea2
22 changed files with 592 additions and 44 deletions

View File

@ -162,6 +162,12 @@ func (x *{{ $obj.Name }}) MarshalJSON() ([]byte, error) {
{{- range $fname, $field := $obj.Fields }}{{- if not ($field.SameField $obj) }}{{- if not (and (eq $fname "type") (not (not $obj.SubTypes))) }}
{{ $field.JsonMarshal }}
{{- end }}{{- end }}{{- end }}
{{- if not (not $obj.SubTypes) }}
d["details"] = x.Details
{{- end }}
{{- range $fname, $field := $obj.Additional }}
{{ $field.JsonMarshal }}
{{- end }}
return json.Marshal(d)
}
@ -399,6 +405,9 @@ func (f Field) StartAction(obj Object, plus bool) string {
return fmt.Sprintf("%sobj.%s = append(obj.%s, num(data))", s, n, n)
} else if f.Type == "string" {
return fmt.Sprintf("%sobj.%s = append(obj.%s, txt(data))", s, n, n)
} else if f.Type == "bool" {
s := "_, err := p.Value()\nif err != nil { return nil, err }\n"
return fmt.Sprintf("%sobj.%s = append(obj.%s, true)", s, n, n)
} else if f.Type == "enum" {
return fmt.Sprintf("%sobj.%s = append(obj.%s, parse%s%s(txt(data)))", s, n, n, obj.Name, f.CorrectedName(obj))
}

View File

@ -62,6 +62,54 @@
"Name": "Ruin",
"Type": "bool"
}
],
"HistoricalEvent": [
{
"Name": "Collection",
"Type": "int"
}
],
"HistoricalEventCollectionAbduction": [
{
"Name": "TargetHfids",
"Type": "[]int"
}
],
"HistoricalEventCollectionBeastAttack": [
{
"Name": "AttackerHfIds",
"Type": "[]int"
}
],
"HistoricalEventCollectionJourney": [
{
"Name": "TravellerHfIds",
"Type": "[]int"
}
],
"HistoricalEventCollectionCeremony": [
{
"Name": "OccasionEventcol",
"Type": "int"
}
],
"HistoricalEventCollectionCompetition": [
{
"Name": "OccasionEventcol",
"Type": "int"
}
],
"HistoricalEventCollectionPerformance": [
{
"Name": "OccasionEventcol",
"Type": "int"
}
],
"HistoricalEventCollectionProcession": [
{
"Name": "OccasionEventcol",
"Type": "int"
}
]
}
}

View File

@ -0,0 +1,187 @@
package model
import (
"fmt"
humanize "github.com/dustin/go-humanize"
"github.com/iancoleman/strcase"
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
)
func (x *HistoricalEventCollection) Link(s string) string {
return fmt.Sprintf(`<a class="collection %s" href="/collection/%d">%s</a>`, strcase.ToKebab(x.Details.Type()), x.Id_, util.Title(s))
}
func (x *HistoricalEventCollection) ParentId() int {
switch t := x.Details.(type) {
case *HistoricalEventCollectionAbduction:
return t.ParentEventcol
case *HistoricalEventCollectionBattle:
return t.WarEventcol
case *HistoricalEventCollectionBeastAttack:
return t.ParentEventcol
case *HistoricalEventCollectionDuel:
return t.ParentEventcol
case *HistoricalEventCollectionRaid:
return t.ParentEventcol
case *HistoricalEventCollectionSiteConquered:
return t.WarEventcol
case *HistoricalEventCollectionTheft:
return t.ParentEventcol
}
return -1
}
func ord(ordinal int) string {
switch ordinal {
case 1:
return ""
case 2:
return "second" + " "
case 3:
return "third" + " "
}
return humanize.Ordinal(ordinal) + " "
}
func (x *HistoricalEventCollectionAbduction) Html(e *HistoricalEventCollection, c *Context) string {
loc := c.location(x.SiteId, " at", x.SubregionId, " at")
switch l := len(x.TargetHfids); {
case l == 0:
return "the " + e.Link(ord(x.Ordinal)+"attempted abduction") + loc
case l == 1:
return "the " + e.Link(ord(x.Ordinal)+"abduction") + " of " + c.hf(x.TargetHfids[0]) + loc
}
return "the " + e.Link(ord(x.Ordinal)+"abduction") + loc
}
func (x *HistoricalEventCollectionBattle) Html(e *HistoricalEventCollection, c *Context) string {
return e.Link(util.Title(x.Name_))
}
func (x *HistoricalEventCollectionBeastAttack) Html(e *HistoricalEventCollection, c *Context) string {
r := "the "
switch l := len(x.AttackerHfIds); {
case l == 1:
r += e.Link(ord(x.Ordinal)+"rampage") + " of " + c.hf(x.AttackerHfIds[0])
case l > 1:
if hf, ok := c.World.HistoricalFigures[x.AttackerHfIds[0]]; ok {
r += e.Link(ord(x.Ordinal) + hf.Race + " " + "rampage")
}
default:
r += e.Link(ord(x.Ordinal) + "rampage")
}
r += c.location(x.SiteId, " in", x.SubregionId, " in")
return r
}
func (x *HistoricalEventCollectionCeremony) Html(e *HistoricalEventCollection, c *Context) string {
r := "ceremony"
if len(e.Event) > 0 {
if event, ok := c.World.HistoricalEvents[e.Event[0]]; ok {
if d, ok := event.Details.(*HistoricalEventCeremony); ok {
if entity, ok := c.World.Entities[d.CivId]; ok {
occ := entity.Occasion[d.OccasionId]
if len(occ.Schedule) > 1 {
switch d.ScheduleId {
case 0:
r = "opening ceremony"
case len(occ.Schedule) - 1:
r = "closing ceremony"
default:
r = "main ceremony"
}
}
}
}
}
}
return "the " + e.Link(ord(x.Ordinal)+r) + " of " + c.collection(x.OccasionEventcol)
}
func (x *HistoricalEventCollectionCompetition) Html(e *HistoricalEventCollection, c *Context) string {
r := "competition"
if len(e.Event) > 0 {
if event, ok := c.World.HistoricalEvents[e.Event[0]]; ok {
if d, ok := event.Details.(*HistoricalEventCompetition); ok {
if entity, ok := c.World.Entities[d.CivId]; ok {
occ := entity.Occasion[d.OccasionId]
r = occ.Schedule[d.ScheduleId].Type_.String()
}
}
}
}
return "the " + e.Link(ord(x.Ordinal)+r) + " of " + c.collection(x.OccasionEventcol)
}
func (x *HistoricalEventCollectionDuel) Html(e *HistoricalEventCollection, c *Context) string {
r := "the "
r += e.Link(ord(x.Ordinal)+"duel") + " of " + c.hf(x.AttackingHfid) + " and " + c.hfRelated(x.DefendingHfid, x.AttackingHfid)
r += c.location(x.SiteId, " in", x.SubregionId, " in")
return r
}
func (x *HistoricalEventCollectionEntityOverthrown) Html(e *HistoricalEventCollection, c *Context) string {
return "the " + e.Link(ord(x.Ordinal)+"overthrow") + " of " + c.entity(x.TargetEntityId) + c.site(x.SiteId, " in")
}
func (x *HistoricalEventCollectionInsurrection) Html(e *HistoricalEventCollection, c *Context) string {
return "the " + e.Link(ord(x.Ordinal)+"insurrection") + c.site(x.SiteId, " at")
}
func (x *HistoricalEventCollectionJourney) Html(e *HistoricalEventCollection, c *Context) string {
r := "the "
r += e.Link(ord(x.Ordinal)+"journey") + " of " + c.hfList(x.TravellerHfIds)
return r
}
func (x *HistoricalEventCollectionOccasion) Html(e *HistoricalEventCollection, c *Context) string {
if civ, ok := c.World.Entities[x.CivId]; ok {
occ := civ.Occasion[x.OccasionId]
return util.If(x.Ordinal > 1, "the "+ord(x.Ordinal)+"occasion of ", "") + e.Link(occ.Name_)
}
return util.If(x.Ordinal > 1, "the "+ord(x.Ordinal)+"occasion of ", "") + e.Link("UNKNOWN OCCASION")
}
func (x *HistoricalEventCollectionPerformance) Html(e *HistoricalEventCollection, c *Context) string {
r := "performance"
if len(e.Event) > 0 {
if event, ok := c.World.HistoricalEvents[e.Event[0]]; ok {
if d, ok := event.Details.(*HistoricalEventPerformance); ok {
if entity, ok := c.World.Entities[d.CivId]; ok {
occ := entity.Occasion[d.OccasionId]
r = occ.Schedule[d.ScheduleId].Type_.String()
}
}
}
}
return "the " + e.Link(ord(x.Ordinal)+r) + " of " + c.collection(x.OccasionEventcol)
}
func (x *HistoricalEventCollectionPersecution) Html(e *HistoricalEventCollection, c *Context) string {
return "the " + e.Link(ord(x.Ordinal)+"persecution") + " of " + c.entity(x.TargetEntityId) + c.site(x.SiteId, " in")
}
func (x *HistoricalEventCollectionProcession) Html(e *HistoricalEventCollection, c *Context) string {
return "the " + e.Link(ord(x.Ordinal)+"procession") + " of " + c.collection(x.OccasionEventcol)
}
func (x *HistoricalEventCollectionPurge) Html(e *HistoricalEventCollection, c *Context) string {
return "the " + e.Link(ord(x.Ordinal)+x.Adjective.String()+" purge") + c.site(x.SiteId, " in")
}
func (x *HistoricalEventCollectionRaid) Html(e *HistoricalEventCollection, c *Context) string {
return "the " + e.Link(ord(x.Ordinal)+"raid") + c.site(x.SiteId, " at")
}
func (x *HistoricalEventCollectionSiteConquered) Html(e *HistoricalEventCollection, c *Context) string {
return "the " + e.Link(ord(x.Ordinal)+"pillaging") + c.site(x.SiteId, " of")
}
func (x *HistoricalEventCollectionTheft) Html(e *HistoricalEventCollection, c *Context) string {
return "the " + e.Link(ord(x.Ordinal)+"theft") + c.site(x.SiteId, " at")
}
func (x *HistoricalEventCollectionWar) Html(e *HistoricalEventCollection, c *Context) string {
return e.Link(util.Title(x.Name_))
}

View File

@ -74,14 +74,14 @@ func (c *Context) hfListRelated(ids []int, to int) string {
func (c *Context) artifact(id int) string {
if x, ok := c.World.Artifacts[id]; ok {
return fmt.Sprintf(`<a class="artifact" href="/artifact/%d"><i class="%s fa-xs"></i>&nbsp;%s</a>`, x.Id(), x.Icon(), util.Title(x.Name()))
return fmt.Sprintf(`<a class="artifact" href="/artifact/%d"><i class="%s fa-xs"></i> %s</a>`, x.Id(), x.Icon(), util.Title(x.Name()))
}
return "UNKNOWN ARTIFACT"
}
func (c *Context) entity(id int) string {
if x, ok := c.World.Entities[id]; ok {
return fmt.Sprintf(`<a class="entity" href="/entity/%d"><i class="%s fa-xs"></i>&nbsp;%s</a>`, x.Id(), x.Icon(), util.Title(x.Name()))
return fmt.Sprintf(`<a class="entity" href="/entity/%d"><i class="%s fa-xs"></i> %s</a>`, x.Id(), x.Icon(), util.Title(x.Name()))
}
return "UNKNOWN ENTITY"
}
@ -115,7 +115,7 @@ func (c *Context) siteStructure(siteId, structureId int, prefix string) string {
func (c *Context) site(id int, prefix string) string {
if x, ok := c.World.Sites[id]; ok {
return fmt.Sprintf(`%s <a class="site" href="/site/%d"><i class="%s fa-xs"></i>&nbsp;%s</a>`, prefix, x.Id(), x.Icon(), util.Title(x.Name()))
return fmt.Sprintf(`%s <a class="site" href="/site/%d"><i class="%s fa-xs"></i> %s</a>`, prefix, x.Id(), x.Icon(), util.Title(x.Name()))
}
return "UNKNOWN SITE"
}
@ -123,7 +123,7 @@ func (c *Context) site(id int, prefix string) string {
func (c *Context) structure(siteId, structureId int) string {
if x, ok := c.World.Sites[siteId]; ok {
if y, ok := x.Structures[structureId]; ok {
return fmt.Sprintf(`<a class="structure" href="/site/%d/structure/%d"><i class="%s fa-xs"></i>&nbsp;%s</a>`, siteId, structureId, y.Icon(), util.Title(y.Name()))
return fmt.Sprintf(`<a class="structure" href="/site/%d/structure/%d"><i class="%s fa-xs"></i> %s</a>`, siteId, structureId, y.Icon(), util.Title(y.Name()))
}
}
return "UNKNOWN STRUCTURE"
@ -191,28 +191,28 @@ func (c *Context) fullIdentity(id int) string {
func (c *Context) danceForm(id int) string {
if x, ok := c.World.DanceForms[id]; ok {
return fmt.Sprintf(`<a class="artform" href="/danceForm/%d"><i class="fa-solid fa-shoe-prints fa-xs"></i>&nbsp;%s</a>`, id, util.Title(x.Name()))
return fmt.Sprintf(`<a class="artform" href="/danceForm/%d"><i class="fa-solid fa-shoe-prints fa-xs"></i> %s</a>`, id, util.Title(x.Name()))
}
return "UNKNOWN DANCE FORM"
}
func (c *Context) musicalForm(id int) string {
if x, ok := c.World.MusicalForms[id]; ok {
return fmt.Sprintf(`<a class="artform" href="/musicalForm/%d"><i class="fa-solid fa-music fa-xs"></i>&nbsp;%s</a>`, id, util.Title(x.Name()))
return fmt.Sprintf(`<a class="artform" href="/musicalForm/%d"><i class="fa-solid fa-music fa-xs"></i> %s</a>`, id, util.Title(x.Name()))
}
return "UNKNOWN MUSICAL FORM"
}
func (c *Context) poeticForm(id int) string {
if x, ok := c.World.PoeticForms[id]; ok {
return fmt.Sprintf(`<a class="artform" href="/poeticForm/%d"><i class="fa-solid fa-comment-dots fa-xs"></i>&nbsp;%s</a>`, id, util.Title(x.Name()))
return fmt.Sprintf(`<a class="artform" href="/poeticForm/%d"><i class="fa-solid fa-comment-dots fa-xs"></i> %s</a>`, id, util.Title(x.Name()))
}
return "UNKNOWN POETIC FORM"
}
func (c *Context) worldConstruction(id int) string {
if x, ok := c.World.WorldConstructions[id]; ok {
return fmt.Sprintf(`<a class="worldconstruction" href="/worldconstruction/%d"><i class="%s fa-xs"></i>&nbsp;%s</a>`, id, x.Icon(), util.Title(x.Name()))
return fmt.Sprintf(`<a class="worldconstruction" href="/worldconstruction/%d"><i class="%s fa-xs"></i> %s</a>`, id, x.Icon(), util.Title(x.Name()))
}
return "UNKNOWN WORLD CONSTRUCTION"
}
@ -224,6 +224,13 @@ func (c *Context) writtenContent(id int) string {
return "UNKNOWN WORLD CONSTRUCTION"
}
func (c *Context) collection(id int) string {
if x, ok := c.World.HistoricalEventCollections[id]; ok {
return x.Details.Html(x, c)
}
return "UNKNOWN EVENT COLLECTION"
}
func (c *Context) feature(x *Feature) string {
switch x.Type_ {
case FeatureType_DancePerformance:

View File

@ -2,6 +2,8 @@ package model
import (
"fmt"
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
)
type HistoricalEventDetails interface {
@ -16,6 +18,8 @@ type HistoricalEventDetails interface {
}
type HistoricalEventCollectionDetails interface {
Type() string
Html(*HistoricalEventCollection, *Context) string
}
type EventList struct {
@ -48,6 +52,8 @@ func NewEventList(world *DfWorld, obj any) *EventList {
el.Events = world.EventsMatching(func(d HistoricalEventDetails) bool { return d.RelatedToRegion(x.Id()) })
case []*HistoricalEvent:
el.Events = x
case []int:
el.Events = util.Map(x, func(id int) *HistoricalEvent { return world.HistoricalEvents[id] })
default:
fmt.Printf("unknown type %T\n", obj)
}

View File

@ -63,6 +63,20 @@ func (w *DfWorld) SiteHistory(siteId int) []*HistoricalEvent {
return list
}
func (c *HistoricalEventCollection) Type() string {
if c.Details == nil {
return "unk"
}
return c.Details.Type()
}
func (e *HistoricalEventCollection) Html(c *Context) string {
if e.Details == nil {
return "unk"
}
return e.Details.Html(e, c)
}
func (e *Artifact) Type() string {
switch e.ItemSubtype {
case "scroll":

View File

@ -23,6 +23,7 @@ var LinkDanceForm = func(w *DfWorld, id int) template.HTML { return template.HTM
var LinkMusicalForm = func(w *DfWorld, id int) template.HTML { return template.HTML((&Context{World: w}).musicalForm(id)) }
var LinkPoeticForm = func(w *DfWorld, id int) template.HTML { return template.HTML((&Context{World: w}).poeticForm(id)) }
var LinkWrittenContent = func(w *DfWorld, id int) template.HTML { return template.HTML((&Context{World: w}).writtenContent(id)) }
var LinkCollection = func(w *DfWorld, id int) template.HTML { return template.HTML((&Context{World: w}).collection(id)) }
var AddMapSite = func(w *DfWorld, id int) template.HTML {
if site, ok := w.Sites[id]; ok {

View File

@ -1631,6 +1631,19 @@ func (x *DfWorld) MarshalJSON() ([]byte, error) {
d["undergroundRegions"] = x.UndergroundRegions
d["worldConstructions"] = x.WorldConstructions
d["writtenContents"] = x.WrittenContents
if x.EndYear != -1 {
d["endYear"] = x.EndYear
}
d["filePath"] = x.FilePath
if x.Height != -1 {
d["height"] = x.Height
}
d["mapData"] = x.MapData
d["mapReady"] = x.MapReady
d["plusFilePath"] = x.PlusFilePath
if x.Width != -1 {
d["width"] = x.Width
}
return json.Marshal(d)
}
@ -2045,6 +2058,7 @@ func (x *Entity) MarshalJSON() ([]byte, error) {
}
d["weapon"] = x.Weapon
d["worshipId"] = x.WorshipId
d["sites"] = x.Sites
return json.Marshal(d)
}
@ -2823,6 +2837,7 @@ type HistoricalEvent struct {
Seconds72 int `json:"seconds72" legend:"base"` // seconds72
Year int `json:"year" legend:"base"` // year
Details HistoricalEventDetails
Collection int `json:"collection" legend:"add"` // Collection
}
func NewHistoricalEvent() *HistoricalEvent {
@ -2830,6 +2845,7 @@ func NewHistoricalEvent() *HistoricalEvent {
Id_: -1,
Seconds72: -1,
Year: -1,
Collection: -1,
}
}
func (x *HistoricalEvent) Id() int { return x.Id_ }
@ -2855,6 +2871,10 @@ func (x *HistoricalEvent) MarshalJSON() ([]byte, error) {
if x.Year != -1 {
d["year"] = x.Year
}
d["details"] = x.Details
if x.Collection != -1 {
d["collection"] = x.Collection
}
return json.Marshal(d)
}
@ -5915,6 +5935,7 @@ func (x *HistoricalEventCollection) MarshalJSON() ([]byte, error) {
if x.StartYear != -1 {
d["startYear"] = x.StartYear
}
d["details"] = x.Details
return json.Marshal(d)
}
@ -5927,6 +5948,7 @@ type HistoricalEventCollectionAbduction struct {
ParentEventcol int `json:"parentEventcol" legend:"base"` // parent_eventcol
SiteId int `json:"siteId" legend:"base"` // site_id
SubregionId int `json:"subregionId" legend:"base"` // subregion_id
TargetHfids []int `json:"targetHfids" legend:"add"` // TargetHfids
}
func NewHistoricalEventCollectionAbduction() *HistoricalEventCollectionAbduction {
@ -5977,6 +5999,7 @@ func (x *HistoricalEventCollectionAbduction) MarshalJSON() ([]byte, error) {
if x.SubregionId != -1 {
d["subregionId"] = x.SubregionId
}
d["targetHfids"] = x.TargetHfids
return json.Marshal(d)
}
@ -6136,6 +6159,7 @@ type HistoricalEventCollectionBeastAttack struct {
ParentEventcol int `json:"parentEventcol" legend:"base"` // parent_eventcol
SiteId int `json:"siteId" legend:"base"` // site_id
SubregionId int `json:"subregionId" legend:"base"` // subregion_id
AttackerHfIds []int `json:"attackerHfIds" legend:"add"` // AttackerHfIds
}
func NewHistoricalEventCollectionBeastAttack() *HistoricalEventCollectionBeastAttack {
@ -6184,16 +6208,19 @@ func (x *HistoricalEventCollectionBeastAttack) MarshalJSON() ([]byte, error) {
if x.SubregionId != -1 {
d["subregionId"] = x.SubregionId
}
d["attackerHfIds"] = x.AttackerHfIds
return json.Marshal(d)
}
type HistoricalEventCollectionCeremony struct {
Ordinal int `json:"ordinal" legend:"base"` // ordinal
OccasionEventcol int `json:"occasionEventcol" legend:"add"` // OccasionEventcol
}
func NewHistoricalEventCollectionCeremony() *HistoricalEventCollectionCeremony {
return &HistoricalEventCollectionCeremony{
Ordinal: -1,
OccasionEventcol: -1,
}
}
func (x *HistoricalEventCollectionCeremony) Type() string { return "ceremony" }
@ -6212,16 +6239,21 @@ func (x *HistoricalEventCollectionCeremony) MarshalJSON() ([]byte, error) {
if x.Ordinal != -1 {
d["ordinal"] = x.Ordinal
}
if x.OccasionEventcol != -1 {
d["occasionEventcol"] = x.OccasionEventcol
}
return json.Marshal(d)
}
type HistoricalEventCollectionCompetition struct {
Ordinal int `json:"ordinal" legend:"base"` // ordinal
OccasionEventcol int `json:"occasionEventcol" legend:"add"` // OccasionEventcol
}
func NewHistoricalEventCollectionCompetition() *HistoricalEventCollectionCompetition {
return &HistoricalEventCollectionCompetition{
Ordinal: -1,
OccasionEventcol: -1,
}
}
func (x *HistoricalEventCollectionCompetition) Type() string { return "competition" }
@ -6240,6 +6272,9 @@ func (x *HistoricalEventCollectionCompetition) MarshalJSON() ([]byte, error) {
if x.Ordinal != -1 {
d["ordinal"] = x.Ordinal
}
if x.OccasionEventcol != -1 {
d["occasionEventcol"] = x.OccasionEventcol
}
return json.Marshal(d)
}
@ -6389,6 +6424,7 @@ func (x *HistoricalEventCollectionInsurrection) MarshalJSON() ([]byte, error) {
type HistoricalEventCollectionJourney struct {
Ordinal int `json:"ordinal" legend:"base"` // ordinal
TravellerHfIds []int `json:"travellerHfIds" legend:"add"` // TravellerHfIds
}
func NewHistoricalEventCollectionJourney() *HistoricalEventCollectionJourney {
@ -6412,6 +6448,7 @@ func (x *HistoricalEventCollectionJourney) MarshalJSON() ([]byte, error) {
if x.Ordinal != -1 {
d["ordinal"] = x.Ordinal
}
d["travellerHfIds"] = x.TravellerHfIds
return json.Marshal(d)
}
@ -6455,11 +6492,13 @@ func (x *HistoricalEventCollectionOccasion) MarshalJSON() ([]byte, error) {
type HistoricalEventCollectionPerformance struct {
Ordinal int `json:"ordinal" legend:"base"` // ordinal
OccasionEventcol int `json:"occasionEventcol" legend:"add"` // OccasionEventcol
}
func NewHistoricalEventCollectionPerformance() *HistoricalEventCollectionPerformance {
return &HistoricalEventCollectionPerformance{
Ordinal: -1,
OccasionEventcol: -1,
}
}
func (x *HistoricalEventCollectionPerformance) Type() string { return "performance" }
@ -6478,6 +6517,9 @@ func (x *HistoricalEventCollectionPerformance) MarshalJSON() ([]byte, error) {
if x.Ordinal != -1 {
d["ordinal"] = x.Ordinal
}
if x.OccasionEventcol != -1 {
d["occasionEventcol"] = x.OccasionEventcol
}
return json.Marshal(d)
}
@ -6523,11 +6565,13 @@ func (x *HistoricalEventCollectionPersecution) MarshalJSON() ([]byte, error) {
type HistoricalEventCollectionProcession struct {
Ordinal int `json:"ordinal" legend:"base"` // ordinal
OccasionEventcol int `json:"occasionEventcol" legend:"add"` // OccasionEventcol
}
func NewHistoricalEventCollectionProcession() *HistoricalEventCollectionProcession {
return &HistoricalEventCollectionProcession{
Ordinal: -1,
OccasionEventcol: -1,
}
}
func (x *HistoricalEventCollectionProcession) Type() string { return "procession" }
@ -6546,6 +6590,9 @@ func (x *HistoricalEventCollectionProcession) MarshalJSON() ([]byte, error) {
if x.Ordinal != -1 {
d["ordinal"] = x.Ordinal
}
if x.OccasionEventcol != -1 {
d["occasionEventcol"] = x.OccasionEventcol
}
return json.Marshal(d)
}
@ -18172,6 +18219,8 @@ func (x *HistoricalFigure) MarshalJSON() ([]byte, error) {
d["sphere"] = x.Sphere
d["usedIdentityId"] = x.UsedIdentityId
d["vagueRelationship"] = x.VagueRelationship
d["vampire"] = x.Vampire
d["werebeast"] = x.Werebeast
return json.Marshal(d)
}
@ -20434,6 +20483,7 @@ func (x *Site) MarshalJSON() ([]byte, error) {
if x.Type_ != 0 {
d["type"] = x.Type_
}
d["ruin"] = x.Ruin
return json.Marshal(d)
}
@ -20855,6 +20905,9 @@ func (x *Structure) MarshalJSON() ([]byte, error) {
if x.WorshipHfid != -1 {
d["worshipHfid"] = x.WorshipHfid
}
if x.SiteId != -1 {
d["siteId"] = x.SiteId
}
return json.Marshal(d)
}
@ -27040,7 +27093,11 @@ func parseHistoricalEventCollectionBattle(p *util.XMLParser) (*HistoricalEventCo
}
obj.AttackingMercEnid = num(data)
case "attacking_squad_animated":
_, err := p.Value()
if err != nil {
return nil, err
}
obj.AttackingSquadAnimated = append(obj.AttackingSquadAnimated, true)
case "attacking_squad_deaths":
data, err := p.Value()
if err != nil {
@ -27072,7 +27129,11 @@ func parseHistoricalEventCollectionBattle(p *util.XMLParser) (*HistoricalEventCo
}
obj.AttackingSquadSite = append(obj.AttackingSquadSite, num(data))
case "company_merc":
_, err := p.Value()
if err != nil {
return nil, err
}
obj.CompanyMerc = append(obj.CompanyMerc, true)
case "coords":
data, err := p.Value()
if err != nil {
@ -27104,7 +27165,11 @@ func parseHistoricalEventCollectionBattle(p *util.XMLParser) (*HistoricalEventCo
}
obj.DefendingMercEnid = num(data)
case "defending_squad_animated":
_, err := p.Value()
if err != nil {
return nil, err
}
obj.DefendingSquadAnimated = append(obj.DefendingSquadAnimated, true)
case "defending_squad_deaths":
data, err := p.Value()
if err != nil {
@ -27142,7 +27207,11 @@ func parseHistoricalEventCollectionBattle(p *util.XMLParser) (*HistoricalEventCo
}
obj.FeatureLayerId = num(data)
case "individual_merc":
_, err := p.Value()
if err != nil {
return nil, err
}
obj.IndividualMerc = append(obj.IndividualMerc, true)
case "name":
data, err := p.Value()
if err != nil {

View File

@ -14,7 +14,6 @@ import (
)
func (e *HistoricalEvent) Name() string { return "" }
func (e *HistoricalEventCollection) Name() string { return "" }
func NewLegendsDecoder(file string) (*xml.Decoder, *os.File, *pb.ProgressBar, error) {
fi, err := os.Stat(file)

View File

@ -3,6 +3,7 @@ package model
import (
"strings"
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
"golang.org/x/exp/slices"
)
@ -16,6 +17,7 @@ func (w *DfWorld) process() {
}
w.processEvents()
w.processCollections()
// check events texts
for _, e := range w.HistoricalEvents {
@ -57,6 +59,79 @@ func (w *DfWorld) processEvents() {
}
}
func (w *DfWorld) processCollections() {
for _, col := range w.HistoricalEventCollections {
for _, eventId := range col.Event {
if e, ok := w.HistoricalEvents[eventId]; ok {
e.Collection = col.Id_
}
}
switch cd := col.Details.(type) {
case *HistoricalEventCollectionAbduction:
targets := make(map[int]bool)
for _, eventId := range col.Event {
if e, ok := w.HistoricalEvents[eventId]; ok {
switch d := e.Details.(type) {
case *HistoricalEventHfAbducted:
targets[d.TargetHfid] = true
}
}
}
delete(targets, -1)
cd.TargetHfids = util.Keys(targets)
case *HistoricalEventCollectionBeastAttack:
attackers := make(map[int]bool)
for _, eventId := range col.Event {
if e, ok := w.HistoricalEvents[eventId]; ok {
switch d := e.Details.(type) {
case *HistoricalEventHfSimpleBattleEvent:
attackers[d.Group1Hfid] = true
case *HistoricalEventHfAttackedSite:
attackers[d.AttackerHfid] = true
case *HistoricalEventHfDestroyedSite:
attackers[d.AttackerHfid] = true
case *HistoricalEventAddHfEntityLink:
attackers[d.Hfid] = true
case *HistoricalEventCreatureDevoured:
attackers[d.Eater] = true
case *HistoricalEventItemStolen:
attackers[d.Histfig] = true
}
}
}
delete(attackers, -1)
cd.AttackerHfIds = util.Keys(attackers)
case *HistoricalEventCollectionJourney:
HistoricalEventCollectionJourneyLoop:
for _, eventId := range col.Event {
if e, ok := w.HistoricalEvents[eventId]; ok {
switch d := e.Details.(type) {
case *HistoricalEventHfTravel:
cd.TravellerHfIds = d.GroupHfid
break HistoricalEventCollectionJourneyLoop
}
}
}
case *HistoricalEventCollectionOccasion:
for _, eventcolId := range col.Eventcol {
if e, ok := w.HistoricalEventCollections[eventcolId]; ok {
switch d := e.Details.(type) {
case *HistoricalEventCollectionCeremony:
d.OccasionEventcol = col.Id_
case *HistoricalEventCollectionCompetition:
d.OccasionEventcol = col.Id_
case *HistoricalEventCollectionPerformance:
d.OccasionEventcol = col.Id_
case *HistoricalEventCollectionProcession:
d.OccasionEventcol = col.Id_
}
}
}
}
}
}
func (w *DfWorld) addEntitySite(entityId, siteId int) {
if e, ok := w.Entities[entityId]; ok {
if !slices.Contains(e.Sites, siteId) {

View File

@ -26,7 +26,7 @@ func (srv *DfServer) RegisterWorldPage(path string, template string, accessor fu
err := srv.templates.Render(w, template, data)
if err != nil {
fmt.Fprintln(w, err)
fmt.Fprint(w, err)
fmt.Println(err)
}
}

View File

@ -4,6 +4,7 @@ import (
"embed"
"fmt"
"net/http"
"os"
"sort"
"strconv"
@ -93,6 +94,16 @@ func StartServer(world *model.DfWorld, static embed.FS) error {
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.RegisterWorldPage("/collections", "collections.html", func(p Parms) any {
return groupBy(srv.context.world.HistoricalEventCollections,
func(e *model.HistoricalEventCollection) string { return e.Type() },
func(e *model.HistoricalEventCollection) bool { return true },
func(e *model.HistoricalEventCollection) string { return model.Time(e.StartYear, e.StartSeconds72) },
)
})
srv.RegisterWorldResourcePage("/collection/{id}", "collection.html", func(id int) any { return srv.context.world.HistoricalEventCollections[id] })
srv.RegisterWorldResourcePage("/popover/collection/{id}", "popoverCollection.html", func(id int) any { return srv.context.world.HistoricalEventCollections[id] })
srv.RegisterWorldPage("/", "index.html", func(p Parms) any {
return &struct {
Civilizations map[string][]*model.Entity
@ -115,6 +126,9 @@ func StartServer(world *model.DfWorld, static embed.FS) error {
srv.router.PathPrefix("/load").Handler(srv.loader)
spa := spaHandler{server: srv, staticFS: static, staticPath: "static", indexPath: "index.html"}
if templates.DebugTemplates {
spa.staticFS = os.DirFS(".")
}
srv.router.PathPrefix("/").Handler(spa)
OpenBrowser("http://localhost:8080")

View File

@ -1,16 +1,16 @@
package server
import (
"embed"
"fmt"
"io/fs"
"io/ioutil"
"net/http"
"os"
)
type spaHandler struct {
server *DfServer
staticFS embed.FS
staticFS fs.FS
staticPath string
indexPath string
}
@ -30,7 +30,12 @@ func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if os.IsNotExist(err) {
// file does not exist, serve index.html
fmt.Println(path)
index, err := h.staticFS.ReadFile(h.staticPath + "/" + h.indexPath)
file, err := h.staticFS.Open(h.staticPath + "/" + h.indexPath)
if err != nil {
h.server.notFound(w)
return
}
index, err := ioutil.ReadAll(file)
if err != nil {
h.server.notFound(w)
return

View File

@ -55,6 +55,20 @@ func (srv *DfServer) LoadTemplates() {
"history": func(siteId int) []*model.HistoricalEvent {
return srv.context.world.SiteHistory(siteId)
},
"collection": func(id int) template.HTML { return model.LinkCollection(srv.context.world, id) },
"getCollection": func(id int) *model.HistoricalEventCollection { return srv.context.world.HistoricalEventCollections[id] },
"getOccasion": func(civId, occasionId int) *model.Occasion {
if civ, ok := srv.context.world.Entities[civId]; ok {
return civ.Occasion[occasionId]
}
return nil
},
"story": func(id int) template.HTML {
if e, ok := srv.context.world.HistoricalEvents[id]; ok {
return template.HTML(e.Details.Html(&model.Context{World: srv.context.world, Story: true}) + " in " + model.Time(e.Year, e.Seconds72))
}
return template.HTML("")
},
"season": model.Season,
"time": model.Time,
"url": url.PathEscape,
@ -66,6 +80,9 @@ func (srv *DfServer) LoadTemplates() {
"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,
}
srv.templates = templates.New(functions)
}

View File

@ -71,17 +71,22 @@ td.object {
font-size: 80%;
}
/*
@media (prefers-color-scheme: dark) {
a {
color: #337ab7;
}
.collection {
color: #718dc9;
}
.artifact {
color: #ea4e00;
}
.historical-figure {
.hf {
color: #5c93ff;
}
@ -93,7 +98,20 @@ td.object {
color: #c70303;
}
.art-form {
.occasion {
color: #ff91ff;
}
.artform {
color: #cc45cc;
}
} */
.worldconstruction {
color: #aaa;
}
.json {
color: #666;
}
}

View File

@ -0,0 +1,16 @@
{{template "layout.html" .}}
{{define "title"}}{{ title (strip (collection .Id)) }}{{end}}
{{define "content"}}
<h3>{{ html (capitalize (string (collection .Id))) }}</h3>
{{- if eq .Type "occasion" }}{{- with getOccasion .Details.CivId .Details.OccasionId }}{{- if ne .Event -1 }}
<p>A festival commemorating {{ story .Event }}</p>
{{- end }}{{- end}}{{- end}}
{{ template "collectionDetail.html" . }}
<p>{{ json . }}</p>
{{- end }}

View File

@ -0,0 +1,11 @@
{{- if gt (len .Eventcol) 0 }}
<ul>
{{- range .Eventcol }}
<li>{{ with getCollection . }}
In {{ time .StartYear .StartSeconds72 }}, {{ collection .Id }} occurred
{{ template "events.html" events .Event }}
{{ end }}</li>
{{- end }}
</ul>
{{- end }}
{{ template "events.html" events .Event }}

View File

@ -0,0 +1,37 @@
{{template "layout.html" .}}
{{define "title"}}Event Collections{{end}}
{{define "content"}}
<h3>Event Collections</h3>
<nav>
<div class="nav nav-tabs" id="nav-tab" role="tablist">
{{- range $t, $v := .}}
<button class="nav-link{{ ifFirst $ $t " active" }}" data-bs-toggle="tab" data-bs-target="#nav-{{kebab $t}}" type="button"
role="tab">{{$t}} ({{ len $v }})</button>
{{- end}}
</div>
</nav>
<div class="tab-content" id="nav-tabContent">
{{- range $t, $v := . }}
<div class="tab-pane{{ ifFirst $ $t " active" }}" id="nav-{{kebab $t}}" role="tabpanel" aria-labelledby="nav-home-tab">
<table class="table table-hover table-sm table-borderless object-table">
<tr>
<th width="100%">Name</th>
<th>Collections</th>
<th>Events</th>
</tr>
{{- range $v }}
<tr>
<td>{{ collection .Id }}</td>
<td>{{ len .Eventcol }}</td>
<td>{{ len .Event }}</td>
</tr>
{{- end}}
</table>
</div>
{{- end}}
</div>
{{- end }}

View File

@ -1,8 +1,11 @@
<ul class="mb-0">
{{- range $event := .Events }}
<li>
[{{ $event.Id }}] In {{ time $event.Year $event.Seconds72 }}, {{
html ($event.Details.Html $.Context) }} {{ json $event.Details }}
[{{ $event.Id }}] In {{ time $event.Year $event.Seconds72 }},
{{ html ($event.Details.Html $.Context) }}
{{ if ne .Collection -1 }} <a class="collection" href="/collection/{{.Collection}}"><i
class="fa-solid fa-magnifying-glass fa-xs"></i></a>{{end}}
{{ json $event.Details }}
</li>
{{- end}}
</ul>

View File

@ -107,7 +107,7 @@
}).responseText;
}
$('a.entity,a.hf,a.region,a.site,a.structure,a.worldconstruction,a.artifact,a.writtencontent').each(function () {
$('a.entity,a.hf,a.region,a.site,a.structure,a.worldconstruction,a.artifact,a.writtencontent,a.collection').each(function () {
var popover = new bootstrap.Popover($(this), { content: loadLinkPopoverData, trigger: "hover", placement: "top", html: true })
})
</script>

View File

@ -0,0 +1,3 @@
{{ collection .Id }}
{{if ne .ParentId -1 }}
<br />as part of {{ collection .ParentId }}{{ end }}

View File

@ -117,3 +117,12 @@ func FirstInMap(a any, b string) bool {
sort.Slice(ks, func(i, j int) bool { return ks[i].String() < ks[j].String() })
return ks[0].String() == b
}
func Strip(html template.HTML) string {
r := regexp.MustCompile(`<.*?>`)
return r.ReplaceAllString(string(html), "")
}
func String(html template.HTML) string {
return string(html)
}