975 lines
23 KiB
Go
975 lines
23 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"github.com/oylshe1314/framework/client/db"
|
|
opts "github.com/oylshe1314/framework/options"
|
|
"github.com/oylshe1314/framework/util"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
type QueryClient struct {
|
|
MongoClient db.MongoClient
|
|
MysqlClient db.MysqlClient
|
|
}
|
|
|
|
func (this *QueryClient) Init() (err error) {
|
|
err = this.MongoClient.Init()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Printf("mongodb %s/%s connected\n", this.MongoClient.Address(), this.MongoClient.Database())
|
|
|
|
err = this.MysqlClient.Init()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Printf("mysql %s/%s connected\n", this.MysqlClient.Address(), this.MysqlClient.Database())
|
|
|
|
return nil
|
|
}
|
|
|
|
func (this *QueryClient) Close() error {
|
|
_ = this.MongoClient.Close()
|
|
_ = this.MysqlClient.Close()
|
|
return nil
|
|
}
|
|
|
|
var functions = []string{
|
|
"query all charge data",
|
|
"query level lost data",
|
|
"query first charge data",
|
|
"query player gold data",
|
|
"query player shop log",
|
|
"query player flirt info",
|
|
"query hero flirt count",
|
|
"query player lottery consume",
|
|
"query mura charge total",
|
|
}
|
|
|
|
func main() {
|
|
|
|
if len(os.Args) < 2 {
|
|
fmt.Println("Usage:")
|
|
fmt.Println(" A number of function index(1-8)")
|
|
for i, function := range functions {
|
|
fmt.Printf(" %d:\n %s\n", i+1, function)
|
|
}
|
|
return
|
|
}
|
|
|
|
index, err := strconv.ParseInt(os.Args[1], 10, 64)
|
|
if err != nil {
|
|
fmt.Println("error args", err)
|
|
return
|
|
}
|
|
|
|
if index < 1 || int(index) > len(functions) {
|
|
fmt.Println("error index")
|
|
return
|
|
}
|
|
|
|
opt, err := opts.ReadJson("./config.json")
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
|
|
var client = &QueryClient{}
|
|
|
|
err = opt.Init(client)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
|
|
defer client.Close()
|
|
|
|
fmt.Println(functions[index-1])
|
|
|
|
switch index {
|
|
case 1:
|
|
err = client.queryAllCharge()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
case 2:
|
|
err = client.queryLevelLost()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
case 3:
|
|
err = client.queryFirstCharge()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
case 4:
|
|
err = client.queryPlayerGold()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
case 5:
|
|
err = client.queryPlayerShopLog()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
case 6:
|
|
err = client.queryFlirtInfo()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
case 7:
|
|
err = client.queryFlirtCount()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
case 8:
|
|
err = client.queryLotteryConsume()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
case 9:
|
|
err = client.queryMuraChargeTotal()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
type _AllChargePlayer struct {
|
|
Base struct {
|
|
Level int32 `bson:"level"`
|
|
CreateTime int64 `bson:"createtime"`
|
|
} `bson:"base"`
|
|
}
|
|
|
|
type _AllChargeOrderAggregate struct {
|
|
OrderId string `bson:"_id"`
|
|
AccountId uint64 `bson:"accountid"`
|
|
ProductId uint64 `bson:"productid"`
|
|
ChargeTime int64 `bson:"chargetime"`
|
|
Players []*_AllChargePlayer `bson:"players"`
|
|
}
|
|
|
|
func (this *QueryClient) queryAllCharge() error {
|
|
|
|
cur, err := this.MongoClient.Collection("chargeorder").Aggregate(
|
|
this.MongoClient.Context(),
|
|
bson.A{
|
|
bson.M{"$match": bson.M{"paystatus": 1}},
|
|
bson.M{"$lookup": bson.M{"from": "player", "localField": "accountid", "foreignField": "_id", "as": "players"}},
|
|
bson.M{"$project": bson.M{"_id": 1, "accountid": 1, "productid": 1, "chargetime": 1, "players.base.level": 1, "players.base.createtime": 1}},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var buff bytes.Buffer
|
|
buff.WriteString("玩家ID,当前等级,充值ID,充值时间,创角时间\n")
|
|
|
|
for cur.Next(context.Background()) {
|
|
var aggregate = new(_AllChargeOrderAggregate)
|
|
err = cur.Decode(aggregate)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(aggregate.Players) < 1 {
|
|
continue
|
|
}
|
|
|
|
fmt.Printf("query player %d\n", aggregate.AccountId)
|
|
|
|
var rt = time.Unix(aggregate.ChargeTime, 0)
|
|
var logTable = fmt.Sprintf("upgrade_level_log_%d%02d%02d", rt.Year(), rt.Month(), rt.Day())
|
|
err = this.MysqlClient.QueryRow(fmt.Sprintf("show tables like '%s';", logTable)).Scan(&logTable)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
fmt.Printf("check table %s does not exists\n", logTable)
|
|
continue
|
|
}
|
|
return err
|
|
}
|
|
|
|
var ct = time.Unix(aggregate.Players[0].Base.CreateTime, 0)
|
|
|
|
buff.WriteString(fmt.Sprintf("%d,%d,%d,%s,%s\n", aggregate.AccountId, aggregate.Players[0].Base.Level, aggregate.ProductId, rt.Format("2006年01月02日15时04分05秒"), ct.Format("2006年01月02日15时04分05秒")))
|
|
}
|
|
|
|
err = os.WriteFile("./all_charge.csv", buff.Bytes(), 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type _PlayerBase struct {
|
|
Level uint32 `bson:"level"`
|
|
CreateTime int64 `bson:"createtime"`
|
|
LogoffTime int64 `bson:"logofftime"`
|
|
MainlineSceneId uint32 `bson:"MainlineSceneId"`
|
|
}
|
|
|
|
type _Player struct {
|
|
AccountId uint64 `bson:"_id"`
|
|
Base _PlayerBase `bson:"base"`
|
|
}
|
|
|
|
func (this *QueryClient) queryLevelLost() error {
|
|
findOpts := options.Find().SetProjection(bson.M{"_id": 1, "base.level": 1, "base.createtime": 1, "base.logofftime": 1, "base.MainlineSceneId": 1})
|
|
cur, err := this.MongoClient.Collection("player").Find(this.MongoClient.Context(), bson.M{}, findOpts)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var buff bytes.Buffer
|
|
buff.WriteString("玩家ID,当前等级,当前关卡,注册时间,下线时间,\n")
|
|
|
|
for cur.Next(context.Background()) {
|
|
var player = new(_Player)
|
|
err = cur.Decode(player)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var ct = time.Unix(player.Base.CreateTime, 0)
|
|
var ot = time.Unix(player.Base.LogoffTime, 0)
|
|
|
|
buff.WriteString(fmt.Sprintf("%d,%d,%d,%s,%s\n",
|
|
player.AccountId,
|
|
player.Base.Level,
|
|
player.Base.MainlineSceneId,
|
|
ct.Format("2006年01月02日15时04分05秒"),
|
|
ot.Format("2006年01月02日15时04分05秒"),
|
|
))
|
|
}
|
|
|
|
err = os.WriteFile("./level_lost.csv", buff.Bytes(), 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type _ChargeOrder struct {
|
|
OrderNumber string `bson:"_id"`
|
|
AccountId uint64 `bson:"accountid"`
|
|
ProductId int32 `bson:"productid"`
|
|
ProductPrice int32 `bson:"productprice"`
|
|
ChargeTime int64 `bson:"chargetime"`
|
|
PayStatus int32 `bson:"paystatus"`
|
|
}
|
|
|
|
type _ChargePlayer struct {
|
|
Base struct {
|
|
CreateTime int64 `bson:"createtime"`
|
|
} `bson:"base"`
|
|
}
|
|
|
|
type _ChargeOrderAggregate struct {
|
|
AccountId uint64 `bson:"_id"`
|
|
ChargeTime int64 `bson:"chargetime"`
|
|
Orders []*_ChargeOrder `bson:"orders"`
|
|
Players []*_ChargePlayer `bson:"players"`
|
|
}
|
|
|
|
func (this *QueryClient) queryFirstCharge() error {
|
|
|
|
cur, err := this.MongoClient.Collection("chargeorder").Aggregate(
|
|
this.MongoClient.Context(),
|
|
bson.A{
|
|
bson.M{"$match": bson.M{"paystatus": 1}},
|
|
bson.M{"$group": bson.M{"_id": "$accountid", "chargetime": bson.M{"$min": "$chargetime"}}},
|
|
bson.M{
|
|
"$lookup": bson.M{
|
|
"from": "chargeorder",
|
|
"let": bson.M{"groupId": "$_id", "groupCt": "$chargetime"},
|
|
"pipeline": bson.A{
|
|
bson.M{
|
|
"$match": bson.M{
|
|
"$expr": bson.M{
|
|
"$and": bson.A{
|
|
bson.M{"$eq": bson.A{"$accountid", "$$groupId"}},
|
|
bson.M{"$eq": bson.A{"$chargetime", "$$groupCt"}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"as": "orders",
|
|
},
|
|
},
|
|
bson.M{"$lookup": bson.M{"from": "player", "localField": "_id", "foreignField": "_id", "as": "players"}},
|
|
bson.M{"$project": bson.M{"_id": 1, "chargetime": 1, "orders": 1, "players.base.createtime": 1}},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var buff bytes.Buffer
|
|
buff.WriteString("玩家ID,当前等级,充值ID,充值时间,\n")
|
|
|
|
for cur.Next(context.Background()) {
|
|
var aggregate = new(_ChargeOrderAggregate)
|
|
err = cur.Decode(aggregate)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(aggregate.Orders) < 1 || len(aggregate.Players) < 1 {
|
|
continue
|
|
}
|
|
|
|
fmt.Printf("query player %d\n", aggregate.AccountId)
|
|
|
|
var ct = time.Unix(aggregate.ChargeTime, 0)
|
|
var logTable = fmt.Sprintf("upgrade_level_log_%d%02d%02d", ct.Year(), ct.Month(), ct.Day())
|
|
err = this.MysqlClient.QueryRow(fmt.Sprintf("show tables like '%s';", logTable)).Scan(&logTable)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
fmt.Printf("check table %s does not exists\n", logTable)
|
|
continue
|
|
}
|
|
return err
|
|
}
|
|
|
|
var curLevel uint32
|
|
|
|
err = this.MysqlClient.QueryRow(
|
|
fmt.Sprintf("select cur_level from %s where account_id=? and log_time < ? order by id desc limit 1;", logTable),
|
|
aggregate.AccountId,
|
|
aggregate.ChargeTime,
|
|
).Scan(&curLevel)
|
|
if err != nil && err != sql.ErrNoRows {
|
|
return err
|
|
}
|
|
|
|
var rt = time.Unix(aggregate.Players[0].Base.CreateTime, 0)
|
|
|
|
buff.WriteString(fmt.Sprintf("%d,%d,%d,%s,%s\n", aggregate.AccountId, curLevel, aggregate.Orders[0].ProductId, rt.Format("2006年01月02日15时04分05秒"), ct.Format("2006年01月02日15时04分05秒")))
|
|
}
|
|
|
|
err = os.WriteFile("./first_charge.csv", buff.Bytes(), 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type _PlayerGold struct {
|
|
AccountId uint64 `bson:"_id"`
|
|
Base struct {
|
|
Gold int `bson:"gold"`
|
|
} `bson:"base"`
|
|
ObtainTotal int `bson:"-"`
|
|
ConsumeTotel int `bson:"-"`
|
|
}
|
|
|
|
func (this *QueryClient) queryPlayerGold() error {
|
|
var opt = options.Find()
|
|
opt.SetProjection(bson.M{"_id": 1, "base.gold": 1})
|
|
cur, err := this.MongoClient.Collection("player").Find(context.Background(), bson.M{}, opt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var playerMap = map[uint64]*_PlayerGold{}
|
|
for cur.Next(context.Background()) {
|
|
var player = new(_PlayerGold)
|
|
err = cur.Decode(player)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
playerMap[player.AccountId] = player
|
|
}
|
|
|
|
var beginTime = int64(1689091200)
|
|
var now = util.Unix()
|
|
|
|
for ; beginTime < now; beginTime += 86400 {
|
|
var y, m, d = time.Unix(beginTime, 0).In(util.UTC8()).Date()
|
|
var ymd = y*10000 + int(m)*100 + d
|
|
|
|
var rows *sql.Rows
|
|
var table = fmt.Sprintf("obtain_money_log_%d", ymd)
|
|
|
|
rows, err = this.MysqlClient.Query(fmt.Sprintf("show tables like '%s';", table))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rows.Next() {
|
|
_ = rows.Close()
|
|
|
|
rows, err = this.MysqlClient.Query(fmt.Sprintf("select player_id, sum(consume_count) from %s where money_type=0 group by player_id", table))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for rows.Next() {
|
|
var playerId uint64
|
|
var obtainTotal int
|
|
err = rows.Scan(&playerId, &obtainTotal)
|
|
if err != nil {
|
|
_ = rows.Close()
|
|
return err
|
|
}
|
|
|
|
var player = playerMap[playerId]
|
|
if player != nil {
|
|
player.ObtainTotal += obtainTotal
|
|
}
|
|
}
|
|
|
|
_ = rows.Close()
|
|
} else {
|
|
_ = rows.Close()
|
|
}
|
|
|
|
table = fmt.Sprintf("consume_money_log_%d", ymd)
|
|
|
|
rows, err = this.MysqlClient.Query(fmt.Sprintf("show tables like '%s';", table))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rows.Next() {
|
|
_ = rows.Close()
|
|
|
|
rows, err = this.MysqlClient.Query(fmt.Sprintf("select player_id, sum(consume_count) from %s where money_type=0 group by player_id", table))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for rows.Next() {
|
|
var playerId uint64
|
|
var consumeTotal int
|
|
err = rows.Scan(&playerId, &consumeTotal)
|
|
if err != nil {
|
|
_ = rows.Close()
|
|
return err
|
|
}
|
|
|
|
var player = playerMap[playerId]
|
|
if player != nil {
|
|
player.ConsumeTotel += consumeTotal
|
|
}
|
|
}
|
|
|
|
_ = rows.Close()
|
|
} else {
|
|
_ = rows.Close()
|
|
}
|
|
}
|
|
|
|
var buff bytes.Buffer
|
|
buff.WriteString("玩家ID,当前五彩石,总产出量,总消耗量,\n")
|
|
for _, player := range playerMap {
|
|
if player.Base.Gold == 0 && player.ObtainTotal == 0 && player.ConsumeTotel == 0 {
|
|
continue
|
|
}
|
|
buff.WriteString(fmt.Sprintf("%d,%d,%d,%d,\n", player.AccountId, player.Base.Gold, player.ObtainTotal, player.ConsumeTotel))
|
|
}
|
|
|
|
err = os.WriteFile("./player_gold.csv", buff.Bytes(), 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type _ShopLog struct {
|
|
ItemId int
|
|
ItemNum int
|
|
}
|
|
|
|
type _PlayerGem struct {
|
|
AccountId uint64 `bson:"_id"`
|
|
Base struct {
|
|
Gem int `bson:"gem"`
|
|
} `bson:"base"`
|
|
|
|
ShopLog map[int]*_ShopLog
|
|
}
|
|
|
|
func (this *QueryClient) queryPlayerShopLog() error {
|
|
var opt = options.Find()
|
|
opt.SetProjection(bson.M{"_id": 1, "base.gem": 1})
|
|
cur, err := this.MongoClient.Collection("player").Find(context.Background(), bson.M{"base.level": bson.M{"$gte": 20}}, opt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var gemTotal int
|
|
var playerMap = map[uint64]*_PlayerGem{}
|
|
for cur.Next(context.Background()) {
|
|
var player = &_PlayerGem{ShopLog: map[int]*_ShopLog{}}
|
|
err = cur.Decode(player)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
playerMap[player.AccountId] = player
|
|
gemTotal += player.Base.Gem
|
|
}
|
|
|
|
var beginTime = int64(1689091200)
|
|
var now = util.Unix()
|
|
|
|
for ; beginTime < now; beginTime += 86400 {
|
|
var y, m, d = time.Unix(beginTime, 0).In(util.UTC8()).Date()
|
|
var ymd = y*10000 + int(m)*100 + d
|
|
|
|
var rows *sql.Rows
|
|
var table = fmt.Sprintf("shop_log_%d", ymd)
|
|
|
|
rows, err = this.MysqlClient.Query(fmt.Sprintf("show tables like '%s';", table))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rows.Next() {
|
|
_ = rows.Close()
|
|
|
|
rows, err = this.MysqlClient.Query(fmt.Sprintf("select player_id,item_id,count(1) from %s where shop_type=0 group by player_id, item_id;", table))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for rows.Next() {
|
|
var playerId uint64
|
|
var itemId int
|
|
var itemNum int
|
|
err = rows.Scan(&playerId, &itemId, &itemNum)
|
|
if err != nil {
|
|
_ = rows.Close()
|
|
return err
|
|
}
|
|
|
|
var player = playerMap[playerId]
|
|
if player != nil {
|
|
var log = player.ShopLog[itemId]
|
|
if log == nil {
|
|
log = &_ShopLog{ItemId: itemId, ItemNum: itemNum}
|
|
player.ShopLog[log.ItemId] = log
|
|
} else {
|
|
log.ItemNum += itemNum
|
|
}
|
|
}
|
|
}
|
|
|
|
_ = rows.Close()
|
|
} else {
|
|
_ = rows.Close()
|
|
}
|
|
}
|
|
|
|
var buff bytes.Buffer
|
|
buff.WriteString("星石总量,\n")
|
|
buff.WriteString(fmt.Sprintf("%d,\n", gemTotal))
|
|
|
|
buff.WriteString("玩家ID,玩家星石,道具ID,道具数量,\n")
|
|
for _, player := range playerMap {
|
|
for _, log := range player.ShopLog {
|
|
buff.WriteString(fmt.Sprintf("%d,%d,%d,%d,\n", player.AccountId, player.Base.Gem, log.ItemId, log.ItemNum))
|
|
}
|
|
}
|
|
|
|
err = os.WriteFile("./player_shop_log.csv", buff.Bytes(), 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var sealCopyScenes = map[int]struct{}{
|
|
50201: {},
|
|
50204: {},
|
|
50207: {},
|
|
50210: {},
|
|
50213: {},
|
|
50216: {},
|
|
50219: {},
|
|
50301: {},
|
|
50304: {},
|
|
50307: {},
|
|
50310: {},
|
|
50313: {},
|
|
50316: {},
|
|
50319: {},
|
|
50401: {},
|
|
50404: {},
|
|
50407: {},
|
|
50410: {},
|
|
50413: {},
|
|
50416: {},
|
|
50419: {},
|
|
}
|
|
|
|
var heroFlirtItems = map[int]struct{}{
|
|
13001: {},
|
|
13002: {},
|
|
13003: {},
|
|
13004: {},
|
|
13005: {},
|
|
13006: {},
|
|
13007: {},
|
|
13008: {},
|
|
13009: {},
|
|
13010: {},
|
|
13011: {},
|
|
13012: {},
|
|
13013: {},
|
|
13014: {},
|
|
13015: {},
|
|
13016: {},
|
|
13017: {},
|
|
13018: {},
|
|
13019: {},
|
|
13020: {},
|
|
13101: {},
|
|
13102: {},
|
|
13103: {},
|
|
13104: {},
|
|
13105: {},
|
|
13106: {},
|
|
13107: {},
|
|
13108: {},
|
|
13109: {},
|
|
13110: {},
|
|
}
|
|
|
|
type _PassedCopy struct {
|
|
SceneId int `name:"copypassed" key:"1"`
|
|
TotalNum int
|
|
}
|
|
|
|
type _PlayerHero struct {
|
|
HeroID int
|
|
Talent int //天赋
|
|
FlirtLevel []bool //当前调戏层级
|
|
FlirtExciting []int //当前兴奋值
|
|
FlirtAttrUnlock []bool //调戏属性解锁
|
|
}
|
|
|
|
func (this *_PlayerHero) FlirtFinishedLevel() int {
|
|
var li = 0
|
|
for i, b := range this.FlirtAttrUnlock {
|
|
if !b {
|
|
break
|
|
}
|
|
li = i + 1
|
|
}
|
|
return li
|
|
}
|
|
|
|
type _ConsumeItem struct {
|
|
ItemId int
|
|
ItemNum int
|
|
}
|
|
|
|
type _PlayerCopyPassed struct {
|
|
AccountId uint64 `bson:"_id"`
|
|
PassedCopy map[int]*_PassedCopy `bson:"copypassed"`
|
|
PlayerHero map[int]*_PlayerHero `bson:"hero"`
|
|
ConsumeItem map[int]*_ConsumeItem
|
|
}
|
|
|
|
func (this *QueryClient) queryFlirtInfo() error {
|
|
var opt = options.Find()
|
|
opt.SetProjection(bson.M{"_id": 1, "copypassed": 1, "hero": 1})
|
|
cur, err := this.MongoClient.Collection("player").Find(context.Background(), bson.M{"base.level": bson.M{"$gte": 20}}, opt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var playerMap = map[uint64]*_PlayerCopyPassed{}
|
|
for cur.Next(context.Background()) {
|
|
var player = &_PlayerCopyPassed{PassedCopy: map[int]*_PassedCopy{}, PlayerHero: map[int]*_PlayerHero{}, ConsumeItem: map[int]*_ConsumeItem{}}
|
|
err = cur.Decode(player)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
playerMap[player.AccountId] = player
|
|
}
|
|
|
|
var beginTime = int64(1689091200)
|
|
var now = util.Unix()
|
|
|
|
for ; beginTime < now; beginTime += 86400 {
|
|
var y, m, d = time.Unix(beginTime, 0).In(util.UTC8()).Date()
|
|
var ymd = y*10000 + int(m)*100 + d
|
|
|
|
var rows *sql.Rows
|
|
var table = fmt.Sprintf("consume_item_log_%d", ymd)
|
|
|
|
rows, err = this.MysqlClient.Query(fmt.Sprintf("show tables like '%s';", table))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rows.Next() {
|
|
_ = rows.Close()
|
|
|
|
rows, err = this.MysqlClient.Query(fmt.Sprintf("select player_id, item_id, sum(item_num) from %s where log_type in (515,516) group by player_id, item_id;", table))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for rows.Next() {
|
|
var playerId uint64
|
|
var itemId int
|
|
var itemNum int
|
|
err = rows.Scan(&playerId, &itemId, &itemNum)
|
|
if err != nil {
|
|
_ = rows.Close()
|
|
return err
|
|
}
|
|
|
|
var player = playerMap[playerId]
|
|
if player != nil {
|
|
var item = player.ConsumeItem[itemId]
|
|
if item == nil {
|
|
item = &_ConsumeItem{ItemId: itemId, ItemNum: itemNum}
|
|
player.ConsumeItem[item.ItemId] = item
|
|
} else {
|
|
item.ItemNum += itemNum
|
|
}
|
|
}
|
|
}
|
|
|
|
_ = rows.Close()
|
|
} else {
|
|
_ = rows.Close()
|
|
}
|
|
}
|
|
|
|
var buff bytes.Buffer
|
|
|
|
buff.WriteString("玩家ID,场景ID,通关次数,\n")
|
|
for _, player := range playerMap {
|
|
for _, passedCopy := range player.PassedCopy {
|
|
if _, ok := sealCopyScenes[passedCopy.SceneId]; ok {
|
|
buff.WriteString(fmt.Sprintf("%d,%d,%d,\n", player.AccountId, passedCopy.SceneId, passedCopy.TotalNum))
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, player := range playerMap {
|
|
buff.WriteString("\n玩家ID,英雄数量,\n")
|
|
buff.WriteString(fmt.Sprintf("%d,%d,\n", player.AccountId, len(player.PlayerHero)))
|
|
buff.WriteString("玩家ID,英雄ID,契印星数,完成调教房间,房间1高潮值,房间2高潮值\n")
|
|
for _, playerHero := range player.PlayerHero {
|
|
buff.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,\n", player.AccountId, playerHero.HeroID, playerHero.Talent+1, playerHero.FlirtFinishedLevel(), playerHero.FlirtExciting[0], playerHero.FlirtExciting[1]))
|
|
}
|
|
}
|
|
|
|
buff.WriteString("\n玩家ID,道具ID,道具使用数量,\n")
|
|
for _, player := range playerMap {
|
|
for _, item := range player.ConsumeItem {
|
|
if _, ok := heroFlirtItems[item.ItemId]; ok {
|
|
buff.WriteString(fmt.Sprintf("%d,%d,%d,\n", player.AccountId, item.ItemId, item.ItemNum))
|
|
}
|
|
}
|
|
}
|
|
|
|
err = os.WriteFile("./player_flirt_info.csv", buff.Bytes(), 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type _PlayerFlirtCount struct {
|
|
AccountId uint64 `bson:"_id"`
|
|
PlayerHero map[int]*_PlayerHero `bson:"hero"`
|
|
}
|
|
|
|
func (this *QueryClient) queryFlirtCount() error {
|
|
cur, err := this.MongoClient.Collection("player").Find(this.MongoClient.Context(), bson.M{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var players []*_PlayerFlirtCount
|
|
err = cur.All(this.MongoClient.Context(), &players)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var heroMap = map[int]map[int]int{}
|
|
for _, player := range players {
|
|
for _, hero := range player.PlayerHero {
|
|
var levelMap = heroMap[hero.HeroID]
|
|
if levelMap == nil {
|
|
levelMap = map[int]int{}
|
|
heroMap[hero.HeroID] = levelMap
|
|
}
|
|
for i, b := range hero.FlirtAttrUnlock {
|
|
if i < len(heroMap) && b {
|
|
levelMap[i+1] = levelMap[i+1] + 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var buff bytes.Buffer
|
|
|
|
buff.WriteString("英雄ID,房间1完成数,房间2完成数,房间3完成数,\n")
|
|
for heroId, levelMap := range heroMap {
|
|
buff.WriteString(fmt.Sprintf("%d,%d,%d,%d,\n", heroId, levelMap[1], levelMap[2], levelMap[3]))
|
|
}
|
|
|
|
err = os.WriteFile("./player_flirt_info.csv", buff.Bytes(), 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type _PlayerLotteryConsume struct {
|
|
PlayerId uint64
|
|
Ordinary uint64
|
|
Advanced uint64
|
|
}
|
|
|
|
func (this *QueryClient) queryLotteryConsume() error {
|
|
var beginDate = "2023-12-29" //include the day of the beginning date
|
|
var endDate = "2024-01-10" //but exclude the day of the end date
|
|
|
|
timeBegin, err := time.ParseInLocation(time.DateOnly, beginDate, util.UTC8())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
timeEnd, err := time.ParseInLocation(time.DateOnly, endDate, util.UTC8())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var tables []string
|
|
for ; timeBegin.Before(timeEnd); timeBegin = timeBegin.AddDate(0, 0, 1) {
|
|
tables = append(tables, fmt.Sprintf("consume_item_log_%s", timeBegin.Format("20060102")))
|
|
}
|
|
|
|
var rows *sql.Rows
|
|
var players = map[uint64]*_PlayerLotteryConsume{}
|
|
for _, table := range tables {
|
|
fmt.Printf("querying table %s\n", table)
|
|
|
|
rows, err = this.MysqlClient.Query(fmt.Sprintf("show tables like '%s';", table))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rows.Next() {
|
|
_ = rows.Close()
|
|
|
|
var query = fmt.Sprintf("select player_id, item_id, sum(item_num) from %s where item_id in (10007, 10013) group by player_id, item_id;", table)
|
|
|
|
rows, err = this.MysqlClient.Query(query)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for rows.Next() {
|
|
var playerId, itemId, itemNum uint64
|
|
err = rows.Scan(&playerId, &itemId, &itemNum)
|
|
var player = players[playerId]
|
|
if player == nil {
|
|
player = &_PlayerLotteryConsume{PlayerId: playerId}
|
|
players[player.PlayerId] = player
|
|
}
|
|
|
|
switch itemId {
|
|
case 10007:
|
|
player.Ordinary += itemNum
|
|
case 10013:
|
|
player.Advanced += itemNum
|
|
}
|
|
}
|
|
|
|
_ = rows.Close()
|
|
}
|
|
}
|
|
|
|
var buff bytes.Buffer
|
|
|
|
buff.WriteString("玩家ID,普通抽奖券消耗,高级抽奖券消耗,\n")
|
|
for _, player := range players {
|
|
buff.WriteString(fmt.Sprintf("%d,%d,%d,\n", player.PlayerId, player.Ordinary, player.Advanced))
|
|
}
|
|
|
|
err = os.WriteFile("./player_lottery_consume.csv", buff.Bytes(), 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type _MuraPlayer struct {
|
|
AccountId uint64 `bson:"_id"`
|
|
Platform uint32 `bson:"platform"`
|
|
}
|
|
|
|
func (this *QueryClient) queryMuraChargeTotal() error {
|
|
cur, err := this.MongoClient.Collection("player").Find(this.MongoClient.Context(), bson.M{"platform": 6})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var total int32 = 0
|
|
var player = new(_MuraPlayer)
|
|
for cur.Next(this.MongoClient.Context()) {
|
|
err = cur.Decode(player)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Println("Query Mura charge player: ", player.AccountId)
|
|
cc, err := this.MongoClient.Collection("chargeorder").Find(this.MongoClient.Context(), bson.M{"accountid": player.AccountId, "paystatus": 1})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for cc.Next(this.MongoClient.Context()) {
|
|
var order = new(_ChargeOrder)
|
|
err = cc.Decode(order)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Println("Query Mura charge order: ", order.OrderNumber)
|
|
total += order.ProductPrice
|
|
}
|
|
}
|
|
|
|
fmt.Println("Query Mura charge total: ", total)
|
|
return nil
|
|
}
|