admin_backend/util/statistics.go
2025-02-20 15:40:00 +08:00

186 lines
5.9 KiB
Go

package util
import (
"backend/Type"
"backend/common"
"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) // 计算注册
Login := Login(now, LogDb) // 计算登录
Recharge := Recharge(now, LogDb) // 计算充值
Db := MPool.GetTopicDB(AppConfig.Topic)
if Db == nil {
log.Printf("failed to get mysql database")
return
}
_, err := Db.Exec("INSERT INTO `remain` (`Date`, `SecondRemain`, `ThirdRemain`, `SeventhRemain`, `FourteenthRemain`, `ThirtiethRemain`, `Register`, `Login`, `Recharge`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE SecondRemain = ?, ThirdRemain = ?, SeventhRemain = ?, FourteenthRemain = ?, ThirtiethRemain = ?, Register = ?, Login = ?, Recharge = ?", Date, SecondRemain, ThirdRemain, SeventhRemain, FourteenthRemain, ThirtiethRemain, Register, Login, Recharge, SecondRemain, ThirdRemain, SeventhRemain, FourteenthRemain, ThirtiethRemain, Register, Login, Recharge)
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 SendInfo(Db *db) error {
if Db == nil {
log.Printf("GetOperation MySQL nil")
return nil
}
defer Db.Close()
Retain := []*Type.Retain{}
ZeroTimestamp := ZeroTimestampByTz("Europe/London") - 86400
ZeroTime := time.Unix(ZeroTimestamp, 0).In(time.UTC)
StartDate := ZeroTime.AddDate(0, 0, -7).Format("2006-01-02")
EndDate := ZeroTime.Format("2006-01-02")
err := Db.Select(&Retain, "SELECT `Date`, `Register`, `SecondRemain`, `ThirdRemain`, `SeventhRemain`, `ThirtiethRemain`, `Recharge`, `Login` FROM remain where `Date` >= ? and `Date` <= ? order by `Date` desc", StartDate, EndDate)
if err != nil {
log.Printf("GetOperation Select error: %v", err)
return err
}
var Register int
err = Db.Get(&Register, "SELECT count(`Uid`) as count FROM log_login WHERE Event = 'register'")
if err != nil {
log.Printf("GetOperation Select error: %v", err)
return err
}
var Recharge float64
err = Db.Get(&Recharge, "SELECT IFNULL(SUM(Price), 0) as sum FROM log_order")
if err != nil {
log.Printf("GetOperation Select error: %v", err)
return err
}
var InactiveUsers int
err = Db.Get(&InactiveUsers, "SELECT count(distinct Uid) as count from (SELECT Uid, MAX(Timestamp) as LastLogin FROM log_login WHERE Event = 'Login_log' GROUP BY Uid) as lt where lastlogin < ?", ZeroTimestamp-7*86400)
if err != nil {
log.Printf("GetOperation Select error: %v", err)
return err
}
ChurnRate := 100 * float64(InactiveUsers) / float64(Register)
Result := &Type.Operation{Retain: Retain, Register: Register, Recharge: Recharge, ChurnRate: ChurnRate}
err = common.SendOperationMsg(Result)
if err != nil {
log.Printf("SendOperationMsg error: %v", err)
return err
}
return nil
}