vRp.CD2g_test/planner/configexport/internal/config.go

424 lines
9.3 KiB
Go

package internal
import (
"bytes"
"fmt"
jsonIter "github.com/json-iterator/go"
"github.com/kercylan98/minotaur/utils/geometry/matrix"
"github.com/kercylan98/minotaur/utils/hash"
"github.com/kercylan98/minotaur/utils/str"
"github.com/kercylan98/minotaur/utils/xlsxtool"
"github.com/tealeg/xlsx"
"strconv"
"strings"
"text/template"
)
// NewConfig 定位为空将读取Sheet名称
// - 表格中需要严格遵守 描述、名称、类型、导出参数、数据列的顺序
func NewConfig(sheet *xlsx.Sheet, exist map[string]bool) (*Config, error) {
config := &Config{
ignore: "#",
excludeFields: map[int]bool{0: true},
Exist: exist,
}
if strings.HasPrefix(sheet.Name, config.ignore) {
return nil, ErrReadConfigFailedIgnore
}
if err := config.initField(sheet); err != nil {
return nil, err
}
return config, nil
}
type Config struct {
Exist map[string]bool
Prefix string
DisplayName string
Name string
Describe string
ExportParam string
IndexCount int
Fields []*Field
matrix *matrix.Matrix[*xlsx.Cell]
excludeFields map[int]bool // 排除的字段
ignore string
horizontal bool
dataStart int
dataServer map[any]any
dataClient map[any]any
}
func (slf *Config) initField(sheet *xlsx.Sheet) error {
slf.matrix = xlsxtool.GetSheetMatrix(sheet)
var displayName *Position
name, indexCount := NewPosition(1, 0), NewPosition(1, 1)
if displayName == nil {
slf.DisplayName = sheet.Name
} else {
if value := slf.matrix.Get(displayName.X, displayName.Y); value == nil {
return ErrReadConfigFailedWithDisplayName
} else {
slf.DisplayName = strings.TrimSpace(value.String())
}
}
if name == nil {
slf.Name = sheet.Name
} else {
if value := slf.matrix.Get(name.X, name.Y); value == nil {
return ErrReadConfigFailedWithName
} else {
slf.Name = str.FirstUpper(strings.TrimSpace(value.String()))
}
}
if strings.HasPrefix(sheet.Name, slf.ignore) {
return ErrReadConfigFailedIgnore
}
if hash.Exist(slf.Exist, slf.Name) {
return ErrReadConfigFailedSame
}
if indexCount == nil {
slf.IndexCount, _ = strconv.Atoi(sheet.Name)
} else {
if value := slf.matrix.Get(indexCount.X, indexCount.Y); value == nil {
return ErrReadConfigFailedWithIndexCount
} else {
indexCount, err := value.Int()
if err != nil {
return err
}
if indexCount < 0 {
return ErrReadConfigFailedWithIndexCountLessThanZero
}
slf.IndexCount = indexCount
}
}
var (
describeStart int
horizontal bool
fields = make(map[string]bool)
dx, dy, nx, ny, tx, ty, ex, ey int
)
horizontal = slf.IndexCount > 0
slf.horizontal = horizontal
if horizontal {
describeStart = 3
dy = describeStart
ny = dy + 1
ty = ny + 1
ey = ty + 1
slf.dataStart = ey + 1
} else {
delete(slf.excludeFields, 0)
describeStart = 4
dy = describeStart
ny = dy
ty = dy
ey = dy
nx = dx + 1
tx = nx + 1
ex = tx + 1
slf.dataStart = ey + 1
}
var index = slf.IndexCount
for {
var (
describe, fieldName, fieldType, exportParam string
)
var skip bool
if value, exist := slf.matrix.GetExist(dx, dy); !exist {
skip = true
} else {
describe = value.String()
}
if value, exist := slf.matrix.GetExist(nx, ny); !exist {
skip = true
} else {
fieldName = str.FirstUpper(strings.TrimSpace(value.String()))
}
if value, exist := slf.matrix.GetExist(tx, ty); !exist {
skip = true
} else {
fieldType = strings.TrimSpace(value.String())
}
if value, exist := slf.matrix.GetExist(ex, ey); !exist {
skip = true
} else {
exportParam = strings.ToLower(strings.TrimSpace(value.String()))
}
if len(strings.TrimSpace(fieldName))+len(strings.TrimSpace(fieldType))+len(strings.TrimSpace(exportParam)) < 3 {
skip = true
}
var field = NewField(slf.Name, fieldName, fieldType)
field.Describe = strings.ReplaceAll(describe, "\n", ", ")
if strings.HasSuffix(field.Describe, ", ") {
field.Describe = field.Describe[:len(field.Describe)-2]
}
field.ExportParam = exportParam
switch field.ExportParam {
case "s", "sc", "cs":
field.Server = true
}
if horizontal {
dx++
nx++
tx++
ex++
} else {
dy++
ny++
ty++
ey++
}
if !skip {
field.Ignore = slf.excludeFields[len(slf.Fields)]
if !field.Ignore {
if strings.HasPrefix(field.Describe, slf.ignore) {
field.Ignore = true
} else if strings.HasPrefix(field.Name, slf.ignore) {
field.Ignore = true
} else if strings.HasPrefix(field.Type, slf.ignore) {
field.Ignore = true
} else if strings.HasPrefix(field.ExportParam, slf.ignore) {
field.Ignore = true
}
}
if !field.Ignore {
switch exportParam {
case "s", "c", "sc", "cs":
default:
continue
}
}
if fields[field.Name] && !field.Ignore {
return ErrReadConfigFailedWithNameDuplicate
}
if index > 0 && !field.Ignore {
if _, exist := basicTypeName[field.Type]; !exist {
return ErrReadConfigFailedWithIndexTypeException
}
index--
}
fields[field.Name] = true
slf.Fields = append(slf.Fields, field)
}
if horizontal {
if dx >= slf.matrix.GetWidth() {
break
}
} else {
if dy >= slf.matrix.GetHeight() {
break
}
}
}
return slf.initData()
}
func (slf *Config) initData() error {
var x, y int
if slf.horizontal {
y = slf.dataStart
} else {
x = 4
y = 4
}
var dataSourceServer = make(map[any]any)
var dataSourceClient = make(map[any]any)
for {
var dataServer = dataSourceServer
var dataClient = dataSourceClient
var currentIndex = 0
var lineServer = map[any]any{}
var lineClient = map[any]any{}
var skip bool
var offset int
var stop bool
for i := 0; i < len(slf.Fields); i++ {
if slf.excludeFields[i] {
if c := slf.matrix.Get(x+i, y); c != nil && strings.HasPrefix(c.String(), "#") {
skip = true
break
}
continue
}
field := slf.Fields[i]
if field.Ignore {
continue
}
var value any
var zero bool
if slf.horizontal {
c := slf.matrix.Get(x+i, y)
if c == nil {
if currentIndex < slf.IndexCount {
stop = true
break
}
value = getValueZero(field.SourceType)
zero = true
} else if currentIndex < slf.IndexCount && len(strings.TrimSpace(c.String())) == 0 {
stop = true
break
}
if !zero {
value = getValueWithType(field.SourceType, c.String())
}
} else {
c := slf.matrix.Get(x, y+i+offset)
for c == nil {
offset++
c = slf.matrix.Get(x, y+i+offset)
if y+i+offset >= slf.matrix.GetHeight() {
break
}
}
value = getValueWithType(field.SourceType, c.String())
}
switch field.ExportParam {
case "s":
lineServer[field.Name] = value
case "c":
lineClient[field.Name] = value
case "sc", "cs":
lineServer[field.Name] = value
lineClient[field.Name] = value
default:
skip = true
break
}
if currentIndex < slf.IndexCount {
currentIndex++
m, exist := dataServer[value]
if !exist {
if currentIndex == slf.IndexCount {
dataServer[value] = lineServer
} else {
m = map[any]any{}
dataServer[value] = m
}
}
if currentIndex < slf.IndexCount {
dataServer = m.(map[any]any)
}
m, exist = dataClient[value]
if !exist {
if currentIndex == slf.IndexCount {
dataClient[value] = lineClient
} else {
m = map[any]any{}
dataClient[value] = m
}
}
if currentIndex < slf.IndexCount {
dataClient = m.(map[any]any)
}
}
}
if stop {
break
} else if slf.horizontal {
y++
if y >= slf.matrix.GetHeight() {
break
}
} else {
if !skip {
slf.dataServer = lineServer
slf.dataClient = lineClient
}
break
}
}
if slf.horizontal {
slf.dataServer = dataSourceServer
slf.dataClient = dataSourceClient
}
return nil
}
func (slf *Config) String() string {
tmpl, err := template.New("struct").Parse(generateConfigTemplate)
if err != nil {
return ""
}
var buf bytes.Buffer
if err = tmpl.Execute(&buf, slf); err != nil {
return ""
}
var result string
_ = str.RangeLine(buf.String(), func(index int, line string) error {
if len(strings.TrimSpace(line)) == 0 {
return nil
}
result += fmt.Sprintf("%s\n", strings.ReplaceAll(line, "\t\t", "\t"))
if len(strings.TrimSpace(line)) == 1 {
result += "\n"
}
return nil
})
return result
}
func (slf *Config) JsonServer() []byte {
buffer := &bytes.Buffer{}
encoder := jsonIter.NewEncoder(buffer)
encoder.SetEscapeHTML(false)
encoder.SetIndent("", " ")
_ = encoder.Encode(slf.dataServer)
return buffer.Bytes()
}
func (slf *Config) JsonClient() []byte {
buffer := &bytes.Buffer{}
encoder := jsonIter.NewEncoder(buffer)
encoder.SetEscapeHTML(false)
encoder.SetIndent("", " ")
_ = encoder.Encode(slf.dataClient)
return buffer.Bytes()
}
func (slf *Config) GetVariable() string {
var result string
var count int
if slf.IndexCount > 0 {
for _, field := range slf.Fields {
if field.Ignore {
continue
}
result += fmt.Sprintf("map[%s]", field.Type)
count++
if count >= slf.IndexCount {
break
}
}
}
return fmt.Sprintf("%s*%sDefine", result, slf.Name)
}
func (slf *Config) GetVariableGen() string {
if slf.IndexCount == 0 {
return fmt.Sprintf("new(%s)", strings.TrimPrefix(slf.GetVariable(), "*"))
}
return fmt.Sprintf("make(%s)", slf.GetVariable())
}