refactor: 导表工具重构,增加部分特性,修复部分问题

1、增加测试用例;
2、支持多文件合并导表;
3、支持 "#" 开头忽略;
4、修复越界问题;
5、优化模板样式,增加模板规则说明;
This commit is contained in:
kercylan98 2023-07-01 16:07:30 +08:00
parent 73cefc9b48
commit afdda793bc
22 changed files with 268 additions and 313 deletions

View File

@ -36,9 +36,12 @@ func Init(loadDir string, loadHandle LoadHandle, refreshHandle RefreshHandle) {
cLoadDir = loadDir cLoadDir = loadDir
cLoadHandle = loadHandle cLoadHandle = loadHandle
cRefreshHandle = refreshHandle cRefreshHandle = refreshHandle
Load()
Refresh()
} }
// Load 加载配置 // Load 加载配置
// - 加载后并不会刷新线上配置,需要执行 Refresh 函数对线上配置进行刷新
func Load() { func Load() {
mutex.Lock() mutex.Lock()
if cTicker != nil { if cTicker != nil {

View File

@ -1,14 +0,0 @@
// Code generated by minotaur-config-export. DO NOT EDIT.
package configs
// SystemConfig 系统
type SystemConfig struct {
Addr string // 监听地址
Finish string // 启动完成
}
// WelcomeConfig 欢迎词
type WelcomeConfig struct {
Id int // ID
Text string // 内容
}

View File

@ -1,47 +0,0 @@
// Code generated by minotaur-config-export. DO NOT EDIT.
package configs
import (
jsonIter "github.com/json-iterator/go"
"github.com/kercylan98/minotaur/utils/log"
"go.uber.org/zap"
"os"
)
var json = jsonIter.ConfigCompatibleWithStandardLibrary
var (
ISystemConfig *SystemConfig
iSystemConfig *SystemConfig
IWelcomeConfig map[int]*WelcomeConfig
iWelcomeConfig map[int]*WelcomeConfig
)
func LoadConfig(handle func(filename string, config any) error) {
var err error
iSystemConfig = new(SystemConfig)
if err = handle("SystemConfig.json", iSystemConfig); err != nil {
log.Error("Config", zap.String("Name", "SystemConfig"), zap.Bool("Invalid", true), zap.Error(err))
}
iWelcomeConfig = make(map[int]*WelcomeConfig)
if err = handle("WelcomeConfig.json", &iWelcomeConfig); err != nil {
log.Error("Config", zap.String("Name", "WelcomeConfig"), zap.Bool("Invalid", true), zap.Error(err))
}
}
func Refresh() {
ISystemConfig = iSystemConfig
IWelcomeConfig = iWelcomeConfig
}
func DefaultLoad(filepath string) {
LoadConfig(func(filename string, config any) error {
bytes, err := os.ReadFile(filepath)
if err != nil {
return err
}
return json.Unmarshal(bytes, &config)
})
}

View File

@ -1,4 +0,0 @@
{
"Finish": "StartFinish",
"Addr": ":9999"
}

View File

@ -1,10 +0,0 @@
{
"1": {
"Id": 1,
"Text": "Hello"
},
"2": {
"Id": 2,
"Text": "World"
}
}

View File

@ -1,30 +0,0 @@
// 该案例演示了配置导表工具的使用,其中包括了作为模板的配置文件及导出的配置文件
package main
import (
"github.com/kercylan98/minotaur/config"
"github.com/kercylan98/minotaur/examples/simple-server-config/config/configs"
"github.com/kercylan98/minotaur/planner/configexport"
"github.com/kercylan98/minotaur/utils/log"
"go.uber.org/zap"
"path/filepath"
)
const (
workdir = "./examples/simple-server-config"
)
func main() {
export()
config.Init(filepath.Join(workdir, "config", "json"), configs.LoadConfig, configs.Refresh)
config.Load()
config.Refresh()
log.Info("Config", zap.Any("SystemConfig", configs.ISystemConfig))
log.Info("Config", zap.Any("WelcomeConfig", configs.IWelcomeConfig))
}
func export() {
c := configexport.New(filepath.Join(workdir, "config", "系统配置.xlsx"))
c.ExportGo("", filepath.Join(workdir, "config", "configs"))
c.ExportServer("", filepath.Join(workdir, "config", "json"))
}

View File

@ -5,24 +5,52 @@ import (
"fmt" "fmt"
"github.com/kercylan98/minotaur/planner/configexport/internal" "github.com/kercylan98/minotaur/planner/configexport/internal"
"github.com/kercylan98/minotaur/utils/file" "github.com/kercylan98/minotaur/utils/file"
"github.com/kercylan98/minotaur/utils/log"
"github.com/kercylan98/minotaur/utils/str" "github.com/kercylan98/minotaur/utils/str"
"github.com/tealeg/xlsx" "github.com/tealeg/xlsx"
"go.uber.org/zap"
"os/exec"
"path/filepath" "path/filepath"
"strings" "strings"
"text/template" "text/template"
) )
// New 创建一个导表配置
func New(xlsxPath string) *ConfigExport { func New(xlsxPath string) *ConfigExport {
ce := &ConfigExport{xlsxPath: xlsxPath} ce := &ConfigExport{xlsxPath: xlsxPath, exist: make(map[string]bool)}
xlsxFile, err := xlsx.OpenFile(xlsxPath) xlsxFile, err := xlsx.OpenFile(xlsxPath)
if err != nil { if err != nil {
panic(err) panic(err)
} }
for i := 0; i < len(xlsxFile.Sheets); i++ { for i := 0; i < len(xlsxFile.Sheets); i++ {
if config, err := internal.NewConfig(xlsxFile.Sheets[i]); err != nil { sheet := xlsxFile.Sheets[i]
panic(err) if config, err := internal.NewConfig(sheet, ce.exist); err != nil {
switch err {
case internal.ErrReadConfigFailedSame:
log.Warn("ConfigExport",
zap.String("File", xlsxPath),
zap.String("Sheet", sheet.Name),
zap.String("Info", "A configuration with the same name exists, skipped"),
)
case internal.ErrReadConfigFailedIgnore:
log.Info("ConfigExport",
zap.String("File", xlsxPath),
zap.String("Sheet", sheet.Name),
zap.String("Info", "Excluded non-configuration table files"),
)
default:
log.ErrorHideStack("ConfigExport",
zap.String("File", xlsxPath),
zap.String("Sheet", sheet.Name),
zap.String("Info", "Excluded non-configuration table files"),
)
}
} else { } else {
if config == nil {
continue
}
ce.configs = append(ce.configs, config) ce.configs = append(ce.configs, config)
ce.exist[config.Name] = true
} }
} }
return ce return ce
@ -31,6 +59,34 @@ func New(xlsxPath string) *ConfigExport {
type ConfigExport struct { type ConfigExport struct {
xlsxPath string xlsxPath string
configs []*internal.Config configs []*internal.Config
exist map[string]bool
}
// Merge 合并多个导表配置
func Merge(exports ...*ConfigExport) *ConfigExport {
if len(exports) == 0 {
return nil
}
if len(exports) == 1 {
return exports[0]
}
var export = exports[0]
for i := 1; i < len(exports); i++ {
ce := exports[i]
for _, config := range ce.configs {
if _, ok := export.exist[config.Name]; ok {
log.Warn("ConfigExport",
zap.String("File", ce.xlsxPath),
zap.String("Sheet", config.Name),
zap.String("Info", "A configuration with the same name exists, skipped"),
)
continue
}
export.configs = append(export.configs, config)
export.exist[config.Name] = true
}
}
return export
} }
func (slf *ConfigExport) ExportClient(prefix, outputDir string) { func (slf *ConfigExport) ExportClient(prefix, outputDir string) {
@ -99,9 +155,13 @@ func (slf *ConfigExport) exportGoConfig(outputDir string) {
return nil return nil
}) })
if err := file.WriterFile(filepath.Join(outputDir, "config.go"), []byte(result)); err != nil { filePath := filepath.Join(outputDir, "config.go")
if err := file.WriterFile(filePath, []byte(result)); err != nil {
panic(err) panic(err)
} }
cmd := exec.Command("gofmt", "-w", filePath)
_ = cmd.Run()
} }
func (slf *ConfigExport) exportGoDefine(outputDir string) { func (slf *ConfigExport) exportGoDefine(outputDir string) {
@ -136,7 +196,11 @@ func (slf *ConfigExport) exportGoDefine(outputDir string) {
return nil return nil
}) })
if err := file.WriterFile(filepath.Join(outputDir, "config.define.go"), []byte(result)); err != nil { filePath := filepath.Join(outputDir, "config.define.go")
if err := file.WriterFile(filePath, []byte(result)); err != nil {
panic(err) panic(err)
} }
cmd := exec.Command("gofmt", "-w", filePath)
_ = cmd.Run()
} }

View File

@ -0,0 +1,42 @@
package configexport_test
import (
"fmt"
"github.com/kercylan98/minotaur/config"
"github.com/kercylan98/minotaur/planner/configexport"
"github.com/kercylan98/minotaur/planner/configexport/example"
"os"
"path/filepath"
"strings"
)
func ExampleNew() {
var workdir = "./"
files, err := os.ReadDir(workdir)
if err != nil {
panic(err)
}
var ces []*configexport.ConfigExport
for _, file := range files {
if file.IsDir() || !strings.HasSuffix(file.Name(), ".xlsx") || strings.HasPrefix(file.Name(), "~") {
continue
}
ces = append(ces, configexport.New(filepath.Join(workdir, file.Name())))
}
c := configexport.Merge(ces...)
outDir := filepath.Join(workdir, "example")
c.ExportGo("", outDir)
c.ExportServer("", outDir)
c.ExportClient("", outDir)
// 下方为配置加载代码
// 使用生成的 LoadConfig 函数加载配置
config.Init(outDir, example.LoadConfig, example.Refresh)
fmt.Println("success")
// Output:
// success
}

View File

@ -1,11 +0,0 @@
package configexport
import "testing"
func TestNew(t *testing.T) {
c := New(`./template.xlsx`)
c.ExportGo("server", "./example")
c.ExportClient("client", "./example")
c.ExportServer("server", "./example")
}

