admin_backend/util/statistics.go
2025-03-04 12:05:23 +08:00

208 lines
6.3 KiB
Go

package util
import (
"backend/Type"
"encoding/json"
"fmt"
"log"
"time"
)
var loc *time.Location // 时区
func init() {
loc, _ = time.LoadLocation("Europe/London")
}
func ScheduleDailyTask() {
Statistics()
for {
now := time.Now().In(loc)
next := now.AddDate(0, 0, 1).Truncate(24 * time.Hour)
duration := next.Sub(now) + 3600*time.Second // 每天凌晨1点执行
time.Sleep(duration)
// 执行统计函数
Statistics()
}
}
func Statistics() {
log.Println("start statistics")
AppConfig, err := GetAppConfig(3)
if err != nil {
log.Printf("failed to get app config: %v", err)
return
}
LogDb := MPool.GetTopicDB(AppConfig.Topic)
defer LogDb.Close()
for i := 0; i <= 30; i++ {
remain(-i, LogDb, AppConfig)
}
log.Println("end statistics")
//SendInfo(LogDb)
}
func remain(Day int, LogDb *Db, AppConfig *Type.AppStruct) {
defer func() {
if err := recover(); err != nil {
log.Printf("remain panic: %v", err)
}
}()
now := ZeroTimestampByTz(AppConfig.Tz) + int64(Day)*86400
Date := time.Unix(now, 0).In(loc).Format("2006-01-02")
SecondRemain, _ := DayRemain(now, 1, LogDb) // 计算次留
ThirdRemain, _ := DayRemain(now, 2, LogDb) // 计算三留
SeventhRemain, _ := DayRemain(now, 6, LogDb) // 计算七留
FourteenthRemain, _ := DayRemain(now, 13, LogDb) // 计算14留
ThirtiethRemain, _ := DayRemain(now, 29, LogDb) // 计算30留
Register, _ := DayRemain(now, 0, LogDb) // 计算注册
PerOnlineTime := GetPerOnlineTime(LogDb, now)
PerOrderNum := GetPerOrderNum(LogDb, now)
Login := Login(now, LogDb) // 计算登录
Recharge := Recharge(now, LogDb) // 计算充值
Db := MPool.GetTopicDB(AppConfig.Topic)
if Db == nil {
log.Printf("failed to get mysql database")
return
}
ext := make(map[string]interface{})
ext["PerOnlineTime"] = fmt.Sprintf("%.2f", PerOnlineTime)
ext["PerOrderNum"] = fmt.Sprintf("%.2f", float64(PerOrderNum)/float64(Login))
extStr, _ := json.Marshal(ext)
_, err := Db.Exec("INSERT INTO `remain` (`Date`, `SecondRemain`, `ThirdRemain`, `SeventhRemain`, `FourteenthRemain`, `ThirtiethRemain`, `Register`, `Login`, `Recharge`, `Ext`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?,?) ON DUPLICATE KEY UPDATE SecondRemain = ?, ThirdRemain = ?, SeventhRemain = ?, FourteenthRemain = ?, ThirtiethRemain = ?, Register = ?, Login = ?, Recharge = ?, Ext = ?", Date, SecondRemain, ThirdRemain, SeventhRemain, FourteenthRemain, ThirtiethRemain, Register, Login, Recharge, string(extStr), SecondRemain, ThirdRemain, SeventhRemain, FourteenthRemain, ThirtiethRemain, Register, Login, Recharge, string(extStr))
if err != nil {
log.Printf("failed to insert data: %v", err)
}
log.Printf("remain %s success", Date)
}
func DayRemain(now int64, Day int, LogDb *Db) (int, error) {
if LogDb == nil {
log.Println("failed to get mysql database")
return 0, fmt.Errorf("failed to get mysql database")
}
Timestamp := now + int64(Day)*86400
// log.Print("secondRemain:", Timestamp)
type data struct {
Uid int `db:"Uid"`
}
dataList := []data{}
err := LogDb.Select(&dataList, "SELECT Uid FROM log_login WHERE Event = 'register' and Timestamp >= ? and Timestamp <= ?", now, now+86399)
if err != nil {
log.Fatalf("failed to select data: %v", err)
}
if Day == 0 {
return len(dataList), nil
}
if len(dataList) == 0 {
return 0, nil
}
UidStr := ""
for _, v := range dataList {
UidStr += fmt.Sprintf("%d,", v.Uid)
}
if len(UidStr) > 0 {
UidStr = UidStr[:len(UidStr)-1]
}
DataList2 := []data{}
Sql := fmt.Sprintf("SELECT `Uid` FROM `log_login` WHERE `Event` = 'Login_log' and `Uid` in ( %s ) and Timestamp >= ? and Timestamp <= ? group by `Uid`", UidStr)
err = LogDb.Select(&DataList2, Sql, Timestamp, Timestamp+86399)
if err != nil {
log.Fatalf("failed to select data: %v", err)
}
if len(UidStr) < len(DataList2) {
log.Printf("UidStr:%d, DataList2:%d", len(UidStr), len(DataList2))
}
return len(DataList2), nil
}
func Login(Now int64, LogDb *Db) int {
if LogDb == nil {
log.Println("failed to get mysql database")
return 0
}
var Login int
err := LogDb.Get(&Login, "SELECT count(distinct Uid) as count FROM log_login WHERE Event = 'Login_log' and Timestamp >= ? and Timestamp <= ?", Now, Now+86399)
if err != nil {
log.Fatalf("failed to get login data: %v", err)
}
return Login
}
func Recharge(Now int64, LogDb *Db) float64 {
if LogDb == nil {
log.Println("failed to get mysql database")
return 0
}
var Recharge float64
err := LogDb.Get(&Recharge, "SELECT IFNULL(Sum(Price),0.0) as sum FROM log_order WHERE Timestamp >= ? and Timestamp <= ?", Now, Now+86399)
if err != nil {
log.Fatalf("failed to get recharge data: %v", err)
}
return Recharge
}
func GetPerOrderNum(db *Db, Zero int64) int {
var num int
err := db.Get(&num, "SELECT count(`Event`) FROM log_event WHERE `Event` = 'order_finish' and Timestamp >= ? and Timestamp <= ?", Zero, Zero+86399)
if err != nil {
log.Printf("failed to GetPerOrderNum data: %v", err)
return 0
}
return num
}
func GetPerOnlineTime(db *Db, Zero int64) float64 {
type data struct {
Uid int `db:"Uid"`
Timestamp int64 `db:"Timestamp"`
Event string `db:"Event"`
}
dataList := []data{}
err := db.Select(&dataList, "SELECT `Uid`, `Timestamp`, `Event` FROM log_login WHERE (`Event` = 'Login_log' or `Event` = 'Login_Out') and Timestamp >= ? and Timestamp <= ? ORDER BY Timestamp ASC", Zero, Zero+86399)
if err != nil {
log.Printf("failed to GetPerOnlineTime data: %v", err)
return 0
}
d1 := make(map[int][]*data)
for _, v := range dataList {
if _, ok := d1[v.Uid]; !ok {
d1[v.Uid] = make([]*data, 0)
}
d1[v.Uid] = append(d1[v.Uid], &v)
}
d2 := make(map[int]int64)
d3 := make(map[int][]int64)
for _, v := range d1 {
s := -1
for i := 0; i < len(v); i++ {
if i == 0 && v[i].Event == "Login_Out" {
d2[v[i].Uid] += v[i].Timestamp - Zero - 300
d3[v[i].Uid] = append(d3[v[i].Uid], v[i].Timestamp-Zero-300)
continue
}
if i == len(v)-1 && v[i].Event == "Login_log" {
d2[v[i].Uid] += Zero + 86399 - v[i].Timestamp - 300
continue
}
if v[i].Event == "Login_log" && s == -1 {
s = i
continue
}
if v[i].Event == "Login_Out" {
d2[v[i].Uid] += v[i].Timestamp - v[s].Timestamp - 300
d3[v[i].Uid] = append(d3[v[i].Uid], v[i].Timestamp-v[s].Timestamp-300)
s = -1
}
}
}
log.Println(d2)
var sum int64
for _, v := range d2 {
sum += v
}
return float64(sum/int64(len(d2))) / 60
}