add 数据统计到mysql
This commit is contained in:
parent
70f8ef26e0
commit
6d1fe0c89b
1
go.mod
1
go.mod
|
@ -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
2
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/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=
|
||||||
|
|
|
@ -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 # 人均获得金币
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue