diff --git a/backend/.gitignore b/backend/.gitignore index b78fa79..f5cd815 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1 +1,2 @@ -resources/frontend/* \ No newline at end of file +resources/frontend/* +same.json \ No newline at end of file diff --git a/backend/main.go b/backend/main.go index 78fdc2b..92d1a8e 100644 --- a/backend/main.go +++ b/backend/main.go @@ -4,25 +4,16 @@ import ( "embed" "flag" "fmt" - "html/template" - "io/fs" "net/http" _ "net/http/pprof" "os" - "os/exec" "runtime" - "sort" - "strconv" - "github.com/gorilla/mux" "github.com/pkg/profile" "github.com/robertjanetzko/LegendsBrowser2/backend/model" - "github.com/robertjanetzko/LegendsBrowser2/backend/templates" - "github.com/robertjanetzko/LegendsBrowser2/backend/util" + "github.com/robertjanetzko/LegendsBrowser2/backend/server" ) -var world *model.DfWorld - //go:embed static var static embed.FS @@ -31,34 +22,6 @@ func main() { p := flag.Bool("p", false, "start profiling") flag.Parse() - router := mux.NewRouter().StrictSlash(true) - - functions := template.FuncMap{ - "json": util.Json, - "check": func(condition bool, v any) any { - if condition { - return v - } - return nil - }, - "title": util.Title, - "hf": model.LinkHf, - "getHf": func(id int) *model.HistoricalFigure { return world.HistoricalFigures[id] }, - "entity": model.LinkEntity, - "getEntity": func(id int) *model.Entity { return world.Entities[id] }, - "site": model.LinkSite, - "getSite": func(id int) *model.Site { return world.Sites[id] }, - "region": model.LinkRegion, - "getRegion": func(id int) *model.Region { return world.Regions[id] }, - "events": model.NewEventList, - "season": model.Season, - "time": model.Time, - "html": func(value any) template.HTML { - return template.HTML(fmt.Sprint(value)) - }, - } - t := templates.New(functions) - if len(*f) > 0 { if *p { defer profile.Start(profile.ProfilePath(".")).Stop() @@ -73,137 +36,9 @@ func main() { os.Exit(1) } - world = w runtime.GC() - RegisterResourcePage(router, "/entity/{id}", t, "entity.html", func(id int) any { return world.Entities[id] }) - RegisterResourcePage(router, "/hf/{id}", t, "hf.html", func(id int) any { return world.HistoricalFigures[id] }) - RegisterResourcePage(router, "/region/{id}", t, "region.html", func(id int) any { return world.Regions[id] }) - RegisterResourcePage(router, "/site/{id}", t, "site.html", func(id int) any { return world.Sites[id] }) - RegisterResourcePage(router, "/artifact/{id}", t, "artifact.html", func(id int) any { return world.Artifacts[id] }) - RegisterPage(router, "/events", t, "eventTypes.html", func(p Parms) any { return allEventTypes() }) - RegisterPage(router, "/events/{type}", t, "eventType.html", func(p Parms) any { return eventsOfType(p["type"]) }) - } - - spa := spaHandler{staticFS: static, staticPath: "static", indexPath: "index.html"} - router.PathPrefix("/").Handler(spa) - - openbrowser("http://localhost:8080") - - fmt.Println("Serving at :8080") - http.ListenAndServe(":8080", router) -} - -func openbrowser(url string) { - var err error - - switch runtime.GOOS { - case "linux": - err = exec.Command("xdg-open", url).Start() - case "windows": - err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() - case "darwin": - err = exec.Command("open", url).Start() - default: - err = fmt.Errorf("unsupported platform") - } - if err != nil { - fmt.Println(err) - fmt.Println("navigate to http://localhost:8080 in your browser") + server.StartServer(w, static) } } - -func allEventTypes() []string { - types := make(map[string]bool) - for _, e := range world.HistoricalEvents { - types[e.Details.Type()] = true - } - var list = util.Keys(types) - sort.Strings(list) - return list -} - -func eventsOfType(t string) any { - var list []*model.HistoricalEvent - for _, e := range world.HistoricalEvents { - if e.Details.Type() == t { - list = append(list, e) - } - } - - sort.Slice(list, func(i, j int) bool { return list[i].Id_ < list[j].Id_ }) - - return struct { - Type string - Events []*model.HistoricalEvent - }{ - Type: t, - Events: list, - } -} - -type Parms map[string]string - -func RegisterPage(router *mux.Router, path string, templates *templates.Template, template string, accessor func(Parms) any) { - get := func(w http.ResponseWriter, r *http.Request) { - err := templates.Render(w, template, accessor(mux.Vars(r))) - if err != nil { - fmt.Fprintln(w, err) - fmt.Println(err) - } - } - - router.HandleFunc(path, get).Methods("GET") -} - -func RegisterResourcePage(router *mux.Router, path string, templates *templates.Template, template string, accessor func(int) any) { - RegisterPage(router, path, templates, template, func(params Parms) any { - id, _ := strconv.Atoi(params["id"]) - return accessor(id) - }) -} - -type spaHandler struct { - staticFS embed.FS - staticPath string - indexPath string -} - -func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // get the absolute path to prevent directory traversal - path := r.URL.Path - // if err != nil { - // // if we failed to get the absolute path respond with a 400 bad request and stop - // http.Error(w, err.Error(), http.StatusBadRequest) - // return - // } - // prepend the path with the path to the static directory - path = h.staticPath + path - fmt.Println(r.URL, "->", path) - - _, err := h.staticFS.Open(path) - if os.IsNotExist(err) { - // file does not exist, serve index.html - fmt.Println(path) - index, err := h.staticFS.ReadFile(h.staticPath + "/" + h.indexPath) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.Header().Set("Content-Type", "text/html; charset=utf-8") - w.WriteHeader(http.StatusAccepted) - w.Write(index) - return - } else if err != nil { - // if we got an error (that wasn't that the file doesn't exist) stating the - // file, return a 500 internal server error and stop - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - // get the subdirectory of the static dir - statics, err := fs.Sub(h.staticFS, h.staticPath) - // otherwise, use http.FileServer to serve the static dir - http.FileServer(http.FS(statics)).ServeHTTP(w, r) -} diff --git a/backend/model/context.go b/backend/model/context.go new file mode 100644 index 0000000..ba97b73 --- /dev/null +++ b/backend/model/context.go @@ -0,0 +1,273 @@ +package model + +import ( + "fmt" + + "github.com/iancoleman/strcase" + "github.com/robertjanetzko/LegendsBrowser2/backend/util" +) + +type context struct { + world *DfWorld + hfId int + story bool +} + +func (c *context) hf(id int) string { + if c.hfId != -1 { + if c.hfId == id { + return c.hfShort(id) + } else { + return c.hfRelated(id, c.hfId) + } + } + if x, ok := c.world.HistoricalFigures[id]; ok { + return fmt.Sprintf(`the %s %s`, x.Race+util.If(x.Deity, " deity", "")+util.If(x.Force, " force", ""), x.Id(), util.Title(x.Name())) + } + return "UNKNOWN HISTORICAL FIGURE" +} + +func (c *context) hfShort(id int) string { + if x, ok := c.world.HistoricalFigures[id]; ok { + return fmt.Sprintf(`%s`, x.Id(), util.Title(x.FirstName())) + } + return "UNKNOWN HISTORICAL FIGURE" +} + +func (c *context) hfRelated(id, to int) string { + if c.hfId != -1 { + if c.hfId == id { + return c.hfShort(id) + } else { + return c.hfRelated(id, c.hfId) + } + } + if x, ok := c.world.HistoricalFigures[id]; ok { + if t, ok := c.world.HistoricalFigures[to]; ok { + if y, ok := util.Find(t.HfLink, func(l *HfLink) bool { return l.Hfid == id }); ok { + return fmt.Sprintf(`%s %s %s`, t.PossesivePronoun(), y.LinkType, x.Id(), util.Title(x.Name())) + } + } + return fmt.Sprintf(`the %s %s`, x.Race+util.If(x.Deity, " deity", "")+util.If(x.Force, " force", ""), x.Id(), util.Title(x.Name())) + } + return "UNKNOWN HISTORICAL FIGURE" +} + +func (c *context) hfList(ids []int) string { + return andList(util.Map(ids, func(id int) string { return c.hf(id) })) +} + +func (c *context) hfListRelated(ids []int, to int) string { + return andList(util.Map(ids, func(id int) string { return c.hfRelated(id, to) })) +} + +func (c *context) artifact(id int) string { + if x, ok := c.world.Artifacts[id]; ok { + return fmt.Sprintf(`%s`, x.Id(), 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(`%s`, x.Id(), util.Title(x.Name())) + } + return "UNKNOWN ENTITY" +} + +func (c *context) entityList(ids []int) string { + return andList(util.Map(ids, func(id int) string { return c.entity(id) })) +} + +func (c *context) position(entityId, positionId, hfId int) string { + if e, ok := c.world.Entities[entityId]; ok { + if h, ok := c.world.HistoricalFigures[hfId]; ok { + return e.Position(positionId).GenderName(h) + } + } + return "UNKNOWN POSITION" +} + +func (c *context) siteCiv(siteCivId, civId int) string { + if siteCivId == civId { + return c.entity(civId) + } + return util.If(siteCivId != -1, c.entity(siteCivId), "") + util.If(civId != -1 && siteCivId != -1, " of ", "") + util.If(civId != -1, c.entity(civId), "") +} + +func (c *context) siteStructure(siteId, structureId int, prefix string) string { + if siteId == -1 { + return "" + } + return " " + prefix + " " + util.If(structureId != -1, c.structure(siteId, structureId)+" in ", "") + c.site(siteId, "") +} + +func (c *context) site(id int, prefix string) string { + if x, ok := c.world.Sites[id]; ok { + return fmt.Sprintf(`%s %s`, prefix, x.Id(), util.Title(x.Name())) + } + return "UNKNOWN SITE" +} + +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(`%s`, siteId, structureId, util.Title(y.Name())) + } + } + return "UNKNOWN STRUCTURE" +} + +func (c *context) property(siteId, propertyId int) string { + if x, ok := c.world.Sites[siteId]; ok { + if y, ok := x.SiteProperties[propertyId]; ok { + if y.StructureId != -1 { + return c.structure(siteId, y.StructureId) + } + return articled(y.Type.String()) + } + } + return "UNKNOWN PROPERTY" +} + +func (c *context) region(id int) string { + if x, ok := c.world.Regions[id]; ok { + return fmt.Sprintf(`%s`, x.Id(), util.Title(x.Name())) + } + return "UNKNOWN REGION" +} + +func (c *context) location(siteId int, sitePrefix string, regionId int, regionPrefix string) string { + if siteId != -1 { + return c.site(siteId, sitePrefix) + } + if regionId != -1 { + return regionPrefix + " " + c.region(regionId) + } + return "" +} + +func (c *context) place(structureId, siteId int, sitePrefix string, regionId int, regionPrefix string) string { + if siteId != -1 { + return c.siteStructure(siteId, structureId, sitePrefix) + } + if regionId != -1 { + return regionPrefix + " " + c.region(regionId) + } + return "" +} + +func (c *context) mountain(id int) string { + if x, ok := c.world.MountainPeaks[id]; ok { + return fmt.Sprintf(`%s`, x.Id(), util.Title(x.Name())) + } + return "UNKNOWN MOUNTAIN" +} + +func (c *context) identity(id int) string { + if x, ok := c.world.Identities[id]; ok { + return fmt.Sprintf(`%s`, x.Id(), util.Title(x.Name())) + } + return "UNKNOWN IDENTITY" +} + +func (c *context) fullIdentity(id int) string { + if x, ok := c.world.Identities[id]; ok { + return fmt.Sprintf(`"the %s %s of %s"`, x.Profession.String(), x.Id(), util.Title(x.Name()), c.entity(x.EntityId)) + } + return "UNKNOWN IDENTITY" +} + +func (c *context) danceForm(id int) string { + if x, ok := c.world.DanceForms[id]; ok { + return fmt.Sprintf(`%s`, 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(`%s`, 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(`%s`, 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(`%s`, id, util.Title(x.Name())) + } + return "UNKNOWN WORLD CONSTRUCTION" +} + +func (c *context) writtenContent(id int) string { + if x, ok := c.world.WrittenContents[id]; ok { + return fmt.Sprintf(`%s`, id, util.Title(x.Name())) + } + return "UNKNOWN WORLD CONSTRUCTION" +} + +func (c *context) feature(x *Feature) string { + switch x.Type { + case FeatureType_DancePerformance: + return "a perfomance of " + c.danceForm(x.Reference) + case FeatureType_Images: + if x.Reference != -1 { + return "images of " + c.hf(x.Reference) + } + return "images" + case FeatureType_MusicalPerformance: + return "a perfomance of " + c.musicalForm(x.Reference) + case FeatureType_PoetryRecital: + return "a recital of " + c.poeticForm(x.Reference) + case FeatureType_Storytelling: + if x.Reference != -1 { + if e, ok := c.world.HistoricalEvents[x.Reference]; ok { + return "a telling of the story of " + e.Details.Html(&context{story: true}) + " in " + Time(e.Year, e.Seconds72) + } + } + return "a story recital" + default: + return strcase.ToDelimited(x.Type.String(), ' ') + } +} + +func (c *context) schedule(x *Schedule) string { + switch x.Type { + case ScheduleType_DancePerformance: + return "a perfomance of " + c.danceForm(x.Reference) + case ScheduleType_MusicalPerformance: + return "a perfomance of " + c.musicalForm(x.Reference) + case ScheduleType_PoetryRecital: + return "a recital of " + c.poeticForm(x.Reference) + case ScheduleType_Storytelling: + if x.Reference != -1 { + if e, ok := c.world.HistoricalEvents[x.Reference]; ok { + return "the story of " + e.Details.Html(&context{story: true}) + " in " + Time(e.Year, e.Seconds72) + } + } + return "a story recital" + default: + return strcase.ToDelimited(x.Type.String(), ' ') + } +} + +func (c *context) pronoun(id int) string { + if x, ok := c.world.HistoricalFigures[id]; ok { + return x.Pronoun() + } + return "he" +} + +func (c *context) posessivePronoun(id int) string { + if x, ok := c.world.HistoricalFigures[id]; ok { + return x.PossesivePronoun() + } + return "his" +} diff --git a/backend/model/eventList.go b/backend/model/eventList.go new file mode 100644 index 0000000..c153ada --- /dev/null +++ b/backend/model/eventList.go @@ -0,0 +1,49 @@ +package model + +import ( + "fmt" +) + +type HistoricalEventDetails interface { + RelatedToEntity(int) bool + RelatedToHf(int) bool + RelatedToArtifact(int) bool + RelatedToSite(int) bool + RelatedToRegion(int) bool + Html(*context) string + Type() string +} + +type HistoricalEventCollectionDetails interface { +} + +type EventList struct { + Events []*HistoricalEvent + Context *context +} + +func NewEventList(world *DfWorld, obj any) *EventList { + el := EventList{ + Context: &context{hfId: -1}, + } + + switch x := obj.(type) { + case *Entity: + el.Events = world.EventsMatching(func(d HistoricalEventDetails) bool { return d.RelatedToEntity(x.Id()) }) + case *HistoricalFigure: + el.Context.hfId = x.Id() + el.Events = world.EventsMatching(func(d HistoricalEventDetails) bool { return d.RelatedToHf(x.Id()) }) + case *Artifact: + el.Events = world.EventsMatching(func(d HistoricalEventDetails) bool { return d.RelatedToArtifact(x.Id()) }) + case *Site: + el.Events = world.EventsMatching(func(d HistoricalEventDetails) bool { return d.RelatedToSite(x.Id()) }) + case *Region: + el.Events = world.EventsMatching(func(d HistoricalEventDetails) bool { return d.RelatedToRegion(x.Id()) }) + case []*HistoricalEvent: + el.Events = x + default: + fmt.Printf("unknown type %T\n", obj) + } + + return &el +} diff --git a/backend/model/events.go b/backend/model/events.go index 919401b..c6970aa 100644 --- a/backend/model/events.go +++ b/backend/model/events.go @@ -9,42 +9,18 @@ import ( "github.com/robertjanetzko/LegendsBrowser2/backend/util" ) -func (x *Honor) Requirement() string { - var list []string - if x.RequiresAnyMeleeOrRangedSkill { - list = append(list, "attaining sufficent skill with a weapon or technique") - } - if x.RequiredSkill != HonorRequiredSkill_Unknown { - list = append(list, "attaining enough skill with the "+x.RequiredSkill.String()) - } - if x.RequiredBattles == 1 { - list = append(list, "serving in combat") - } - if x.RequiredBattles > 1 { - list = append(list, fmt.Sprintf("participating in %d battles", x.RequiredBattles)) - } - if x.RequiredYears >= 1 { - list = append(list, fmt.Sprintf("%d years of membership", x.RequiredYears)) - } - if x.RequiredKills >= 1 { - list = append(list, fmt.Sprintf("slaying %d enemies", x.RequiredKills)) - } - - return " after " + andList(list) -} - func (x *HistoricalEventAddHfEntityHonor) Html(c *context) string { - e := world.Entities[x.EntityId] + e := c.world.Entities[x.EntityId] h := e.Honor[x.HonorId] - return fmt.Sprintf("%s received the title %s of %s%s", c.hf(x.Hfid), h.Name(), entity(x.EntityId), h.Requirement()) + return fmt.Sprintf("%s received the title %s of %s%s", c.hf(x.Hfid), h.Name(), c.entity(x.EntityId), h.Requirement()) } func (x *HistoricalEventAddHfEntityLink) Html(c *context) string { h := c.hf(x.Hfid) - e := entity(x.CivId) + e := c.entity(x.CivId) - if c.Story { - return "the ascension of " + h + " to " + position(x.CivId, x.PositionId, x.Hfid) + " of " + e + if c.story { + return "the ascension of " + h + " to " + c.position(x.CivId, x.PositionId, x.Hfid) + " of " + e } if x.AppointerHfid != -1 { @@ -56,7 +32,7 @@ func (x *HistoricalEventAddHfEntityLink) Html(c *context) string { case HistoricalEventAddHfEntityLinkLink_Member: return h + " became a member of " + e case HistoricalEventAddHfEntityLinkLink_Position: - return h + " became " + position(x.CivId, x.PositionId, x.Hfid) + " of " + e + return h + " became " + c.position(x.CivId, x.PositionId, x.Hfid) + " of " + e case HistoricalEventAddHfEntityLinkLink_Prisoner: return h + " was imprisoned by " + e case HistoricalEventAddHfEntityLinkLink_Slave: @@ -96,13 +72,13 @@ func (x *HistoricalEventAddHfSiteLink) Html(c *context) string { h := c.hf(x.Histfig) e := "" if x.Civ != -1 { - e = " of " + entity(x.Civ) + e = " of " + c.entity(x.Civ) } b := "" if x.Structure != -1 { - b = " " + structure(x.SiteId, x.Structure) + b = " " + c.structure(x.SiteId, x.Structure) } - s := site(x.SiteId, "in") + s := c.site(x.SiteId, "in") switch x.LinkType { case HistoricalEventAddHfSiteLinkLinkType_HomeSiteAbstractBuilding: return h + " took up residence in " + b + e + " " + s @@ -125,7 +101,7 @@ func (x *HistoricalEventAgreementConcluded) Html(c *context) string { // TODO wo case HistoricalEventAgreementConcludedTopic_Treequota: r += "a lumber agreement" } - return r + " proposed by " + entity(x.Source) + " was concluded by " + entity(x.Destination) + site(x.Site, " at") + return r + " proposed by " + c.entity(x.Source) + " was concluded by " + c.entity(x.Destination) + c.site(x.Site, " at") } func (x *HistoricalEventAgreementFormed) Html(c *context) string { // TODO no info @@ -142,7 +118,7 @@ func (x *HistoricalEventAgreementMade) Html(c *context) string { case HistoricalEventAgreementMadeTopic_Treequota: r += "a lumber agreement" } - return r + " proposed by " + entity(x.Source) + " was accepted by " + entity(x.Destination) + site(x.SiteId, " at") + return r + " proposed by " + c.entity(x.Source) + " was accepted by " + c.entity(x.Destination) + c.site(x.SiteId, " at") } func (x *HistoricalEventAgreementRejected) Html(c *context) string { @@ -157,17 +133,17 @@ func (x *HistoricalEventAgreementRejected) Html(c *context) string { case HistoricalEventAgreementRejectedTopic_Unknown10: r += "a demand of unconditional surrender" } - return r + " proposed by " + entity(x.Source) + " was rejected by " + entity(x.Destination) + site(x.SiteId, " at") + return r + " proposed by " + c.entity(x.Source) + " was rejected by " + c.entity(x.Destination) + c.site(x.SiteId, " at") } func (x *HistoricalEventArtifactClaimFormed) Html(c *context) string { - a := artifact(x.ArtifactId) + a := c.artifact(x.ArtifactId) switch x.Claim { case HistoricalEventArtifactClaimFormedClaim_Heirloom: return a + " was made a family heirloom by " + c.hf(x.HistFigureId) case HistoricalEventArtifactClaimFormedClaim_Symbol: - p := world.Entities[x.EntityId].Position(x.PositionProfileId).Name_ - e := entity(x.EntityId) + p := c.world.Entities[x.EntityId].Position(x.PositionProfileId).Name_ + e := c.entity(x.EntityId) return a + " was made a symbol of the " + p + " by " + e case HistoricalEventArtifactClaimFormedClaim_Treasure: circumstance := "" @@ -177,7 +153,7 @@ func (x *HistoricalEventArtifactClaimFormed) Html(c *context) string { if x.HistFigureId != -1 { return a + " was claimed by " + c.hf(x.HistFigureId) + circumstance } else if x.EntityId != -1 { - return a + " was claimed by " + entity(x.EntityId) + circumstance + return a + " was claimed by " + c.entity(x.EntityId) + circumstance } } return a + " was claimed" @@ -186,16 +162,16 @@ func (x *HistoricalEventArtifactClaimFormed) Html(c *context) string { func (x *HistoricalEventArtifactCopied) Html(c *context) string { s := util.If(x.FromOriginal, "made a copy of the original", "aquired a copy of") return fmt.Sprintf("%s %s %s %s of %s, keeping it%s", - entity(x.DestEntityId), s, artifact(x.ArtifactId), siteStructure(x.SourceSiteId, x.SourceStructureId, "from"), - entity(x.SourceEntityId), siteStructure(x.DestSiteId, x.DestStructureId, "within")) + c.entity(x.DestEntityId), s, c.artifact(x.ArtifactId), c.siteStructure(x.SourceSiteId, x.SourceStructureId, "from"), + c.entity(x.SourceEntityId), c.siteStructure(x.DestSiteId, x.DestStructureId, "within")) } func (x *HistoricalEventArtifactCreated) Html(c *context) string { - a := artifact(x.ArtifactId) + a := c.artifact(x.ArtifactId) h := c.hf(x.HistFigureId) s := "" if x.SiteId != -1 { - s = site(x.SiteId, " in ") + s = c.site(x.SiteId, " in ") } if !x.NameOnly { return h + " created " + a + s @@ -220,18 +196,18 @@ func (x *HistoricalEventArtifactCreated) Html(c *context) string { } func (x *HistoricalEventArtifactDestroyed) Html(c *context) string { - return artifact(x.ArtifactId) + " was destroyed" + util.If(x.DestroyerEnid != -1, " by "+entity(x.DestroyerEnid), "") + site(x.SiteId, " in") + return c.artifact(x.ArtifactId) + " was destroyed" + util.If(x.DestroyerEnid != -1, " by "+c.entity(x.DestroyerEnid), "") + c.site(x.SiteId, " in") } func (x *HistoricalEventArtifactFound) Html(c *context) string { w := "" if x.SiteId != -1 { - w = site(x.SiteId, "") + w = c.site(x.SiteId, "") if x.SitePropertyId != -1 { - w = property(x.SiteId, x.SitePropertyId) + " in " + w + w = c.property(x.SiteId, x.SitePropertyId) + " in " + w } } - return fmt.Sprintf("%s was found in %s by %s", artifact(x.ArtifactId), w, util.If(x.HistFigureId != -1, c.hf(x.HistFigureId), "an unknown creature")) + return fmt.Sprintf("%s was found in %s by %s", c.artifact(x.ArtifactId), w, util.If(x.HistFigureId != -1, c.hf(x.HistFigureId), "an unknown creature")) } func (x *HistoricalEventArtifactGiven) Html(c *context) string { @@ -239,50 +215,50 @@ func (x *HistoricalEventArtifactGiven) Html(c *context) string { if x.ReceiverHistFigureId != -1 { r = c.hf(x.ReceiverHistFigureId) if x.ReceiverEntityId != -1 { - r += " of " + entity(x.ReceiverEntityId) + r += " of " + c.entity(x.ReceiverEntityId) } } else if x.ReceiverEntityId != -1 { - r += entity(x.ReceiverEntityId) + r += c.entity(x.ReceiverEntityId) } g := "" if x.GiverHistFigureId != -1 { g = c.hf(x.GiverHistFigureId) if x.GiverEntityId != -1 { - g += " of " + entity(x.GiverEntityId) + g += " of " + c.entity(x.GiverEntityId) } } else if x.GiverEntityId != -1 { - g += entity(x.GiverEntityId) + g += c.entity(x.GiverEntityId) } reason := "" switch x.Reason { case HistoricalEventArtifactGivenReason_PartOfTradeNegotiation: reason = " as part of a trade negotiation" } - return fmt.Sprintf("%s was offered to %s by %s%s", artifact(x.ArtifactId), r, g, reason) + return fmt.Sprintf("%s was offered to %s by %s%s", c.artifact(x.ArtifactId), r, g, reason) } func (x *HistoricalEventArtifactLost) Html(c *context) string { w := "" if x.SubregionId != -1 { - w = region(x.SubregionId) + w = c.region(x.SubregionId) } if x.SiteId != -1 { - w = site(x.SiteId, "") + w = c.site(x.SiteId, "") if x.SitePropertyId != -1 { - w = property(x.SiteId, x.SitePropertyId) + " in " + w + w = c.property(x.SiteId, x.SitePropertyId) + " in " + w } } - return fmt.Sprintf("%s was lost in %s", artifact(x.ArtifactId), w) + return fmt.Sprintf("%s was lost in %s", c.artifact(x.ArtifactId), w) } func (x *HistoricalEventArtifactPossessed) Html(c *context) string { - a := artifact(x.ArtifactId) + a := c.artifact(x.ArtifactId) h := c.hf(x.HistFigureId) w := "" if x.SubregionId != -1 { - w = region(x.SubregionId) + w = c.region(x.SubregionId) } if x.SiteId != -1 { - w = site(x.SiteId, "") + w = c.site(x.SiteId, "") } circumstance := "" switch x.Circumstance { @@ -294,22 +270,22 @@ func (x *HistoricalEventArtifactPossessed) Html(c *context) string { case HistoricalEventArtifactPossessedReason_ArtifactIsHeirloomOfFamilyHfid: return fmt.Sprintf("%s was aquired in %s by %s as an heirloom of %s%s", a, w, h, c.hf(x.ReasonId), circumstance) case HistoricalEventArtifactPossessedReason_ArtifactIsSymbolOfEntityPosition: - return fmt.Sprintf("%s was aquired in %s by %s as a symbol of authority within %s%s", a, w, h, entity(x.ReasonId), circumstance) + return fmt.Sprintf("%s was aquired in %s by %s as a symbol of authority within %s%s", a, w, h, c.entity(x.ReasonId), circumstance) } return fmt.Sprintf("%s was claimed in %s by %s%s", a, w, h, circumstance) // TODO wording } func (x *HistoricalEventArtifactRecovered) Html(c *context) string { - a := artifact(x.ArtifactId) + a := c.artifact(x.ArtifactId) h := c.hf(x.HistFigureId) w := "" if x.SubregionId != -1 { - w = "in " + region(x.SubregionId) + w = "in " + c.region(x.SubregionId) } if x.SiteId != -1 { - w = site(x.SiteId, "in ") + w = c.site(x.SiteId, "in ") if x.StructureId != -1 { - w = siteStructure(x.SiteId, x.StructureId, "from") + w = c.siteStructure(x.SiteId, x.StructureId, "from") } } return fmt.Sprintf("%s was recovered %s by %s", a, w, h) @@ -317,29 +293,29 @@ func (x *HistoricalEventArtifactRecovered) Html(c *context) string { func (x *HistoricalEventArtifactStored) Html(c *context) string { if x.HistFigureId != -1 { - return fmt.Sprintf("%s stored %s in %s", c.hf(x.HistFigureId), artifact(x.ArtifactId), site(x.SiteId, "")) + return fmt.Sprintf("%s stored %s in %s", c.hf(x.HistFigureId), c.artifact(x.ArtifactId), c.site(x.SiteId, "")) } else { - return fmt.Sprintf("%s was stored in %s", artifact(x.ArtifactId), site(x.SiteId, "")) + return fmt.Sprintf("%s was stored in %s", c.artifact(x.ArtifactId), c.site(x.SiteId, "")) } } func (x *HistoricalEventArtifactTransformed) Html(c *context) string { - return fmt.Sprintf("%s was made from %s by %s in %s", artifact(x.NewArtifactId), artifact(x.OldArtifactId), c.hf(x.HistFigureId), site(x.SiteId, "")) // TODO wording + return fmt.Sprintf("%s was made from %s by %s in %s", c.artifact(x.NewArtifactId), c.artifact(x.OldArtifactId), c.hf(x.HistFigureId), c.site(x.SiteId, "")) // TODO wording } func (x *HistoricalEventAssumeIdentity) Html(c *context) string { h := c.hf(x.TricksterHfid) - i := identity(x.IdentityId) + i := c.identity(x.IdentityId) if x.TargetEnid == -1 { return fmt.Sprintf(`%s assumed the identity "%s"`, h, i) } else { - return fmt.Sprintf(`%s fooled %s into believing %s was "%s"`, h, entity(x.TargetEnid), pronoun(x.TricksterHfid), i) + return fmt.Sprintf(`%s fooled %s into believing %s was "%s"`, h, c.entity(x.TargetEnid), c.pronoun(x.TricksterHfid), i) } } func (x *HistoricalEventAttackedSite) Html(c *context) string { - atk := entity(x.AttackerCivId) - def := siteCiv(x.SiteCivId, x.DefenderCivId) + atk := c.entity(x.AttackerCivId) + def := c.siteCiv(x.SiteCivId, x.DefenderCivId) generals := "" if x.AttackerGeneralHfid != -1 { generals += ". " + util.Capitalize(c.hf(x.AttackerGeneralHfid)) + " led the attack" @@ -349,18 +325,18 @@ func (x *HistoricalEventAttackedSite) Html(c *context) string { } mercs := "" if x.AttackerMercEnid != -1 { - mercs += fmt.Sprintf(". %s were hired by the attackers", entity(x.AttackerMercEnid)) + mercs += fmt.Sprintf(". %s were hired by the attackers", c.entity(x.AttackerMercEnid)) } if x.ASupportMercEnid != -1 { - mercs += fmt.Sprintf(". %s were hired as scouts by the attackers", entity(x.ASupportMercEnid)) + mercs += fmt.Sprintf(". %s were hired as scouts by the attackers", c.entity(x.ASupportMercEnid)) } if x.DefenderMercEnid != -1 { - mercs += fmt.Sprintf(". The defenders hired %s", entity(x.DefenderMercEnid)) + mercs += fmt.Sprintf(". The defenders hired %s", c.entity(x.DefenderMercEnid)) } if x.DSupportMercEnid != -1 { - mercs += fmt.Sprintf(". The defenders hired %s as scouts", entity(x.DSupportMercEnid)) + mercs += fmt.Sprintf(". The defenders hired %s as scouts", c.entity(x.DSupportMercEnid)) } - return fmt.Sprintf("%s attacked %s at %s%s%s", atk, def, site(x.SiteId, ""), generals, mercs) + return fmt.Sprintf("%s attacked %s at %s%s%s", atk, def, c.site(x.SiteId, ""), generals, mercs) } func (x *HistoricalEventBodyAbused) Html(c *context) string { @@ -368,15 +344,15 @@ func (x *HistoricalEventBodyAbused) Html(c *context) string { switch x.AbuseType { case HistoricalEventBodyAbusedAbuseType_Animated: - s += " animated" + util.If(x.Histfig != -1, " by "+c.hf(x.Histfig), "") + site(x.SiteId, " in ") + s += " animated" + util.If(x.Histfig != -1, " by "+c.hf(x.Histfig), "") + c.site(x.SiteId, " in ") case HistoricalEventBodyAbusedAbuseType_Flayed: - s += " flayed and the skin stretched over " + structure(x.SiteId, x.Structure) + " by " + entity(x.Civ) + site(x.SiteId, " in ") + s += " flayed and the skin stretched over " + c.structure(x.SiteId, x.Structure) + " by " + c.entity(x.Civ) + c.site(x.SiteId, " in ") case HistoricalEventBodyAbusedAbuseType_Hung: - s += " hung from a tree by " + entity(x.Civ) + site(x.SiteId, " in ") + s += " hung from a tree by " + c.entity(x.Civ) + c.site(x.SiteId, " in ") case HistoricalEventBodyAbusedAbuseType_Impaled: - s += " impaled on " + articled(x.ItemMat+" "+x.ItemSubtype.String()) + " by " + entity(x.Civ) + site(x.SiteId, " in ") + s += " impaled on " + articled(x.ItemMat+" "+x.ItemSubtype.String()) + " by " + c.entity(x.Civ) + c.site(x.SiteId, " in ") case HistoricalEventBodyAbusedAbuseType_Mutilated: - s += " horribly mutilated by " + entity(x.Civ) + site(x.SiteId, " in ") + s += " horribly mutilated by " + c.entity(x.Civ) + c.site(x.SiteId, " in ") case HistoricalEventBodyAbusedAbuseType_Piled: s += " added to a " switch x.PileType { @@ -387,27 +363,27 @@ func (x *HistoricalEventBodyAbused) Html(c *context) string { case HistoricalEventBodyAbusedPileType_Gruesomesculpture: s += "gruesome sculpture" } - s += " by " + entity(x.Civ) + site(x.SiteId, " in ") + s += " by " + c.entity(x.Civ) + c.site(x.SiteId, " in ") } return s } func (x *HistoricalEventBuildingProfileAcquired) Html(c *context) string { - return util.If(x.AcquirerEnid != -1, entity(x.AcquirerEnid), c.hf(x.AcquirerHfid)) + + return util.If(x.AcquirerEnid != -1, c.entity(x.AcquirerEnid), c.hf(x.AcquirerHfid)) + util.If(x.PurchasedUnowned, " purchased ", " inherited ") + - property(x.SiteId, x.BuildingProfileId) + site(x.SiteId, " in") + + c.property(x.SiteId, x.BuildingProfileId) + c.site(x.SiteId, " in") + util.If(x.LastOwnerHfid != -1, " formerly owned by "+c.hfRelated(x.LastOwnerHfid, x.AcquirerHfid), "") } func (x *HistoricalEventCeremony) Html(c *context) string { - r := entity(x.CivId) + " held a ceremony in " + site(x.SiteId, "") - if e, ok := world.Entities[x.CivId]; ok { + r := c.entity(x.CivId) + " held a ceremony in " + c.site(x.SiteId, "") + if e, ok := c.world.Entities[x.CivId]; ok { o := e.Occasion[x.OccasionId] r += " as part of " + o.Name() s := o.Schedule[x.ScheduleId] if len(s.Feature) > 0 { - r += ". The event featured " + andList(util.Map(s.Feature, feature)) + r += ". The event featured " + andList(util.Map(s.Feature, c.feature)) } } return r @@ -420,19 +396,19 @@ func (x *HistoricalEventChangeHfBodyState) Html(c *context) string { r += " was entombed" } if x.StructureId != -1 { - r += " within " + structure(x.SiteId, x.StructureId) + r += " within " + c.structure(x.SiteId, x.StructureId) } - r += site(x.SiteId, " in ") + r += c.site(x.SiteId, " in ") return r } func (x *HistoricalEventChangeHfJob) Html(c *context) string { w := "" if x.SubregionId != -1 { - w = " in " + region(x.SubregionId) + w = " in " + c.region(x.SubregionId) } if x.SiteId != -1 { - w = " in " + site(x.SiteId, "") + w = " in " + c.site(x.SiteId, "") } old := articled(strcase.ToDelimited(x.OldJob, ' ')) new := articled(strcase.ToDelimited(x.NewJob, ' ')) @@ -471,23 +447,23 @@ func (x *HistoricalEventChangeHfState) Html(c *context) string { switch x.State { case HistoricalEventChangeHfStateState_Refugee: - return c.hf(x.Hfid) + " fled " + location(x.SiteId, "to", x.SubregionId, "into") + return c.hf(x.Hfid) + " fled " + c.location(x.SiteId, "to", x.SubregionId, "into") case HistoricalEventChangeHfStateState_Settled: switch x.Reason { case HistoricalEventChangeHfStateReason_BeWithMaster, HistoricalEventChangeHfStateReason_Scholarship: - return c.hf(x.Hfid) + " moved to study " + site(x.SiteId, "in") + r + return c.hf(x.Hfid) + " moved to study " + c.site(x.SiteId, "in") + r case HistoricalEventChangeHfStateReason_Flight: - return c.hf(x.Hfid) + " fled " + site(x.SiteId, "to") + return c.hf(x.Hfid) + " fled " + c.site(x.SiteId, "to") case HistoricalEventChangeHfStateReason_ConvictionExile, HistoricalEventChangeHfStateReason_ExiledAfterConviction: - return c.hf(x.Hfid) + " departed " + site(x.SiteId, "to") + r + return c.hf(x.Hfid) + " departed " + c.site(x.SiteId, "to") + r case HistoricalEventChangeHfStateReason_None: - return c.hf(x.Hfid) + " settled " + location(x.SiteId, "in", x.SubregionId, "in") + return c.hf(x.Hfid) + " settled " + c.location(x.SiteId, "in", x.SubregionId, "in") } case HistoricalEventChangeHfStateState_Visiting: - return c.hf(x.Hfid) + " visited " + site(x.SiteId, "in") + r + return c.hf(x.Hfid) + " visited " + c.site(x.SiteId, "in") + r case HistoricalEventChangeHfStateState_Wandering: if x.SubregionId != -1 { - return c.hf(x.Hfid) + " began wandering " + region(x.SubregionId) + return c.hf(x.Hfid) + " began wandering " + c.region(x.SubregionId) } else { return c.hf(x.Hfid) + " began wandering the wilds" } @@ -495,23 +471,23 @@ func (x *HistoricalEventChangeHfState) Html(c *context) string { switch x.Mood { case HistoricalEventChangeHfStateMood_Berserk: - return c.hf(x.Hfid) + " went berserk " + site(x.SiteId, "in") + r + return c.hf(x.Hfid) + " went berserk " + c.site(x.SiteId, "in") + r case HistoricalEventChangeHfStateMood_Catatonic: - return c.hf(x.Hfid) + " stopped responding to the outside world " + site(x.SiteId, "in") + r + return c.hf(x.Hfid) + " stopped responding to the outside world " + c.site(x.SiteId, "in") + r case HistoricalEventChangeHfStateMood_Fell: - return c.hf(x.Hfid) + " was taken by a fell mood " + site(x.SiteId, "in") + r + return c.hf(x.Hfid) + " was taken by a fell mood " + c.site(x.SiteId, "in") + r case HistoricalEventChangeHfStateMood_Fey: - return c.hf(x.Hfid) + " was taken by a fey mood " + site(x.SiteId, "in") + r + return c.hf(x.Hfid) + " was taken by a fey mood " + c.site(x.SiteId, "in") + r case HistoricalEventChangeHfStateMood_Insane: - return c.hf(x.Hfid) + " became crazed " + site(x.SiteId, "in") + r + return c.hf(x.Hfid) + " became crazed " + c.site(x.SiteId, "in") + r case HistoricalEventChangeHfStateMood_Macabre: - return c.hf(x.Hfid) + " began to skulk and brood " + site(x.SiteId, "in") + r + return c.hf(x.Hfid) + " began to skulk and brood " + c.site(x.SiteId, "in") + r case HistoricalEventChangeHfStateMood_Melancholy: - return c.hf(x.Hfid) + " was striken by melancholy " + site(x.SiteId, "in") + r + return c.hf(x.Hfid) + " was striken by melancholy " + c.site(x.SiteId, "in") + r case HistoricalEventChangeHfStateMood_Possessed: - return c.hf(x.Hfid) + " was posessed " + site(x.SiteId, "in") + r + return c.hf(x.Hfid) + " was posessed " + c.site(x.SiteId, "in") + r case HistoricalEventChangeHfStateMood_Secretive: - return c.hf(x.Hfid) + " withdrew from society " + site(x.SiteId, "in") + r + return c.hf(x.Hfid) + " withdrew from society " + c.site(x.SiteId, "in") + r } return "UNKNWON HistoricalEventChangeHfState" } @@ -521,18 +497,18 @@ func (x *HistoricalEventChangedCreatureType) Html(c *context) string { } func (x *HistoricalEventCompetition) Html(c *context) string { - e := world.Entities[x.CivId] + e := c.world.Entities[x.CivId] o := e.Occasion[x.OccasionId] s := o.Schedule[x.ScheduleId] - return entity(x.CivId) + " held a " + strcase.ToDelimited(s.Type.String(), ' ') + site(x.SiteId, " in") + " as part of the " + o.Name() + + return c.entity(x.CivId) + " held a " + strcase.ToDelimited(s.Type.String(), ' ') + c.site(x.SiteId, " in") + " as part of the " + o.Name() + ". Competing " + util.If(len(x.CompetitorHfid) > 1, "were ", "was ") + c.hfList(x.CompetitorHfid) + ". " + util.Capitalize(c.hf(x.WinnerHfid)) + " was the victor" } func (x *HistoricalEventCreateEntityPosition) Html(c *context) string { - e := entity(x.Civ) + e := c.entity(x.Civ) if x.SiteCiv != x.Civ { - e = entity(x.SiteCiv) + " of " + e + e = c.entity(x.SiteCiv) + " of " + e } if x.Histfig != -1 { e = c.hf(x.Histfig) + " of " + e @@ -555,32 +531,32 @@ func (x *HistoricalEventCreateEntityPosition) Html(c *context) string { } func (x *HistoricalEventCreatedSite) Html(c *context) string { - f := util.If(x.ResidentCivId != -1, " for "+entity(x.ResidentCivId), "") + f := util.If(x.ResidentCivId != -1, " for "+c.entity(x.ResidentCivId), "") if x.BuilderHfid != -1 { - return c.hf(x.BuilderHfid) + " created " + site(x.SiteId, "") + f + return c.hf(x.BuilderHfid) + " created " + c.site(x.SiteId, "") + f } - return siteCiv(x.SiteCivId, x.CivId) + " founded " + site(x.SiteId, "") + f + return c.siteCiv(x.SiteCivId, x.CivId) + " founded " + c.site(x.SiteId, "") + f } func (x *HistoricalEventCreatedStructure) Html(c *context) string { // TODO rebuild/rebuilt if x.BuilderHfid != -1 { - return c.hf(x.BuilderHfid) + " thrust a spire of slade up from the underworld, naming it " + structure(x.SiteId, x.StructureId) + - ", and established a gateway between worlds in " + site(x.SiteId, "") + return c.hf(x.BuilderHfid) + " thrust a spire of slade up from the underworld, naming it " + c.structure(x.SiteId, x.StructureId) + + ", and established a gateway between worlds in " + c.site(x.SiteId, "") } - return siteCiv(x.SiteCivId, x.CivId) + util.If(x.Rebuilt, " rebuild ", " constructed ") + siteStructure(x.SiteId, x.StructureId, "") + return c.siteCiv(x.SiteCivId, x.CivId) + util.If(x.Rebuilt, " rebuild ", " constructed ") + c.siteStructure(x.SiteId, x.StructureId, "") } func (x *HistoricalEventCreatedWorldConstruction) Html(c *context) string { - return siteCiv(x.SiteCivId, x.CivId) + " finished the contruction of " + worldConstruction(x.Wcid) + - " connecting " + site(x.SiteId1, "") + " with " + site(x.SiteId2, "") + - util.If(x.MasterWcid != -1, " as part of "+worldConstruction(x.MasterWcid), "") + return c.siteCiv(x.SiteCivId, x.CivId) + " finished the contruction of " + c.worldConstruction(x.Wcid) + + " connecting " + c.site(x.SiteId1, "") + " with " + c.site(x.SiteId2, "") + + util.If(x.MasterWcid != -1, " as part of "+c.worldConstruction(x.MasterWcid), "") } func (x *HistoricalEventCreatureDevoured) Html(c *context) string { return c.hf(x.Eater) + " devoured " + util.If(x.Victim != -1, c.hfRelated(x.Victim, x.Eater), articled(x.Race)) + - util.If(x.Entity != -1, " of "+entity(x.Entity), "") + - location(x.SiteId, " in", x.SubregionId, " in") + util.If(x.Entity != -1, " of "+c.entity(x.Entity), "") + + c.location(x.SiteId, " in", x.SubregionId, " in") } func (x *HistoricalEventDanceFormCreated) Html(c *context) string { @@ -600,69 +576,69 @@ func (x *HistoricalEventDanceFormCreated) Html(c *context) string { case HistoricalEventDanceFormCreatedCircumstance_PrayToHf: circumstance = " after praying to " + util.If(x.ReasonId == x.CircumstanceId, c.hfShort(x.CircumstanceId), c.hfRelated(x.CircumstanceId, x.HistFigureId)) } - return danceForm(x.FormId) + " was created by " + c.hf(x.HistFigureId) + location(x.SiteId, " in", x.SubregionId, " in") + reason + circumstance + return c.danceForm(x.FormId) + " was created by " + c.hf(x.HistFigureId) + c.location(x.SiteId, " in", x.SubregionId, " in") + reason + circumstance } func (x *HistoricalEventDestroyedSite) Html(c *context) string { - return entity(x.AttackerCivId) + " defeated " + siteCiv(x.SiteCivId, x.DefenderCivId) + " and destroyed " + site(x.SiteId, "") + return c.entity(x.AttackerCivId) + " defeated " + c.siteCiv(x.SiteCivId, x.DefenderCivId) + " and destroyed " + c.site(x.SiteId, "") } func (x *HistoricalEventDiplomatLost) Html(c *context) string { - return entity(x.Entity) + " lost a diplomant in " + site(x.SiteId, "") + ". They suspected the involvement of " + entity(x.Involved) + return c.entity(x.Entity) + " lost a diplomant in " + c.site(x.SiteId, "") + ". They suspected the involvement of " + c.entity(x.Involved) } func (x *HistoricalEventEntityAllianceFormed) Html(c *context) string { - return entityList(x.JoiningEnid) + " swore to support " + entity(x.InitiatingEnid) + " in war if the latter did likewise" + return c.entityList(x.JoiningEnid) + " swore to support " + c.entity(x.InitiatingEnid) + " in war if the latter did likewise" } func (x *HistoricalEventEntityBreachFeatureLayer) Html(c *context) string { - return siteCiv(x.SiteEntityId, x.CivEntityId) + " breached the Underworld at " + site(x.SiteId, "") + return c.siteCiv(x.SiteEntityId, x.CivEntityId) + " breached the Underworld at " + c.site(x.SiteId, "") } func (x *HistoricalEventEntityCreated) Html(c *context) string { if x.CreatorHfid != -1 { - return c.hf(x.CreatorHfid) + " formed " + entity(x.EntityId) + siteStructure(x.SiteId, x.StructureId, "in") + return c.hf(x.CreatorHfid) + " formed " + c.entity(x.EntityId) + c.siteStructure(x.SiteId, x.StructureId, "in") } else { - return entity(x.EntityId) + " formed" + siteStructure(x.SiteId, x.StructureId, "in") + return c.entity(x.EntityId) + " formed" + c.siteStructure(x.SiteId, x.StructureId, "in") } } func (x *HistoricalEventEntityDissolved) Html(c *context) string { - return entity(x.EntityId) + " dissolved after " + x.Reason.String() + return c.entity(x.EntityId) + " dissolved after " + x.Reason.String() } func (x *HistoricalEventEntityEquipmentPurchase) Html(c *context) string { // todo check hfid - return entity(x.EntityId) + " purchased " + equipmentLevel(x.NewEquipmentLevel) + " equipment" + return c.entity(x.EntityId) + " purchased " + equipmentLevel(x.NewEquipmentLevel) + " equipment" } func (x *HistoricalEventEntityExpelsHf) Html(c *context) string { - return entity(x.EntityId) + " expelled " + c.hf(x.Hfid) + site(x.SiteId, " from") + return c.entity(x.EntityId) + " expelled " + c.hf(x.Hfid) + c.site(x.SiteId, " from") } func (x *HistoricalEventEntityFledSite) Html(c *context) string { - return entity(x.FledCivId) + " fled " + site(x.SiteId, "") + return c.entity(x.FledCivId) + " fled " + c.site(x.SiteId, "") } func (x *HistoricalEventEntityIncorporated) Html(c *context) string { // TODO site - return entity(x.JoinerEntityId) + util.If(x.PartialIncorporation, " began operating at the direction of ", " fully incorporated into ") + - entity(x.JoinedEntityId) + " under the leadership of " + c.hf(x.LeaderHfid) + return c.entity(x.JoinerEntityId) + util.If(x.PartialIncorporation, " began operating at the direction of ", " fully incorporated into ") + + c.entity(x.JoinedEntityId) + " under the leadership of " + c.hf(x.LeaderHfid) } func (x *HistoricalEventEntityLaw) Html(c *context) string { switch x.LawAdd { case HistoricalEventEntityLawLawAdd_Harsh: - return c.hf(x.HistFigureId) + " laid a series of oppressive edicts upon " + entity(x.EntityId) + return c.hf(x.HistFigureId) + " laid a series of oppressive edicts upon " + c.entity(x.EntityId) } switch x.LawRemove { case HistoricalEventEntityLawLawRemove_Harsh: - return c.hf(x.HistFigureId) + " lifted numerous oppressive laws from " + entity(x.EntityId) + return c.hf(x.HistFigureId) + " lifted numerous oppressive laws from " + c.entity(x.EntityId) } - return c.hf(x.HistFigureId) + " UNKNOWN LAW upon " + entity(x.EntityId) + return c.hf(x.HistFigureId) + " UNKNOWN LAW upon " + c.entity(x.EntityId) } func (x *HistoricalEventEntityOverthrown) Html(c *context) string { - return c.hf(x.InstigatorHfid) + " toppled the government of " + util.If(x.OverthrownHfid != -1, c.hfRelated(x.OverthrownHfid, x.InstigatorHfid)+" of ", "") + entity(x.EntityId) + " and " + - util.If(x.PosTakerHfid == x.InstigatorHfid, "assumed control", "placed "+c.hfRelated(x.PosTakerHfid, x.InstigatorHfid)+" in power") + site(x.SiteId, " in") + + return c.hf(x.InstigatorHfid) + " toppled the government of " + util.If(x.OverthrownHfid != -1, c.hfRelated(x.OverthrownHfid, x.InstigatorHfid)+" of ", "") + c.entity(x.EntityId) + " and " + + util.If(x.PosTakerHfid == x.InstigatorHfid, "assumed control", "placed "+c.hfRelated(x.PosTakerHfid, x.InstigatorHfid)+" in power") + c.site(x.SiteId, " in") + util.If(len(x.ConspiratorHfid) > 0, ". The support of "+c.hfListRelated(x.ConspiratorHfid, x.InstigatorHfid)+" was crucial to the coup", "") } @@ -675,35 +651,35 @@ func (x *HistoricalEventEntityPersecuted) Html(c *context) string { l = append(l, "most property was confiscated") } if x.DestroyedStructureId != -1 { - l = append(l, structure(x.SiteId, x.DestroyedStructureId)+" was destroyed"+util.If(x.ShrineAmountDestroyed > 0, " along with several smaller sacred sites", "")) + l = append(l, c.structure(x.SiteId, x.DestroyedStructureId)+" was destroyed"+util.If(x.ShrineAmountDestroyed > 0, " along with several smaller sacred sites", "")) } else if x.ShrineAmountDestroyed > 0 { l = append(l, "some sacred sites were desecrated") } - return c.hf(x.PersecutorHfid) + " of " + entity(x.PersecutorEnid) + " persecuted " + entity(x.TargetEnid) + " in " + site(x.SiteId, "") + + return c.hf(x.PersecutorHfid) + " of " + c.entity(x.PersecutorEnid) + " persecuted " + c.entity(x.TargetEnid) + " in " + c.site(x.SiteId, "") + util.If(len(l) > 0, ". "+util.Capitalize(andList(l)), "") } func (x *HistoricalEventEntityPrimaryCriminals) Html(c *context) string { // TODO structure - return entity(x.EntityId) + " became the primary criminal organization in " + site(x.SiteId, "") + return c.entity(x.EntityId) + " became the primary criminal organization in " + c.site(x.SiteId, "") } func (x *HistoricalEventEntityRampagedInSite) Html(c *context) string { - return "the forces of " + entity(x.RampageCivId) + " rampaged throughout " + site(x.SiteId, "") + return "the forces of " + c.entity(x.RampageCivId) + " rampaged throughout " + c.site(x.SiteId, "") } func (x *HistoricalEventEntityRelocate) Html(c *context) string { - return entity(x.EntityId) + " moved" + siteStructure(x.SiteId, x.StructureId, "to") + return c.entity(x.EntityId) + " moved" + c.siteStructure(x.SiteId, x.StructureId, "to") } func (x *HistoricalEventEntitySearchedSite) Html(c *context) string { - return entity(x.SearcherCivId) + " searched " + site(x.SiteId, "") + + return c.entity(x.SearcherCivId) + " searched " + c.site(x.SiteId, "") + util.If(x.Result == HistoricalEventEntitySearchedSiteResult_FoundNothing, " and found nothing", "") } func (x *HistoricalEventFailedFrameAttempt) Html(c *context) string { return c.hf(x.FramerHfid) + " attempted to frame " + c.hfRelated(x.TargetHfid, x.FramerHfid) + " for " + x.Crime.String() + util.If(x.PlotterHfid != -1, " at the behest of "+c.hfRelated(x.PlotterHfid, x.FramerHfid), "") + - " by fooling " + c.hfRelated(x.FooledHfid, x.FramerHfid) + " and " + entity(x.ConvicterEnid) + + " by fooling " + c.hfRelated(x.FooledHfid, x.FramerHfid) + " and " + c.entity(x.ConvicterEnid) + " with fabricated evidence, but nothing came of it" } @@ -722,7 +698,7 @@ func (x *HistoricalEventFailedIntrigueCorruption) Html(c *context) string { method := "" switch x.Method { case HistoricalEventFailedIntrigueCorruptionMethod_BlackmailOverEmbezzlement: - method = "made a blackmail threat, due to embezzlement using the position " + position(x.RelevantEntityId, x.RelevantPositionProfileId, x.CorruptorHfid) + " of " + entity(x.RelevantEntityId) + method = "made a blackmail threat, due to embezzlement using the position " + c.position(x.RelevantEntityId, x.RelevantPositionProfileId, x.CorruptorHfid) + " of " + c.entity(x.RelevantEntityId) case HistoricalEventFailedIntrigueCorruptionMethod_Bribe: method = "offered a bribe" case HistoricalEventFailedIntrigueCorruptionMethod_Flatter: @@ -732,7 +708,7 @@ func (x *HistoricalEventFailedIntrigueCorruption) Html(c *context) string { case HistoricalEventFailedIntrigueCorruptionMethod_OfferImmortality: method = "offered immortality" case HistoricalEventFailedIntrigueCorruptionMethod_Precedence: - method = "pulled rank as " + position(x.RelevantEntityId, x.RelevantPositionProfileId, x.CorruptorHfid) + " of " + entity(x.RelevantEntityId) + method = "pulled rank as " + c.position(x.RelevantEntityId, x.RelevantPositionProfileId, x.CorruptorHfid) + " of " + c.entity(x.RelevantEntityId) case HistoricalEventFailedIntrigueCorruptionMethod_ReligiousSympathy: method = "played for sympathy" + util.If(x.RelevantIdForMethod != -1, " by appealing to shared worship of "+c.hfRelated(x.RelevantIdForMethod, x.CorruptorHfid), "") case HistoricalEventFailedIntrigueCorruptionMethod_RevengeOnGrudge: @@ -761,7 +737,7 @@ func (x *HistoricalEventFailedIntrigueCorruption) Html(c *context) string { case HistoricalEventFailedIntrigueCorruptionTopFacet_Vengeful: } return c.hf(x.CorruptorHfid) + " attempted to corrupt " + c.hfRelated(x.TargetHfid, x.CorruptorHfid) + - " in order to " + action + location(x.SiteId, " in", x.SubregionId, " in") + ". " + + " in order to " + action + c.location(x.SiteId, " in", x.SubregionId, " in") + ". " + util.Capitalize(util.If(x.LureHfid != -1, c.hfRelated(x.LureHfid, x.CorruptorHfid)+" lured "+c.hfShort(x.TargetHfid)+" to a meeting with "+c.hfShort(x.CorruptorHfid)+", where the latter", c.hfShort(x.CorruptorHfid)+" met with "+c.hfShort(x.TargetHfid))) + @@ -769,8 +745,8 @@ func (x *HistoricalEventFailedIntrigueCorruption) Html(c *context) string { } func (x *HistoricalEventFieldBattle) Html(c *context) string { - atk := entity(x.AttackerCivId) - def := entity(x.DefenderCivId) + atk := c.entity(x.AttackerCivId) + def := c.entity(x.DefenderCivId) generals := "" if x.AttackerGeneralHfid != -1 { generals += ". " + util.Capitalize(c.hf(x.AttackerGeneralHfid)) + " led the attack" @@ -780,22 +756,22 @@ func (x *HistoricalEventFieldBattle) Html(c *context) string { } mercs := "" if x.AttackerMercEnid != -1 { - mercs += fmt.Sprintf(". %s were hired by the attackers", entity(x.AttackerMercEnid)) + mercs += fmt.Sprintf(". %s were hired by the attackers", c.entity(x.AttackerMercEnid)) } if x.ASupportMercEnid != -1 { - mercs += fmt.Sprintf(". %s were hired as scouts by the attackers", entity(x.ASupportMercEnid)) + mercs += fmt.Sprintf(". %s were hired as scouts by the attackers", c.entity(x.ASupportMercEnid)) } if x.DefenderMercEnid != -1 { - mercs += fmt.Sprintf(". The defenders hired %s", entity(x.DefenderMercEnid)) + mercs += fmt.Sprintf(". The defenders hired %s", c.entity(x.DefenderMercEnid)) } if x.DSupportMercEnid != -1 { - mercs += fmt.Sprintf(". The defenders hired %s as scouts", entity(x.DSupportMercEnid)) + mercs += fmt.Sprintf(". The defenders hired %s as scouts", c.entity(x.DSupportMercEnid)) } - return fmt.Sprintf("%s attacked %s at %s%s%s", atk, def, region(x.SubregionId), generals, mercs) + return fmt.Sprintf("%s attacked %s at %s%s%s", atk, def, c.region(x.SubregionId), generals, mercs) } func (x *HistoricalEventFirstContact) Html(c *context) string { - return entity(x.ContactorEnid) + " made contact with " + entity(x.ContactedEnid) + site(x.SiteId, " at") + return c.entity(x.ContactorEnid) + " made contact with " + c.entity(x.ContactedEnid) + c.site(x.SiteId, " at") } func (x *HistoricalEventGamble) Html(c *context) string { @@ -810,20 +786,20 @@ func (x *HistoricalEventGamble) Html(c *context) string { case d <= 5000: outcome = "made a fortune" } - return c.hf(x.GamblerHfid) + " " + outcome + " gambling" + siteStructure(x.SiteId, x.StructureId, " in") + + return c.hf(x.GamblerHfid) + " " + outcome + " gambling" + c.siteStructure(x.SiteId, x.StructureId, " in") + util.If(x.OldAccount >= 0 && x.NewAccount < 0, " and went into debt", "") } func (x *HistoricalEventHfAbducted) Html(c *context) string { - return c.hf(x.TargetHfid) + " was abducted " + location(x.SiteId, "from", x.SubregionId, "from") + " by " + c.hfRelated(x.SnatcherHfid, x.TargetHfid) + return c.hf(x.TargetHfid) + " was abducted " + c.location(x.SiteId, "from", x.SubregionId, "from") + " by " + c.hfRelated(x.SnatcherHfid, x.TargetHfid) } func (x *HistoricalEventHfAttackedSite) Html(c *context) string { - return c.hf(x.AttackerHfid) + " attacked " + siteCiv(x.SiteCivId, x.DefenderCivId) + site(x.SiteId, " in") + return c.hf(x.AttackerHfid) + " attacked " + c.siteCiv(x.SiteCivId, x.DefenderCivId) + c.site(x.SiteId, " in") } func (x *HistoricalEventHfConfronted) Html(c *context) string { - return c.hf(x.Hfid) + " aroused " + x.Situation.String() + location(x.SiteId, " in", x.SubregionId, " in") + " after " + + return c.hf(x.Hfid) + " aroused " + x.Situation.String() + c.location(x.SiteId, " in", x.SubregionId, " in") + " after " + andList(util.Map(x.Reason, func(r HistoricalEventHfConfrontedReason) string { switch r { case HistoricalEventHfConfrontedReason_Ageless: @@ -834,6 +810,7 @@ func (x *HistoricalEventHfConfronted) Html(c *context) string { return "" })) } + func (x *HistoricalEventHfConvicted) Html(c *context) string { // TODO no_prison_available, interrogator_hfid r := util.If(x.ConfessedAfterApbArrestEnid != -1, "after being recognized and arrested, ", "") switch { @@ -847,7 +824,7 @@ func (x *HistoricalEventHfConvicted) Html(c *context) string { // TODO no_prison r += "due to ongoing surveillance on the target " + c.hfRelated(x.TargetHfid, x.ConvictedHfid) + " as the plot unfolded, " } r += c.hf(x.ConvictedHfid) + util.If(x.ConfessedAfterApbArrestEnid != -1, " confessed and", "") + " was " + util.If(x.WrongfulConviction, "wrongfully ", "") + "convicted " + - util.If(x.ConvictIsContact, "as a go-between in a conspiracy to commit ", "of ") + x.Crime.String() + " by " + entity(x.ConvicterEnid) + util.If(x.ConvictIsContact, "as a go-between in a conspiracy to commit ", "of ") + x.Crime.String() + " by " + c.entity(x.ConvicterEnid) if x.FooledHfid != -1 { r += " after " + c.hfRelated(x.FramerHfid, x.ConvictedHfid) + " fooled " + c.hfRelated(x.FooledHfid, x.ConvictedHfid) + " with fabricated evidence" + util.If(x.PlotterHfid != -1, " at the behest of "+c.hfRelated(x.PlotterHfid, x.ConvictedHfid), "") @@ -893,19 +870,19 @@ func (x *HistoricalEventHfConvicted) Html(c *context) string { // TODO no_prison } func (x *HistoricalEventHfDestroyedSite) Html(c *context) string { - return c.hf(x.AttackerHfid) + " routed " + siteCiv(x.SiteCivId, x.DefenderCivId) + " and destroyed " + site(x.SiteId, "") + return c.hf(x.AttackerHfid) + " routed " + c.siteCiv(x.SiteCivId, x.DefenderCivId) + " and destroyed " + c.site(x.SiteId, "") } func (x *HistoricalEventHfDied) Html(c *context) string { hf := c.hf(x.Hfid) - loc := location(x.SiteId, " in", x.SubregionId, " in") + loc := c.location(x.SiteId, " in", x.SubregionId, " in") slayer := "" if x.SlayerHfid != -1 { slayer = " by " + c.hfRelated(x.SlayerHfid, x.Hfid) } if x.SlayerItemId != -1 { - slayer += " with " + artifact(x.SlayerItemId) + slayer += " with " + c.artifact(x.SlayerItemId) } else { } switch x.Cause { @@ -971,7 +948,7 @@ func (x *HistoricalEventHfDied) Html(c *context) string { case HistoricalEventHfDiedCause_Suffocate, HistoricalEventHfDiedCause_Air: return hf + " suffocated, slain by " + slayer + loc case HistoricalEventHfDiedCause_SuicideDrowned, HistoricalEventHfDiedCause_DrownAltTwo: - return hf + " drowned " + util.If(world.HistoricalFigures[x.Hfid].Female(), "herself ", "himself ") + loc + return hf + " drowned " + util.If(c.world.HistoricalFigures[x.Hfid].Female(), "herself ", "himself ") + loc case HistoricalEventHfDiedCause_SuicideLeaping, HistoricalEventHfDiedCause_LeaptFromHeight: return hf + " leapt from a great height" + loc case HistoricalEventHfDiedCause_Thirst: @@ -984,20 +961,20 @@ func (x *HistoricalEventHfDied) Html(c *context) string { } func (x *HistoricalEventHfDisturbedStructure) Html(c *context) string { - return c.hf(x.HistFigId) + " disturbed " + siteStructure(x.SiteId, x.StructureId, "") + return c.hf(x.HistFigId) + " disturbed " + c.siteStructure(x.SiteId, x.StructureId, "") } func (x *HistoricalEventHfDoesInteraction) Html(c *context) string { // TODO ignore source i := strings.Index(x.InteractionAction, " ") if i > 0 { - return c.hf(x.DoerHfid) + " " + x.InteractionAction[:i+1] + c.hfRelated(x.TargetHfid, x.DoerHfid) + x.InteractionAction[i:] + util.If(x.Site != -1, site(x.Site, " in"), "") + return c.hf(x.DoerHfid) + " " + x.InteractionAction[:i+1] + c.hfRelated(x.TargetHfid, x.DoerHfid) + x.InteractionAction[i:] + util.If(x.Site != -1, c.site(x.Site, " in"), "") } else { - return c.hf(x.DoerHfid) + " UNKNOWN INTERACTION " + c.hfRelated(x.TargetHfid, x.DoerHfid) + util.If(x.Site != -1, site(x.Site, " in"), "") + return c.hf(x.DoerHfid) + " UNKNOWN INTERACTION " + c.hfRelated(x.TargetHfid, x.DoerHfid) + util.If(x.Site != -1, c.site(x.Site, " in"), "") } } func (x *HistoricalEventHfEnslaved) Html(c *context) string { - return c.hf(x.SellerHfid) + " sold " + c.hfRelated(x.EnslavedHfid, x.SellerHfid) + " to " + entity(x.PayerEntityId) + site(x.MovedToSiteId, " in") + return c.hf(x.SellerHfid) + " sold " + c.hfRelated(x.EnslavedHfid, x.SellerHfid) + " to " + c.entity(x.PayerEntityId) + c.site(x.MovedToSiteId, " in") } func (x *HistoricalEventHfEquipmentPurchase) Html(c *context) string { // TODO site, structure, region @@ -1005,39 +982,39 @@ func (x *HistoricalEventHfEquipmentPurchase) Html(c *context) string { // TODO s } func (x *HistoricalEventHfFreed) Html(c *context) string { - return util.If(x.FreeingHfid != -1, c.hf(x.FreeingHfid), "the forces") + " of " + entity(x.FreeingCivId) + " freed " + c.hfList(x.RescuedHfid) + - site(x.SiteId, " from") + " and " + siteCiv(x.SiteCivId, x.HoldingCivId) + return util.If(x.FreeingHfid != -1, c.hf(x.FreeingHfid), "the forces") + " of " + c.entity(x.FreeingCivId) + " freed " + c.hfList(x.RescuedHfid) + + c.site(x.SiteId, " from") + " and " + c.siteCiv(x.SiteCivId, x.HoldingCivId) } func (x *HistoricalEventHfGainsSecretGoal) Html(c *context) string { switch x.SecretGoal { case HistoricalEventHfGainsSecretGoalSecretGoal_Immortality: - return c.hf(x.Hfid) + " became obsessed with " + posessivePronoun(x.Hfid) + " own mortality and sought to extend " + posessivePronoun(x.Hfid) + " life by any means" + return c.hf(x.Hfid) + " became obsessed with " + c.posessivePronoun(x.Hfid) + " own mortality and sought to extend " + c.posessivePronoun(x.Hfid) + " life by any means" } return c.hf(x.Hfid) + " UNKNOWN SECRET GOAL" } func (x *HistoricalEventHfInterrogated) Html(c *context) string { // TODO wanted_and_recognized, held_firm_in_interrogation, implicated_hfid - return c.hf(x.TargetHfid) + " was recognized and arrested by " + entity(x.ArrestingEnid) + + return c.hf(x.TargetHfid) + " was recognized and arrested by " + c.entity(x.ArrestingEnid) + ". Despite the interrogation by " + c.hfRelated(x.InterrogatorHfid, x.TargetHfid) + ", " + c.hfShort(x.TargetHfid) + " refused to reveal anything and was released" } func (x *HistoricalEventHfLearnsSecret) Html(c *context) string { if x.ArtifactId != -1 { - return c.hf(x.StudentHfid) + " learned " + x.SecretText.String() + " from " + artifact(x.ArtifactId) + return c.hf(x.StudentHfid) + " learned " + x.SecretText.String() + " from " + c.artifact(x.ArtifactId) } else { return c.hf(x.TeacherHfid) + " taught " + c.hfRelated(x.StudentHfid, x.TeacherHfid) + " " + x.SecretText.String() } } func (x *HistoricalEventHfNewPet) Html(c *context) string { - return c.hf(x.GroupHfid) + " tamed " + articled(x.Pets) + location(x.SiteId, " of", x.SubregionId, " of") + return c.hf(x.GroupHfid) + " tamed " + articled(x.Pets) + c.location(x.SiteId, " of", x.SubregionId, " of") } func (x *HistoricalEventHfPerformedHorribleExperiments) Html(c *context) string { - return c.hf(x.GroupHfid) + " performed horrible experiments " + place(x.StructureId, x.SiteId, " in", x.SubregionId, " in") + return c.hf(x.GroupHfid) + " performed horrible experiments " + c.place(x.StructureId, x.SiteId, " in", x.SubregionId, " in") } func (x *HistoricalEventHfPrayedInsideStructure) Html(c *context) string { - return c.hf(x.HistFigId) + " prayed " + siteStructure(x.SiteId, x.StructureId, "inside") + return c.hf(x.HistFigId) + " prayed " + c.siteStructure(x.SiteId, x.StructureId, "inside") } func (x *HistoricalEventHfPreach) Html(c *context) string { // relevant site @@ -1048,25 +1025,25 @@ func (x *HistoricalEventHfPreach) Html(c *context) string { // relevant site case HistoricalEventHfPreachTopic_SetEntity1AgainstEntityTwo: topic = ", inveighing against " } - return c.hf(x.SpeakerHfid) + " preached to " + entity(x.Entity1) + topic + entity(x.Entity2) + site(x.SiteHfid, " in") + return c.hf(x.SpeakerHfid) + " preached to " + c.entity(x.Entity1) + topic + c.entity(x.Entity2) + c.site(x.SiteHfid, " in") } func (x *HistoricalEventHfProfanedStructure) Html(c *context) string { - return c.hf(x.HistFigId) + " profaned " + siteStructure(x.SiteId, x.StructureId, "") + return c.hf(x.HistFigId) + " profaned " + c.siteStructure(x.SiteId, x.StructureId, "") } func (x *HistoricalEventHfRansomed) Html(c *context) string { - return c.hf(x.RansomerHfid) + " ransomed " + c.hfRelated(x.RansomedHfid, x.RansomerHfid) + " to " + util.If(x.PayerHfid != -1, c.hfRelated(x.PayerHfid, x.RansomerHfid), entity(x.PayerEntityId)) + - ". " + c.hfShort(x.RansomedHfid) + " was sent " + site(x.MovedToSiteId, "to") + return c.hf(x.RansomerHfid) + " ransomed " + c.hfRelated(x.RansomedHfid, x.RansomerHfid) + " to " + util.If(x.PayerHfid != -1, c.hfRelated(x.PayerHfid, x.RansomerHfid), c.entity(x.PayerEntityId)) + + ". " + c.hfShort(x.RansomedHfid) + " was sent " + c.site(x.MovedToSiteId, "to") } func (x *HistoricalEventHfReachSummit) Html(c *context) string { - id, _, _ := util.FindInMap(world.MountainPeaks, func(m *MountainPeak) bool { return m.Coords == x.Coords }) - return c.hfList(x.GroupHfid) + util.If(len(x.GroupHfid) > 1, " were", " was") + " the first to reach the summit of " + mountain(id) + " which rises above " + region(x.SubregionId) + id, _, _ := util.FindInMap(c.world.MountainPeaks, func(m *MountainPeak) bool { return m.Coords == x.Coords }) + return c.hfList(x.GroupHfid) + util.If(len(x.GroupHfid) > 1, " were", " was") + " the first to reach the summit of " + c.mountain(id) + " which rises above " + c.region(x.SubregionId) } func (x *HistoricalEventHfRecruitedUnitTypeForEntity) Html(c *context) string { - return c.hf(x.Hfid) + " recruited " + x.UnitType.String() + "s into " + entity(x.EntityId) + location(x.SiteId, " in", x.SubregionId, " in") + return c.hf(x.Hfid) + " recruited " + x.UnitType.String() + "s into " + c.entity(x.EntityId) + c.location(x.SiteId, " in", x.SubregionId, " in") } func (x *HistoricalEventHfRelationshipDenied) Html(c *context) string { @@ -1088,7 +1065,7 @@ func (x *HistoricalEventHfRelationshipDenied) Html(c *context) string { } func (x *HistoricalEventHfReunion) Html(c *context) string { - return c.hf(x.Group1Hfid) + " was reunited with " + c.hfListRelated(x.Group2Hfid, x.Group1Hfid) + location(x.SiteId, " in", x.SubregionId, " in") + return c.hf(x.Group1Hfid) + " was reunited with " + c.hfListRelated(x.Group2Hfid, x.Group1Hfid) + c.location(x.SiteId, " in", x.SubregionId, " in") } func (x *HistoricalEventHfRevived) Html(c *context) string { @@ -1103,13 +1080,13 @@ func (x *HistoricalEventHfRevived) Html(c *context) string { r += " came back from the dead" } return r + util.If(x.RaisedBefore, " once more, this time", "") + " as " + articled(util.If(x.Ghost == HistoricalEventHfRevivedGhost_Unknown, "undead", x.Ghost.String())) + - location(x.SiteId, " in", x.SubregionId, " in") + c.location(x.SiteId, " in", x.SubregionId, " in") } func (x *HistoricalEventHfSimpleBattleEvent) Html(c *context) string { group1 := c.hf(x.Group1Hfid) group2 := c.hfRelated(x.Group2Hfid, x.Group1Hfid) - loc := location(x.SiteId, " in", x.SubregionId, " in") + loc := c.location(x.SiteId, " in", x.SubregionId, " in") switch x.Subtype { case HistoricalEventHfSimpleBattleEventSubtype_Ambushed: return group1 + " ambushed " + group2 + loc @@ -1140,11 +1117,11 @@ func (x *HistoricalEventHfSimpleBattleEvent) Html(c *context) string { } func (x *HistoricalEventHfTravel) Html(c *context) string { - return c.hfList(x.GroupHfid) + util.If(x.Return, " returned", " made a journey") + location(x.SiteId, " to", x.SubregionId, " to") + return c.hfList(x.GroupHfid) + util.If(x.Return, " returned", " made a journey") + c.location(x.SiteId, " to", x.SubregionId, " to") } func (x *HistoricalEventHfViewedArtifact) Html(c *context) string { - return c.hf(x.HistFigId) + " viewed " + artifact(x.ArtifactId) + siteStructure(x.SiteId, x.StructureId, " in") + return c.hf(x.HistFigId) + " viewed " + c.artifact(x.ArtifactId) + c.siteStructure(x.SiteId, x.StructureId, " in") } func (x *HistoricalEventHfWounded) Html(c *context) string { @@ -1163,13 +1140,13 @@ func (x *HistoricalEventHfWounded) Html(c *context) string { r += " was wounded by " } - return r + c.hfRelated(x.WounderHfid, x.WoundeeHfid) + location(x.SiteId, " in", x.SubregionId, " in") + util.If(x.WasTorture, " as a means of torture", "") + return r + c.hfRelated(x.WounderHfid, x.WoundeeHfid) + c.location(x.SiteId, " in", x.SubregionId, " in") + util.If(x.WasTorture, " as a means of torture", "") } func (x *HistoricalEventHfsFormedIntrigueRelationship) Html(c *context) string { if x.Circumstance == HistoricalEventHfsFormedIntrigueRelationshipCircumstance_IsEntitySubordinate { - return c.hf(x.CorruptorHfid) + " subordinated " + c.hfRelated(x.TargetHfid, x.CorruptorHfid) + " as a member of " + entity(x.CircumstanceId) + - " toward the fullfillment of plots and schemes" + location(x.SiteId, " in", x.SubregionId, " in") + return c.hf(x.CorruptorHfid) + " subordinated " + c.hfRelated(x.TargetHfid, x.CorruptorHfid) + " as a member of " + c.entity(x.CircumstanceId) + + " toward the fullfillment of plots and schemes" + c.location(x.SiteId, " in", x.SubregionId, " in") } action := "" @@ -1182,7 +1159,7 @@ func (x *HistoricalEventHfsFormedIntrigueRelationship) Html(c *context) string { method := "" switch x.Method { case HistoricalEventHfsFormedIntrigueRelationshipMethod_BlackmailOverEmbezzlement: - method = "made a blackmail threat, due to embezzlement using the position " + position(x.RelevantEntityId, x.RelevantPositionProfileId, x.CorruptorHfid) + " of " + entity(x.RelevantEntityId) + method = "made a blackmail threat, due to embezzlement using the position " + c.position(x.RelevantEntityId, x.RelevantPositionProfileId, x.CorruptorHfid) + " of " + c.entity(x.RelevantEntityId) case HistoricalEventHfsFormedIntrigueRelationshipMethod_Bribe: method = "offered a bribe" case HistoricalEventHfsFormedIntrigueRelationshipMethod_Flatter: @@ -1192,7 +1169,7 @@ func (x *HistoricalEventHfsFormedIntrigueRelationship) Html(c *context) string { case HistoricalEventHfsFormedIntrigueRelationshipMethod_OfferImmortality: method = "offered immortality" case HistoricalEventHfsFormedIntrigueRelationshipMethod_Precedence: - method = "pulled rank as " + position(x.RelevantEntityId, x.RelevantPositionProfileId, x.CorruptorHfid) + " of " + entity(x.RelevantEntityId) + method = "pulled rank as " + c.position(x.RelevantEntityId, x.RelevantPositionProfileId, x.CorruptorHfid) + " of " + c.entity(x.RelevantEntityId) case HistoricalEventHfsFormedIntrigueRelationshipMethod_ReligiousSympathy: method = "played for sympathy" + util.If(x.RelevantIdForMethod != -1, " by appealing to shared worship of "+c.hfRelated(x.RelevantIdForMethod, x.CorruptorHfid), "") case HistoricalEventHfsFormedIntrigueRelationshipMethod_RevengeOnGrudge: @@ -1221,7 +1198,7 @@ func (x *HistoricalEventHfsFormedIntrigueRelationship) Html(c *context) string { case HistoricalEventHfsFormedIntrigueRelationshipTopFacet_Vengeful: } return c.hf(x.CorruptorHfid) + " corrupted " + c.hfRelated(x.TargetHfid, x.CorruptorHfid) + - " in order to " + action + location(x.SiteId, " in", x.SubregionId, " in") + ". " + + " in order to " + action + c.location(x.SiteId, " in", x.SubregionId, " in") + ". " + util.Capitalize(util.If(x.LureHfid != -1, c.hfRelated(x.LureHfid, x.CorruptorHfid)+" lured "+c.hfShort(x.TargetHfid)+" to a meeting with "+c.hfShort(x.CorruptorHfid)+", where the latter", c.hfShort(x.CorruptorHfid)+" met with "+c.hfShort(x.TargetHfid))) + @@ -1229,9 +1206,9 @@ func (x *HistoricalEventHfsFormedIntrigueRelationship) Html(c *context) string { } func (x *HistoricalEventHfsFormedReputationRelationship) Html(c *context) string { - hf1 := c.hf(x.Hfid1) + util.If(x.IdentityId1 != -1, " as "+fullIdentity(x.IdentityId1), "") - hf2 := c.hfRelated(x.Hfid2, x.Hfid1) + util.If(x.IdentityId2 != -1, " as "+fullIdentity(x.IdentityId2), "") - loc := location(x.SiteId, " in", x.SubregionId, " in") + hf1 := c.hf(x.Hfid1) + util.If(x.IdentityId1 != -1, " as "+c.fullIdentity(x.IdentityId1), "") + hf2 := c.hfRelated(x.Hfid2, x.Hfid1) + util.If(x.IdentityId2 != -1, " as "+c.fullIdentity(x.IdentityId2), "") + loc := c.location(x.SiteId, " in", x.SubregionId, " in") switch x.HfRep2Of1 { case HistoricalEventHfsFormedReputationRelationshipHfRep2Of1_Friendly: return hf1 + " and " + hf2 + ", formed a false friendship where each used the other for information" + loc @@ -1242,21 +1219,21 @@ func (x *HistoricalEventHfsFormedReputationRelationship) Html(c *context) string } func (x *HistoricalEventHolyCityDeclaration) Html(c *context) string { - return entity(x.ReligionId) + " declared " + site(x.SiteId, "") + " to be a holy site" + return c.entity(x.ReligionId) + " declared " + c.site(x.SiteId, "") + " to be a holy site" } func (x *HistoricalEventInsurrectionStarted) Html(c *context) string { - e := util.If(x.TargetCivId != -1, entity(x.TargetCivId), "the local government") + e := util.If(x.TargetCivId != -1, c.entity(x.TargetCivId), "the local government") switch x.Outcome { case HistoricalEventInsurrectionStartedOutcome_LeadershipOverthrown: - return "the insurrection " + site(x.SiteId, "in") + " concluded with " + e + " overthrown" + return "the insurrection " + c.site(x.SiteId, "in") + " concluded with " + e + " overthrown" case HistoricalEventInsurrectionStartedOutcome_PopulationGone: - return "an insurrection " + site(x.SiteId, "in") + " against " + e + " ended with the disappearance of the rebelling population" + return "an insurrection " + c.site(x.SiteId, "in") + " against " + e + " ended with the disappearance of the rebelling population" default: - return "an insurrection against " + e + " began " + site(x.SiteId, "in") + return "an insurrection against " + e + " began " + c.site(x.SiteId, "in") } } func (x *HistoricalEventItemStolen) Html(c *context) string { - i := util.If(x.Item != -1, artifact(x.Item), articled(x.Mat+" "+x.ItemType)) + i := util.If(x.Item != -1, c.artifact(x.Item), articled(x.Mat+" "+x.ItemType)) circumstance := "" if x.Circumstance != nil { switch x.Circumstance.Type { @@ -1270,14 +1247,14 @@ func (x *HistoricalEventItemStolen) Html(c *context) string { switch x.TheftMethod { case HistoricalEventItemStolenTheftMethod_Confiscated: - return i + " was confiscated by " + c.hf(x.Histfig) + circumstance + util.If(x.Site != -1, site(x.Site, " in"), "") + return i + " was confiscated by " + c.hf(x.Histfig) + circumstance + util.If(x.Site != -1, c.site(x.Site, " in"), "") case HistoricalEventItemStolenTheftMethod_Looted: - return i + " was looted " + util.If(x.Site != -1, site(x.Site, " from"), "") + " by " + c.hf(x.Histfig) + circumstance + return i + " was looted " + util.If(x.Site != -1, c.site(x.Site, " from"), "") + " by " + c.hf(x.Histfig) + circumstance case HistoricalEventItemStolenTheftMethod_Recovered: - return i + " was recovered by " + c.hf(x.Histfig) + circumstance + util.If(x.Site != -1, site(x.Site, " in"), "") + return i + " was recovered by " + c.hf(x.Histfig) + circumstance + util.If(x.Site != -1, c.site(x.Site, " in"), "") } - return i + " was stolen " + siteStructure(x.Site, x.Structure, "from") + " by " + c.hf(x.Histfig) + circumstance + - util.If(x.StashSite != -1, " and brought "+site(x.StashSite, "to"), "") + return i + " was stolen " + c.siteStructure(x.Site, x.Structure, "from") + " by " + c.hf(x.Histfig) + circumstance + + util.If(x.StashSite != -1, " and brought "+c.site(x.StashSite, "to"), "") } func (x *HistoricalEventKnowledgeDiscovered) Html(c *context) string { @@ -1287,26 +1264,26 @@ func (x *HistoricalEventKnowledgeDiscovered) Html(c *context) string { func (x *HistoricalEventMasterpieceArchConstructed) Html(c *context) string { return c.hf(x.Hfid) + " constructed a masterful " + util.If(x.BuildingSubtype != HistoricalEventMasterpieceArchConstructedBuildingSubtype_Unknown, x.BuildingSubtype.String(), x.BuildingType.String()) + - " for " + entity(x.EntityId) + site(x.SiteId, " in") + " for " + c.entity(x.EntityId) + c.site(x.SiteId, " in") } func (x *HistoricalEventMasterpieceDye) Html(c *context) string { return c.hf(x.Hfid) + " masterfully dyed a " + x.Mat.String() + " " + x.ItemType.String() + " with " + x.DyeMat + - " for " + entity(x.EntityId) + site(x.SiteId, " in") + " for " + c.entity(x.EntityId) + c.site(x.SiteId, " in") } func (x *HistoricalEventMasterpieceEngraving) Html(c *context) string { return c.hf(x.Hfid) + " created a masterful " + "engraving" + - " for " + entity(x.EntityId) + site(x.SiteId, " in") + " for " + c.entity(x.EntityId) + c.site(x.SiteId, " in") } func (x *HistoricalEventMasterpieceFood) Html(c *context) string { return c.hf(x.Hfid) + " prepared a masterful " + x.ItemSubtype.String() + - " for " + entity(x.EntityId) + site(x.SiteId, " in") + " for " + c.entity(x.EntityId) + c.site(x.SiteId, " in") } func (x *HistoricalEventMasterpieceItem) Html(c *context) string { return c.hf(x.Hfid) + " created a masterful " + x.Mat + " " + util.If(x.ItemSubtype != "", x.ItemSubtype, x.ItemType) + - " for " + entity(x.EntityId) + site(x.SiteId, " in") + " for " + c.entity(x.EntityId) + c.site(x.SiteId, " in") } func (x *HistoricalEventMasterpieceItemImprovement) Html(c *context) string { i := "" @@ -1326,41 +1303,41 @@ func (x *HistoricalEventMasterpieceItemImprovement) Html(c *context) string { } return c.hf(x.Hfid) + " added " + i + " to " + articled(x.Mat+" "+util.If(x.ItemSubtype != "", x.ItemSubtype, x.ItemType)) + - " for " + entity(x.EntityId) + site(x.SiteId, " in") + " for " + c.entity(x.EntityId) + c.site(x.SiteId, " in") } func (x *HistoricalEventMasterpieceLost) Html(c *context) string { - if e, ok := world.HistoricalEvents[x.CreationEvent]; ok { + if e, ok := c.world.HistoricalEvents[x.CreationEvent]; ok { switch y := e.Details.(type) { case *HistoricalEventMasterpieceArchConstructed: return "the " + util.If(y.BuildingSubtype != HistoricalEventMasterpieceArchConstructedBuildingSubtype_Unknown, y.BuildingSubtype.String(), y.BuildingType.String()) + - " masterfully constructed by " + c.hf(y.Hfid) + " for " + entity(y.EntityId) + site(x.Site, " at") + " in " + Time(e.Year, e.Seconds72) + + " masterfully constructed by " + c.hf(y.Hfid) + " for " + c.entity(y.EntityId) + c.site(x.Site, " at") + " in " + Time(e.Year, e.Seconds72) + " was destroyed" + util.If(x.Histfig != -1, " by "+c.hfRelated(x.Histfig, y.Hfid), "") + - " by " + x.Method + site(x.Site, " at") + " by " + x.Method + c.site(x.Site, " at") case *HistoricalEventMasterpieceEngraving: - return "a masterful engraving created by " + c.hf(y.Hfid) + " for " + entity(y.EntityId) + site(x.Site, " at") + " in " + Time(e.Year, e.Seconds72) + + return "a masterful engraving created by " + c.hf(y.Hfid) + " for " + c.entity(y.EntityId) + c.site(x.Site, " at") + " in " + Time(e.Year, e.Seconds72) + " was destroyed" + util.If(x.Histfig != -1, " by "+c.hfRelated(x.Histfig, y.Hfid), "") + - " by " + x.Method + site(x.Site, " at") + " by " + x.Method + c.site(x.Site, " at") case *HistoricalEventMasterpieceItem: return "the masterful " + y.Mat + " " + util.If(y.ItemSubtype != "", y.ItemSubtype, y.ItemType) + - " created by " + c.hf(y.Hfid) + " for " + entity(y.EntityId) + site(x.Site, " at") + " in " + Time(e.Year, e.Seconds72) + + " created by " + c.hf(y.Hfid) + " for " + c.entity(y.EntityId) + c.site(x.Site, " at") + " in " + Time(e.Year, e.Seconds72) + " was destroyed" + util.If(x.Histfig != -1, " by "+c.hfRelated(x.Histfig, y.Hfid), "") + - " by " + x.Method + site(x.Site, " at") + " by " + x.Method + c.site(x.Site, " at") default: - return c.hf(x.Histfig) + " destroyed a masterful item" + site(x.Site, " in") + " -- " + fmt.Sprintf("%T", e.Details) + return c.hf(x.Histfig) + " destroyed a masterful item" + c.site(x.Site, " in") + " -- " + fmt.Sprintf("%T", e.Details) } } - return c.hf(x.Histfig) + " destroyed a masterful item" + site(x.Site, " in") + return c.hf(x.Histfig) + " destroyed a masterful item" + c.site(x.Site, " in") } func (x *HistoricalEventMerchant) Html(c *context) string { - return "merchants from " + entity(x.TraderEntityId) + " visited " + entity(x.DepotEntityId) + site(x.SiteId, " at") + + return "merchants from " + c.entity(x.TraderEntityId) + " visited " + c.entity(x.DepotEntityId) + c.site(x.SiteId, " at") + util.If(x.Hardship, " and suffered great hardship", "") + util.If(x.LostValue, ". They reported irregularities with their goods", "") } func (x *HistoricalEventModifiedBuilding) Html(c *context) string { - return c.hf(x.ModifierHfid) + " had " + articled(x.Modification.String()) + " added " + siteStructure(x.SiteId, x.StructureId, "to") + return c.hf(x.ModifierHfid) + " had " + articled(x.Modification.String()) + " added " + c.siteStructure(x.SiteId, x.StructureId, "to") } func (x *HistoricalEventMusicalFormCreated) Html(c *context) string { @@ -1380,37 +1357,37 @@ func (x *HistoricalEventMusicalFormCreated) Html(c *context) string { case HistoricalEventMusicalFormCreatedCircumstance_PrayToHf: circumstance = " after praying to " + util.If(x.ReasonId == x.CircumstanceId, c.hfShort(x.CircumstanceId), c.hfRelated(x.CircumstanceId, x.HistFigureId)) } - return musicalForm(x.FormId) + " was created by " + c.hf(x.HistFigureId) + site(x.SiteId, " in") + reason + circumstance + return c.musicalForm(x.FormId) + " was created by " + c.hf(x.HistFigureId) + c.site(x.SiteId, " in") + reason + circumstance } func (x *HistoricalEventNewSiteLeader) Html(c *context) string { - return entity(x.AttackerCivId) + " defeated " + siteCiv(x.SiteCivId, x.DefenderCivId) + " and placed " + c.hf(x.NewLeaderHfid) + " in charge of" + site(x.SiteId, "") + - ". The new government was called " + entity(x.NewSiteCivId) + return c.entity(x.AttackerCivId) + " defeated " + c.siteCiv(x.SiteCivId, x.DefenderCivId) + " and placed " + c.hf(x.NewLeaderHfid) + " in charge of" + c.site(x.SiteId, "") + + ". The new government was called " + c.entity(x.NewSiteCivId) } func (x *HistoricalEventPeaceAccepted) Html(c *context) string { - return entity(x.Destination) + " accepted an offer of peace from " + entity(x.Source) + return c.entity(x.Destination) + " accepted an offer of peace from " + c.entity(x.Source) } func (x *HistoricalEventPeaceRejected) Html(c *context) string { - return entity(x.Destination) + " rejected an offer of peace from " + entity(x.Source) + return c.entity(x.Destination) + " rejected an offer of peace from " + c.entity(x.Source) } func (x *HistoricalEventPerformance) Html(c *context) string { - r := entity(x.CivId) + " held " - if e, ok := world.Entities[x.CivId]; ok { + r := c.entity(x.CivId) + " held " + if e, ok := c.world.Entities[x.CivId]; ok { o := e.Occasion[x.OccasionId] s := o.Schedule[x.ScheduleId] - r += schedule(s) + r += c.schedule(s) r += " as part of " + o.Name() - r += site(x.SiteId, " in") + r += c.site(x.SiteId, " in") r += string(util.Json(s)) } return r } func (x *HistoricalEventPlunderedSite) Html(c *context) string { // TODO no_defeat_mention, took_items, took_livestock, was_raid - return entity(x.AttackerCivId) + " defeated " + siteCiv(x.SiteCivId, x.DefenderCivId) + " and pillaged " + site(x.SiteId, "") + return c.entity(x.AttackerCivId) + " defeated " + c.siteCiv(x.SiteCivId, x.DefenderCivId) + " and pillaged " + c.site(x.SiteId, "") } func (x *HistoricalEventPoeticFormCreated) Html(c *context) string { @@ -1421,25 +1398,25 @@ func (x *HistoricalEventPoeticFormCreated) Html(c *context) string { case HistoricalEventPoeticFormCreatedCircumstance_Nightmare: circumstance = " after a nightmare" } - return poeticForm(x.FormId) + " was created by " + c.hf(x.HistFigureId) + site(x.SiteId, " in") + circumstance + return c.poeticForm(x.FormId) + " was created by " + c.hf(x.HistFigureId) + c.site(x.SiteId, " in") + circumstance } func (x *HistoricalEventProcession) Html(c *context) string { - r := entity(x.CivId) + " held a procession in " + site(x.SiteId, "") - if e, ok := world.Entities[x.CivId]; ok { + r := c.entity(x.CivId) + " held a procession in " + c.site(x.SiteId, "") + if e, ok := c.world.Entities[x.CivId]; ok { o := e.Occasion[x.OccasionId] r += " as part of " + o.Name() s := o.Schedule[x.ScheduleId] if s.Reference != -1 { - r += ". It started at " + structure(x.SiteId, s.Reference) + r += ". It started at " + c.structure(x.SiteId, s.Reference) if s.Reference2 != -1 && s.Reference2 != s.Reference { - r += " and ended at " + structure(x.SiteId, s.Reference2) + r += " and ended at " + c.structure(x.SiteId, s.Reference2) } else { r += " and returned there after following its route" } } if len(s.Feature) > 0 { - r += ". The event featured " + andList(util.Map(s.Feature, feature)) + r += ". The event featured " + andList(util.Map(s.Feature, c.feature)) } r += string(util.Json(s)) } @@ -1447,28 +1424,28 @@ func (x *HistoricalEventProcession) Html(c *context) string { } func (x *HistoricalEventRazedStructure) Html(c *context) string { - return entity(x.CivId) + " razed " + siteStructure(x.SiteId, x.StructureId, "") + return c.entity(x.CivId) + " razed " + c.siteStructure(x.SiteId, x.StructureId, "") } func (x *HistoricalEventReclaimSite) Html(c *context) string { if x.Unretire { - return siteCiv(x.SiteCivId, x.CivId) + " were taken by a mood to act against their judgment " + site(x.SiteId, "at") + return c.siteCiv(x.SiteCivId, x.CivId) + " were taken by a mood to act against their judgment " + c.site(x.SiteId, "at") } - return siteCiv(x.SiteCivId, x.CivId) + " launched an expedition to reclaim " + site(x.SiteId, "") + return c.siteCiv(x.SiteCivId, x.CivId) + " launched an expedition to reclaim " + c.site(x.SiteId, "") } func (x *HistoricalEventRegionpopIncorporatedIntoEntity) Html(c *context) string { // TODO Race - return strconv.Itoa(x.PopNumberMoved) + " of " + strconv.Itoa(x.PopRace) + " from " + region(x.PopSrid) + " joined with " + entity(x.JoinEntityId) + site(x.SiteId, " at") + return strconv.Itoa(x.PopNumberMoved) + " of " + strconv.Itoa(x.PopRace) + " from " + c.region(x.PopSrid) + " joined with " + c.entity(x.JoinEntityId) + c.site(x.SiteId, " at") } func (x *HistoricalEventRemoveHfEntityLink) Html(c *context) string { hf := c.hf(x.Hfid) - civ := entity(x.CivId) + civ := c.entity(x.CivId) switch x.Link { case HistoricalEventRemoveHfEntityLinkLink_Member: return hf + " left " + civ case HistoricalEventRemoveHfEntityLinkLink_Position: - return hf + " ceased to be the " + position(x.CivId, x.PositionId, x.Hfid) + " of " + civ + return hf + " ceased to be the " + c.position(x.CivId, x.PositionId, x.Hfid) + " of " + civ case HistoricalEventRemoveHfEntityLinkLink_Prisoner: return hf + " escaped from the prisons of " + civ case HistoricalEventRemoveHfEntityLinkLink_Slave: @@ -1484,58 +1461,58 @@ func (x *HistoricalEventRemoveHfHfLink) Html(c *context) string { // divorced func (x *HistoricalEventRemoveHfSiteLink) Html(c *context) string { switch x.LinkType { case HistoricalEventRemoveHfSiteLinkLinkType_HomeSiteAbstractBuilding: - return c.hf(x.Histfig) + " moved out " + siteStructure(x.SiteId, x.Structure, "of") + return c.hf(x.Histfig) + " moved out " + c.siteStructure(x.SiteId, x.Structure, "of") case HistoricalEventRemoveHfSiteLinkLinkType_Occupation: - return c.hf(x.Histfig) + " stopped working " + siteStructure(x.SiteId, x.Structure, "at") + return c.hf(x.Histfig) + " stopped working " + c.siteStructure(x.SiteId, x.Structure, "at") case HistoricalEventRemoveHfSiteLinkLinkType_SeatOfPower: - return c.hf(x.Histfig) + " stopped ruling " + siteStructure(x.SiteId, x.Structure, "from") + return c.hf(x.Histfig) + " stopped ruling " + c.siteStructure(x.SiteId, x.Structure, "from") } - return c.hf(x.Histfig) + " stopped working " + siteStructure(x.SiteId, x.Structure, "at") + return c.hf(x.Histfig) + " stopped working " + c.siteStructure(x.SiteId, x.Structure, "at") } func (x *HistoricalEventReplacedStructure) Html(c *context) string { - return siteCiv(x.SiteCivId, x.CivId) + " replaced " + siteStructure(x.SiteId, x.OldAbId, "") + " with " + structure(x.SiteId, x.NewAbId) + return c.siteCiv(x.SiteCivId, x.CivId) + " replaced " + c.siteStructure(x.SiteId, x.OldAbId, "") + " with " + c.structure(x.SiteId, x.NewAbId) } func (x *HistoricalEventSiteDied) Html(c *context) string { - return siteCiv(x.SiteCivId, x.CivId) + " abandonned the settlement of " + site(x.SiteId, "") + return c.siteCiv(x.SiteCivId, x.CivId) + " abandonned the settlement of " + c.site(x.SiteId, "") } func (x *HistoricalEventSiteDispute) Html(c *context) string { - return entity(x.EntityId1) + " of " + site(x.SiteId1, "") + " and " + entity(x.EntityId2) + " of " + site(x.SiteId2, "") + " became embroiled in a dispute over " + x.Dispute.String() + return c.entity(x.EntityId1) + " of " + c.site(x.SiteId1, "") + " and " + c.entity(x.EntityId2) + " of " + c.site(x.SiteId2, "") + " became embroiled in a dispute over " + x.Dispute.String() } func (x *HistoricalEventSiteRetired) Html(c *context) string { - return siteCiv(x.SiteCivId, x.CivId) + " at the settlement " + site(x.SiteId, "of") + " regained their senses after " + util.If(x.First, "an initial", "another") + " period of questionable judgment" + return c.siteCiv(x.SiteCivId, x.CivId) + " at the settlement " + c.site(x.SiteId, "of") + " regained their senses after " + util.If(x.First, "an initial", "another") + " period of questionable judgment" } func (x *HistoricalEventSiteSurrendered) Html(c *context) string { - return siteCiv(x.SiteCivId, x.DefenderCivId) + " surrendered " + site(x.SiteId, "") + " to " + entity(x.AttackerCivId) + return c.siteCiv(x.SiteCivId, x.DefenderCivId) + " surrendered " + c.site(x.SiteId, "") + " to " + c.entity(x.AttackerCivId) } func (x *HistoricalEventSiteTakenOver) Html(c *context) string { - return entity(x.AttackerCivId) + " defeated " + siteCiv(x.SiteCivId, x.DefenderCivId) + " and took over " + site(x.SiteId, "") + ". The new government was called " + entity(x.NewSiteCivId) + return c.entity(x.AttackerCivId) + " defeated " + c.siteCiv(x.SiteCivId, x.DefenderCivId) + " and took over " + c.site(x.SiteId, "") + ". The new government was called " + c.entity(x.NewSiteCivId) } func (x *HistoricalEventSiteTributeForced) Html(c *context) string { - return entity(x.AttackerCivId) + " secured tribute from " + siteCiv(x.SiteCivId, x.DefenderCivId) + - util.If(x.SiteId != -1, ", to be delivered"+site(x.SiteId, " from"), "") + + return c.entity(x.AttackerCivId) + " secured tribute from " + c.siteCiv(x.SiteCivId, x.DefenderCivId) + + util.If(x.SiteId != -1, ", to be delivered"+c.site(x.SiteId, " from"), "") + util.If(x.Season != HistoricalEventSiteTributeForcedSeason_Unknown, " every "+x.Season.String(), "") } func (x *HistoricalEventSneakIntoSite) Html(c *context) string { - return util.If(x.AttackerCivId != -1, entity(x.AttackerCivId), "an unknown civilization") + " slipped " + site(x.SiteId, "into") + - util.If(x.SiteCivId != -1 || x.DefenderCivId != -1, ", undetected by "+siteCiv(x.SiteCivId, x.DefenderCivId), "") + return util.If(x.AttackerCivId != -1, c.entity(x.AttackerCivId), "an unknown civilization") + " slipped " + c.site(x.SiteId, "into") + + util.If(x.SiteCivId != -1 || x.DefenderCivId != -1, ", undetected by "+c.siteCiv(x.SiteCivId, x.DefenderCivId), "") } func (x *HistoricalEventSpottedLeavingSite) Html(c *context) string { - return c.hf(x.SpotterHfid) + " of " + entity(x.SiteCivId) + " spotted the forces of " + util.If(x.LeaverCivId != -1, entity(x.LeaverCivId), "an unknown civilization") + " slipping out of " + site(x.SiteId, "") + return c.hf(x.SpotterHfid) + " of " + c.entity(x.SiteCivId) + " spotted the forces of " + util.If(x.LeaverCivId != -1, c.entity(x.LeaverCivId), "an unknown civilization") + " slipping out of " + c.site(x.SiteId, "") } func (x *HistoricalEventSquadVsSquad) Html(c *context) string { // TODO a_leader_hfid return c.hfList(x.AHfid) + " clashed with " + util.If(len(x.DHfid) > 0, c.hfList(x.DHfid), fmt.Sprintf("%d race_%d", x.DNumber, x.DRace)) + - site(x.SiteId, " in") + + c.site(x.SiteId, " in") + util.If(x.DSlain > 0, fmt.Sprintf(", slaying %d", x.DSlain), "") } @@ -1584,7 +1561,7 @@ func (x *HistoricalEventTacticalSituation) Html(c *context) string { case HistoricalEventTacticalSituationSituation_NeitherFavored: r += ", but neither side had a positional advantage" } - return r + site(x.SiteId, " in") + return r + c.site(x.SiteId, " in") } func (x *HistoricalEventTrade) Html(c *context) string { @@ -1597,7 +1574,7 @@ func (x *HistoricalEventTrade) Html(c *context) string { default: outcome = " broke even" } - return c.hf(x.TraderHfid) + util.If(x.TraderEntityId != -1, " of "+entity(x.TraderEntityId), "") + outcome + " trading" + site(x.SourceSiteId, " from") + site(x.DestSiteId, " to") + return c.hf(x.TraderHfid) + util.If(x.TraderEntityId != -1, " of "+c.entity(x.TraderEntityId), "") + outcome + " trading" + c.site(x.SourceSiteId, " from") + c.site(x.DestSiteId, " to") } func (x *HistoricalEventWrittenContentComposed) Html(c *context) string { @@ -1617,5 +1594,5 @@ func (x *HistoricalEventWrittenContentComposed) Html(c *context) string { case HistoricalEventWrittenContentComposedCircumstance_PrayToHf: circumstance = " after praying to " + util.If(x.ReasonId == x.CircumstanceId, c.hfShort(x.CircumstanceId), c.hfRelated(x.CircumstanceId, x.HistFigureId)) } - return writtenContent(x.WcId) + " was authored by " + c.hf(x.HistFigureId) + location(x.SiteId, " in", x.SubregionId, " in") + reason + circumstance + return c.writtenContent(x.WcId) + " was authored by " + c.hf(x.HistFigureId) + c.location(x.SiteId, " in", x.SubregionId, " in") + reason + circumstance } diff --git a/backend/model/extensions.go b/backend/model/extensions.go index a9d806a..384ca7b 100644 --- a/backend/model/extensions.go +++ b/backend/model/extensions.go @@ -2,15 +2,52 @@ package model import ( "fmt" - "html/template" - "regexp" "sort" "strings" - "github.com/iancoleman/strcase" "github.com/robertjanetzko/LegendsBrowser2/backend/util" ) +func (w *DfWorld) AllEventTypes() []string { + types := make(map[string]bool) + for _, e := range w.HistoricalEvents { + types[e.Details.Type()] = true + } + var list = util.Keys(types) + sort.Strings(list) + return list +} + +func (w *DfWorld) EventsOfType(t string) any { + var list []*HistoricalEvent + for _, e := range w.HistoricalEvents { + if e.Details.Type() == t { + list = append(list, e) + } + } + + sort.Slice(list, func(i, j int) bool { return list[i].Id_ < list[j].Id_ }) + + return struct { + Type string + Events []*HistoricalEvent + }{ + Type: t, + Events: list, + } +} + +func (w *DfWorld) EventsMatching(f func(HistoricalEventDetails) bool) []*HistoricalEvent { + var list []*HistoricalEvent + for _, e := range w.HistoricalEvents { + if f(e.Details) { + list = append(list, e) + } + } + sort.Slice(list, func(a, b int) bool { return list[a].Id_ < list[b].Id_ }) + return list +} + func (e *Entity) Position(id int) *EntityPosition { for _, p := range e.EntityPosition { if p.Id_ == id { @@ -56,434 +93,30 @@ func (hf *HistoricalFigure) FirstName() string { return strings.Split(hf.Name_, " ")[0] } +func (x *Honor) Requirement() string { + var list []string + if x.RequiresAnyMeleeOrRangedSkill { + list = append(list, "attaining sufficent skill with a weapon or technique") + } + if x.RequiredSkill != HonorRequiredSkill_Unknown { + list = append(list, "attaining enough skill with the "+x.RequiredSkill.String()) + } + if x.RequiredBattles == 1 { + list = append(list, "serving in combat") + } + if x.RequiredBattles > 1 { + list = append(list, fmt.Sprintf("participating in %d battles", x.RequiredBattles)) + } + if x.RequiredYears >= 1 { + list = append(list, fmt.Sprintf("%d years of membership", x.RequiredYears)) + } + if x.RequiredKills >= 1 { + list = append(list, fmt.Sprintf("slaying %d enemies", x.RequiredKills)) + } + + return " after " + andList(list) +} + func (w *WrittenContent) Name() string { return w.Title } - -type HistoricalEventDetails interface { - RelatedToEntity(int) bool - RelatedToHf(int) bool - RelatedToArtifact(int) bool - RelatedToSite(int) bool - RelatedToRegion(int) bool - Html(*context) string - Type() string -} - -type HistoricalEventCollectionDetails interface { -} - -type EventList struct { - Events []*HistoricalEvent - Context *context -} - -func filter(f func(HistoricalEventDetails) bool) []*HistoricalEvent { - var list []*HistoricalEvent - for _, e := range world.HistoricalEvents { - if f(e.Details) { - list = append(list, e) - } - } - sort.Slice(list, func(a, b int) bool { return list[a].Id_ < list[b].Id_ }) - return list -} - -func NewEventList(obj any) *EventList { - el := EventList{ - Context: &context{HfId: -1}, - } - - switch x := obj.(type) { - case *Entity: - el.Events = filter(func(d HistoricalEventDetails) bool { return d.RelatedToEntity(x.Id()) }) - case *HistoricalFigure: - el.Context.HfId = x.Id() - el.Events = filter(func(d HistoricalEventDetails) bool { return d.RelatedToHf(x.Id()) }) - case *Artifact: - el.Events = filter(func(d HistoricalEventDetails) bool { return d.RelatedToArtifact(x.Id()) }) - case *Site: - el.Events = filter(func(d HistoricalEventDetails) bool { return d.RelatedToSite(x.Id()) }) - case *Region: - el.Events = filter(func(d HistoricalEventDetails) bool { return d.RelatedToRegion(x.Id()) }) - case []*HistoricalEvent: - el.Events = x - default: - fmt.Printf("unknown type %T\n", obj) - } - - return &el -} - -type context struct { - HfId int - Story bool -} - -func (c *context) hf(id int) string { - if c.HfId != -1 { - if c.HfId == id { - return hfShort(id) - } else { - return hfRelated(id, c.HfId) - } - } - return hf(id) -} - -func (c *context) hfShort(id int) string { - return hfShort(id) -} - -func (c *context) hfRelated(id, to int) string { - if c.HfId != -1 { - if c.HfId == id { - return hfShort(id) - } else { - return hfRelated(id, c.HfId) - } - } - return hfRelated(id, to) -} - -func (c *context) hfList(ids []int) string { - return andList(util.Map(ids, func(id int) string { return c.hf(id) })) -} - -func (c *context) hfListRelated(ids []int, to int) string { - return andList(util.Map(ids, func(id int) string { return c.hfRelated(id, to) })) -} - -func containsInt(list []int, id int) bool { - for _, v := range list { - if v == id { - return true - } - } - return false -} - -var world *DfWorld - -func andList(list []string) string { - if len(list) > 1 { - return strings.Join(list[:len(list)-1], ", ") + " and " + list[len(list)-1] - } - return strings.Join(list, ", ") -} - -func articled(s string) string { - if ok, _ := regexp.MatchString("^([aeio]|un|ul).*", s); ok { - return "an " + s - } - return "a " + s -} - -func artifact(id int) string { - if x, ok := world.Artifacts[id]; ok { - return fmt.Sprintf(`%s`, x.Id(), util.Title(x.Name())) - } - return "UNKNOWN ARTIFACT" -} - -func entity(id int) string { - if x, ok := world.Entities[id]; ok { - return fmt.Sprintf(`%s`, x.Id(), util.Title(x.Name())) - } - return "UNKNOWN ENTITY" -} - -func entityList(ids []int) string { - return andList(util.Map(ids, entity)) -} - -func position(entityId, positionId, hfId int) string { - if e, ok := world.Entities[entityId]; ok { - if h, ok := world.HistoricalFigures[hfId]; ok { - return e.Position(positionId).GenderName(h) - } - } - return "UNKNOWN POSITION" -} - -func siteCiv(siteCivId, civId int) string { - if siteCivId == civId { - return entity(civId) - } - return util.If(siteCivId != -1, entity(siteCivId), "") + util.If(civId != -1 && siteCivId != -1, " of ", "") + util.If(civId != -1, entity(civId), "") -} - -func siteStructure(siteId, structureId int, prefix string) string { - if siteId == -1 { - return "" - } - return " " + prefix + " " + util.If(structureId != -1, structure(siteId, structureId)+" in ", "") + site(siteId, "") -} - -func hf(id int) string { - if x, ok := world.HistoricalFigures[id]; ok { - return fmt.Sprintf(`the %s %s`, x.Race+util.If(x.Deity, " deity", "")+util.If(x.Force, " force", ""), x.Id(), util.Title(x.Name())) - } - return "UNKNOWN HISTORICAL FIGURE" -} - -func hfShort(id int) string { - if x, ok := world.HistoricalFigures[id]; ok { - return fmt.Sprintf(`%s`, x.Id(), util.Title(x.FirstName())) - } - return "UNKNOWN HISTORICAL FIGURE" -} - -func hfRelated(id, to int) string { - if x, ok := world.HistoricalFigures[id]; ok { - if t, ok := world.HistoricalFigures[to]; ok { - if y, ok := util.Find(t.HfLink, func(l *HfLink) bool { return l.Hfid == id }); ok { - return fmt.Sprintf(`%s %s %s`, t.PossesivePronoun(), y.LinkType, x.Id(), util.Title(x.Name())) - } - } - return fmt.Sprintf(`the %s %s`, x.Race+util.If(x.Deity, " deity", "")+util.If(x.Force, " force", ""), x.Id(), util.Title(x.Name())) - } - return "UNKNOWN HISTORICAL FIGURE" -} - -func hfLink(id, to int) string { - if x, ok := world.HistoricalFigures[id]; ok { - if y, ok := util.Find(x.HfLink, func(l *HfLink) bool { return l.Hfid == to }); ok { - return y.LinkType.String() - } - } - return "UNKNOWN LINK" -} - -func pronoun(id int) string { - if x, ok := world.HistoricalFigures[id]; ok { - return x.Pronoun() - } - return "he" -} - -func posessivePronoun(id int) string { - if x, ok := world.HistoricalFigures[id]; ok { - return x.PossesivePronoun() - } - return "his" -} - -func site(id int, prefix string) string { - if x, ok := world.Sites[id]; ok { - return fmt.Sprintf(`%s %s`, prefix, x.Id(), util.Title(x.Name())) - } - return "UNKNOWN SITE" -} - -func structure(siteId, structureId int) string { - if x, ok := world.Sites[siteId]; ok { - if y, ok := x.Structures[structureId]; ok { - return fmt.Sprintf(`%s`, siteId, structureId, util.Title(y.Name())) - } - } - return "UNKNOWN STRUCTURE" -} - -func property(siteId, propertyId int) string { - if x, ok := world.Sites[siteId]; ok { - if y, ok := x.SiteProperties[propertyId]; ok { - if y.StructureId != -1 { - return structure(siteId, y.StructureId) - } - return articled(y.Type.String()) - } - } - return "UNKNOWN PROPERTY" -} - -func region(id int) string { - if x, ok := world.Regions[id]; ok { - return fmt.Sprintf(`%s`, x.Id(), util.Title(x.Name())) - } - return "UNKNOWN REGION" -} - -func location(siteId int, sitePrefix string, regionId int, regionPrefix string) string { - if siteId != -1 { - return site(siteId, sitePrefix) - } - if regionId != -1 { - return regionPrefix + " " + region(regionId) - } - return "" -} - -func place(structureId, siteId int, sitePrefix string, regionId int, regionPrefix string) string { - if siteId != -1 { - return siteStructure(siteId, structureId, sitePrefix) - } - if regionId != -1 { - return regionPrefix + " " + region(regionId) - } - return "" -} - -func mountain(id int) string { - if x, ok := world.MountainPeaks[id]; ok { - return fmt.Sprintf(`%s`, x.Id(), util.Title(x.Name())) - } - return "UNKNOWN MOUNTAIN" -} - -func identity(id int) string { - if x, ok := world.Identities[id]; ok { - return fmt.Sprintf(`%s`, x.Id(), util.Title(x.Name())) - } - return "UNKNOWN IDENTITY" -} - -func fullIdentity(id int) string { - if x, ok := world.Identities[id]; ok { - return fmt.Sprintf(`"the %s %s of %s"`, x.Profession.String(), x.Id(), util.Title(x.Name()), entity(x.EntityId)) - } - return "UNKNOWN IDENTITY" -} - -func feature(x *Feature) string { - switch x.Type { - case FeatureType_DancePerformance: - return "a perfomance of " + danceForm(x.Reference) - case FeatureType_Images: - if x.Reference != -1 { - return "images of " + hf(x.Reference) - } - return "images" - case FeatureType_MusicalPerformance: - return "a perfomance of " + musicalForm(x.Reference) - case FeatureType_PoetryRecital: - return "a recital of " + poeticForm(x.Reference) - case FeatureType_Storytelling: - if x.Reference != -1 { - if e, ok := world.HistoricalEvents[x.Reference]; ok { - return "a telling of the story of " + e.Details.Html(&context{Story: true}) + " in " + Time(e.Year, e.Seconds72) - } - } - return "a story recital" - default: - return strcase.ToDelimited(x.Type.String(), ' ') - } -} - -func schedule(x *Schedule) string { - switch x.Type { - case ScheduleType_DancePerformance: - return "a perfomance of " + danceForm(x.Reference) - case ScheduleType_MusicalPerformance: - return "a perfomance of " + musicalForm(x.Reference) - case ScheduleType_PoetryRecital: - return "a recital of " + poeticForm(x.Reference) - case ScheduleType_Storytelling: - if x.Reference != -1 { - if e, ok := world.HistoricalEvents[x.Reference]; ok { - return "the story of " + e.Details.Html(&context{Story: true}) + " in " + Time(e.Year, e.Seconds72) - } - } - return "a story recital" - default: - return strcase.ToDelimited(x.Type.String(), ' ') - } -} - -func ShortTime(year, seconds int) string { - if year == -1 { - return "a time before time" - } - return fmt.Sprintf("%d", year) -} - -func Time(year, seconds int) string { - if year == -1 { - return "a time before time" - } - if seconds == -1 { - return fmt.Sprintf("%d", year) - } - return fmt.Sprintf("%s of %d", Season(seconds), year) -} - -func Season(seconds int) string { - r := "" - month := seconds % 100800 - if month <= 33600 { - r += "early " - } else if month <= 67200 { - r += "mid" - } else if month <= 100800 { - r += "late " - } - - season := seconds % 403200 - if season < 100800 { - r += "spring" - } else if season < 201600 { - r += "summer" - } else if season < 302400 { - r += "autumn" - } else if season < 403200 { - r += "winter" - } - - return r -} - -func danceForm(id int) string { - if x, ok := world.DanceForms[id]; ok { - return fmt.Sprintf(`%s`, id, util.Title(x.Name())) - } - return "UNKNOWN DANCE FORM" -} - -func musicalForm(id int) string { - if x, ok := world.MusicalForms[id]; ok { - return fmt.Sprintf(`%s`, id, util.Title(x.Name())) - } - return "UNKNOWN MUSICAL FORM" -} - -func poeticForm(id int) string { - if x, ok := world.PoeticForms[id]; ok { - return fmt.Sprintf(`%s`, id, util.Title(x.Name())) - } - return "UNKNOWN POETIC FORM" -} - -func worldConstruction(id int) string { - if x, ok := world.WorldConstructions[id]; ok { - return fmt.Sprintf(`%s`, id, util.Title(x.Name())) - } - return "UNKNOWN WORLD CONSTRUCTION" -} - -func writtenContent(id int) string { - if x, ok := world.WrittenContents[id]; ok { - return fmt.Sprintf(`%s`, id, util.Title(x.Name())) - } - return "UNKNOWN WORLD CONSTRUCTION" -} - -var LinkHf = func(id int) template.HTML { return template.HTML(hf(id)) } -var LinkEntity = func(id int) template.HTML { return template.HTML(entity(id)) } -var LinkSite = func(id int) template.HTML { return template.HTML(site(id, "")) } -var LinkRegion = func(id int) template.HTML { return template.HTML(region(id)) } - -func equipmentLevel(level int) string { - switch level { - case 1: - return "well-crafted" - case 2: - return "finely-crafted" - case 3: - return "superior quality" - case 4: - return "exceptional" - case 5: - return "masterwork" - } - return "" -} diff --git a/backend/model/functions.go b/backend/model/functions.go new file mode 100644 index 0000000..1643b4a --- /dev/null +++ b/backend/model/functions.go @@ -0,0 +1,94 @@ +package model + +import ( + "fmt" + "html/template" + "regexp" + "strings" +) + +var LinkHf = func(w *DfWorld, id int) template.HTML { return template.HTML((&context{world: w}).hf(id)) } +var LinkEntity = func(w *DfWorld, id int) template.HTML { return template.HTML((&context{world: w}).entity(id)) } +var LinkSite = func(w *DfWorld, id int) template.HTML { return template.HTML((&context{world: w}).site(id, "")) } +var LinkRegion = func(w *DfWorld, id int) template.HTML { return template.HTML((&context{world: w}).region(id)) } + +func andList(list []string) string { + if len(list) > 1 { + return strings.Join(list[:len(list)-1], ", ") + " and " + list[len(list)-1] + } + return strings.Join(list, ", ") +} + +func articled(s string) string { + if ok, _ := regexp.MatchString("^([aeio]|un|ul).*", s); ok { + return "an " + s + } + return "a " + s +} + +func ShortTime(year, seconds int) string { + if year == -1 { + return "a time before time" + } + return fmt.Sprintf("%d", year) +} + +func Time(year, seconds int) string { + if year == -1 { + return "a time before time" + } + if seconds == -1 { + return fmt.Sprintf("%d", year) + } + return fmt.Sprintf("%s of %d", Season(seconds), year) +} + +func Season(seconds int) string { + r := "" + month := seconds % 100800 + if month <= 33600 { + r += "early " + } else if month <= 67200 { + r += "mid" + } else if month <= 100800 { + r += "late " + } + + season := seconds % 403200 + if season < 100800 { + r += "spring" + } else if season < 201600 { + r += "summer" + } else if season < 302400 { + r += "autumn" + } else if season < 403200 { + r += "winter" + } + + return r +} + +func equipmentLevel(level int) string { + switch level { + case 1: + return "well-crafted" + case 2: + return "finely-crafted" + case 3: + return "superior quality" + case 4: + return "exceptional" + case 5: + return "masterwork" + } + return "" +} + +func containsInt(list []int, id int) bool { + for _, v := range list { + if v == id { + return true + } + } + return false +} diff --git a/backend/model/parse.go b/backend/model/parse.go index 9fb35ef..467af71 100644 --- a/backend/model/parse.go +++ b/backend/model/parse.go @@ -70,6 +70,8 @@ func Parse(file string) (*DfWorld, error) { } defer xmlFile.Close() + world := &DfWorld{} + BaseLoop: for { t, n, err := p.Token() diff --git a/backend/same.json b/backend/same.json deleted file mode 100644 index 3098dd5..0000000 --- a/backend/same.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "HistoricalEventAddHfEntityLink": { - "LinkType": "Link" - }, - "HistoricalEventAddHfSiteLink": { - "Site": "SiteId" - }, - "HistoricalEventAgreementMade": { - "Destination": "SiteId", - "Site": "SiteId", - "Source": "SiteId" - }, - "HistoricalEventAgreementRejected": { - "Destination": "SiteId", - "Site": "SiteId", - "Source": "SiteId" - }, - "HistoricalEventDiplomatLost": { - "Entity": "SiteId", - "Involved": "SiteId", - "Site": "SiteId" - }, - "HistoricalEventHfDied": { - "DeathCause": "Cause", - "ShooterItemSubtype": "Cause", - "ShooterItemType": "Cause" - }, - "HistoricalEventPeaceAccepted": { - "Site": "SiteId" - }, - "HistoricalEventPeaceRejected": { - "Site": "SiteId" - }, - "HistoricalEventRemoveHfEntityLink": { - "LinkType": "Link" - }, - "HistoricalEventRemoveHfSiteLink": { - "Site": "SiteId" - } -} \ No newline at end of file diff --git a/backend/server/resource.go b/backend/server/resource.go index f272006..2c85332 100644 --- a/backend/server/resource.go +++ b/backend/server/resource.go @@ -1,39 +1,30 @@ package server import ( - "encoding/json" "fmt" "net/http" "strconv" "github.com/gorilla/mux" - "github.com/robertjanetzko/LegendsBrowser2/backend/model" ) -type Info struct { - Id int `json:"id"` - Name string `json:"name"` -} - -func RegisterResource[T model.Named](router *mux.Router, resourceName string, resources map[int]T) { - list := func(w http.ResponseWriter, r *http.Request) { - values := make([]Info, 0, len(resources)) - for _, v := range resources { - values = append(values, Info{Id: v.Id(), Name: v.Name()}) - - } - json.NewEncoder(w).Encode(values) - } +type Parms map[string]string +func (srv *DfServer) RegisterPage(path string, template string, accessor func(Parms) any) { get := func(w http.ResponseWriter, r *http.Request) { - id, err := strconv.Atoi(mux.Vars(r)["id"]) + err := srv.templates.Render(w, template, accessor(mux.Vars(r))) if err != nil { + fmt.Fprintln(w, err) fmt.Println(err) } - - json.NewEncoder(w).Encode(resources[id]) } - router.HandleFunc(fmt.Sprintf("/api/%s", resourceName), list).Methods("GET") - router.HandleFunc(fmt.Sprintf("/api/%s/{id}", resourceName), get).Methods("GET") + srv.router.HandleFunc(path, get).Methods("GET") +} + +func (srv *DfServer) RegisterResourcePage(path string, template string, accessor func(int) any) { + srv.RegisterPage(path, template, func(params Parms) any { + id, _ := strconv.Atoi(params["id"]) + return accessor(id) + }) } diff --git a/backend/server/server.go b/backend/server/server.go new file mode 100644 index 0000000..658be8f --- /dev/null +++ b/backend/server/server.go @@ -0,0 +1,90 @@ +package server + +import ( + "embed" + "fmt" + "io/fs" + "net/http" + "os" + + "github.com/gorilla/mux" + "github.com/robertjanetzko/LegendsBrowser2/backend/model" + "github.com/robertjanetzko/LegendsBrowser2/backend/templates" +) + +type DfServer struct { + router *mux.Router + templates *templates.Template + world *model.DfWorld +} + +func StartServer(world *model.DfWorld, static embed.FS) { + srv := &DfServer{ + router: mux.NewRouter().StrictSlash(true), + world: world, + } + srv.LoadTemplates() + + srv.RegisterResourcePage("/entity/{id}", "entity.html", func(id int) any { return srv.world.Entities[id] }) + srv.RegisterResourcePage("/hf/{id}", "hf.html", func(id int) any { return srv.world.HistoricalFigures[id] }) + srv.RegisterResourcePage("/region/{id}", "region.html", func(id int) any { return srv.world.Regions[id] }) + srv.RegisterResourcePage("/site/{id}", "site.html", func(id int) any { return srv.world.Sites[id] }) + srv.RegisterResourcePage("/artifact/{id}", "artifact.html", func(id int) any { return srv.world.Artifacts[id] }) + srv.RegisterPage("/events", "eventTypes.html", func(p Parms) any { return srv.world.AllEventTypes() }) + srv.RegisterPage("/events/{type}", "eventType.html", func(p Parms) any { return srv.world.EventsOfType(p["type"]) }) + + spa := spaHandler{staticFS: static, staticPath: "static", indexPath: "index.html"} + srv.router.PathPrefix("/").Handler(spa) + + OpenBrowser("http://localhost:8080") + + fmt.Println("Serving at :8080") + http.ListenAndServe(":8080", srv.router) +} + +type spaHandler struct { + staticFS embed.FS + staticPath string + indexPath string +} + +func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // get the absolute path to prevent directory traversal + path := r.URL.Path + // if err != nil { + // // if we failed to get the absolute path respond with a 400 bad request and stop + // http.Error(w, err.Error(), http.StatusBadRequest) + // return + // } + // prepend the path with the path to the static directory + path = h.staticPath + path + fmt.Println(r.URL, "->", path) + + _, err := h.staticFS.Open(path) + if os.IsNotExist(err) { + // file does not exist, serve index.html + fmt.Println(path) + index, err := h.staticFS.ReadFile(h.staticPath + "/" + h.indexPath) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.WriteHeader(http.StatusAccepted) + w.Write(index) + return + } else if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // get the subdirectory of the static dir + statics, err := fs.Sub(h.staticFS, h.staticPath) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // otherwise, use http.FileServer to serve the static dir + http.FileServer(http.FS(statics)).ServeHTTP(w, r) +} diff --git a/backend/server/templates.go b/backend/server/templates.go new file mode 100644 index 0000000..4151d3a --- /dev/null +++ b/backend/server/templates.go @@ -0,0 +1,38 @@ +package server + +import ( + "fmt" + "html/template" + + "github.com/robertjanetzko/LegendsBrowser2/backend/model" + "github.com/robertjanetzko/LegendsBrowser2/backend/templates" + "github.com/robertjanetzko/LegendsBrowser2/backend/util" +) + +func (srv *DfServer) LoadTemplates() { + functions := template.FuncMap{ + "json": util.Json, + "check": func(condition bool, v any) any { + if condition { + return v + } + return nil + }, + "title": util.Title, + "hf": func(id int) template.HTML { return model.LinkHf(srv.world, id) }, + "getHf": func(id int) *model.HistoricalFigure { return srv.world.HistoricalFigures[id] }, + "entity": func(id int) template.HTML { return model.LinkEntity(srv.world, id) }, + "getEntity": func(id int) *model.Entity { return srv.world.Entities[id] }, + "site": func(id int) template.HTML { return model.LinkSite(srv.world, id) }, + "getSite": func(id int) *model.Site { return srv.world.Sites[id] }, + "region": func(id int) template.HTML { return model.LinkRegion(srv.world, id) }, + "getRegion": func(id int) *model.Region { return srv.world.Regions[id] }, + "events": func(obj any) *model.EventList { return model.NewEventList(srv.world, obj) }, + "season": model.Season, + "time": model.Time, + "html": func(value any) template.HTML { + return template.HTML(fmt.Sprint(value)) + }, + } + srv.templates = templates.New(functions) +} diff --git a/backend/server/util.go b/backend/server/util.go new file mode 100644 index 0000000..8608d28 --- /dev/null +++ b/backend/server/util.go @@ -0,0 +1,27 @@ +package server + +import ( + "fmt" + "os/exec" + "runtime" +) + +func OpenBrowser(url string) { + var err error + + switch runtime.GOOS { + case "linux": + err = exec.Command("xdg-open", url).Start() + case "windows": + err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() + case "darwin": + err = exec.Command("open", url).Start() + default: + err = fmt.Errorf("unsupported platform") + } + if err != nil { + fmt.Println(err) + fmt.Println("navigate to http://localhost:8080 in your browser") + } + +}