game_sync/statistics/task/task/bankruptoffline.go

154 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package task
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"go.mongodb.org/mongo-driver/bson"
"mongo.games.com/game/common"
mymongo "mongo.games.com/goserver/core/mongox"
mymysql "mongo.games.com/goserver/core/mysqlx"
)
// 破产后离线破产后5分钟内有离线行为
type BankruptOfflineData struct {
One int
Two int
Three int
Recharge int
D time.Duration
}
func BankruptOffline(plt string, startTime, endTime string) (ret *BankruptOfflineData, err error) {
s, e := common.StrRFC3339TimeToTime(startTime), common.StrRFC3339TimeToTime(endTime)
if s.IsZero() || e.IsZero() {
return nil, fmt.Errorf("time format error")
}
db, err := mymysql.GetDatabase("count")
if err != nil {
return nil, err
}
/*
SELECT
snid,
GROUP_CONCAT(bankrupt_time ORDER BY bankrupt_time ASC LIMIT 3) AS top_3_bankrupt_times,
COUNT(*) AS record_count
FROM
bankrupt_log
GROUP BY
snid;
*/
type BankruptLog struct {
Snid int `gorm:"column:snid"`
MaxBankruptTime string `gorm:"column:top_3_bankrupt_times"`
Times []int64 `gorm:"-"`
}
var logs []*BankruptLog
tx := db.Raw(`
WITH RankedData AS (
SELECT
snid,
bankrupt_time,
ROW_NUMBER() OVER (PARTITION BY snid ORDER BY bankrupt_time ASC) AS ranks
FROM bankrupt_log
WHERE bankrupt_time >= ? AND bankrupt_time < ?
)
SELECT
snid,
GROUP_CONCAT(bankrupt_time ORDER BY bankrupt_time ASC) AS top_3_bankrupt_times
FROM RankedData
WHERE ranks <= 3
GROUP BY snid
`, s.Unix(), e.Unix()).Scan(&logs)
if tx.Error != nil {
return nil, tx.Error
}
var timeSecond int
var total int
ret = &BankruptOfflineData{}
for _, v := range logs {
if v == nil || len(v.MaxBankruptTime) == 0 {
continue
}
for _, vv := range strings.Split(v.MaxBankruptTime, ",") {
n, err := strconv.Atoi(vv)
if err != nil {
return nil, err
}
v.Times = append(v.Times, int64(n))
}
// 破产后5分钟内有离线行为
db, err = mymysql.GetDatabase(plt)
if err != nil {
return nil, err
}
var isOffline bool
for k, vv := range v.Times {
var n int64
stime, etime := time.Unix(vv, 0), time.Unix(vv, 0).Add(5*time.Minute)
if err = db.Table("user_logins").Where("snid = ? AND offline_time >= ? AND offline_time < ?",
v.Snid, stime, etime).Count(&n).Error; err != nil {
return nil, err
}
switch k {
case 0:
if n > 0 {
ret.One++
isOffline = true
}
case 1:
if n > 0 {
ret.Two++
isOffline = true
}
case 2:
if n > 0 {
ret.Three++
isOffline = true
}
}
}
if isOffline {
// 充值
c, err := mymongo.GetLogCollection(plt, "log_dbshop")
if err != nil {
return nil, err
}
count, err := c.CountDocuments(context.TODO(), bson.M{"snid": v.Snid, "ts": bson.M{"$gte": s.Unix(), "$lt": e.Unix()}, "consume": 3, "state": 1})
if err != nil {
return nil, err
}
if count > 0 {
ret.Recharge++
}
// 平均对局时长
times, to, err := NewPlayerGameTime(plt, []int{v.Snid}, startTime, endTime, 0)
if err != nil {
return nil, err
}
timeSecond += times
total += to
}
}
if total > 0 {
ret.D = time.Second * time.Duration(timeSecond/total)
}
return ret, nil
}