dorfylegends/backend/main.go

245 lines
7.6 KiB
Go
Raw Normal View History

2022-04-09 12:01:04 +03:00
package main
import (
2022-04-15 17:46:51 +03:00
"embed"
2022-04-13 08:28:07 +03:00
"flag"
2022-04-09 12:01:04 +03:00
"fmt"
2022-04-16 21:34:19 +03:00
"html/template"
2022-04-15 17:46:51 +03:00
"io/fs"
2022-04-09 12:01:04 +03:00
"net/http"
2022-04-11 00:27:37 +03:00
_ "net/http/pprof"
2022-04-14 16:49:09 +03:00
"os"
2022-04-11 00:27:37 +03:00
"runtime"
2022-04-18 11:36:29 +03:00
"sort"
2022-04-16 21:34:19 +03:00
"strconv"
2022-04-09 12:01:04 +03:00
"github.com/gorilla/mux"
2022-04-13 08:28:07 +03:00
"github.com/pkg/profile"
2022-04-14 18:39:18 +03:00
"github.com/robertjanetzko/LegendsBrowser2/backend/model"
2022-04-16 21:34:19 +03:00
"github.com/robertjanetzko/LegendsBrowser2/backend/templates"
2022-04-19 18:46:11 +03:00
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
2022-04-09 12:01:04 +03:00
)
2022-04-14 18:39:18 +03:00
var world *model.DfWorld
2022-04-09 12:01:04 +03:00
2022-04-19 12:46:43 +03:00
//go:embed static
var static embed.FS
2022-04-15 17:46:51 +03:00
2022-04-09 12:01:04 +03:00
func main() {
2022-04-13 15:01:20 +03:00
f := flag.String("f", "", "open a file")
2022-04-20 13:46:42 +03:00
p := flag.Bool("p", false, "start profiling")
2022-04-13 15:01:20 +03:00
flag.Parse()
2022-04-15 17:46:51 +03:00
router := mux.NewRouter().StrictSlash(true)
2022-04-16 21:34:19 +03:00
functions := template.FuncMap{
2022-04-21 17:25:35 +03:00
"json": util.Json,
2022-04-16 21:34:19 +03:00
"check": func(condition bool, v any) any {
if condition {
return v
}
return nil
},
2022-04-21 17:25:35 +03:00
"title": util.Title,
2022-04-22 18:45:10 +03:00
"hf": model.LinkHf,
2022-04-16 21:34:19 +03:00
"getHf": func(id int) *model.HistoricalFigure { return world.HistoricalFigures[id] },
2022-04-22 18:45:10 +03:00
"entity": model.LinkEntity,
2022-04-16 21:34:19 +03:00
"getEntity": func(id int) *model.Entity { return world.Entities[id] },
2022-04-22 18:45:10 +03:00
"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] },
2022-04-23 22:38:03 +03:00
"events": model.NewEventList,
2022-04-18 11:36:29 +03:00
"season": func(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
},
2022-04-19 12:46:43 +03:00
"html": func(value any) template.HTML {
return template.HTML(fmt.Sprint(value))
},
2022-04-16 21:34:19 +03:00
}
t := templates.New(functions)
2022-04-13 15:01:20 +03:00
if len(*f) > 0 {
2022-04-20 13:46:42 +03:00
if *p {
defer profile.Start(profile.ProfilePath(".")).Stop()
go func() {
http.ListenAndServe(":8081", nil)
}()
}
2022-04-14 16:49:09 +03:00
2022-04-14 18:39:18 +03:00
w, err := model.Parse(*f)
2022-04-13 15:01:20 +03:00
if err != nil {
fmt.Println(err)
2022-04-14 16:49:09 +03:00
os.Exit(1)
2022-04-13 15:01:20 +03:00
}
world = w
2022-04-09 12:01:04 +03:00
2022-04-14 16:49:09 +03:00
fmt.Println("Hallo Welt!")
runtime.GC()
// world.Process()
// model.ListOtherElements("world", &[]*model.World{&world})
// model.ListOtherElements("region", &world.Regions)
// model.ListOtherElements("underground regions", &world.UndergroundRegions)
// model.ListOtherElements("landmasses", &world.Landmasses)
// model.ListOtherElements("sites", &world.Sites)
// model.ListOtherElements("world constructions", &world.WorldConstructions)
// model.ListOtherElements("artifacts", &world.Artifacts)
// model.ListOtherElements("entities", &world.Entities)
// model.ListOtherElements("hf", &world.HistoricalFigures)
// model.ListOtherElements("events", &world.HistoricalEvents)
// model.ListOtherElements("collections", &world.HistoricalEventCollections)
// model.ListOtherElements("era", &world.HistoricalEras)
// model.ListOtherElements("danceForm", &world.DanceForms)
// model.ListOtherElements("musicalForm", &world.MusicalForms)
// model.ListOtherElements("poeticForm", &world.PoeticForms)
// model.ListOtherElements("written", &world.WrittenContents)
2022-04-16 23:12:23 +03:00
// server.RegisterResource(router, "region", world.Regions)
// // server.RegisterResource(router, "undergroundRegion", world.UndergroundRegions)
// server.RegisterResource(router, "landmass", world.Landmasses)
// server.RegisterResource(router, "site", world.Sites)
// server.RegisterResource(router, "worldConstruction", world.WorldConstructions)
// server.RegisterResource(router, "artifact", world.Artifacts)
// server.RegisterResource(router, "hf", world.HistoricalFigures)
// server.RegisterResource(router, "collection", world.HistoricalEventCollections)
// server.RegisterResource(router, "entity", world.Entities)
// server.RegisterResource(router, "event", world.HistoricalEvents)
// // server.RegisterResource(router, "era", world.HistoricalEras)
// server.RegisterResource(router, "danceForm", world.DanceForms)
// server.RegisterResource(router, "musicalForm", world.MusicalForms)
// server.RegisterResource(router, "poeticForm", world.PoeticForms)
2022-04-14 16:49:09 +03:00
// server.RegisterResource(router, "written", world.WrittenContents)
2022-04-16 21:34:19 +03:00
2022-04-19 18:46:11 +03:00
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] })
2022-04-22 18:45:10 +03:00
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] })
2022-04-19 18:46:11 +03:00
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"]) })
2022-04-15 17:46:51 +03:00
}
2022-04-19 12:46:43 +03:00
spa := spaHandler{staticFS: static, staticPath: "static", indexPath: "index.html"}
2022-04-15 17:46:51 +03:00
router.PathPrefix("/").Handler(spa)
fmt.Println("Serving at :8080")
http.ListenAndServe(":8080", router)
2022-04-19 18:46:11 +03:00
}
2022-04-14 16:49:09 +03:00
2022-04-19 18:46:11 +03:00
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
2022-04-15 17:46:51 +03:00
}
2022-04-19 18:46:11 +03:00
func eventsOfType(t string) any {
var list []*model.HistoricalEvent
for _, e := range world.HistoricalEvents {
if e.Details.Type() == t {
list = append(list, e)
2022-04-16 21:34:19 +03:00
}
2022-04-19 18:46:11 +03:00
}
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)))
2022-04-16 21:34:19 +03:00
if err != nil {
fmt.Fprintln(w, err)
fmt.Println(err)
}
}
router.HandleFunc(path, get).Methods("GET")
}
2022-04-19 18:46:11 +03:00
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)
})
}
2022-04-15 17:46:51 +03:00
type spaHandler struct {
staticFS embed.FS
staticPath string
indexPath string
}
2022-04-14 16:49:09 +03:00
2022-04-15 17:46:51 +03:00
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
2022-04-19 12:46:43 +03:00
fmt.Println(r.URL, "->", path)
2022-04-15 17:46:51 +03:00
_, 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
2022-04-14 16:49:09 +03:00
}
2022-04-09 19:37:44 +03:00
2022-04-15 17:46:51 +03:00
// 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)
2022-04-09 12:01:04 +03:00
}