From 6d1fe0c89b699d625d3aba84c3ad0612d443c353 Mon Sep 17 00:00:00 2001 From: sk <123456@qq.com> Date: Wed, 25 Dec 2024 13:57:19 +0800 Subject: [PATCH] =?UTF-8?q?add=20=E6=95=B0=E6=8D=AE=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E5=88=B0mysql?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 1 + go.sum | 2 + statistics/task/etc/config.yaml | 16 ++-- statistics/task/excelmgr.go | 139 ++++++++++++++++++++++++++++++++ statistics/task/main.go | 33 +++++--- 5 files changed, 172 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 24ed7df..101e647 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/jinzhu/now v1.1.5 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 github.com/mojocn/base64Captcha v1.3.6 + github.com/mozillazg/go-pinyin v0.20.0 github.com/spf13/cast v1.7.0 github.com/spf13/viper v1.19.0 github.com/tealeg/xlsx v1.0.5 diff --git a/go.sum b/go.sum index ea89a77..b521a07 100644 --- a/go.sum +++ b/go.sum @@ -226,6 +226,8 @@ github.com/mojocn/base64Captcha v1.3.6 h1:gZEKu1nsKpttuIAQgWHO+4Mhhls8cAKyiV2Ew0 github.com/mojocn/base64Captcha v1.3.6/go.mod h1:i5CtHvm+oMbj1UzEPXaA8IH/xHFZ3DGY3Wh3dBpZ28E= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+GnMFQ= +github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= diff --git a/statistics/task/etc/config.yaml b/statistics/task/etc/config.yaml index 8b39ca9..a5f0508 100644 --- a/statistics/task/etc/config.yaml +++ b/statistics/task/etc/config.yaml @@ -1,13 +1,15 @@ -StartTime: "2024-12-19T00:00:00+08:00" -EndTime: "2024-12-20T00:00:00+08:00" +#StartTime: "2024-12-19T00:00:00+08:00" +#EndTime: "2024-12-20T00:00:00+08:00" + +IsDatabaseMode: true Switch: # 1: open, 0: close - - 0 # 新用户游戏破产率 - - 0 # 新用户平均游戏时长 + - 1 # 新用户游戏破产率 + - 1 # 新用户平均游戏时长 - 1 # 用户平均游戏时长 - - 0 # 新用户平均局数 - - 0 # 平均倍数 - - 0 # 活跃破产率 + - 1 # 新用户平均局数 + - 1 # 平均倍数 + - 1 # 活跃破产率 - 0 # 控输赢胜率 - 0 # 机器人胜率 - 0 # 人均获得金币 diff --git a/statistics/task/excelmgr.go b/statistics/task/excelmgr.go index f324bb5..b7dd8ca 100644 --- a/statistics/task/excelmgr.go +++ b/statistics/task/excelmgr.go @@ -1,8 +1,16 @@ package main import ( + "errors" "fmt" + "golang.org/x/exp/maps" + "strings" + + "github.com/mozillazg/go-pinyin" "github.com/xuri/excelize/v2" + "gorm.io/gorm" + "mongo.games.com/goserver/core/logger" + "mongo.games.com/goserver/core/mysqlx" ) type ExcelData struct { @@ -84,5 +92,136 @@ func (e *ExcelMgr) Save(id int, fileName string) error { if d == nil { return nil } + + if VP.GetBool("IsDatabaseMode") { + rows, err := d.GetRows("Sheet1") + if err != nil { + return err + } + + db, err := mysqlx.GetDatabase("1") + if err != nil { + logger.Logger.Errorf("GetDatabase error: %v", err) + return err + } + + list := strings.Split(fileName, "_") + name := ChineseToPinYin(list) + if len(name) == 0 { + return errors.New("tableName is empty") + } + tableName := fmt.Sprintf("task_%s", name[0]) + files := make(map[string]string) + index := make(map[string]string) + for _, v := range d.Head { + cl := ChineseToPinYin([]string{v})[0] + files[cl] = v + if strings.Contains(v, "*") { + index[cl] = "INDEX" + } + } + + createSQL := buildCreateTableSQLWithIndices(tableName, list[0], files, index) + + if err = db.Exec(createSQL).Error; err != nil { + logger.Logger.Errorf("createTable error: %v", err) + return err + } + + if err = insertData(db.DB, tableName, maps.Keys(files), rows); err != nil { + logger.Logger.Errorf("insertData error: %v", err) + return err + } + + return nil + } + return d.SaveAs(fileName) } + +// 构建创建表的 SQL 语句,支持中文描述和索引 +func buildCreateTableSQLWithIndices(tableName string, comment string, fields map[string]string, indices map[string]string) string { + var columns []string + var indexDefs []string + + // 遍历字段定义 + for field, comment := range fields { + column := fmt.Sprintf("`%s` VARCHAR(255) COMMENT '%s'", field, comment) + columns = append(columns, column) + + // 根据索引类型添加索引定义 + if indexType, ok := indices[field]; ok { + switch strings.ToUpper(indexType) { + case "PRIMARY": + indexDefs = append(indexDefs, fmt.Sprintf("PRIMARY KEY (`%s`)", field)) + case "UNIQUE": + indexDefs = append(indexDefs, fmt.Sprintf("UNIQUE KEY `idx_%s` (`%s`)", field, field)) + case "INDEX": + indexDefs = append(indexDefs, fmt.Sprintf("KEY `idx_%s` (`%s`)", field, field)) + } + } + } + + // 拼接字段和索引部分 + allDefs := append(columns, indexDefs...) + + ret := fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n%s\n) COMMENT='%s';", + tableName, + strings.Join(allDefs, ",\n"), comment) + logger.Logger.Tracef("createTableSQL: %s", ret) + // 拼接最终的 SQL + return ret +} + +func insertData(db *gorm.DB, tableName string, header []string, rows [][]string) error { + placeholders := strings.Repeat("?,", len(header)) + placeholders = placeholders[:len(placeholders)-1] // 移除多余的逗号 + + insertSQL := fmt.Sprintf("INSERT INTO `%s` (%s) VALUES (%s)", tableName, "`"+strings.Join(header, "`,`")+"`", placeholders) + + for _, row := range rows { + // 确保每行数据长度和表头一致 + if len(row) < len(header) { + for len(row) < len(header) { + row = append(row, "") // 填充缺失列 + } + } + err := db.Exec(insertSQL, interfaceSlice(row)...).Error + if err != nil { + return err + } + } + return nil +} + +func interfaceSlice(slice []string) []interface{} { + result := make([]interface{}, len(slice)) + for i, v := range slice { + result[i] = v + } + return result +} + +var args = pinyin.NewArgs() + +func init() { + args.Style = pinyin.Normal +} + +func joinPinyin(py [][]string) string { + var result []string + for _, word := range py { + if len(word) > 0 { + result = append(result, word[0]) // 每个字的拼音取第一个候选 + } + } + return strings.Join(result, "_") +} + +func ChineseToPinYin(param []string) []string { + var ret []string + for _, v := range param { + ret = append(ret, joinPinyin(pinyin.Pinyin(v, args))) + } + return ret +} diff --git a/statistics/task/main.go b/statistics/task/main.go index 6d7f433..886904e 100644 --- a/statistics/task/main.go +++ b/statistics/task/main.go @@ -11,6 +11,7 @@ import ( "mongo.games.com/goserver/core/mysqlx" "mongo.games.com/goserver/core/viperx" + "mongo.games.com/game/common" "mongo.games.com/game/statistics/task/gamefree" "mongo.games.com/game/statistics/task/task" ) @@ -36,6 +37,7 @@ func main() { logger.Logger.Flush() logger.Logger.Close() }() + VP = viperx.GetViper("config.yaml") // mongo vp := viperx.GetViper("mongo.yaml") @@ -58,6 +60,13 @@ func main() { mysqlx.Init(myConf) defer mysqlx.Close() + if VP.GetString("StartTime") == "" { + VP.Set("StartTime", common.HMSToTime(0, 0, 0).Format(time.RFC3339)) + } + if VP.GetString("EndTime") == "" { + VP.Set("EndTime", common.HMSToTime(0, 0, 0).AddDate(0, 0, 1).Format(time.RFC3339)) + } + startTime, err := time.Parse(time.RFC3339, VP.GetString("StartTime")) if err != nil { panic(fmt.Sprintf("time.Parse err: %v", err)) @@ -70,18 +79,18 @@ func main() { } mgr := NewExcelMgr() - mgr.Register(ExcelTypeNewPlayerBankrupt, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"}) - mgr.Register(ExcelTypeGameTimeAvg, []string{"日期", "场次id", "参与人数", "平均游戏时长"}) - mgr.Register(ExcelTypeGameTimeAllAvg, []string{"日期", "场次id", "参与人数", "平均游戏时长"}) - mgr.Register(ExcelTypeGameCountAvg, []string{"日期", "场次id", "参与人数", "平均局数"}) - mgr.Register(ExcelTypeGameRate, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}) - mgr.Register(ExcelTypeActiveRate, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"}) - mgr.Register(ExcelTypeCtrlWinRate, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}) - mgr.Register(ExcelTypeCtrlWinRate*10, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}) - mgr.Register(ExcelTypeRobotWinRate, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}) - mgr.Register(ExcelTypeCoinAvg, []string{"日期", "场次id", "参与人数", "人均获得金币"}) - mgr.Register(ExcelTypeBankruptOffline, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"}) - mgr.Register(ExcelTypeOfflineCoin, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"}) + mgr.Register(ExcelTypeNewPlayerBankrupt, []string{"日期*", "场次id*", "破产人数", "参与人数", "破产率"}) + mgr.Register(ExcelTypeGameTimeAvg, []string{"日期*", "场次id*", "参与人数", "平均游戏时长"}) + mgr.Register(ExcelTypeGameTimeAllAvg, []string{"日期*", "场次id*", "参与人数", "平均游戏时长"}) + mgr.Register(ExcelTypeGameCountAvg, []string{"日期*", "场次id*", "参与人数", "平均局数"}) + mgr.Register(ExcelTypeGameRate, []string{"日期*", "场次id*", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}) + mgr.Register(ExcelTypeActiveRate, []string{"日期*", "场次id*", "破产人数", "参与人数", "破产率"}) + mgr.Register(ExcelTypeCtrlWinRate, []string{"日期*", "场次id*", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}) + mgr.Register(ExcelTypeCtrlWinRate*10, []string{"日期*", "场次id*", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}) + mgr.Register(ExcelTypeRobotWinRate, []string{"日期*", "场次id*", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}) + mgr.Register(ExcelTypeCoinAvg, []string{"日期*", "场次id*", "参与人数", "人均获得金币"}) + mgr.Register(ExcelTypeBankruptOffline, []string{"日期*", "场次id*", "破产人数", "参与人数", "破产率"}) + mgr.Register(ExcelTypeOfflineCoin, []string{"日期*", "场次id*", "破产人数", "参与人数", "破产率"}) switchArr := VP.GetIntSlice("Switch") for {