154 lines
3.3 KiB
Go
154 lines
3.3 KiB
Go
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
|
||
}
|