admin_backend/model/Statistics.go
2025-10-21 14:23:05 +08:00

290 lines
7.6 KiB
Go

package model
import (
"backend/util"
"fmt"
"sort"
"strconv"
)
type Statistics struct {
AppId int `json:"AppId"`
ServerList []int `json:"ServerList"`
Emit []string `json:"Emit"`
}
func (s *Statistics) StatisticsLevel() (interface{}, error) {
AppConfig, err := util.GetAppConfig(s.AppId)
if err != nil {
return nil, err
}
res := make([]map[string]interface{}, 0)
res1 := make(map[int]int)
type dbres struct {
Sum int `db:"sum"`
Level int `db:"level"`
}
for _, v := range s.ServerList {
Db := util.MPool.GetMysqlDB(AppConfig, v)
if Db == nil {
return nil, fmt.Errorf("failed to get mysql database")
}
var result []dbres
err = Db.Select(&result, "select count(*) as sum , `level` from t_player_baseinfo group by `level`")
if err != nil {
return nil, fmt.Errorf("failed to get level count: %v", err)
}
for r := range result {
res1[result[r].Level] += result[r].Sum
}
Db.Close()
}
keys := make([]int, 0, len(res1))
for k := range res1 {
keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
res = append(res, map[string]interface{}{
"Level": k,
"Sum": res1[k],
})
}
return map[string]interface{}{
"data": res,
"total": len(res),
}, nil
}
func (s *Statistics) StatisticsInfo() (interface{}, error) {
AppConfig, err := util.GetAppConfig(s.AppId)
if err != nil {
return nil, err
}
LogDb := util.MPool.GetTopicDB(AppConfig.Topic)
defer LogDb.Close()
if LogDb == nil {
return nil, fmt.Errorf("failed to get mysql database")
}
StartTime, _ := util.GetZeroTimestamp(AppConfig.Tz, 0)
EndTime, _ := util.GetZeroTimestamp(AppConfig.Tz, 1)
var Register int
var TotalRegistger int
var Recharge float64
var TotalRecharge float64
var RechargeUser int
err = LogDb.Get(&Register, "select count(*) as sum from log_login where Event = 'register' and Timestamp >= ? and Timestamp <= ?", StartTime, EndTime)
if err != nil {
return nil, fmt.Errorf("failed to get register count: %v", err)
}
err = LogDb.Get(&TotalRegistger, "select count(*) as sum from log_login where Event = 'register'")
if err != nil {
return nil, fmt.Errorf("failed to get total register count: %v", err)
}
err = LogDb.Get(&Recharge, "select IFNULL(SUM(Price), 0) as sum from log_order where Timestamp >= ? and Timestamp <= ?", StartTime, EndTime)
if err != nil {
return nil, fmt.Errorf("failed to get recharge count: %v", err)
}
err = LogDb.Get(&TotalRecharge, "select IFNULL(SUM(Price), 0) as sum from log_order")
if err != nil {
return nil, fmt.Errorf("failed to get total recharge count: %v", err)
}
// 充值人数统计
err = LogDb.Get(&RechargeUser, "select count(distinct Uid) as sum from log_order where Timestamp >= ? and Timestamp <= ?", StartTime, EndTime)
if err != nil {
return nil, fmt.Errorf("failed to get recharge count: %v", err)
}
var TotalRechargeUser int
// 充值总人数统计
err = LogDb.Get(&TotalRechargeUser, "select count(distinct Uid) as sum from log_order")
if err != nil {
return nil, fmt.Errorf("failed to get total recharge count: %v", err)
}
type RemainCount struct {
Register int `db:"register"`
SecondRemain int `db:"SecondRemain"`
}
var rc RemainCount
err = LogDb.Get(&rc, "select sum(`Register`) as register, sum(`SecondRemain`) as SecondRemain from remain")
if err != nil {
return nil, fmt.Errorf("failed to get recharge count: %v", err)
}
rechargeFloat, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", Recharge), 64)
totalRechargeFloat, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", TotalRecharge), 64)
return map[string]interface{}{
"register": Register,
"totalRegister": TotalRegistger,
"recharge": rechargeFloat,
"totalRecharge": totalRechargeFloat,
"rechargeUser": RechargeUser,
"totalRechargeUser": TotalRechargeUser,
"remain": util.FloatDecimals(100*float64(rc.SecondRemain)/float64(rc.Register), 2),
}, nil
}
func (s *Statistics) StatisticsHeat() (interface{}, error) {
AppConfig, err := util.GetAppConfig(s.AppId)
if err != nil {
return nil, err
}
LogDb := util.MPool.GetTopicDB(AppConfig.Topic)
defer LogDb.Close()
if LogDb == nil {
return nil, fmt.Errorf("failed to get mysql database")
}
now := util.Now()
value := make([]int, 0, 24)
value2 := make([]int, 0, 24)
key := make([]string, 0, 24)
for i := 0; i < 24; i++ {
key = append(key, fmt.Sprintf("%02d:00", i))
}
type r struct {
Sum1 int `db:"sum1"`
Sum2 int `db:"sum2"`
}
var result r
for i := 0; i < 24; i++ {
err := LogDb.Get(&result, "select count(*) as sum1, count(distinct Uid) as sum2 from log_event where Timestamp >= ? and Timestamp <= ?", now-int64(i)*3600-3600, now-int64(i)*3600)
if err != nil {
return nil, fmt.Errorf("failed to get heat count: %v", err)
}
value = append(value, result.Sum1)
value2 = append(value2, result.Sum2)
key[i] = fmt.Sprintf("%02d:00", util.GetHour(now-int64(i)*3600, AppConfig.Tz))
}
if len(value) < 2 {
return value, nil
}
// 反转key和value
for i, j := 0, len(value)-1; i < j; i, j = i+1, j-1 {
key[i], key[j] = key[j], key[i]
value2[i], value2[j] = value2[j], value2[i]
value[i], value[j] = value[j], value[i]
}
return map[string]interface{}{
"key": key,
"value": value,
"value2": value2,
}, nil
}
func (s *Statistics) StatisticsOrder() (interface{}, error) {
AppConfig, err := util.GetAppConfig(s.AppId)
if err != nil {
return nil, err
}
LogDb := util.MPool.GetTopicDB(AppConfig.Topic)
defer LogDb.Close()
if LogDb == nil {
return nil, fmt.Errorf("failed to get mysql database")
}
// 订单统计
var result []struct {
Param string `db:"Param"`
}
err = LogDb.Select(&result, "select Param from log_event where `Event` = 'logout' and Timestamp <= ?", util.Now()-86400*7)
if err != nil {
return nil, fmt.Errorf("failed to get order count: %v", err)
}
type r struct {
count int
m map[int]int
}
hard := r{}
hard.m = make(map[int]int)
mid := r{}
mid.m = make(map[int]int)
for _, v := range result {
paramMap := util.ParseParam(v.Param)
orderList := paramMap["order_list"].(map[string]interface{})
if paramMap["after_level"].(float64) < 12 {
continue
}
hardNum := 0
midNum := 0
for _, order := range orderList {
orderMap := order.(map[string]interface{})
MergeList := make([]string, 0)
if mergeIDs, ok := orderMap["MergeId"].([]any); ok && mergeIDs != nil {
for _, m := range mergeIDs {
mInt := fmt.Sprintf("%v", m)
MergeList = append(MergeList, mInt)
}
}
// 检测是否包含难度符文
if int(orderMap["Diff"].(float64)) == 3 && util.CheckContainChess(MergeList, s.Emit) {
hardNum++
}
if int(orderMap["Diff"].(float64)) == 2 && util.CheckContainChess(MergeList, s.Emit) {
midNum++
}
}
if hardNum > 0 {
hard.count++
hard.m[hardNum]++
}
if midNum > 0 {
mid.count++
mid.m[midNum]++
}
}
type rr struct {
Type string `json:"Type"`
Num int `json:"Num"`
Sum int `json:"Sum"`
Prop float64 `json:"Prop"`
}
hardData := make([]rr, 10)
for i := 0; i <= 4; i++ {
num := 0
if i == 0 {
num = hard.count
}
if v, ok := hard.m[i]; ok {
num = v
}
prop := 0.0
if hard.count > 0 {
prop = util.FloatDecimals(100*float64(num)/float64(hard.count), 2)
}
hardData[i] = rr{
Type: "高难度",
Num: i,
Sum: num,
Prop: prop,
}
}
for i := 5; i <= 9; i++ {
num := 0
if i-5 == 0 {
num = mid.count
}
if v, ok := mid.m[i-5]; ok {
num = v
}
prop := 0.0
if mid.count > 0 {
prop = util.FloatDecimals(100*float64(num)/float64(mid.count), 2)
}
hardData[i] = rr{
Type: "中难度",
Num: i - 5,
Sum: num,
Prop: prop,
}
}
return map[string]interface{}{
"data": hardData,
"data2": mid,
}, nil
}