View File

@ -1,18 +1,17 @@
{ {
"Other": {
"1": {
"id": 2,
"name": "刘备"
},
"0": {
"id": 1,
"name": "张飞"
}
},
"Id": 1, "Id": 1,
"Count": "a",
"Award": { "Award": {
"0": "asd", "0": "asd",
"1": "12" "1": "12"
},
"Other": {
"0": {
"id": 1,
"name": "张飞"
},
"1": {
"id": 2,
"name": "刘备"
}
} }
} }

View File

@ -1,22 +1,22 @@
{ {
"1": { "1": {
"b": { "b": {
"Id": 1,
"Count": "b",
"Award": { "Award": {
"0": "asd", "0": "asd",
"1": "12" "1": "12"
}, },
"Other": { "Other": {
"0": { "0": {
"id": 1, "name": "张飞",
"name": "张飞" "id": 1
}, },
"1": { "1": {
"id": 2, "name": "刘备",
"name": "刘备" "id": 2
}
} }
},
"Id": 1,
"Count": "b"
} }
}, },
"2": { "2": {
@ -27,12 +27,12 @@
}, },
"Other": { "Other": {
"0": { "0": {
"id": 1, "name": "张飞",
"name": "张飞" "id": 1
}, },
"1": { "1": {
"name": "刘备", "id": 2,
"id": 2 "name": "刘备"
} }
}, },
"Id": 2, "Id": 2,
@ -42,8 +42,8 @@
"Id": 2, "Id": 2,
"Count": "d", "Count": "d",
"Award": { "Award": {
"0": "asd", "1": "12",
"1": "12" "0": "asd"
}, },
"Other": { "Other": {
"0": { "0": {

View File

@ -1,13 +1,22 @@
// Code generated by minotaur-config-export. DO NOT EDIT. // Code generated by minotaur-config-export. DO NOT EDIT.
package example package example
// IndexConfig 有索引
type IndexConfig struct { // IndexConfigDefine 有索引
type IndexConfigDefine struct {
Id int // 任务ID Id int // 任务ID
Count string // 次数 Count string // 次数
Info *IndexConfigInfo // 信息 Info *IndexConfigInfo // 信息
Other map[int]*IndexConfigOther // 信息2 Other map[int]*IndexConfigOther // 信息2
} }
func (slf *IndexConfigDefine) String() string {
if data, err := json.Marshal(slf); err == nil {
return string(data)
}
return "{}"
}
type IndexConfigInfo struct { type IndexConfigInfo struct {
Id int Id int
Name string Name string
@ -29,14 +38,21 @@ type IndexConfigOther struct {
Name string Name string
} }
// EasyConfig 无索引 // EasyConfigDefine 无索引
type EasyConfig struct { type EasyConfigDefine struct {
Id int // 任务ID Id int // 任务ID
Count string // 次数
Info *EasyConfigInfo // 信息 Info *EasyConfigInfo // 信息
Other map[int]*EasyConfigOther // 信息2 Other map[int]*EasyConfigOther // 信息2
} }
func (slf *EasyConfigDefine) String() string {
if data, err := json.Marshal(slf); err == nil {
return string(data)
}
return "{}"
}
type EasyConfigInfo struct { type EasyConfigInfo struct {
Id int Id int
Name string Name string
@ -57,4 +73,3 @@ type EasyConfigOther struct {
Id int Id int
Name string Name string
} }

View File

@ -1,5 +1,6 @@
// Code generated by minotaur-config-export. DO NOT EDIT. // Code generated by minotaur-config-export. DO NOT EDIT.
package example package example
import ( import (
jsonIter "github.com/json-iterator/go" jsonIter "github.com/json-iterator/go"
"github.com/kercylan98/minotaur/utils/log" "github.com/kercylan98/minotaur/utils/log"
@ -9,29 +10,31 @@ import (
var json = jsonIter.ConfigCompatibleWithStandardLibrary var json = jsonIter.ConfigCompatibleWithStandardLibrary
var ( var (
IIndexConfig map[int]map[string]*IndexConfig // IndexConfig 有索引
iIndexConfig map[int]map[string]*IndexConfig IndexConfig map[int]map[string]*IndexConfigDefine
IEasyConfig *EasyConfig _IndexConfig map[int]map[string]*IndexConfigDefine
iEasyConfig *EasyConfig // EasyConfig 无索引
EasyConfig *EasyConfigDefine
_EasyConfig *EasyConfigDefine
) )
func LoadConfig(handle func(filename string, config any) error) { func LoadConfig(handle func(filename string, config any) error) {
var err error var err error
iIndexConfig = make(map[int]map[string]*IndexConfig) _IndexConfig = make(map[int]map[string]*IndexConfigDefine)
if err = handle("server.IndexConfig.json", &iIndexConfig); err != nil { if err = handle("IndexConfig.json", &_IndexConfig); err != nil {
log.Error("Config", zap.String("Name", "IndexConfig"), zap.Bool("Invalid", true), zap.Error(err)) log.Error("Config", zap.String("Name", "IndexConfig"), zap.Bool("Invalid", true), zap.Error(err))
} }
iEasyConfig = new(EasyConfig) _EasyConfig = new(EasyConfigDefine)
if err = handle("server.EasyConfig.json", iEasyConfig); err != nil { if err = handle("EasyConfig.json", _EasyConfig); err != nil {
log.Error("Config", zap.String("Name", "EasyConfig"), zap.Bool("Invalid", true), zap.Error(err)) log.Error("Config", zap.String("Name", "EasyConfig"), zap.Bool("Invalid", true), zap.Error(err))
} }
} }
func Refresh() { func Refresh() {
IIndexConfig = iIndexConfig IndexConfig = _IndexConfig
IEasyConfig = iEasyConfig EasyConfig = _EasyConfig
} }
func DefaultLoad(filepath string) { func DefaultLoad(filepath string) {
@ -44,4 +47,3 @@ func DefaultLoad(filepath string) {
return json.Unmarshal(bytes, &config) return json.Unmarshal(bytes, &config)
}) })
} }

View File

@ -1,25 +0,0 @@
{
"Other": {
"0": {
"id": 1,
"name": "张飞"
},
"1": {
"id": 2,
"name": "刘备"
}
},
"Id": 1,
"Count": "a",
"Info": {
"id": 1,
"name": "小明",
"info": {
"lv": 1,
"exp": {
"mux": 10,
"count": 100
}
}
}
}

View File

@ -1,81 +0,0 @@
{
"2": {
"c": {
"Info": {
"id": 1,
"name": "小明",
"info": {
"lv": 1,
"exp": {
"mux": 10,
"count": 100
}
}
},
"Other": {
"0": {
"id": 1,
"name": "张飞"
},
"1": {
"id": 2,
"name": "刘备"
}
},
"Id": 2,
"Count": "c"
},
"d": {
"Id": 2,
"Count": "d",
"Info": {
"id": 1,
"name": "小明",
"info": {
"lv": 1,
"exp": {
"mux": 10,
"count": 100
}
}
},
"Other": {
"0": {
"id": 1,
"name": "张飞"
},
"1": {
"id": 2,
"name": "刘备"
}
}
}
},
"1": {
"b": {
"Id": 1,
"Count": "b",
"Info": {
"id": 1,
"name": "小明",
"info": {
"lv": 1,
"exp": {
"mux": 10,
"count": 100
}
}
},
"Other": {
"0": {
"id": 1,
"name": "张飞"
},
"1": {
"id": 2,
"name": "刘备"
}
}
}
}
}

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
jsonIter "github.com/json-iterator/go" jsonIter "github.com/json-iterator/go"
"github.com/kercylan98/minotaur/utils/geometry/matrix" "github.com/kercylan98/minotaur/utils/geometry/matrix"
"github.com/kercylan98/minotaur/utils/hash"
"github.com/kercylan98/minotaur/utils/str" "github.com/kercylan98/minotaur/utils/str"
"github.com/kercylan98/minotaur/utils/xlsxtool" "github.com/kercylan98/minotaur/utils/xlsxtool"
"github.com/tealeg/xlsx" "github.com/tealeg/xlsx"
@ -15,10 +16,14 @@ import (
// NewConfig 定位为空将读取Sheet名称 // NewConfig 定位为空将读取Sheet名称
// - 表格中需要严格遵守 描述、名称、类型、导出参数、数据列的顺序 // - 表格中需要严格遵守 描述、名称、类型、导出参数、数据列的顺序
func NewConfig(sheet *xlsx.Sheet) (*Config, error) { func NewConfig(sheet *xlsx.Sheet, exist map[string]bool) (*Config, error) {
config := &Config{ config := &Config{
ignore: "#", ignore: "#",
excludeFields: map[int]bool{0: true}, 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 { if err := config.initField(sheet); err != nil {
return nil, err return nil, err
@ -27,6 +32,7 @@ func NewConfig(sheet *xlsx.Sheet) (*Config, error) {
} }
type Config struct { type Config struct {
Exist map[string]bool
Prefix string Prefix string
DisplayName string DisplayName string
Name string Name string
@ -68,6 +74,12 @@ func (slf *Config) initField(sheet *xlsx.Sheet) error {
slf.Name = str.FirstUpper(strings.TrimSpace(value.String())) 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 { if indexCount == nil {
slf.IndexCount, _ = strconv.Atoi(sheet.Name) slf.IndexCount, _ = strconv.Atoi(sheet.Name)
@ -120,22 +132,22 @@ func (slf *Config) initField(sheet *xlsx.Sheet) error {
describe, fieldName, fieldType, exportParam string describe, fieldName, fieldType, exportParam string
) )
var skip bool var skip bool
if value := slf.matrix.Get(dx, dy); value == nil { if value, exist := slf.matrix.GetExist(dx, dy); !exist {
skip = true skip = true
} else { } else {
describe = value.String() describe = value.String()
} }
if value := slf.matrix.Get(nx, ny); value == nil { if value, exist := slf.matrix.GetExist(nx, ny); !exist {
skip = true skip = true
} else { } else {
fieldName = str.FirstUpper(strings.TrimSpace(value.String())) fieldName = str.FirstUpper(strings.TrimSpace(value.String()))
} }
if value := slf.matrix.Get(tx, ty); value == nil { if value, exist := slf.matrix.GetExist(tx, ty); !exist {
skip = true skip = true
} else { } else {
fieldType = strings.TrimSpace(value.String()) fieldType = strings.TrimSpace(value.String())
} }
if value := slf.matrix.Get(ex, ey); value == nil { if value, exist := slf.matrix.GetExist(ex, ey); !exist {
skip = true skip = true
} else { } else {
exportParam = strings.ToLower(strings.TrimSpace(value.String())) exportParam = strings.ToLower(strings.TrimSpace(value.String()))
@ -233,6 +245,7 @@ func (slf *Config) initData() error {
var lineClient = map[any]any{} var lineClient = map[any]any{}
var skip bool var skip bool
var offset int var offset int
var stop bool
for i := 0; i < len(slf.Fields); i++ { for i := 0; i < len(slf.Fields); i++ {
if slf.excludeFields[i] { if slf.excludeFields[i] {
if c := slf.matrix.Get(x+i, y); c != nil && strings.HasPrefix(c.String(), "#") { if c := slf.matrix.Get(x+i, y); c != nil && strings.HasPrefix(c.String(), "#") {
@ -249,8 +262,8 @@ func (slf *Config) initData() error {
var value any var value any
if slf.horizontal { if slf.horizontal {
c := slf.matrix.Get(x+i, y) c := slf.matrix.Get(x+i, y)
if c == nil || (currentIndex < slf.IndexCount && len(c.String()) == 0) { if c == nil || (currentIndex < slf.IndexCount && len(strings.TrimSpace(c.String())) == 0) {
skip = true stop = true
break break
} }
value = getValueWithType(field.SourceType, c.String()) value = getValueWithType(field.SourceType, c.String())
@ -273,6 +286,9 @@ func (slf *Config) initData() error {
case "sc", "cs": case "sc", "cs":
lineServer[field.Name] = value lineServer[field.Name] = value
lineClient[field.Name] = value lineClient[field.Name] = value
default:
skip = true
break
} }
if currentIndex < slf.IndexCount { if currentIndex < slf.IndexCount {
@ -304,7 +320,9 @@ func (slf *Config) initData() error {
} }
} }
} }
if slf.horizontal { if stop {
break
} else if slf.horizontal {
y++ y++
if y >= slf.matrix.GetHeight() { if y >= slf.matrix.GetHeight() {
break break
@ -373,7 +391,7 @@ func (slf *Config) GetVariable() string {
} }
} }
} }
return fmt.Sprintf("%s*%s", result, slf.Name) return fmt.Sprintf("%s*%sDefine", result, slf.Name)
} }
func (slf *Config) GetVariableGen() string { func (slf *Config) GetVariableGen() string {

View File

@ -3,6 +3,8 @@ package internal
import "errors" import "errors"
var ( var (
ErrReadConfigFailedIgnore = errors.New("read config skip ignore")
ErrReadConfigFailedSame = errors.New("read config skip, same name")
ErrReadConfigFailedWithDisplayName = errors.New("read config display name failed, can not found position") ErrReadConfigFailedWithDisplayName = errors.New("read config display name failed, can not found position")
ErrReadConfigFailedWithName = errors.New("read config name failed, can not found position") ErrReadConfigFailedWithName = errors.New("read config name failed, can not found position")
ErrReadConfigFailedWithIndexCount = errors.New("read config index count failed, can not found position") ErrReadConfigFailedWithIndexCount = errors.New("read config index count failed, can not found position")

View File

@ -3,12 +3,19 @@ package internal
const ( const (
generateConfigTemplate = ` generateConfigTemplate = `
// {{.Name}} {{.DisplayName}} // {{.Name}}Define {{.DisplayName}}
type {{.Name}} struct { type {{.Name}}Define struct {
{{range $index, $value := .Fields}}{{if eq $value.Server true}}{{if eq $value.Ignore false}}{{$value.Name}} {{$value.Type}} // {{$value.Describe}}{{end}}{{end}} {{range $index, $value := .Fields}}{{if eq $value.Server true}}{{if eq $value.Ignore false}}{{$value.Name}} {{$value.Type}} // {{$value.Describe}}{{end}}{{end}}
{{end}} {{end}}
} }
func (slf *{{.Name}}Define) String() string {
if data, err := json.Marshal(slf); err == nil {
return string(data)
}
return "{}"
}
{{range $index, $value := .Fields}}{{$value}}{{end}} {{range $index, $value := .Fields}}{{$value}}{{end}}
` `
@ -37,21 +44,22 @@ var json = jsonIter.ConfigCompatibleWithStandardLibrary
var ( var (
{{range $index, $config := .Configs}} {{range $index, $config := .Configs}}
I{{$config.Name}} {{$config.GetVariable}} // {{$config.Name}} {{$config.DisplayName}}
i{{$config.Name}} {{$config.GetVariable}} {{$config.Name}} {{$config.GetVariable}}
_{{$config.Name}} {{$config.GetVariable}}
{{end}} {{end}}
) )
func LoadConfig(handle func(filename string, config any) error) { func LoadConfig(handle func(filename string, config any) error) {
var err error var err error
{{range $index, $config := .Configs}} {{range $index, $config := .Configs}}
i{{$config.Name}} = {{$config.GetVariableGen}} _{{$config.Name}} = {{$config.GetVariableGen}}
{{if eq $config.IndexCount 0}} {{if eq $config.IndexCount 0}}
if err = handle("{{$config.Prefix}}{{$config.Name}}.json", i{{$config.Name}}); err != nil { if err = handle("{{$config.Prefix}}{{$config.Name}}.json", _{{$config.Name}}); err != nil {
log.Error("Config", zap.String("Name", "{{$config.Name}}"), zap.Bool("Invalid", true), zap.Error(err)) log.Error("Config", zap.String("Name", "{{$config.Name}}"), zap.Bool("Invalid", true), zap.Error(err))
} }
{{else}} {{else}}
if err = handle("{{$config.Prefix}}{{$config.Name}}.json", &i{{$config.Name}}); err != nil { if err = handle("{{$config.Prefix}}{{$config.Name}}.json", &_{{$config.Name}}); err != nil {
log.Error("Config", zap.String("Name", "{{$config.Name}}"), zap.Bool("Invalid", true), zap.Error(err)) log.Error("Config", zap.String("Name", "{{$config.Name}}"), zap.Bool("Invalid", true), zap.Error(err))
} }
{{end}} {{end}}
@ -60,7 +68,7 @@ func LoadConfig(handle func(filename string, config any) error) {
func Refresh() { func Refresh() {
{{range $index, $config := .Configs}} {{range $index, $config := .Configs}}
I{{$config.Name}} = i{{$config.Name}} {{$config.Name}} = _{{$config.Name}}
{{end}} {{end}}
} }

Binary file not shown.

View File

@ -1,6 +1,7 @@
package matrix package matrix
import ( import (
"github.com/kercylan98/minotaur/utils/generic"
"github.com/kercylan98/minotaur/utils/geometry" "github.com/kercylan98/minotaur/utils/geometry"
) )
@ -60,6 +61,19 @@ func (slf *Matrix[T]) Get(x, y int) (value T) {
return slf.m[geometry.CoordinateToPos(slf.w, x, y)] return slf.m[geometry.CoordinateToPos(slf.w, x, y)]
} }
// GetExist 获取特定坐标的内容,如果不存在则返回 false
func (slf *Matrix[T]) GetExist(x, y int) (value T, exist bool) {
pos := geometry.CoordinateToPos(slf.w, x, y)
if pos >= len(slf.m) {
return
}
t := slf.m[pos]
if generic.IsNil(t) {
return
}
return slf.m[pos], true
}
// GetWithPos 获取特定坐标的内容 // GetWithPos 获取特定坐标的内容
func (slf *Matrix[T]) GetWithPos(pos int) (value T) { func (slf *Matrix[T]) GetWithPos(pos int) (value T) {
return slf.m[pos] return slf.m[pos]

View File

@ -1,5 +1,7 @@
package hash package hash
import "encoding/json"
// Exist 检查特定 key 是否存在 // Exist 检查特定 key 是否存在
func Exist[K comparable, V any](m map[K]V, key K) bool { func Exist[K comparable, V any](m map[K]V, key K) bool {
_, exist := m[key] _, exist := m[key]
@ -15,3 +17,11 @@ func AllExist[K comparable, V any](m map[K]V, keys ...K) bool {
} }
return true return true
} }
// ToJson 将 map 转换为 json 字符串
func ToJson[K comparable, V any](m map[K]V) string {
if data, err := json.Marshal(m); err == nil {
return string(data)
}
return "{}"
}