dorfylegends/backend/model/parse.go

291 lines
5.0 KiB
Go
Raw Normal View History

2022-04-14 18:39:18 +03:00
package model
2022-04-13 15:01:20 +03:00
import (
2022-04-19 21:32:20 +03:00
"bufio"
2022-04-13 15:01:20 +03:00
"encoding/xml"
"fmt"
2022-04-15 16:27:51 +03:00
"log"
2022-04-13 15:01:20 +03:00
"os"
2022-04-15 16:27:51 +03:00
"strconv"
"strings"
2022-04-13 15:01:20 +03:00
2022-04-18 13:13:38 +03:00
"github.com/cheggaaa/pb/v3"
2022-04-14 18:39:18 +03:00
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
)
2022-04-14 16:49:09 +03:00
2022-05-03 15:59:47 +03:00
func (e *HistoricalEvent) Name() string { return "" }
2022-04-13 15:01:20 +03:00
2022-04-18 13:13:38 +03:00
func NewLegendsDecoder(file string) (*xml.Decoder, *os.File, *pb.ProgressBar, error) {
fi, err := os.Stat(file)
if err != nil {
return nil, nil, nil, err
}
size := fi.Size()
bar := pb.Full.Start64(size)
2022-04-18 11:36:29 +03:00
2022-04-13 15:01:20 +03:00
xmlFile, err := os.Open(file)
if err != nil {
fmt.Println(err)
}
2022-05-10 10:51:04 +03:00
fmt.Println("Loading:", file)
2022-04-13 15:01:20 +03:00
converter := util.NewConvertReader(xmlFile)
2022-04-18 13:13:38 +03:00
barReader := bar.NewProxyReader(converter)
d := xml.NewDecoder(barReader)
return d, xmlFile, bar, err
}
2022-04-19 21:32:20 +03:00
func NewLegendsParser(file string) (*util.XMLParser, *os.File, *pb.ProgressBar, error) {
fi, err := os.Stat(file)
if err != nil {
return nil, nil, nil, err
}
size := fi.Size()
bar := pb.Full.Start64(size)
xmlFile, err := os.Open(file)
if err != nil {
fmt.Println(err)
}
2022-05-10 10:51:04 +03:00
fmt.Println("\nLoading:", file)
2022-04-19 21:32:20 +03:00
2022-04-20 13:46:42 +03:00
barReader := bar.NewProxyReader(xmlFile)
2022-04-19 21:32:20 +03:00
d := util.NewXMLParser(bufio.NewReader(barReader))
return d, xmlFile, bar, err
}
2022-04-26 22:00:09 +03:00
type LoadProgress struct {
Message string
ProgressBar *pb.ProgressBar
}
func Parse(file string, lp *LoadProgress) (*DfWorld, error) {
2022-04-18 13:13:38 +03:00
InitSameFields()
2022-04-19 21:32:20 +03:00
p, xmlFile, bar, err := NewLegendsParser(file)
2022-04-26 22:00:09 +03:00
if lp != nil {
lp.Message = "Loading " + file
lp.ProgressBar = bar
}
2022-04-18 13:13:38 +03:00
if err != nil {
return nil, err
}
defer xmlFile.Close()
2022-04-13 15:01:20 +03:00
2022-04-26 22:00:09 +03:00
var world *DfWorld
2022-04-26 10:24:16 +03:00
2022-04-15 16:27:51 +03:00
BaseLoop:
2022-04-13 15:01:20 +03:00
for {
2022-04-19 21:32:20 +03:00
t, n, err := p.Token()
2022-04-13 15:01:20 +03:00
if err != nil {
return nil, err
}
2022-04-19 21:32:20 +03:00
switch t {
case util.StartElement:
if n == "df_world" {
world, err = parseDfWorld(p)
2022-04-15 16:27:51 +03:00
if err != nil {
return nil, err
}
break BaseLoop
2022-04-13 15:01:20 +03:00
}
}
}
2022-05-01 13:29:39 +03:00
world.FilePath = file
2022-04-15 16:27:51 +03:00
2022-04-18 13:13:38 +03:00
bar.Finish()
2022-05-08 17:38:38 +03:00
plus := false
2022-05-10 10:51:04 +03:00
file = strings.Replace(file, "-legends.xml", "-legends_plus.xml", 1)
if _, err := os.Stat(file); err == nil {
plus = true
} else {
fmt.Println("\nno legends_plus.xml found")
}
2022-04-15 16:27:51 +03:00
if plus {
2022-04-19 21:32:20 +03:00
p, xmlFile, bar, err = NewLegendsParser(file)
2022-04-26 22:00:09 +03:00
if lp != nil {
lp.Message = "Loading " + file
lp.ProgressBar = bar
}
2022-04-15 16:27:51 +03:00
if err != nil {
2022-04-18 13:13:38 +03:00
return nil, err
2022-04-15 16:27:51 +03:00
}
defer xmlFile.Close()
PlusLoop:
for {
2022-04-19 21:32:20 +03:00
t, n, err := p.Token()
2022-04-15 16:27:51 +03:00
if err != nil {
return nil, err
}
2022-04-19 21:32:20 +03:00
switch t {
case util.StartElement:
if n == "df_world" {
world, err = parseDfWorldPlus(p, world)
2022-04-15 16:27:51 +03:00
if err != nil {
return nil, err
}
break PlusLoop
}
}
}
2022-05-08 17:38:38 +03:00
world.Plus = true
2022-05-01 13:29:39 +03:00
world.PlusFilePath = file
2022-04-18 13:13:38 +03:00
bar.Finish()
2022-04-15 16:27:51 +03:00
}
2022-05-01 13:29:39 +03:00
// same, err := json.MarshalIndent(exportSameFields(), "", " ")
// if err != nil {
// return world, err
// }
// ioutil.WriteFile("same.json", same, 0644)
world.LoadMap()
2022-05-05 23:18:31 +03:00
world.LoadHistory()
2022-04-18 11:36:29 +03:00
2022-04-29 16:28:08 +03:00
world.process()
2022-04-28 22:24:55 +03:00
2022-04-15 16:27:51 +03:00
return world, nil
2022-04-13 15:01:20 +03:00
}
2022-04-19 21:32:20 +03:00
func parseArray[T any](p *util.XMLParser, dest *[]T, creator func(*util.XMLParser) (T, error)) {
2022-04-13 15:01:20 +03:00
for {
2022-04-19 21:32:20 +03:00
t, _, err := p.Token()
2022-04-13 15:01:20 +03:00
if err != nil {
return // nil, err
}
2022-04-19 21:32:20 +03:00
switch t {
case util.StartElement:
x, _ := creator(p)
2022-04-13 15:01:20 +03:00
*dest = append(*dest, x)
2022-04-19 21:32:20 +03:00
case util.EndElement:
2022-04-13 15:01:20 +03:00
return
}
}
}
2022-05-04 10:26:26 +03:00
func parseArrayPlus[T any](p *util.XMLParser, dest *[]T, creator func(*util.XMLParser, T) (T, error)) {
for {
t, _, err := p.Token()
if err != nil {
return // nil, err
}
switch t {
case util.StartElement:
var x T
x, _ = creator(p, x)
*dest = append(*dest, x)
case util.EndElement:
return
}
}
}
2022-04-19 21:32:20 +03:00
func parseMap[T Identifiable](p *util.XMLParser, dest *map[int]T, creator func(*util.XMLParser) (T, error)) {
2022-04-13 15:01:20 +03:00
for {
2022-04-19 21:32:20 +03:00
t, _, err := p.Token()
2022-04-13 15:01:20 +03:00
if err != nil {
return // nil, err
}
2022-04-19 21:32:20 +03:00
switch t {
case util.StartElement:
x, _ := creator(p)
2022-04-13 15:01:20 +03:00
(*dest)[x.Id()] = x
2022-04-19 21:32:20 +03:00
case util.EndElement:
2022-04-13 15:01:20 +03:00
return
}
}
}
2022-04-15 16:27:51 +03:00
2022-04-19 21:32:20 +03:00
func parseMapPlus[T Identifiable](p *util.XMLParser, dest *map[int]T, creator func(*util.XMLParser, T) (T, error)) {
2022-04-15 16:27:51 +03:00
for {
2022-04-19 21:32:20 +03:00
t, _, err := p.Token()
2022-04-15 16:27:51 +03:00
if err != nil {
return
}
2022-04-19 21:32:20 +03:00
switch t {
case util.StartElement:
id, err := parseId(p)
2022-04-15 16:27:51 +03:00
if err != nil {
log.Fatal(err)
}
2022-04-19 21:32:20 +03:00
x, err := creator(p, (*dest)[id])
2022-04-28 22:24:55 +03:00
x.setId(id)
2022-04-15 16:27:51 +03:00
if err != nil {
return
}
(*dest)[id] = x
2022-04-19 21:32:20 +03:00
case util.EndElement:
2022-04-15 16:27:51 +03:00
return
}
}
}
2022-04-19 21:32:20 +03:00
func parseId(p *util.XMLParser) (int, error) {
2022-04-15 16:27:51 +03:00
for {
2022-04-19 21:32:20 +03:00
t, n, err := p.Token()
2022-04-15 16:27:51 +03:00
if err != nil {
return -1, err
}
2022-04-19 21:32:20 +03:00
switch t {
case util.StartElement:
if n == "id" {
2022-04-20 13:46:42 +03:00
d, err := p.Value()
2022-04-19 21:32:20 +03:00
if err != nil {
return -1, err
}
2022-04-20 13:46:42 +03:00
return strconv.Atoi(string(d))
2022-04-19 21:32:20 +03:00
} else {
p.Skip()
2022-04-15 16:27:51 +03:00
}
}
}
}
2022-04-18 11:36:29 +03:00
2022-04-20 13:46:42 +03:00
func num(b []byte) int {
v, _ := strconv.Atoi(string(b))
2022-04-19 21:32:20 +03:00
return v
}
2022-04-20 13:46:42 +03:00
func txt(b []byte) string {
return util.ConvertCp473(b)
}
2022-04-18 11:36:29 +03:00
var sameFields map[string]map[string]map[string]bool
func exportSameFields() map[string]map[string]string {
export := make(map[string]map[string]string)
for objectType, v := range sameFields {
fields := make(map[string]string)
for field, v2 := range v {
c := 0
f := ""
for field2, same := range v2 {
if same {
c++
f = field2
}
}
if c == 1 {
fields[field] = f
}
}
if len(fields) > 0 {
export[objectType] = fields
}
}
return export
}