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-18 11:36:29 +03:00
|
|
|
"encoding/json"
|
2022-04-13 15:01:20 +03:00
|
|
|
"encoding/xml"
|
|
|
|
"fmt"
|
2022-04-18 11:36:29 +03:00
|
|
|
"io/ioutil"
|
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
|
|
|
|
|
|
|
func (e *HistoricalEvent) Name() string { return "" }
|
|
|
|
func (e *HistoricalEventCollection) 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)
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Println("Successfully Opened", file)
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Println("Successfully Opened", file)
|
|
|
|
|
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-18 13:13:38 +03:00
|
|
|
func Parse(file string) (*DfWorld, error) {
|
|
|
|
InitSameFields()
|
|
|
|
|
2022-04-19 21:32:20 +03:00
|
|
|
p, xmlFile, bar, err := NewLegendsParser(file)
|
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 10:24:16 +03:00
|
|
|
world := &DfWorld{}
|
|
|
|
|
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-04-15 16:27:51 +03:00
|
|
|
|
2022-04-18 13:13:38 +03:00
|
|
|
bar.Finish()
|
|
|
|
|
2022-04-15 16:27:51 +03:00
|
|
|
plus := true
|
|
|
|
|
|
|
|
if plus {
|
|
|
|
file = strings.Replace(file, "-legends.xml", "-legends_plus.xml", 1)
|
2022-04-18 13:13:38 +03:00
|
|
|
|
2022-04-19 21:32:20 +03:00
|
|
|
p, xmlFile, bar, err = NewLegendsParser(file)
|
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-04-18 13:13:38 +03:00
|
|
|
|
|
|
|
bar.Finish()
|
2022-04-15 16:27:51 +03:00
|
|
|
}
|
|
|
|
|
2022-04-18 11:36:29 +03:00
|
|
|
same, err := json.MarshalIndent(exportSameFields(), "", " ")
|
|
|
|
if err != nil {
|
|
|
|
return world, err
|
|
|
|
}
|
|
|
|
ioutil.WriteFile("same.json", same, 0644)
|
|
|
|
|
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-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-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
|
|
|
|
}
|