add 数据统计到mysql

This commit is contained in:
sk 2024-12-25 13:57:19 +08:00
parent 70f8ef26e0
commit 6d1fe0c89b
5 changed files with 172 additions and 19 deletions

1
go.mod
View File

@ -19,6 +19,7 @@ require (
github.com/jinzhu/now v1.1.5 github.com/jinzhu/now v1.1.5
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/mojocn/base64Captcha v1.3.6 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/cast v1.7.0
github.com/spf13/viper v1.19.0 github.com/spf13/viper v1.19.0
github.com/tealeg/xlsx v1.0.5 github.com/tealeg/xlsx v1.0.5

2
go.sum
View File

@ -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/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 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= 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/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 h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=

View File

@ -1,13 +1,15 @@
StartTime: "2024-12-19T00:00:00+08:00" #StartTime: "2024-12-19T00:00:00+08:00"
EndTime: "2024-12-20T00:00:00+08:00" #EndTime: "2024-12-20T00:00:00+08:00"
IsDatabaseMode: true
Switch: # 1: open, 0: close Switch: # 1: open, 0: close
- 0 # 新用户游戏破产率 - 1 # 新用户游戏破产率
- 0 # 新用户平均游戏时长 - 1 # 新用户平均游戏时长
- 1 # 用户平均游戏时长 - 1 # 用户平均游戏时长
- 0 # 新用户平均局数 - 1 # 新用户平均局数
- 0 # 平均倍数 - 1 # 平均倍数
- 0 # 活跃破产率 - 1 # 活跃破产率
- 0 # 控输赢胜率 - 0 # 控输赢胜率
- 0 # 机器人胜率 - 0 # 机器人胜率
- 0 # 人均获得金币 - 0 # 人均获得金币

View File

@ -1,8 +1,16 @@
package main package main
import ( import (
"errors"
"fmt" "fmt"
"golang.org/x/exp/maps"
"strings"
"github.com/mozillazg/go-pinyin"
"github.com/xuri/excelize/v2" "github.com/xuri/excelize/v2"
"gorm.io/gorm"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/mysqlx"
) )
type ExcelData struct { type ExcelData struct {
@ -84,5 +92,136 @@ func (e *ExcelMgr) Save(id int, fileName string) error {
if d == nil { if d == nil {
return 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) 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
}

View File

@ -11,6 +11,7 @@ import (
"mongo.games.com/goserver/core/mysqlx" "mongo.games.com/goserver/core/mysqlx"
"mongo.games.com/goserver/core/viperx" "mongo.games.com/goserver/core/viperx"
"mongo.games.com/game/common"
"mongo.games.com/game/statistics/task/gamefree" "mongo.games.com/game/statistics/task/gamefree"
"mongo.games.com/game/statistics/task/task" "mongo.games.com/game/statistics/task/task"
) )
@ -36,6 +37,7 @@ func main() {
logger.Logger.Flush() logger.Logger.Flush()
logger.Logger.Close() logger.Logger.Close()
}() }()
VP = viperx.GetViper("config.yaml") VP = viperx.GetViper("config.yaml")
// mongo // mongo
vp := viperx.GetViper("mongo.yaml") vp := viperx.GetViper("mongo.yaml")
@ -58,6 +60,13 @@ func main() {
mysqlx.Init(myConf) mysqlx.Init(myConf)
defer mysqlx.Close() 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")) startTime, err := time.Parse(time.RFC3339, VP.GetString("StartTime"))
if err != nil { if err != nil {
panic(fmt.Sprintf("time.Parse err: %v", err)) panic(fmt.Sprintf("time.Parse err: %v", err))
@ -70,18 +79,18 @@ func main() {
} }
mgr := NewExcelMgr() mgr := NewExcelMgr()
mgr.Register(ExcelTypeNewPlayerBankrupt, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"}) mgr.Register(ExcelTypeNewPlayerBankrupt, []string{"日期*", "场次id*", "破产人数", "参与人数", "破产率"})
mgr.Register(ExcelTypeGameTimeAvg, []string{"日期", "场次id", "参与人数", "平均游戏时长"}) mgr.Register(ExcelTypeGameTimeAvg, []string{"日期*", "场次id*", "参与人数", "平均游戏时长"})
mgr.Register(ExcelTypeGameTimeAllAvg, []string{"日期", "场次id", "参与人数", "平均游戏时长"}) mgr.Register(ExcelTypeGameTimeAllAvg, []string{"日期*", "场次id*", "参与人数", "平均游戏时长"})
mgr.Register(ExcelTypeGameCountAvg, []string{"日期", "场次id", "参与人数", "平均局数"}) mgr.Register(ExcelTypeGameCountAvg, []string{"日期*", "场次id*", "参与人数", "平均局数"})
mgr.Register(ExcelTypeGameRate, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}) mgr.Register(ExcelTypeGameRate, []string{"日期*", "场次id*", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"})
mgr.Register(ExcelTypeActiveRate, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"}) mgr.Register(ExcelTypeActiveRate, []string{"日期*", "场次id*", "破产人数", "参与人数", "破产率"})
mgr.Register(ExcelTypeCtrlWinRate, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}) mgr.Register(ExcelTypeCtrlWinRate, []string{"日期*", "场次id*", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"})
mgr.Register(ExcelTypeCtrlWinRate*10, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}) mgr.Register(ExcelTypeCtrlWinRate*10, []string{"日期*", "场次id*", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"})
mgr.Register(ExcelTypeRobotWinRate, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}) mgr.Register(ExcelTypeRobotWinRate, []string{"日期*", "场次id*", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"})
mgr.Register(ExcelTypeCoinAvg, []string{"日期", "场次id", "参与人数", "人均获得金币"}) mgr.Register(ExcelTypeCoinAvg, []string{"日期*", "场次id*", "参与人数", "人均获得金币"})
mgr.Register(ExcelTypeBankruptOffline, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"}) mgr.Register(ExcelTypeBankruptOffline, []string{"日期*", "场次id*", "破产人数", "参与人数", "破产率"})
mgr.Register(ExcelTypeOfflineCoin, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"}) mgr.Register(ExcelTypeOfflineCoin, []string{"日期*", "场次id*", "破产人数", "参与人数", "破产率"})
switchArr := VP.GetIntSlice("Switch") switchArr := VP.GetIntSlice("Switch")
for { for {