restructure
This commit is contained in:
parent
597f26b4dd
commit
a9f3597edf
|
@ -0,0 +1,2 @@
|
||||||
|
*.json
|
||||||
|
analyze
|
|
@ -1,22 +1,9 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"encoding/xml"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/iancoleman/strcase"
|
"github.com/robertjanetzko/LegendsBrowser2/analyze/df"
|
||||||
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -25,541 +12,10 @@ func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if len(*a) > 0 {
|
if len(*a) > 0 {
|
||||||
Analyze(*a)
|
df.Analyze(*a)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *g {
|
if *g {
|
||||||
fmt.Println("Generating")
|
df.Generate()
|
||||||
Generate()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Analyze(filex string) {
|
|
||||||
fmt.Println("Search...", filex)
|
|
||||||
files, err := filepath.Glob(filex + "/*.xml")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println(files)
|
|
||||||
|
|
||||||
a := NewAnalyzeData()
|
|
||||||
|
|
||||||
for _, file := range files {
|
|
||||||
analyze(file, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, _ := json.MarshalIndent(a, "", " ")
|
|
||||||
_ = ioutil.WriteFile("analyze.json", file, 0644)
|
|
||||||
|
|
||||||
createMetadata(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Generate() {
|
|
||||||
data, err := ioutil.ReadFile("analyze.json")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
a := NewAnalyzeData()
|
|
||||||
json.Unmarshal(data, a)
|
|
||||||
createMetadata(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
type FieldData struct {
|
|
||||||
IsString bool
|
|
||||||
Multiple bool
|
|
||||||
Base bool
|
|
||||||
Plus bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFieldData() *FieldData {
|
|
||||||
return &FieldData{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type AnalyzeData struct {
|
|
||||||
// Types map[string]bool
|
|
||||||
Fields map[string]*FieldData
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewAnalyzeData() *AnalyzeData {
|
|
||||||
return &AnalyzeData{
|
|
||||||
// Types: make(map[string]bool, 0),
|
|
||||||
Fields: make(map[string]*FieldData, 0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AnalyzeData) GetField(s string) *FieldData {
|
|
||||||
if f, ok := a.Fields[s]; ok {
|
|
||||||
return f
|
|
||||||
} else {
|
|
||||||
f := &FieldData{}
|
|
||||||
a.Fields[s] = f
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func analyze(file string, a *AnalyzeData) error {
|
|
||||||
xmlFile, err := os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
plus := strings.HasSuffix(file, "_plus.xml")
|
|
||||||
|
|
||||||
fmt.Println("Successfully Opened", file)
|
|
||||||
defer xmlFile.Close()
|
|
||||||
|
|
||||||
converter := util.NewConvertReader(xmlFile)
|
|
||||||
|
|
||||||
return analyzeElement(xml.NewDecoder(converter), a, make([]string, 0), plus)
|
|
||||||
}
|
|
||||||
|
|
||||||
const PATH_SEPARATOR = "|"
|
|
||||||
|
|
||||||
func analyzeElement(d *xml.Decoder, a *AnalyzeData, path []string, plus bool) error {
|
|
||||||
if len(path) > 1 {
|
|
||||||
s := strings.Join(path, PATH_SEPARATOR)
|
|
||||||
fd := NewFieldData()
|
|
||||||
a.Fields[s] = fd
|
|
||||||
if plus {
|
|
||||||
fd.Plus = true
|
|
||||||
} else {
|
|
||||||
fd.Base = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
data []byte
|
|
||||||
)
|
|
||||||
value := true
|
|
||||||
|
|
||||||
fields := make(map[string]bool)
|
|
||||||
|
|
||||||
Loop:
|
|
||||||
for {
|
|
||||||
tok, err := d.Token()
|
|
||||||
if err == io.EOF {
|
|
||||||
break Loop
|
|
||||||
} else if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
switch t := tok.(type) {
|
|
||||||
case xml.StartElement:
|
|
||||||
value = false
|
|
||||||
|
|
||||||
// a.Types[strings.Join(path, PATH_SEPARATOR)] = true
|
|
||||||
|
|
||||||
newPath := append(path, t.Name.Local)
|
|
||||||
|
|
||||||
if _, ok := fields[t.Name.Local]; ok {
|
|
||||||
a.Fields[strings.Join(newPath, PATH_SEPARATOR)].Multiple = true
|
|
||||||
}
|
|
||||||
fields[t.Name.Local] = true
|
|
||||||
|
|
||||||
analyzeElement(d, a, newPath, plus)
|
|
||||||
|
|
||||||
case xml.CharData:
|
|
||||||
data = append(data, t...)
|
|
||||||
|
|
||||||
case xml.EndElement:
|
|
||||||
if value {
|
|
||||||
if _, err := strconv.Atoi(string(data)); err != nil {
|
|
||||||
a.Fields[strings.Join(path, PATH_SEPARATOR)].IsString = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if t.Name.Local == "type" {
|
|
||||||
path[len(path)-2] = path[len(path)-2] + "+" + strcase.ToCamel(string(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var allowedTyped = map[string]bool{
|
|
||||||
"df_world|historical_events|historical_event": true,
|
|
||||||
"df_world|historical_event_collections|historical_event_collection": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
func filterSubtypes(data *map[string]*FieldData) []string {
|
|
||||||
filtered := make(map[string]*FieldData)
|
|
||||||
for k, v := range *data {
|
|
||||||
path := strings.Split(k, PATH_SEPARATOR)
|
|
||||||
for index, seg := range path {
|
|
||||||
if strings.Contains(seg, "+") {
|
|
||||||
base := seg[:strings.Index(seg, "+")]
|
|
||||||
basePath := strings.Join(append(path[:index], base), PATH_SEPARATOR)
|
|
||||||
if allowedTyped[basePath] {
|
|
||||||
path[index] = seg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filtered[strings.Join(path, PATH_SEPARATOR)] = v
|
|
||||||
}
|
|
||||||
*data = filtered
|
|
||||||
list := util.Keys(filtered)
|
|
||||||
sort.Strings(list)
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSubtypes(objectTypes []string, k string) *[]string {
|
|
||||||
subtypes := make(map[string]bool)
|
|
||||||
|
|
||||||
for _, t := range objectTypes {
|
|
||||||
if strings.HasPrefix(t, k+"+") && !strings.Contains(t[len(k):], PATH_SEPARATOR) {
|
|
||||||
subtypes[t[strings.LastIndex(t, "+")+1:]] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
keys := util.Keys(subtypes)
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
if len(keys) > 0 {
|
|
||||||
return &keys
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSubtypeOf(k string) *string {
|
|
||||||
if strings.Contains(k, PATH_SEPARATOR) {
|
|
||||||
last := k[strings.LastIndex(k, PATH_SEPARATOR)+1:]
|
|
||||||
if strings.Contains(last, "+") {
|
|
||||||
base := strcase.ToCamel(last[:strings.Index(last, "+")])
|
|
||||||
return &base
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createMetadata(a *AnalyzeData) {
|
|
||||||
|
|
||||||
// ts := filterSubtypes(a.Types)
|
|
||||||
fs := filterSubtypes(&a.Fields)
|
|
||||||
|
|
||||||
var objectTypes []string
|
|
||||||
for k := range a.Fields {
|
|
||||||
path := strings.Split(k, PATH_SEPARATOR)
|
|
||||||
if len(path) >= 2 {
|
|
||||||
objectTypes = append(objectTypes, strings.Join(path[:len(path)-1], PATH_SEPARATOR))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// for _, s := range fs {
|
|
||||||
// fmt.Println(s)
|
|
||||||
// }
|
|
||||||
|
|
||||||
objects := make(map[string]Object, 0)
|
|
||||||
|
|
||||||
for _, k := range objectTypes {
|
|
||||||
if ok, _ := isArray(k, fs); !ok {
|
|
||||||
n := k
|
|
||||||
if strings.Contains(k, PATH_SEPARATOR) {
|
|
||||||
n = k[strings.LastIndex(k, PATH_SEPARATOR)+1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
if n == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
objFields := make(map[string]Field, 0)
|
|
||||||
|
|
||||||
for _, f := range fs {
|
|
||||||
if strings.HasPrefix(f, k+PATH_SEPARATOR) {
|
|
||||||
fn := f[len(k)+1:]
|
|
||||||
if !strings.Contains(fn, PATH_SEPARATOR) {
|
|
||||||
legend := ""
|
|
||||||
if a.Fields[f].Base && a.Fields[f].Plus {
|
|
||||||
legend = "both"
|
|
||||||
} else if a.Fields[f].Base {
|
|
||||||
legend = "base"
|
|
||||||
} else if a.Fields[f].Plus {
|
|
||||||
legend = "plus"
|
|
||||||
}
|
|
||||||
|
|
||||||
field := Field{
|
|
||||||
Name: strcase.ToCamel(fn),
|
|
||||||
Type: "int",
|
|
||||||
Multiple: a.Fields[f].Multiple,
|
|
||||||
Legend: legend,
|
|
||||||
}
|
|
||||||
if ok, elements := isArray(f, fs); ok {
|
|
||||||
el := elements[strings.LastIndex(elements, PATH_SEPARATOR)+1:]
|
|
||||||
if _, ok := a.Fields[elements+PATH_SEPARATOR+"id"]; ok {
|
|
||||||
field.Type = "map"
|
|
||||||
} else {
|
|
||||||
field.Type = "array"
|
|
||||||
}
|
|
||||||
field.ElementType = &(el)
|
|
||||||
} else if ok, _ := isObject(f, fs); ok {
|
|
||||||
field.Type = "object"
|
|
||||||
} else if a.Fields[f].IsString {
|
|
||||||
field.Type = "string"
|
|
||||||
}
|
|
||||||
objFields[fn] = field
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
objects[n] = Object{
|
|
||||||
Name: strcase.ToCamel(n),
|
|
||||||
Id: a.Fields[k+PATH_SEPARATOR+"id"] != nil,
|
|
||||||
Named: a.Fields[k+PATH_SEPARATOR+"name"] != nil,
|
|
||||||
Typed: a.Fields[k+PATH_SEPARATOR+"type"] != nil,
|
|
||||||
SubTypes: getSubtypes(objectTypes, k),
|
|
||||||
SubTypeOf: getSubtypeOf(k),
|
|
||||||
Fields: objFields,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file, _ := json.MarshalIndent(objects, "", " ")
|
|
||||||
_ = ioutil.WriteFile("model.json", file, 0644)
|
|
||||||
|
|
||||||
f, err := os.Create("df/model.go")
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
err = packageTemplate.Execute(f, struct {
|
|
||||||
Objects map[string]Object
|
|
||||||
}{
|
|
||||||
Objects: objects,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isArray(typ string, types []string) (bool, string) {
|
|
||||||
fc := 0
|
|
||||||
elements := ""
|
|
||||||
|
|
||||||
if !strings.Contains(typ, PATH_SEPARATOR) || strings.Contains(typ[strings.LastIndex(typ, PATH_SEPARATOR):], "+") {
|
|
||||||
return false, ""
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, t := range types {
|
|
||||||
if !strings.HasPrefix(t, typ+PATH_SEPARATOR) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.Contains(t[len(typ)+1:], PATH_SEPARATOR) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fc++
|
|
||||||
elements = t
|
|
||||||
}
|
|
||||||
return fc == 1, elements
|
|
||||||
}
|
|
||||||
|
|
||||||
func isObject(typ string, types []string) (bool, string) {
|
|
||||||
fc := 0
|
|
||||||
|
|
||||||
for _, t := range types {
|
|
||||||
if !strings.HasPrefix(t, typ+PATH_SEPARATOR) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fc++
|
|
||||||
}
|
|
||||||
return fc > 0, typ
|
|
||||||
}
|
|
||||||
|
|
||||||
type Object struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Id bool `json:"id,omitempty"`
|
|
||||||
Named bool `json:"named,omitempty"`
|
|
||||||
Typed bool `json:"typed,omitempty"`
|
|
||||||
SubTypes *[]string `json:"subtypes,omitempty"`
|
|
||||||
SubTypeOf *string `json:"subtypeof,omitempty"`
|
|
||||||
Fields map[string]Field `json:"fields"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Field struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Multiple bool `json:"multiple,omitempty"`
|
|
||||||
ElementType *string `json:"elements,omitempty"`
|
|
||||||
Legend string `json:"legend"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f Field) TypeLine(objects map[string]Object) string {
|
|
||||||
n := f.Name
|
|
||||||
|
|
||||||
if n == "Id" || n == "Name" {
|
|
||||||
n = n + "_"
|
|
||||||
}
|
|
||||||
|
|
||||||
m := ""
|
|
||||||
if f.Multiple {
|
|
||||||
m = "[]"
|
|
||||||
}
|
|
||||||
t := f.Type
|
|
||||||
if f.Type == "array" {
|
|
||||||
t = "[]*" + objects[*f.ElementType].Name
|
|
||||||
}
|
|
||||||
if f.Type == "map" {
|
|
||||||
t = "map[int]*" + objects[*f.ElementType].Name
|
|
||||||
}
|
|
||||||
if f.Type == "object" {
|
|
||||||
t = "*" + f.Name
|
|
||||||
}
|
|
||||||
j := fmt.Sprintf("`json:\"%s\" legend:\"%s\"`", strcase.ToLowerCamel(f.Name), f.Legend)
|
|
||||||
return fmt.Sprintf("%s %s%s %s", n, m, t, j)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f Field) StartAction() string {
|
|
||||||
n := f.Name
|
|
||||||
|
|
||||||
if n == "Id" || n == "Name" {
|
|
||||||
n = n + "_"
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.Type == "object" {
|
|
||||||
p := fmt.Sprintf("v, _ := parse%s(d, &t)", f.Name)
|
|
||||||
if !f.Multiple {
|
|
||||||
return fmt.Sprintf("%s\nobj.%s = v", p, n)
|
|
||||||
} else {
|
|
||||||
return fmt.Sprintf("%s\nobj.%s = append(obj.%s, v)", p, n, n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.Type == "array" || f.Type == "map" {
|
|
||||||
el := strcase.ToCamel(*f.ElementType)
|
|
||||||
gen := fmt.Sprintf("parse%s", el)
|
|
||||||
|
|
||||||
if f.Type == "array" {
|
|
||||||
return fmt.Sprintf("parseArray(d, &obj.%s, %s)", f.Name, gen)
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.Type == "map" {
|
|
||||||
return fmt.Sprintf("obj.%s = make(map[int]*%s)\nparseMap(d, &obj.%s, %s)", f.Name, el, f.Name, gen)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.Type == "int" || f.Type == "string" {
|
|
||||||
return "data = nil"
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f Field) EndAction() string {
|
|
||||||
n := f.Name
|
|
||||||
|
|
||||||
if n == "Id" || n == "Name" {
|
|
||||||
n = n + "_"
|
|
||||||
}
|
|
||||||
|
|
||||||
if !f.Multiple {
|
|
||||||
if f.Type == "int" {
|
|
||||||
return fmt.Sprintf("obj.%s = n(data)", n)
|
|
||||||
} else if f.Type == "string" {
|
|
||||||
return fmt.Sprintf("obj.%s = string(data)", n)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if f.Type == "int" {
|
|
||||||
return fmt.Sprintf("obj.%s = append(obj.%s, n(data))", n, n)
|
|
||||||
} else if f.Type == "string" {
|
|
||||||
return fmt.Sprintf("obj.%s = append(obj.%s, string(data))", n, n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var packageTemplate = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT.
|
|
||||||
package df
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/xml"
|
|
||||||
"strconv"
|
|
||||||
"github.com/iancoleman/strcase"
|
|
||||||
)
|
|
||||||
|
|
||||||
{{- range $name, $obj := .Objects }}
|
|
||||||
type {{ $obj.Name }} struct {
|
|
||||||
{{- range $fname, $field := $obj.Fields }}
|
|
||||||
{{- if not (and (eq $fname "type") (not (not $obj.SubTypes))) }}
|
|
||||||
{{ $field.TypeLine $.Objects }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if not (not $obj.SubTypes) }}
|
|
||||||
Details any
|
|
||||||
{{- end }}
|
|
||||||
}
|
|
||||||
|
|
||||||
{{- if $obj.Id }}
|
|
||||||
func (x *{{ $obj.Name }}) Id() int { return x.Id_ }
|
|
||||||
{{- end }}
|
|
||||||
{{- if $obj.Named }}
|
|
||||||
func (x *{{ $obj.Name }}) Name() string { return x.Name_ }
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
// Parser
|
|
||||||
|
|
||||||
func n(d []byte) int {
|
|
||||||
v, _ := strconv.Atoi(string(d))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
{{- range $name, $obj := .Objects }}
|
|
||||||
func parse{{ $obj.Name }}(d *xml.Decoder, start *xml.StartElement) (*{{ $obj.Name }}, error) {
|
|
||||||
var (
|
|
||||||
obj = {{ $obj.Name }}{}
|
|
||||||
data []byte
|
|
||||||
)
|
|
||||||
for {
|
|
||||||
tok, err := d.Token()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
switch t := tok.(type) {
|
|
||||||
case xml.StartElement:
|
|
||||||
switch t.Name.Local {
|
|
||||||
{{- range $fname, $field := $obj.Fields }}
|
|
||||||
case "{{ $fname }}":
|
|
||||||
{{ $field.StartAction }}
|
|
||||||
{{- end }}
|
|
||||||
default:
|
|
||||||
// fmt.Println("unknown field", t.Name.Local)
|
|
||||||
d.Skip()
|
|
||||||
}
|
|
||||||
|
|
||||||
case xml.CharData:
|
|
||||||
data = append(data, t...)
|
|
||||||
|
|
||||||
case xml.EndElement:
|
|
||||||
if t.Name.Local == start.Name.Local {
|
|
||||||
return &obj, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch t.Name.Local {
|
|
||||||
{{- range $fname, $field := $obj.Fields }}
|
|
||||||
case "{{ $fname }}":
|
|
||||||
{{- if and (eq $fname "type") (not (not $obj.SubTypes)) }}
|
|
||||||
var err error
|
|
||||||
switch strcase.ToCamel(string(data)) {
|
|
||||||
{{- range $sub := $obj.SubTypes }}
|
|
||||||
case "{{ $sub }}":
|
|
||||||
obj.Details, err = parse{{ $obj.Name }}{{ $sub }}(d, start)
|
|
||||||
{{- end }}
|
|
||||||
default:
|
|
||||||
d.Skip()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &obj, nil
|
|
||||||
{{- else }}
|
|
||||||
{{ $field.EndAction }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
default:
|
|
||||||
// fmt.Println("unknown field", t.Name.Local)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{{- end }}
|
|
||||||
`))
|
|
||||||
|
|
|
@ -0,0 +1,235 @@
|
||||||
|
package df
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/iancoleman/strcase"
|
||||||
|
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Analyze(filex string) error {
|
||||||
|
fmt.Println("Search...", filex)
|
||||||
|
files, err := filepath.Glob(filex + "/*.xml")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(files)
|
||||||
|
|
||||||
|
a := NewAnalyzeData()
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
analyze(file, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.Save()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Generate() error {
|
||||||
|
a, err := LoadAnalyzeData()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return createMetadata(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
var allowedTyped = map[string]bool{
|
||||||
|
"df_world|historical_events|historical_event": true,
|
||||||
|
"df_world|historical_event_collections|historical_event_collection": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterSubtypes(data *map[string]*FieldData) []string {
|
||||||
|
filtered := make(map[string]*FieldData)
|
||||||
|
for k, v := range *data {
|
||||||
|
path := strings.Split(k, PATH_SEPARATOR)
|
||||||
|
for index, seg := range path {
|
||||||
|
if strings.Contains(seg, "+") {
|
||||||
|
base := seg[:strings.Index(seg, "+")]
|
||||||
|
basePath := strings.Join(append(path[:index], base), PATH_SEPARATOR)
|
||||||
|
if allowedTyped[basePath] {
|
||||||
|
path[index] = seg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filtered[strings.Join(path, PATH_SEPARATOR)] = v
|
||||||
|
}
|
||||||
|
*data = filtered
|
||||||
|
list := util.Keys(filtered)
|
||||||
|
sort.Strings(list)
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSubtypes(objectTypes []string, k string) *[]string {
|
||||||
|
subtypes := make(map[string]bool)
|
||||||
|
|
||||||
|
for _, t := range objectTypes {
|
||||||
|
if strings.HasPrefix(t, k+"+") && !strings.Contains(t[len(k):], PATH_SEPARATOR) {
|
||||||
|
subtypes[t[strings.LastIndex(t, "+")+1:]] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keys := util.Keys(subtypes)
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
if len(keys) > 0 {
|
||||||
|
return &keys
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSubtypeOf(k string) *string {
|
||||||
|
if strings.Contains(k, PATH_SEPARATOR) {
|
||||||
|
last := k[strings.LastIndex(k, PATH_SEPARATOR)+1:]
|
||||||
|
if strings.Contains(last, "+") {
|
||||||
|
base := strcase.ToCamel(last[:strings.Index(last, "+")])
|
||||||
|
return &base
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createMetadata(a *AnalyzeData) error {
|
||||||
|
fs := filterSubtypes(&a.Fields)
|
||||||
|
|
||||||
|
var objectTypes []string
|
||||||
|
for k := range a.Fields {
|
||||||
|
path := strings.Split(k, PATH_SEPARATOR)
|
||||||
|
if len(path) >= 2 {
|
||||||
|
objectTypes = append(objectTypes, strings.Join(path[:len(path)-1], PATH_SEPARATOR))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
objects := make(map[string]Object, 0)
|
||||||
|
|
||||||
|
for _, k := range objectTypes {
|
||||||
|
if ok, _ := isArray(k, fs); !ok {
|
||||||
|
n := k
|
||||||
|
if strings.Contains(k, PATH_SEPARATOR) {
|
||||||
|
n = k[strings.LastIndex(k, PATH_SEPARATOR)+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
objFields := make(map[string]Field, 0)
|
||||||
|
|
||||||
|
for _, f := range fs {
|
||||||
|
if strings.HasPrefix(f, k+PATH_SEPARATOR) {
|
||||||
|
fn := f[len(k)+1:]
|
||||||
|
if !strings.Contains(fn, PATH_SEPARATOR) {
|
||||||
|
legend := ""
|
||||||
|
if a.Fields[f].Base && a.Fields[f].Plus {
|
||||||
|
legend = "both"
|
||||||
|
} else if a.Fields[f].Base {
|
||||||
|
legend = "base"
|
||||||
|
} else if a.Fields[f].Plus {
|
||||||
|
legend = "plus"
|
||||||
|
}
|
||||||
|
|
||||||
|
field := Field{
|
||||||
|
Name: strcase.ToCamel(fn),
|
||||||
|
Type: "int",
|
||||||
|
Multiple: a.Fields[f].Multiple,
|
||||||
|
Legend: legend,
|
||||||
|
}
|
||||||
|
if ok, elements := isArray(f, fs); ok {
|
||||||
|
el := elements[strings.LastIndex(elements, PATH_SEPARATOR)+1:]
|
||||||
|
if _, ok := a.Fields[elements+PATH_SEPARATOR+"id"]; ok {
|
||||||
|
field.Type = "map"
|
||||||
|
} else {
|
||||||
|
field.Type = "array"
|
||||||
|
}
|
||||||
|
field.ElementType = &(el)
|
||||||
|
} else if ok, _ := isObject(f, fs); ok {
|
||||||
|
field.Type = "object"
|
||||||
|
} else if a.Fields[f].IsString {
|
||||||
|
field.Type = "string"
|
||||||
|
}
|
||||||
|
objFields[fn] = field
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
objects[n] = Object{
|
||||||
|
Name: strcase.ToCamel(n),
|
||||||
|
Id: a.Fields[k+PATH_SEPARATOR+"id"] != nil,
|
||||||
|
Named: a.Fields[k+PATH_SEPARATOR+"name"] != nil,
|
||||||
|
Typed: a.Fields[k+PATH_SEPARATOR+"type"] != nil,
|
||||||
|
SubTypes: getSubtypes(objectTypes, k),
|
||||||
|
SubTypeOf: getSubtypeOf(k),
|
||||||
|
Fields: objFields,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return generateCode(&objects)
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateCode(objects *map[string]Object) error {
|
||||||
|
file, _ := json.MarshalIndent(objects, "", " ")
|
||||||
|
_ = ioutil.WriteFile("model.json", file, 0644)
|
||||||
|
|
||||||
|
f, err := os.Create("../backend/model/model.go")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err = packageTemplate.Execute(&buf, struct {
|
||||||
|
Objects *map[string]Object
|
||||||
|
}{
|
||||||
|
Objects: objects,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p, err := format.Source(buf.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = f.Write(p)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func isArray(typ string, types []string) (bool, string) {
|
||||||
|
fc := 0
|
||||||
|
elements := ""
|
||||||
|
|
||||||
|
if !strings.Contains(typ, PATH_SEPARATOR) || strings.Contains(typ[strings.LastIndex(typ, PATH_SEPARATOR):], "+") {
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, t := range types {
|
||||||
|
if !strings.HasPrefix(t, typ+PATH_SEPARATOR) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.Contains(t[len(typ)+1:], PATH_SEPARATOR) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fc++
|
||||||
|
elements = t
|
||||||
|
}
|
||||||
|
return fc == 1, elements
|
||||||
|
}
|
||||||
|
|
||||||
|
func isObject(typ string, types []string) (bool, string) {
|
||||||
|
fc := 0
|
||||||
|
|
||||||
|
for _, t := range types {
|
||||||
|
if !strings.HasPrefix(t, typ+PATH_SEPARATOR) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fc++
|
||||||
|
}
|
||||||
|
return fc > 0, typ
|
||||||
|
}
|
|
@ -0,0 +1,208 @@
|
||||||
|
package df
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/iancoleman/strcase"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Object struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Id bool `json:"id,omitempty"`
|
||||||
|
Named bool `json:"named,omitempty"`
|
||||||
|
Typed bool `json:"typed,omitempty"`
|
||||||
|
SubTypes *[]string `json:"subtypes,omitempty"`
|
||||||
|
SubTypeOf *string `json:"subtypeof,omitempty"`
|
||||||
|
Fields map[string]Field `json:"fields"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Field struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Multiple bool `json:"multiple,omitempty"`
|
||||||
|
ElementType *string `json:"elements,omitempty"`
|
||||||
|
Legend string `json:"legend"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f Field) TypeLine(objects map[string]Object) string {
|
||||||
|
n := f.Name
|
||||||
|
|
||||||
|
if n == "Id" || n == "Name" {
|
||||||
|
n = n + "_"
|
||||||
|
}
|
||||||
|
|
||||||
|
m := ""
|
||||||
|
if f.Multiple {
|
||||||
|
m = "[]"
|
||||||
|
}
|
||||||
|
t := f.Type
|
||||||
|
if f.Type == "array" {
|
||||||
|
t = "[]*" + objects[*f.ElementType].Name
|
||||||
|
}
|
||||||
|
if f.Type == "map" {
|
||||||
|
t = "map[int]*" + objects[*f.ElementType].Name
|
||||||
|
}
|
||||||
|
if f.Type == "object" {
|
||||||
|
t = "*" + f.Name
|
||||||
|
}
|
||||||
|
j := fmt.Sprintf("`json:\"%s\" legend:\"%s\"`", strcase.ToLowerCamel(f.Name), f.Legend)
|
||||||
|
return fmt.Sprintf("%s %s%s %s", n, m, t, j)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f Field) StartAction() string {
|
||||||
|
n := f.Name
|
||||||
|
|
||||||
|
if n == "Id" || n == "Name" {
|
||||||
|
n = n + "_"
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.Type == "object" {
|
||||||
|
p := fmt.Sprintf("v, _ := parse%s(d, &t)", f.Name)
|
||||||
|
if !f.Multiple {
|
||||||
|
return fmt.Sprintf("%s\nobj.%s = v", p, n)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%s\nobj.%s = append(obj.%s, v)", p, n, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.Type == "array" || f.Type == "map" {
|
||||||
|
el := strcase.ToCamel(*f.ElementType)
|
||||||
|
gen := fmt.Sprintf("parse%s", el)
|
||||||
|
|
||||||
|
if f.Type == "array" {
|
||||||
|
return fmt.Sprintf("parseArray(d, &obj.%s, %s)", f.Name, gen)
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.Type == "map" {
|
||||||
|
return fmt.Sprintf("obj.%s = make(map[int]*%s)\nparseMap(d, &obj.%s, %s)", f.Name, el, f.Name, gen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.Type == "int" || f.Type == "string" {
|
||||||
|
return "data = nil"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f Field) EndAction() string {
|
||||||
|
n := f.Name
|
||||||
|
|
||||||
|
if n == "Id" || n == "Name" {
|
||||||
|
n = n + "_"
|
||||||
|
}
|
||||||
|
|
||||||
|
if !f.Multiple {
|
||||||
|
if f.Type == "int" {
|
||||||
|
return fmt.Sprintf("obj.%s = n(data)", n)
|
||||||
|
} else if f.Type == "string" {
|
||||||
|
return fmt.Sprintf("obj.%s = string(data)", n)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if f.Type == "int" {
|
||||||
|
return fmt.Sprintf("obj.%s = append(obj.%s, n(data))", n, n)
|
||||||
|
} else if f.Type == "string" {
|
||||||
|
return fmt.Sprintf("obj.%s = append(obj.%s, string(data))", n, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var packageTemplate = template.Must(template.New("").Parse(`// Code generated by legendsbrowser; DO NOT EDIT.
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"strconv"
|
||||||
|
"github.com/iancoleman/strcase"
|
||||||
|
)
|
||||||
|
|
||||||
|
{{- range $name, $obj := .Objects }}
|
||||||
|
type {{ $obj.Name }} struct {
|
||||||
|
{{- range $fname, $field := $obj.Fields }}
|
||||||
|
{{- if not (and (eq $fname "type") (not (not $obj.SubTypes))) }}
|
||||||
|
{{ $field.TypeLine $.Objects }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if not (not $obj.SubTypes) }}
|
||||||
|
Details any
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{- if $obj.Id }}
|
||||||
|
func (x *{{ $obj.Name }}) Id() int { return x.Id_ }
|
||||||
|
{{- end }}
|
||||||
|
{{- if $obj.Named }}
|
||||||
|
func (x *{{ $obj.Name }}) Name() string { return x.Name_ }
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
// Parser
|
||||||
|
|
||||||
|
func n(d []byte) int {
|
||||||
|
v, _ := strconv.Atoi(string(d))
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
{{- range $name, $obj := .Objects }}
|
||||||
|
func parse{{ $obj.Name }}(d *xml.Decoder, start *xml.StartElement) (*{{ $obj.Name }}, error) {
|
||||||
|
var (
|
||||||
|
obj = {{ $obj.Name }}{}
|
||||||
|
data []byte
|
||||||
|
)
|
||||||
|
for {
|
||||||
|
tok, err := d.Token()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
switch t := tok.(type) {
|
||||||
|
case xml.StartElement:
|
||||||
|
switch t.Name.Local {
|
||||||
|
{{- range $fname, $field := $obj.Fields }}
|
||||||
|
case "{{ $fname }}":
|
||||||
|
{{ $field.StartAction }}
|
||||||
|
{{- end }}
|
||||||
|
default:
|
||||||
|
// fmt.Println("unknown field", t.Name.Local)
|
||||||
|
d.Skip()
|
||||||
|
}
|
||||||
|
|
||||||
|
case xml.CharData:
|
||||||
|
data = append(data, t...)
|
||||||
|
|
||||||
|
case xml.EndElement:
|
||||||
|
if t.Name.Local == start.Name.Local {
|
||||||
|
return &obj, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t.Name.Local {
|
||||||
|
{{- range $fname, $field := $obj.Fields }}
|
||||||
|
case "{{ $fname }}":
|
||||||
|
{{- if and (eq $fname "type") (not (not $obj.SubTypes)) }}
|
||||||
|
var err error
|
||||||
|
switch strcase.ToCamel(string(data)) {
|
||||||
|
{{- range $sub := $obj.SubTypes }}
|
||||||
|
case "{{ $sub }}":
|
||||||
|
obj.Details, err = parse{{ $obj.Name }}{{ $sub }}(d, start)
|
||||||
|
{{- end }}
|
||||||
|
default:
|
||||||
|
d.Skip()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &obj, nil
|
||||||
|
{{- else }}
|
||||||
|
{{ $field.EndAction }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
default:
|
||||||
|
// fmt.Println("unknown field", t.Name.Local)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
`))
|
|
@ -0,0 +1,143 @@
|
||||||
|
package df
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/iancoleman/strcase"
|
||||||
|
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FieldData struct {
|
||||||
|
IsString bool
|
||||||
|
Multiple bool
|
||||||
|
Base bool
|
||||||
|
Plus bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFieldData() *FieldData {
|
||||||
|
return &FieldData{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type AnalyzeData struct {
|
||||||
|
Fields map[string]*FieldData
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAnalyzeData() *AnalyzeData {
|
||||||
|
return &AnalyzeData{
|
||||||
|
Fields: make(map[string]*FieldData, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AnalyzeData) Save() error {
|
||||||
|
file, err := json.MarshalIndent(a, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ioutil.WriteFile("analyze.json", file, 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadAnalyzeData() (*AnalyzeData, error) {
|
||||||
|
data, err := ioutil.ReadFile("analyze.json")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
a := NewAnalyzeData()
|
||||||
|
json.Unmarshal(data, a)
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AnalyzeData) GetField(s string) *FieldData {
|
||||||
|
if f, ok := a.Fields[s]; ok {
|
||||||
|
return f
|
||||||
|
} else {
|
||||||
|
f := &FieldData{}
|
||||||
|
a.Fields[s] = f
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func analyze(file string, a *AnalyzeData) error {
|
||||||
|
xmlFile, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
plus := strings.HasSuffix(file, "_plus.xml")
|
||||||
|
|
||||||
|
fmt.Println("Successfully Opened", file)
|
||||||
|
defer xmlFile.Close()
|
||||||
|
|
||||||
|
converter := util.NewConvertReader(xmlFile)
|
||||||
|
|
||||||
|
return analyzeElement(xml.NewDecoder(converter), a, make([]string, 0), plus)
|
||||||
|
}
|
||||||
|
|
||||||
|
const PATH_SEPARATOR = "|"
|
||||||
|
|
||||||
|
func analyzeElement(d *xml.Decoder, a *AnalyzeData, path []string, plus bool) error {
|
||||||
|
if len(path) > 1 {
|
||||||
|
s := strings.Join(path, PATH_SEPARATOR)
|
||||||
|
fd := NewFieldData()
|
||||||
|
a.Fields[s] = fd
|
||||||
|
if plus {
|
||||||
|
fd.Plus = true
|
||||||
|
} else {
|
||||||
|
fd.Base = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
data []byte
|
||||||
|
)
|
||||||
|
value := true
|
||||||
|
|
||||||
|
fields := make(map[string]bool)
|
||||||
|
|
||||||
|
Loop:
|
||||||
|
for {
|
||||||
|
tok, err := d.Token()
|
||||||
|
if err == io.EOF {
|
||||||
|
break Loop
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch t := tok.(type) {
|
||||||
|
case xml.StartElement:
|
||||||
|
value = false
|
||||||
|
|
||||||
|
newPath := append(path, t.Name.Local)
|
||||||
|
|
||||||
|
if _, ok := fields[t.Name.Local]; ok {
|
||||||
|
a.Fields[strings.Join(newPath, PATH_SEPARATOR)].Multiple = true
|
||||||
|
}
|
||||||
|
fields[t.Name.Local] = true
|
||||||
|
|
||||||
|
analyzeElement(d, a, newPath, plus)
|
||||||
|
|
||||||
|
case xml.CharData:
|
||||||
|
data = append(data, t...)
|
||||||
|
|
||||||
|
case xml.EndElement:
|
||||||
|
if value {
|
||||||
|
if _, err := strconv.Atoi(string(data)); err != nil {
|
||||||
|
a.Fields[strings.Join(path, PATH_SEPARATOR)].IsString = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.Name.Local == "type" {
|
||||||
|
path[len(path)-2] = path[len(path)-2] + "+" + strcase.ToCamel(string(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -3,3 +3,5 @@ module github.com/robertjanetzko/LegendsBrowser2/analyze
|
||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require github.com/iancoleman/strcase v0.2.0
|
require github.com/iancoleman/strcase v0.2.0
|
||||||
|
|
||||||
|
require github.com/robertjanetzko/LegendsBrowser2/backend v0.0.0-20220414135947-77b720f8d215
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=
|
||||||
|
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||||
|
github.com/robertjanetzko/LegendsBrowser2/backend v0.0.0-20220414135947-77b720f8d215 h1:i23QGS93i7zoDyarU2dQLYDYxSo8MkatzhISsRQuljM=
|
||||||
|
github.com/robertjanetzko/LegendsBrowser2/backend v0.0.0-20220414135947-77b720f8d215/go.mod h1:b6NU94RVWS7nz92lGiifeWN1cLV2EeNSzx0Oop+Ma54=
|
12619
backend/df/model.go
12619
backend/df/model.go
File diff suppressed because it is too large
Load Diff
|
@ -3,8 +3,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"legendsbrowser/df"
|
|
||||||
"legendsbrowser/server"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,9 +10,11 @@ import (
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/pkg/profile"
|
"github.com/pkg/profile"
|
||||||
|
"github.com/robertjanetzko/LegendsBrowser2/backend/model"
|
||||||
|
"github.com/robertjanetzko/LegendsBrowser2/backend/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
var world *df.DfWorld
|
var world *model.DfWorld
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
f := flag.String("f", "", "open a file")
|
f := flag.String("f", "", "open a file")
|
||||||
|
@ -26,7 +26,7 @@ func main() {
|
||||||
http.ListenAndServe(":8081", nil)
|
http.ListenAndServe(":8081", nil)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
w, err := df.Parse(*f)
|
w, err := model.Parse(*f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
package model
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"legendsbrowser/util"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/iancoleman/strcase"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ListOtherElements[T Others](name string, items *[]T) {
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println(name)
|
|
||||||
fmt.Println()
|
|
||||||
m := make(map[string]map[string]bool)
|
|
||||||
cantInt := make(map[string]bool)
|
|
||||||
isObj := make(map[string]bool)
|
|
||||||
isMultiple := make(map[string]bool)
|
|
||||||
for _, item := range *items {
|
|
||||||
found := make(map[string]bool)
|
|
||||||
for _, el := range item.Others() {
|
|
||||||
t := name // item.Type()
|
|
||||||
if !m[el.XMLName.Local][t] {
|
|
||||||
if m[el.XMLName.Local] == nil {
|
|
||||||
m[el.XMLName.Local] = map[string]bool{}
|
|
||||||
}
|
|
||||||
m[el.XMLName.Local][t] = true
|
|
||||||
}
|
|
||||||
_, err := strconv.Atoi(el.Value)
|
|
||||||
if err != nil {
|
|
||||||
cantInt[el.XMLName.Local] = true
|
|
||||||
}
|
|
||||||
if strings.Contains(el.Value, "<") {
|
|
||||||
isObj[el.XMLName.Local] = true
|
|
||||||
}
|
|
||||||
if found[el.XMLName.Local] {
|
|
||||||
isMultiple[el.XMLName.Local] = true
|
|
||||||
}
|
|
||||||
found[el.XMLName.Local] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ks := util.Keys(m)
|
|
||||||
sort.Strings(ks)
|
|
||||||
for _, k := range ks {
|
|
||||||
events := util.Keys(m[k])
|
|
||||||
sort.Strings(events)
|
|
||||||
// fmt.Println(strconv.FormatBool(cantInt[k]) + " - " + k + ": " + strings.Join(events, ", "))
|
|
||||||
var mult string
|
|
||||||
if isMultiple[k] {
|
|
||||||
mult = "[]"
|
|
||||||
} else {
|
|
||||||
mult = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if isObj[k] {
|
|
||||||
fmt.Printf("// %s object\n", k)
|
|
||||||
} else if cantInt[k] {
|
|
||||||
fmt.Printf("%s *%sstring `xml:\"%s\" json:\"%s,omitempty\"`\n", strcase.ToCamel(k), mult, k, strcase.ToLowerCamel(k))
|
|
||||||
} else {
|
|
||||||
var types []string
|
|
||||||
if util.ContainsAny(k, "entity_id", "enid", "civ_id", "entity_1", "entity_2") {
|
|
||||||
types = append(types, "entity")
|
|
||||||
}
|
|
||||||
if util.ContainsAny(k, "site_id") {
|
|
||||||
types = append(types, "site")
|
|
||||||
}
|
|
||||||
if util.ContainsAny(k, "structure_id") {
|
|
||||||
types = append(types, "structure")
|
|
||||||
}
|
|
||||||
if util.ContainsAny(k, "hfid", "hist_figure_id", "hist_fig_id") {
|
|
||||||
types = append(types, "hf")
|
|
||||||
}
|
|
||||||
if util.ContainsAny(k, "wcid", "wc_id") {
|
|
||||||
types = append(types, "wc")
|
|
||||||
}
|
|
||||||
if util.ContainsAny(k, "artifact_id") {
|
|
||||||
types = append(types, "artifact")
|
|
||||||
}
|
|
||||||
typestr := strings.Join(types, ",")
|
|
||||||
if typestr != "" {
|
|
||||||
typestr = fmt.Sprintf(" legend:\"%s\"", typestr)
|
|
||||||
}
|
|
||||||
fmt.Printf("%s *%sint `xml:\"%s\" json:\"%s,omitempty\"%s`\n", strcase.ToCamel(k), mult, k, strcase.ToLowerCamel(k), typestr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,242 +0,0 @@
|
||||||
package model
|
|
||||||
|
|
||||||
type HistoricalEvent struct {
|
|
||||||
Id_ int `xml:"id" json:"id"`
|
|
||||||
Year int `xml:"year" json:"year"`
|
|
||||||
Seconds int `xml:"seconds72" json:"seconds72"`
|
|
||||||
TypedObject
|
|
||||||
|
|
||||||
ASupportMercEnid *int `xml:"a_support_merc_enid" json:"aSupportMercEnid,omitempty" legend:"entity"`
|
|
||||||
AccountShift *int `xml:"account_shift" json:"accountShift,omitempty"`
|
|
||||||
AcquirerEnid *int `xml:"acquirer_enid" json:"acquirerEnid,omitempty" legend:"entity"`
|
|
||||||
AcquirerHfid *int `xml:"acquirer_hfid" json:"acquirerHfid,omitempty" legend:"hf"`
|
|
||||||
Action *string `xml:"action" json:"action,omitempty"`
|
|
||||||
ActorHfid *int `xml:"actor_hfid" json:"actorHfid,omitempty" legend:"hf"`
|
|
||||||
AgreementId *int `xml:"agreement_id" json:"agreementId,omitempty"`
|
|
||||||
Allotment *int `xml:"allotment" json:"allotment,omitempty"`
|
|
||||||
AllotmentIndex *int `xml:"allotment_index" json:"allotmentIndex,omitempty"`
|
|
||||||
AllyDefenseBonus *int `xml:"ally_defense_bonus" json:"allyDefenseBonus,omitempty"`
|
|
||||||
AppointerHfid *int `xml:"appointer_hfid" json:"appointerHfid,omitempty" legend:"hf"`
|
|
||||||
ArrestingEnid *int `xml:"arresting_enid" json:"arrestingEnid,omitempty" legend:"entity"`
|
|
||||||
ArtifactId *int `xml:"artifact_id" json:"artifactId,omitempty" legend:"artifact"`
|
|
||||||
AttackerCivId *int `xml:"attacker_civ_id" json:"attackerCivId,omitempty" legend:"entity"`
|
|
||||||
AttackerGeneralHfid *int `xml:"attacker_general_hfid" json:"attackerGeneralHfid,omitempty" legend:"hf"`
|
|
||||||
AttackerHfid *int `xml:"attacker_hfid" json:"attackerHfid,omitempty" legend:"hf"`
|
|
||||||
AttackerMercEnid *int `xml:"attacker_merc_enid" json:"attackerMercEnid,omitempty" legend:"entity"`
|
|
||||||
BodyState *string `xml:"body_state" json:"bodyState,omitempty"`
|
|
||||||
BuilderHfid *int `xml:"builder_hfid" json:"builderHfid,omitempty" legend:"hf"`
|
|
||||||
BuildingProfileId *int `xml:"building_profile_id" json:"buildingProfileId,omitempty"`
|
|
||||||
Cause *string `xml:"cause" json:"cause,omitempty"`
|
|
||||||
ChangeeHfid *int `xml:"changee_hfid" json:"changeeHfid,omitempty" legend:"hf"`
|
|
||||||
ChangerHfid *int `xml:"changer_hfid" json:"changerHfid,omitempty" legend:"hf"`
|
|
||||||
Circumstance *string `xml:"circumstance" json:"circumstance,omitempty"`
|
|
||||||
CircumstanceId *int `xml:"circumstance_id" json:"circumstanceId,omitempty"`
|
|
||||||
CivEntityId *int `xml:"civ_entity_id" json:"civEntityId,omitempty" legend:"entity"`
|
|
||||||
CivId *int `xml:"civ_id" json:"civId,omitempty" legend:"entity"`
|
|
||||||
Claim *string `xml:"claim" json:"claim,omitempty"`
|
|
||||||
CoconspiratorBonus *int `xml:"coconspirator_bonus" json:"coconspiratorBonus,omitempty"`
|
|
||||||
CompetitorHfid *[]int `xml:"competitor_hfid" json:"competitorHfid,omitempty" legend:"hf"`
|
|
||||||
ConfessedAfterApbArrestEnid *int `xml:"confessed_after_apb_arrest_enid" json:"confessedAfterApbArrestEnid,omitempty" legend:"entity"`
|
|
||||||
ConspiratorHfid *[]int `xml:"conspirator_hfid" json:"conspiratorHfid,omitempty" legend:"hf"`
|
|
||||||
ContactHfid *int `xml:"contact_hfid" json:"contactHfid,omitempty" legend:"hf"`
|
|
||||||
ConvictIsContact *string `xml:"convict_is_contact" json:"convictIsContact,omitempty"`
|
|
||||||
ConvictedHfid *int `xml:"convicted_hfid" json:"convictedHfid,omitempty" legend:"hf"`
|
|
||||||
ConvicterEnid *int `xml:"convicter_enid" json:"convicterEnid,omitempty" legend:"entity"`
|
|
||||||
Coords *string `xml:"coords" json:"coords,omitempty"`
|
|
||||||
CorruptConvicterHfid *int `xml:"corrupt_convicter_hfid" json:"corruptConvicterHfid,omitempty" legend:"hf"`
|
|
||||||
CorruptorHfid *int `xml:"corruptor_hfid" json:"corruptorHfid,omitempty" legend:"hf"`
|
|
||||||
CorruptorIdentity *int `xml:"corruptor_identity" json:"corruptorIdentity,omitempty"`
|
|
||||||
CorruptorSeenAs *string `xml:"corruptor_seen_as" json:"corruptorSeenAs,omitempty"`
|
|
||||||
CreatorHfid *int `xml:"creator_hfid" json:"creatorHfid,omitempty" legend:"hf"`
|
|
||||||
Crime *string `xml:"crime" json:"crime,omitempty"`
|
|
||||||
DSupportMercEnid *int `xml:"d_support_merc_enid" json:"dSupportMercEnid,omitempty" legend:"entity"`
|
|
||||||
DeathPenalty *string `xml:"death_penalty" json:"deathPenalty,omitempty"`
|
|
||||||
DefenderCivId *int `xml:"defender_civ_id" json:"defenderCivId,omitempty" legend:"entity"`
|
|
||||||
DefenderGeneralHfid *int `xml:"defender_general_hfid" json:"defenderGeneralHfid,omitempty" legend:"hf"`
|
|
||||||
DefenderMercEnid *int `xml:"defender_merc_enid" json:"defenderMercEnid,omitempty" legend:"entity"`
|
|
||||||
Delegated *string `xml:"delegated" json:"delegated,omitempty"`
|
|
||||||
DestEntityId *int `xml:"dest_entity_id" json:"destEntityId,omitempty" legend:"entity"`
|
|
||||||
DestSiteId *int `xml:"dest_site_id" json:"destSiteId,omitempty" legend:"site"`
|
|
||||||
DestStructureId *int `xml:"dest_structure_id" json:"destStructureId,omitempty" legend:"structure"`
|
|
||||||
DestroyedStructureId *int `xml:"destroyed_structure_id" json:"destroyedStructureId,omitempty" legend:"structure"`
|
|
||||||
DestroyerEnid *int `xml:"destroyer_enid" json:"destroyerEnid,omitempty" legend:"entity"`
|
|
||||||
Detected *string `xml:"detected" json:"detected,omitempty"`
|
|
||||||
DidNotRevealAllInInterrogation *string `xml:"did_not_reveal_all_in_interrogation" json:"didNotRevealAllInInterrogation,omitempty"`
|
|
||||||
Dispute *string `xml:"dispute" json:"dispute,omitempty"`
|
|
||||||
DoerHfid *int `xml:"doer_hfid" json:"doerHfid,omitempty" legend:"hf"`
|
|
||||||
Entity1 *int `xml:"entity_1" json:"entity1,omitempty" legend:"entity"`
|
|
||||||
Entity2 *int `xml:"entity_2" json:"entity2,omitempty" legend:"entity"`
|
|
||||||
EntityId *int `xml:"entity_id" json:"entityId,omitempty" legend:"entity"`
|
|
||||||
EntityId1 *int `xml:"entity_id_1" json:"entityId1,omitempty" legend:"entity"`
|
|
||||||
EntityId2 *int `xml:"entity_id_2" json:"entityId2,omitempty" legend:"entity"`
|
|
||||||
Exiled *string `xml:"exiled" json:"exiled,omitempty"`
|
|
||||||
ExpelledCreature *[]int `xml:"expelled_creature" json:"expelledCreature,omitempty"`
|
|
||||||
ExpelledHfid *[]int `xml:"expelled_hfid" json:"expelledHfid,omitempty" legend:"hf"`
|
|
||||||
ExpelledNumber *[]int `xml:"expelled_number" json:"expelledNumber,omitempty"`
|
|
||||||
ExpelledPopId *[]int `xml:"expelled_pop_id" json:"expelledPopId,omitempty"`
|
|
||||||
FailedJudgmentTest *string `xml:"failed_judgment_test" json:"failedJudgmentTest,omitempty"`
|
|
||||||
FeatureLayerId *int `xml:"feature_layer_id" json:"featureLayerId,omitempty"`
|
|
||||||
First *string `xml:"first" json:"first,omitempty"`
|
|
||||||
FooledHfid *int `xml:"fooled_hfid" json:"fooledHfid,omitempty" legend:"hf"`
|
|
||||||
FormId *int `xml:"form_id" json:"formId,omitempty"`
|
|
||||||
FramerHfid *int `xml:"framer_hfid" json:"framerHfid,omitempty" legend:"hf"`
|
|
||||||
FromOriginal *string `xml:"from_original" json:"fromOriginal,omitempty"`
|
|
||||||
GamblerHfid *int `xml:"gambler_hfid" json:"gamblerHfid,omitempty" legend:"hf"`
|
|
||||||
GiverEntityId *int `xml:"giver_entity_id" json:"giverEntityId,omitempty" legend:"entity"`
|
|
||||||
GiverHistFigureId *int `xml:"giver_hist_figure_id" json:"giverHistFigureId,omitempty" legend:"hf"`
|
|
||||||
Group1Hfid *int `xml:"group_1_hfid" json:"group1Hfid,omitempty" legend:"hf"`
|
|
||||||
Group2Hfid *[]int `xml:"group_2_hfid" json:"group2Hfid,omitempty" legend:"hf"`
|
|
||||||
GroupHfid *[]int `xml:"group_hfid" json:"groupHfid,omitempty" legend:"hf"`
|
|
||||||
HeldFirmInInterrogation *string `xml:"held_firm_in_interrogation" json:"heldFirmInInterrogation,omitempty"`
|
|
||||||
HfRep1Of2 *string `xml:"hf_rep_1_of_2" json:"hfRep1Of2,omitempty"`
|
|
||||||
HfRep2Of1 *string `xml:"hf_rep_2_of_1" json:"hfRep2Of1,omitempty"`
|
|
||||||
Hfid *[]int `xml:"hfid" json:"hfid,omitempty" legend:"hf"`
|
|
||||||
Hfid1 *int `xml:"hfid1" json:"hfid1,omitempty" legend:"hf"`
|
|
||||||
Hfid2 *int `xml:"hfid2" json:"hfid2,omitempty" legend:"hf"`
|
|
||||||
HfidTarget *int `xml:"hfid_target" json:"hfidTarget,omitempty" legend:"hf"`
|
|
||||||
HistFigId *int `xml:"hist_fig_id" json:"histFigId,omitempty" legend:"hf"`
|
|
||||||
HistFigureId *int `xml:"hist_figure_id" json:"histFigureId,omitempty" legend:"hf"`
|
|
||||||
HonorId *int `xml:"honor_id" json:"honorId,omitempty"`
|
|
||||||
IdentityId *int `xml:"identity_id" json:"identityId,omitempty" legend:"entity"`
|
|
||||||
IdentityId1 *int `xml:"identity_id1" json:"identityId1,omitempty" legend:"entity"`
|
|
||||||
IdentityId2 *int `xml:"identity_id2" json:"identityId2,omitempty" legend:"entity"`
|
|
||||||
ImplicatedHfid *[]int `xml:"implicated_hfid" json:"implicatedHfid,omitempty" legend:"hf"`
|
|
||||||
Inherited *string `xml:"inherited" json:"inherited,omitempty"`
|
|
||||||
InitiatingEnid *int `xml:"initiating_enid" json:"initiatingEnid,omitempty" legend:"entity"`
|
|
||||||
InstigatorHfid *int `xml:"instigator_hfid" json:"instigatorHfid,omitempty" legend:"hf"`
|
|
||||||
Interaction *string `xml:"interaction" json:"interaction,omitempty"`
|
|
||||||
InterrogatorHfid *int `xml:"interrogator_hfid" json:"interrogatorHfid,omitempty" legend:"hf"`
|
|
||||||
JoinEntityId *int `xml:"join_entity_id" json:"joinEntityId,omitempty" legend:"entity"`
|
|
||||||
JoinedEntityId *int `xml:"joined_entity_id" json:"joinedEntityId,omitempty" legend:"entity"`
|
|
||||||
JoinerEntityId *int `xml:"joiner_entity_id" json:"joinerEntityId,omitempty" legend:"entity"`
|
|
||||||
JoiningEnid *[]int `xml:"joining_enid" json:"joiningEnid,omitempty" legend:"entity"`
|
|
||||||
Knowledge *string `xml:"knowledge" json:"knowledge,omitempty"`
|
|
||||||
LastOwnerHfid *int `xml:"last_owner_hfid" json:"lastOwnerHfid,omitempty" legend:"hf"`
|
|
||||||
LeaderHfid *int `xml:"leader_hfid" json:"leaderHfid,omitempty" legend:"hf"`
|
|
||||||
Link *string `xml:"link" json:"link,omitempty"`
|
|
||||||
LureHfid *int `xml:"lure_hfid" json:"lureHfid,omitempty" legend:"hf"`
|
|
||||||
MasterWcid *int `xml:"master_wcid" json:"masterWcid,omitempty" legend:"wc"`
|
|
||||||
Method *string `xml:"method" json:"method,omitempty"`
|
|
||||||
Modification *string `xml:"modification" json:"modification,omitempty"`
|
|
||||||
ModifierHfid *int `xml:"modifier_hfid" json:"modifierHfid,omitempty" legend:"hf"`
|
|
||||||
Mood *string `xml:"mood" json:"mood,omitempty"`
|
|
||||||
NameOnly *string `xml:"name_only" json:"nameOnly,omitempty"`
|
|
||||||
NewAbId *int `xml:"new_ab_id" json:"newAbId,omitempty"`
|
|
||||||
NewAccount *int `xml:"new_account" json:"newAccount,omitempty"`
|
|
||||||
NewCaste *string `xml:"new_caste" json:"newCaste,omitempty"`
|
|
||||||
NewEquipmentLevel *int `xml:"new_equipment_level" json:"newEquipmentLevel,omitempty"`
|
|
||||||
NewLeaderHfid *int `xml:"new_leader_hfid" json:"newLeaderHfid,omitempty" legend:"hf"`
|
|
||||||
NewRace *string `xml:"new_race" json:"newRace,omitempty"`
|
|
||||||
NewSiteCivId *int `xml:"new_site_civ_id" json:"newSiteCivId,omitempty" legend:"entity"`
|
|
||||||
OccasionId *int `xml:"occasion_id" json:"occasionId,omitempty"`
|
|
||||||
OldAbId *int `xml:"old_ab_id" json:"oldAbId,omitempty"`
|
|
||||||
OldAccount *int `xml:"old_account" json:"oldAccount,omitempty"`
|
|
||||||
OldCaste *string `xml:"old_caste" json:"oldCaste,omitempty"`
|
|
||||||
OldRace *string `xml:"old_race" json:"oldRace,omitempty"`
|
|
||||||
OverthrownHfid *int `xml:"overthrown_hfid" json:"overthrownHfid,omitempty" legend:"hf"`
|
|
||||||
PartialIncorporation *string `xml:"partial_incorporation" json:"partialIncorporation,omitempty"`
|
|
||||||
PersecutorEnid *int `xml:"persecutor_enid" json:"persecutorEnid,omitempty" legend:"entity"`
|
|
||||||
PersecutorHfid *int `xml:"persecutor_hfid" json:"persecutorHfid,omitempty" legend:"hf"`
|
|
||||||
PlotterHfid *int `xml:"plotter_hfid" json:"plotterHfid,omitempty" legend:"hf"`
|
|
||||||
PopFlid *int `xml:"pop_flid" json:"popFlid,omitempty"`
|
|
||||||
PopNumberMoved *int `xml:"pop_number_moved" json:"popNumberMoved,omitempty"`
|
|
||||||
PopRace *int `xml:"pop_race" json:"popRace,omitempty"`
|
|
||||||
PopSrid *int `xml:"pop_srid" json:"popSrid,omitempty"`
|
|
||||||
PosTakerHfid *int `xml:"pos_taker_hfid" json:"posTakerHfid,omitempty" legend:"hf"`
|
|
||||||
PositionId *int `xml:"position_id" json:"positionId,omitempty"`
|
|
||||||
PositionProfileId *int `xml:"position_profile_id" json:"positionProfileId,omitempty"`
|
|
||||||
PrisonMonths *int `xml:"prison_months" json:"prisonMonths,omitempty"`
|
|
||||||
ProductionZoneId *int `xml:"production_zone_id" json:"productionZoneId,omitempty"`
|
|
||||||
PromiseToHfid *int `xml:"promise_to_hfid" json:"promiseToHfid,omitempty" legend:"hf"`
|
|
||||||
PropertyConfiscatedFromHfid *[]int `xml:"property_confiscated_from_hfid" json:"propertyConfiscatedFromHfid,omitempty" legend:"hf"`
|
|
||||||
PurchasedUnowned *string `xml:"purchased_unowned" json:"purchasedUnowned,omitempty"`
|
|
||||||
Quality *int `xml:"quality" json:"quality,omitempty"`
|
|
||||||
Reason *string `xml:"reason" json:"reason,omitempty"`
|
|
||||||
ReasonId *int `xml:"reason_id" json:"reasonId,omitempty"`
|
|
||||||
RebuiltRuined *string `xml:"rebuilt_ruined" json:"rebuiltRuined,omitempty"`
|
|
||||||
ReceiverEntityId *int `xml:"receiver_entity_id" json:"receiverEntityId,omitempty" legend:"entity"`
|
|
||||||
ReceiverHistFigureId *int `xml:"receiver_hist_figure_id" json:"receiverHistFigureId,omitempty" legend:"hf"`
|
|
||||||
Relationship *string `xml:"relationship" json:"relationship,omitempty"`
|
|
||||||
RelevantEntityId *int `xml:"relevant_entity_id" json:"relevantEntityId,omitempty" legend:"entity"`
|
|
||||||
RelevantIdForMethod *int `xml:"relevant_id_for_method" json:"relevantIdForMethod,omitempty"`
|
|
||||||
RelevantPositionProfileId *int `xml:"relevant_position_profile_id" json:"relevantPositionProfileId,omitempty"`
|
|
||||||
ReligionId *int `xml:"religion_id" json:"religionId,omitempty"`
|
|
||||||
ResidentCivId *int `xml:"resident_civ_id" json:"residentCivId,omitempty" legend:"entity"`
|
|
||||||
Return *string `xml:"return" json:"return,omitempty"`
|
|
||||||
ScheduleId *int `xml:"schedule_id" json:"scheduleId,omitempty"`
|
|
||||||
SecretGoal *string `xml:"secret_goal" json:"secretGoal,omitempty"`
|
|
||||||
SeekerHfid *int `xml:"seeker_hfid" json:"seekerHfid,omitempty" legend:"hf"`
|
|
||||||
ShrineAmountDestroyed *int `xml:"shrine_amount_destroyed" json:"shrineAmountDestroyed,omitempty"`
|
|
||||||
SiteCivId *int `xml:"site_civ_id" json:"siteCivId,omitempty" legend:"entity"`
|
|
||||||
SiteEntityId *int `xml:"site_entity_id" json:"siteEntityId,omitempty" legend:"entity"`
|
|
||||||
SiteHfid *int `xml:"site_hfid" json:"siteHfid,omitempty" legend:"hf"`
|
|
||||||
SiteId *int `xml:"site_id" json:"siteId,omitempty" legend:"site"`
|
|
||||||
SiteId1 *int `xml:"site_id1" json:"siteId1,omitempty" legend:"site"`
|
|
||||||
SiteId2 *int `xml:"site_id2" json:"siteId2,omitempty" legend:"site"`
|
|
||||||
SiteId_1 *int `xml:"site_id_1" json:"siteId_1,omitempty" legend:"site"`
|
|
||||||
SiteId_2 *int `xml:"site_id_2" json:"siteId_2,omitempty" legend:"site"`
|
|
||||||
SitePropertyId *int `xml:"site_property_id" json:"sitePropertyId,omitempty"`
|
|
||||||
Situation *string `xml:"situation" json:"situation,omitempty"`
|
|
||||||
SlayerCaste *string `xml:"slayer_caste" json:"slayerCaste,omitempty"`
|
|
||||||
SlayerHfid *int `xml:"slayer_hfid" json:"slayerHfid,omitempty" legend:"hf"`
|
|
||||||
SlayerItemId *int `xml:"slayer_item_id" json:"slayerItemId,omitempty"`
|
|
||||||
SlayerRace *string `xml:"slayer_race" json:"slayerRace,omitempty"`
|
|
||||||
SlayerShooterItemId *int `xml:"slayer_shooter_item_id" json:"slayerShooterItemId,omitempty"`
|
|
||||||
SnatcherHfid *int `xml:"snatcher_hfid" json:"snatcherHfid,omitempty" legend:"hf"`
|
|
||||||
SourceEntityId *int `xml:"source_entity_id" json:"sourceEntityId,omitempty" legend:"entity"`
|
|
||||||
SourceSiteId *int `xml:"source_site_id" json:"sourceSiteId,omitempty" legend:"site"`
|
|
||||||
SourceStructureId *int `xml:"source_structure_id" json:"sourceStructureId,omitempty" legend:"structure"`
|
|
||||||
SpeakerHfid *int `xml:"speaker_hfid" json:"speakerHfid,omitempty" legend:"hf"`
|
|
||||||
State *string `xml:"state" json:"state,omitempty"`
|
|
||||||
StructureId *int `xml:"structure_id" json:"structureId,omitempty" legend:"structure"`
|
|
||||||
StudentHfid *int `xml:"student_hfid" json:"studentHfid,omitempty" legend:"hf"`
|
|
||||||
SubregionId *int `xml:"subregion_id" json:"subregionId,omitempty"`
|
|
||||||
Subtype *string `xml:"subtype" json:"subtype,omitempty"`
|
|
||||||
Successful *string `xml:"successful" json:"successful,omitempty"`
|
|
||||||
SurveiledContact *string `xml:"surveiled_contact" json:"surveiledContact,omitempty"`
|
|
||||||
SurveiledConvicted *string `xml:"surveiled_convicted" json:"surveiledConvicted,omitempty"`
|
|
||||||
TargetEnid *int `xml:"target_enid" json:"targetEnid,omitempty" legend:"entity"`
|
|
||||||
TargetHfid *int `xml:"target_hfid" json:"targetHfid,omitempty" legend:"hf"`
|
|
||||||
TargetIdentity *int `xml:"target_identity" json:"targetIdentity,omitempty"`
|
|
||||||
TargetSeenAs *string `xml:"target_seen_as" json:"targetSeenAs,omitempty"`
|
|
||||||
TeacherHfid *int `xml:"teacher_hfid" json:"teacherHfid,omitempty" legend:"hf"`
|
|
||||||
TopFacet *string `xml:"top_facet" json:"topFacet,omitempty"`
|
|
||||||
TopFacetModifier *int `xml:"top_facet_modifier" json:"topFacetModifier,omitempty"`
|
|
||||||
TopFacetRating *int `xml:"top_facet_rating" json:"topFacetRating,omitempty"`
|
|
||||||
TopRelationshipFactor *string `xml:"top_relationship_factor" json:"topRelationshipFactor,omitempty"`
|
|
||||||
TopRelationshipModifier *int `xml:"top_relationship_modifier" json:"topRelationshipModifier,omitempty"`
|
|
||||||
TopRelationshipRating *int `xml:"top_relationship_rating" json:"topRelationshipRating,omitempty"`
|
|
||||||
TopValue *string `xml:"top_value" json:"topValue,omitempty"`
|
|
||||||
TopValueModifier *int `xml:"top_value_modifier" json:"topValueModifier,omitempty"`
|
|
||||||
TopValueRating *int `xml:"top_value_rating" json:"topValueRating,omitempty"`
|
|
||||||
Topic *string `xml:"topic" json:"topic,omitempty"`
|
|
||||||
TraderEntityId *int `xml:"trader_entity_id" json:"traderEntityId,omitempty" legend:"entity"`
|
|
||||||
TraderHfid *int `xml:"trader_hfid" json:"traderHfid,omitempty" legend:"hf"`
|
|
||||||
TricksterHfid *int `xml:"trickster_hfid" json:"tricksterHfid,omitempty" legend:"hf"`
|
|
||||||
UnitId *int `xml:"unit_id" json:"unitId,omitempty"`
|
|
||||||
UnitType *string `xml:"unit_type" json:"unitType,omitempty"`
|
|
||||||
WantedAndRecognized *string `xml:"wanted_and_recognized" json:"wantedAndRecognized,omitempty"`
|
|
||||||
WcId *int `xml:"wc_id" json:"wcId,omitempty" legend:"wc"`
|
|
||||||
Wcid *int `xml:"wcid" json:"wcid,omitempty" legend:"wc"`
|
|
||||||
WinnerHfid *int `xml:"winner_hfid" json:"winnerHfid,omitempty" legend:"hf"`
|
|
||||||
WoundeeHfid *int `xml:"woundee_hfid" json:"woundeeHfid,omitempty" legend:"hf"`
|
|
||||||
WounderHfid *int `xml:"wounder_hfid" json:"wounderHfid,omitempty" legend:"hf"`
|
|
||||||
WrongfulConviction *string `xml:"wrongful_conviction" json:"wrongfulConviction,omitempty"`
|
|
||||||
|
|
||||||
//OtherElements
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *HistoricalEvent) Id() int { return r.Id_ }
|
|
||||||
func (r *HistoricalEvent) Name() string { return r.Type() }
|
|
||||||
|
|
||||||
type EventObject struct {
|
|
||||||
Events []*HistoricalEvent `json:"events"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *EventObject) GetEvents() []*HistoricalEvent { return r.Events }
|
|
||||||
func (r *EventObject) SetEvents(events []*HistoricalEvent) { r.Events = events }
|
|
||||||
|
|
||||||
type HasEvents interface {
|
|
||||||
GetEvents() []*HistoricalEvent
|
|
||||||
SetEvents([]*HistoricalEvent)
|
|
||||||
}
|
|
12852
backend/model/model.go
12852
backend/model/model.go
File diff suppressed because it is too large
Load Diff
|
@ -1,16 +1,13 @@
|
||||||
package df
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"legendsbrowser/util"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// type DfWorld struct{}
|
|
||||||
|
|
||||||
// func parseDfWorld(d *xml.Decoder, start *xml.StartElement) (*DfWorld, error) { return nil, nil }
|
|
||||||
|
|
||||||
func (e *HistoricalEvent) Name() string { return "" }
|
func (e *HistoricalEvent) Name() string { return "" }
|
||||||
func (e *HistoricalEventCollection) Name() string { return "" }
|
func (e *HistoricalEventCollection) Name() string { return "" }
|
||||||
|
|
||||||
|
@ -38,20 +35,6 @@ func Parse(file string) (*DfWorld, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// return nil, errors.New("Fehler!")
|
|
||||||
}
|
|
||||||
|
|
||||||
type Identifiable interface {
|
|
||||||
Id() int
|
|
||||||
}
|
|
||||||
|
|
||||||
type Parsable interface {
|
|
||||||
Parse(d *xml.Decoder, start *xml.StartElement) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type IdentifiableParsable interface {
|
|
||||||
Identifiable
|
|
||||||
Parsable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseArray[T any](d *xml.Decoder, dest *[]T, creator func(*xml.Decoder, *xml.StartElement) (T, error)) {
|
func parseArray[T any](d *xml.Decoder, dest *[]T, creator func(*xml.Decoder, *xml.StartElement) (T, error)) {
|
|
@ -1,293 +0,0 @@
|
||||||
package model
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/xml"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"legendsbrowser/util"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type World struct {
|
|
||||||
XMLName xml.Name `xml:"df_world"`
|
|
||||||
Name string `xml:"name"`
|
|
||||||
AltName string `xml:"altname"`
|
|
||||||
|
|
||||||
OtherElements
|
|
||||||
|
|
||||||
RegionMap map[int]*Region `xml:"regions>region"`
|
|
||||||
UndergroundRegionMap map[int]*UndergroundRegion `xml:"underground_regions>underground_region"`
|
|
||||||
LandmassMap map[int]*Landmass `xml:"landmasses>landmass"`
|
|
||||||
SiteMap map[int]*Site `xml:"sites>site"`
|
|
||||||
WorldConstructionMap map[int]*WorldConstruction `xml:"world_constructions>world_construction"`
|
|
||||||
ArtifactMap map[int]*Artifact `xml:"artifacts>artifact"`
|
|
||||||
HistoricalFigureMap map[int]*HistoricalFigure `xml:"historical_figures>historical_figure"`
|
|
||||||
HistoricalEventMap map[int]*HistoricalEvent `xml:"historical_events>historical_event"`
|
|
||||||
HistoricalEventCollectionMap map[int]*HistoricalEventCollection `xml:"historical_event_collections>historical_event_collection"`
|
|
||||||
HistoricalEraMap map[int]*HistoricalEra `xml:"historical_eras>historical_era"`
|
|
||||||
EntityMap map[int]*Entity `xml:"entities>entity"`
|
|
||||||
DanceFormMap map[int]*DanceForm `xml:"dance_forms>dance_form"`
|
|
||||||
MusicalFormMap map[int]*MusicalForm `xml:"musical_forms>musical_form"`
|
|
||||||
PoeticFormMap map[int]*PoeticForm `xml:"poetic_forms>poetic_form"`
|
|
||||||
WrittenContentMap map[int]*WrittenContent `xml:"written_contents>written_content"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *World) Load(file string) {
|
|
||||||
xmlFile, err := os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Successfully Opened users.xml")
|
|
||||||
defer xmlFile.Close()
|
|
||||||
|
|
||||||
converter := util.NewConvertReader(xmlFile)
|
|
||||||
|
|
||||||
// byteValue, _ := io.ReadAll(converter)
|
|
||||||
// fmt.Println(len(byteValue))
|
|
||||||
|
|
||||||
fillTypes(reflect.TypeOf(w))
|
|
||||||
fmt.Println(types["Region"])
|
|
||||||
|
|
||||||
d := xml.NewDecoder(converter)
|
|
||||||
parseObject(d, nil, reflect.ValueOf(w))
|
|
||||||
|
|
||||||
// err = xml.Unmarshal(byteValue, w)
|
|
||||||
// if err != nil {
|
|
||||||
// fmt.Println(err)
|
|
||||||
// }
|
|
||||||
fmt.Println("World loaded")
|
|
||||||
}
|
|
||||||
|
|
||||||
var types = make(map[string]map[string]reflect.StructField)
|
|
||||||
|
|
||||||
func fillTypes(t reflect.Type) {
|
|
||||||
if t.Kind() == reflect.Pointer {
|
|
||||||
t = t.Elem()
|
|
||||||
}
|
|
||||||
if t.Kind() != reflect.Struct {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println(t.Name())
|
|
||||||
|
|
||||||
if _, ok := types[t.Name()]; ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
info := make(map[string]reflect.StructField)
|
|
||||||
DeepFields(t, &info, make([]int, 0))
|
|
||||||
|
|
||||||
types[t.Name()] = info
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeepFields(t reflect.Type, info *map[string]reflect.StructField, index []int) {
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
f := t.Field(i)
|
|
||||||
f.Index = append(index, f.Index[0])
|
|
||||||
if xml, ok := f.Tag.Lookup("xml"); ok {
|
|
||||||
if p := strings.Index(xml, ">"); p >= 0 {
|
|
||||||
(*info)[xml[0:p]] = f
|
|
||||||
} else {
|
|
||||||
for _, s := range strings.Split(xml, "|") {
|
|
||||||
(*info)[s] = f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if f.Type.Kind() == reflect.Map || f.Type.Kind() == reflect.Slice {
|
|
||||||
fillTypes(f.Type.Elem())
|
|
||||||
}
|
|
||||||
fmt.Println(i, f)
|
|
||||||
}
|
|
||||||
if f.Type.Kind() == reflect.Struct && f.Anonymous {
|
|
||||||
DeepFields(f.Type, info, f.Index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseObject(d *xml.Decoder, start *xml.StartElement, val reflect.Value) error {
|
|
||||||
if start == nil {
|
|
||||||
for {
|
|
||||||
tok, err := d.Token()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if t, ok := tok.(xml.StartElement); ok {
|
|
||||||
start = &t
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if val.Kind() == reflect.Pointer {
|
|
||||||
val = val.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
typ, ok := types[val.Type().Name()]
|
|
||||||
if !ok {
|
|
||||||
d.Skip()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
Loop:
|
|
||||||
for {
|
|
||||||
tok, err := d.Token()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
switch t := tok.(type) {
|
|
||||||
case xml.StartElement:
|
|
||||||
if ty, ok := typ[t.Name.Local]; ok {
|
|
||||||
if ty.Type.Kind() == reflect.Map {
|
|
||||||
fmt.Println(" ", t.Name.Local, val.Type().Name(), ty)
|
|
||||||
f := val.Field(ty.Index[0])
|
|
||||||
if f.IsNil() {
|
|
||||||
f.Set(reflect.MakeMapWithSize(ty.Type, 0))
|
|
||||||
}
|
|
||||||
parseMap(d, ty, f)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
d.Skip()
|
|
||||||
}
|
|
||||||
// parseObject(d, &t, val)
|
|
||||||
case xml.EndElement:
|
|
||||||
break Loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseMap(d *xml.Decoder, field reflect.StructField, dest reflect.Value) error {
|
|
||||||
x, ok := field.Tag.Lookup("xml")
|
|
||||||
if !ok {
|
|
||||||
return errors.New("no xml tag")
|
|
||||||
}
|
|
||||||
elementName := strings.Split(x, ">")[1]
|
|
||||||
|
|
||||||
var lastStart *xml.StartElement
|
|
||||||
var id int
|
|
||||||
|
|
||||||
Loop:
|
|
||||||
for {
|
|
||||||
tok, err := d.Token()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
switch t := tok.(type) {
|
|
||||||
case xml.StartElement:
|
|
||||||
if t.Name.Local == elementName {
|
|
||||||
lastStart = &t
|
|
||||||
id = -1
|
|
||||||
} else if t.Name.Local == "id" {
|
|
||||||
if id != -1 {
|
|
||||||
return errors.New("ID at invalid place")
|
|
||||||
}
|
|
||||||
d.DecodeElement(&id, &t)
|
|
||||||
|
|
||||||
obj := dest.MapIndex(reflect.ValueOf(id))
|
|
||||||
if !obj.IsValid() {
|
|
||||||
obj = reflect.New(field.Type.Elem().Elem())
|
|
||||||
dest.SetMapIndex(reflect.ValueOf(id), obj)
|
|
||||||
obj.Elem().FieldByIndex(types[obj.Type().Elem().Name()]["id"].Index).SetInt(int64(id))
|
|
||||||
}
|
|
||||||
d.DecodeElement(obj.Interface(), lastStart)
|
|
||||||
} else {
|
|
||||||
fmt.Println("SKIP", elementName, t.Name.Local)
|
|
||||||
d.Skip()
|
|
||||||
}
|
|
||||||
case xml.EndElement:
|
|
||||||
if t.Name.Local != elementName {
|
|
||||||
break Loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *World) Process() {
|
|
||||||
// w.RegionMap = make(map[int]*Region)
|
|
||||||
// mapObjects(&w.Regions, &w.RegionMap)
|
|
||||||
|
|
||||||
// w.UndergroundRegionMap = make(map[int]*UndergroundRegion)
|
|
||||||
// mapObjects(&w.UndergroundRegions, &w.UndergroundRegionMap)
|
|
||||||
|
|
||||||
// w.LandmassMap = make(map[int]*Landmass)
|
|
||||||
// mapObjects(&w.Landmasses, &w.LandmassMap)
|
|
||||||
|
|
||||||
// w.SiteMap = make(map[int]*Site)
|
|
||||||
// mapObjects(&w.Sites, &w.SiteMap)
|
|
||||||
|
|
||||||
// w.WorldConstructionMap = make(map[int]*WorldConstruction)
|
|
||||||
// mapObjects(&w.WorldConstructions, &w.WorldConstructionMap)
|
|
||||||
|
|
||||||
// w.ArtifactMap = make(map[int]*Artifact)
|
|
||||||
// mapObjects(&w.Artifacts, &w.ArtifactMap)
|
|
||||||
|
|
||||||
// w.HistoricalFigureMap = make(map[int]*HistoricalFigure)
|
|
||||||
// mapObjects(&w.HistoricalFigures, &w.HistoricalFigureMap)
|
|
||||||
|
|
||||||
// w.HistoricalEventMap = make(map[int]*HistoricalEvent)
|
|
||||||
// mapObjects(&w.HistoricalEvents, &w.HistoricalEventMap)
|
|
||||||
|
|
||||||
// w.HistoricalEventCollectionMap = make(map[int]*HistoricalEventCollection)
|
|
||||||
// mapObjects(&w.HistoricalEventCollections, &w.HistoricalEventCollectionMap)
|
|
||||||
|
|
||||||
// w.EntityMap = make(map[int]*Entity)
|
|
||||||
// mapObjects(&w.Entities, &w.EntityMap)
|
|
||||||
|
|
||||||
w.processEvents()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *World) processEvents() {
|
|
||||||
legendFields := make(map[string][]int)
|
|
||||||
|
|
||||||
t := reflect.TypeOf(HistoricalEvent{})
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
f := t.Field(i)
|
|
||||||
l, ok := f.Tag.Lookup("legend")
|
|
||||||
if ok {
|
|
||||||
legendFields[l] = append(legendFields[l], i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// for eventIndex := 0; eventIndex < len(w.HistoricalEvents); eventIndex++ {
|
|
||||||
// e := w.HistoricalEvents[eventIndex]
|
|
||||||
// v := reflect.ValueOf(*e)
|
|
||||||
// processEvent(e, &v, legendFields["entity"], &w.EntityMap)
|
|
||||||
// processEvent(e, &v, legendFields["site"], &w.SiteMap)
|
|
||||||
// processEvent(e, &v, legendFields["hf"], &w.HistoricalFigureMap)
|
|
||||||
// processEvent(e, &v, legendFields["artifact"], &w.ArtifactMap)
|
|
||||||
// // processEvent(e, &v, legendFields["wc"], &w.WorldConstructionMap)
|
|
||||||
// // processEvent(e, &v, legendFields["structure"], &w.St)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
func processEvent[T HasEvents](event *HistoricalEvent, v *reflect.Value, fields []int, objectMap *map[int]T) {
|
|
||||||
for _, i := range fields {
|
|
||||||
val := v.Field(i)
|
|
||||||
if !val.IsZero() {
|
|
||||||
switch val.Elem().Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
ids := val.Interface().(*[]int)
|
|
||||||
for _, id := range *ids {
|
|
||||||
if x, ok := (*objectMap)[id]; ok {
|
|
||||||
x.SetEvents(append(x.GetEvents(), event))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Int:
|
|
||||||
id := int(val.Elem().Int())
|
|
||||||
if x, ok := (*objectMap)[id]; ok {
|
|
||||||
x.SetEvents(append(x.GetEvents(), event))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
fmt.Println("unknown", val.Elem().Kind())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func mapObjects[T Identifiable](objects *[]T, objectMap *map[int]T) {
|
|
||||||
for i, obj := range *objects {
|
|
||||||
(*objectMap)[obj.Id()] = (*objects)[i]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,11 +3,11 @@ package server
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"legendsbrowser/model"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/robertjanetzko/LegendsBrowser2/backend/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Info struct {
|
type Info struct {
|
||||||
|
|
12097
contributors.go
12097
contributors.go
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +0,0 @@
|
||||||
//go:build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
// func main() {
|
|
||||||
// generate.Generate()
|
|
||||||
// }
|
|
Loading…
Reference in New Issue