Compare commits
23 Commits
1f24dd29b6
...
1235383c87
Author | SHA1 | Date |
---|---|---|
|
1235383c87 | |
|
8177397b26 | |
|
694e8a5992 | |
|
b186967189 | |
|
d82c5ed055 | |
|
e044a590d4 | |
|
39890efbfa | |
|
09a609b1b3 | |
|
e2095d6878 | |
|
bb8af52a6b | |
|
08023bcdea | |
|
893bc4cbbb | |
|
a9efaed491 | |
|
88b4c08740 | |
|
167e1e9c10 | |
|
1ed0d5b4d7 | |
|
7a7baa9568 | |
|
30d3ba1cc0 | |
|
9b59039d4b | |
|
7d0d5e9509 | |
|
93792b3e38 | |
|
f4964a57a2 | |
|
0c65af22ea |
|
@ -250,6 +250,7 @@ func RegisterClockFunc(fs *ClockFunc) {
|
|||
if fs == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if fs.OnSecTimerFunc != nil {
|
||||
fs.event = fs.event | 1<<ClockEventSecond
|
||||
}
|
||||
|
@ -272,5 +273,9 @@ func RegisterClockFunc(fs *ClockFunc) {
|
|||
fs.event = fs.event | 1<<ClockEventShutdown
|
||||
}
|
||||
|
||||
if fs.event == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ClockMgrSingleton.RegisterSinker(fs)
|
||||
}
|
||||
|
|
|
@ -899,6 +899,6 @@ var GuideIdToGainWay = map[int]int{
|
|||
GuideIdCustom: GainWayGuide2,
|
||||
}
|
||||
|
||||
func GetGameDifKey(gamedif string) string {
|
||||
func GetKeyGameDif(gamedif string) string {
|
||||
return fmt.Sprintf("gamedif-%v", gamedif)
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ const (
|
|||
ThirteenWaterPlayerOpReset = 4 // 重新选牌
|
||||
ThirteenWaterPlayerJoin = 5 // 加入游戏
|
||||
ThirteenWaterPlayerOpSelect = 6 // 预选牌
|
||||
ThirteenWaterPlayerOpAuto = 7 // 自动摆牌 1自动 2手动
|
||||
)
|
||||
const (
|
||||
ThirteenWaterSceneWaitTimeout = time.Second * 2 //等待倒计时
|
||||
|
|
|
@ -653,6 +653,12 @@ func (this *Player) ReportGameEvent(param *ReportGameEventParam) *ReportGameEven
|
|||
gameTimes = dataGame.Statics.GameTimes
|
||||
}
|
||||
|
||||
dataGameDif, ok := this.GDatas[common.GetKeyGameDif(this.scene.GetDBGameFree().GetGameDif())]
|
||||
if ok {
|
||||
gamedifFirstTime = dataGameDif.FirstTime
|
||||
gamedifTimes = dataGameDif.Statics.GameTimes
|
||||
}
|
||||
|
||||
isNew := int32(0)
|
||||
tCreateDay := now.New(this.CreateTime.Local()).BeginningOfDay()
|
||||
if now.BeginningOfDay().Equal(tCreateDay) {
|
||||
|
|
|
@ -2111,7 +2111,7 @@ func (this *Scene) Statistics(param *StaticParam) {
|
|||
var statics []*model.PlayerGameStatics
|
||||
keyGameId := strconv.Itoa(this.GetGameId())
|
||||
keyGameFreeId := strconv.Itoa(int(this.GetGameFreeId()))
|
||||
keyGameDif := common.GetGameDifKey(this.GetDBGameFree().GetGameDif())
|
||||
keyGameDif := common.GetKeyGameDif(this.GetDBGameFree().GetGameDif())
|
||||
// 当天数据统计
|
||||
// 按场次分
|
||||
if data, ok := p.TodayGameData.CtrlData[keyGameFreeId]; ok {
|
||||
|
@ -2350,7 +2350,7 @@ func (this *Scene) StaticsLaba(param *StaticLabaParam) {
|
|||
var statics []*model.PlayerGameStatics
|
||||
keyGameId := strconv.Itoa(this.GetGameId())
|
||||
keyGameFreeId := strconv.Itoa(int(this.GetGameFreeId()))
|
||||
keyGameDif := common.GetGameDifKey(this.GetDBGameFree().GetGameDif())
|
||||
keyGameDif := common.GetKeyGameDif(this.GetDBGameFree().GetGameDif())
|
||||
// 当天数据统计
|
||||
// 按场次分
|
||||
if data, ok := p.TodayGameData.CtrlData[keyGameFreeId]; ok {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package thirteen
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"mongo.games.com/goserver/core/logger"
|
||||
|
||||
"mongo.games.com/game/gamerule/thirteen"
|
||||
|
@ -26,6 +28,9 @@ type PlayerEx struct {
|
|||
totalScore int64
|
||||
defGroup *thirteen.Group
|
||||
playerPool int // 个人水池分
|
||||
AutoState int // 是否自动模式
|
||||
AutoMill time.Duration // 自动时长
|
||||
HandMill time.Duration // 手动时长
|
||||
}
|
||||
|
||||
func (this *PlayerEx) Clear() {
|
||||
|
@ -42,6 +47,9 @@ func (this *PlayerEx) Clear() {
|
|||
this.gainCoin = 0
|
||||
this.taxCoin = 0
|
||||
this.deterMine = false
|
||||
this.AutoState = 0
|
||||
this.AutoMill = time.Duration(0)
|
||||
this.HandMill = time.Duration(0)
|
||||
this.score = [7]int64{0, 0, 0, 0, 0, 0, 0}
|
||||
this.tableScore = [6]int64{}
|
||||
this.winThreePos = make(map[int]int64)
|
||||
|
|
|
@ -86,6 +86,7 @@ type SceneEx struct {
|
|||
ctrlType int // 1控赢 2控输 0不控
|
||||
cardsArr [][13]int
|
||||
cardsGroup []map[int]*rule.Group
|
||||
timestamp time.Time
|
||||
}
|
||||
|
||||
func NewThirteenWaterSceneData(s *base.Scene) *SceneEx {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"mongo.games.com/goserver/core"
|
||||
"mongo.games.com/goserver/core/logger"
|
||||
|
||||
|
@ -11,6 +12,7 @@ import (
|
|||
rule "mongo.games.com/game/gamerule/thirteen"
|
||||
"mongo.games.com/game/gamesrv/base"
|
||||
"mongo.games.com/game/model"
|
||||
"mongo.games.com/game/mq"
|
||||
"mongo.games.com/game/proto"
|
||||
"mongo.games.com/game/protocol/thirteen"
|
||||
)
|
||||
|
@ -808,6 +810,11 @@ func (this *StateOp) OnEnter(s *base.Scene) {
|
|||
logger.Logger.Tracef("(this *StateOp) OnEnter, sceneid=%v", s.GetSceneId())
|
||||
this.BaseState.OnEnter(s)
|
||||
ThirteenWaterBroadcastRoomState(s)
|
||||
sceneEx, ok := s.ExtraData.(*SceneEx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
sceneEx.timestamp = time.Now()
|
||||
}
|
||||
|
||||
// 玩家操作
|
||||
|
@ -826,38 +833,34 @@ func (this *StateOp) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, param
|
|||
return false
|
||||
}
|
||||
|
||||
returnFunc := func(code thirteen.OpResultCode) {
|
||||
returnFunc := func(code thirteen.OpResultCode, broadcast bool) {
|
||||
pack := &thirteen.SCThirteenPlayerOp{
|
||||
OpRetCode: code,
|
||||
OpCode: int32(opcode),
|
||||
OpParam: params,
|
||||
Pos: int32(playerEx.GetPos()),
|
||||
}
|
||||
if code == thirteen.OpResultCode_OPRC_Error {
|
||||
proto.SetDefaults(pack)
|
||||
logger.Logger.Trace("SCThirteenPlayerOp:", pack)
|
||||
if broadcast {
|
||||
playerEx.Broadcast(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack, 0)
|
||||
} else {
|
||||
playerEx.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack)
|
||||
return
|
||||
}
|
||||
logger.Logger.Trace("SCThirteenPlayerOp:", pack)
|
||||
}
|
||||
|
||||
if !playerEx.IsGameing() {
|
||||
returnFunc(thirteen.OpResultCode_OPRC_Error)
|
||||
returnFunc(thirteen.OpResultCode_OPRC_Error, false)
|
||||
return true
|
||||
}
|
||||
|
||||
switch opcode {
|
||||
case rule.ThirteenWaterPlayerOpMS: //确定牌
|
||||
//if playerEx.deterMine { // 确认牌型
|
||||
// returnFunc(thirteen.OpResultCode_OPRC_Error)
|
||||
// return false
|
||||
//}
|
||||
if len(params) == 13 {
|
||||
//校验牌
|
||||
a := rule.DelCards(playerEx.cards[:], common.Int64Toint(params))
|
||||
if len(a) != 0 {
|
||||
logger.Logger.Error("the cards is error.")
|
||||
returnFunc(thirteen.OpResultCode_OPRC_Error)
|
||||
returnFunc(thirteen.OpResultCode_OPRC_Error, false)
|
||||
return true
|
||||
}
|
||||
//牌赋值
|
||||
|
@ -873,6 +876,7 @@ func (this *StateOp) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, param
|
|||
playerEx.Trusteeship = 0
|
||||
playerEx.UnmarkFlag(base.PlayerState_Auto)
|
||||
playerEx.deterMine = true
|
||||
playerEx.AutoState = 0
|
||||
//如果所有玩家都确认牌之后 可以直接开始下一阶段
|
||||
a := true
|
||||
for _, v := range sceneEx.players {
|
||||
|
@ -892,38 +896,70 @@ func (this *StateOp) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, param
|
|||
playerEx.cardsO = &rule.Group{Head: [3]int{-1, -1, -1}, Mid: [5]int{-1, -1, -1, -1, -1}, End: [5]int{-1, -1, -1, -1, -1}, PokerType: -1}
|
||||
playerEx.Trusteeship = 0
|
||||
playerEx.UnmarkFlag(base.PlayerState_Auto)
|
||||
pack := &thirteen.SCThirteenPlayerOp{
|
||||
OpRetCode: thirteen.OpResultCode_OPRC_Sucess,
|
||||
OpCode: int32(opcode),
|
||||
OpParam: params,
|
||||
Pos: int32(playerEx.GetPos()),
|
||||
}
|
||||
if len(params) == 13 {
|
||||
//校验牌
|
||||
a := rule.DelCards(playerEx.cards[:], common.Int64Toint(params))
|
||||
if len(a) != 0 {
|
||||
remain := len(playerEx.cards)
|
||||
remainCards := make([]int, remain)
|
||||
copy(remainCards, playerEx.cards[:])
|
||||
for _, v := range params {
|
||||
if v >= 0 {
|
||||
a := rule.DelCards(remainCards, []int{int(v)})
|
||||
if len(a) == remain {
|
||||
logger.Logger.Error("the cards is error.")
|
||||
returnFunc(thirteen.OpResultCode_OPRC_Error)
|
||||
returnFunc(thirteen.OpResultCode_OPRC_Error, false)
|
||||
return true
|
||||
}
|
||||
remain = len(a)
|
||||
remainCards = a
|
||||
}
|
||||
}
|
||||
|
||||
//牌赋值
|
||||
copy(playerEx.preCardsO.Head[:], common.Int64Toint(params[:3]))
|
||||
copy(playerEx.preCardsO.Mid[:], common.Int64Toint(params[3:8]))
|
||||
copy(playerEx.preCardsO.End[:], common.Int64Toint(params[8:]))
|
||||
playerEx.preCardsO.PokerType = 0
|
||||
|
||||
for k, v := range playerEx.preCardsO.Head {
|
||||
if v < 0 {
|
||||
playerEx.preCardsO.Head[k] = remainCards[0]
|
||||
remainCards = remainCards[1:]
|
||||
}
|
||||
playerEx.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack)
|
||||
}
|
||||
for k, v := range playerEx.preCardsO.Mid {
|
||||
if v < 0 {
|
||||
playerEx.preCardsO.Mid[k] = remainCards[0]
|
||||
remainCards = remainCards[1:]
|
||||
}
|
||||
}
|
||||
for k, v := range playerEx.preCardsO.End {
|
||||
if v < 0 {
|
||||
playerEx.preCardsO.End[k] = remainCards[0]
|
||||
remainCards = remainCards[1:]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(params) == 1 {
|
||||
sceneEx.SelectCards(playerEx, int(params[0]))
|
||||
}
|
||||
|
||||
if len(params) == 0 {
|
||||
playerEx.preCardsO = &rule.Group{Head: [3]int{-1, -1, -1}, Mid: [5]int{-1, -1, -1, -1, -1}, End: [5]int{-1, -1, -1, -1, -1}, PokerType: -1}
|
||||
}
|
||||
returnFunc(thirteen.OpResultCode_OPRC_Sucess, true)
|
||||
|
||||
case rule.ThirteenWaterPlayerOpReset:
|
||||
// 取消确认
|
||||
playerEx.deterMine = false
|
||||
pack := &thirteen.SCThirteenPlayerOp{
|
||||
OpRetCode: thirteen.OpResultCode_OPRC_Sucess,
|
||||
OpCode: int32(opcode),
|
||||
OpParam: params,
|
||||
Pos: int32(playerEx.GetPos()),
|
||||
returnFunc(thirteen.OpResultCode_OPRC_Sucess, true)
|
||||
|
||||
case rule.ThirteenWaterPlayerOpAuto:
|
||||
if len(params) == 0 {
|
||||
return true
|
||||
}
|
||||
playerEx.Broadcast(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack, 0)
|
||||
|
||||
playerEx.AutoState = int(params[0])
|
||||
|
||||
default:
|
||||
return false
|
||||
|
@ -941,6 +977,19 @@ func (this *StateOp) OnLeave(s *base.Scene) {
|
|||
|
||||
for _, player := range sceneEx.players {
|
||||
if player != nil && player.IsGameing() {
|
||||
|
||||
if !player.IsRobot() {
|
||||
mq.Write(model.ThirteenAutoLog{
|
||||
Id: primitive.NewObjectID().Hex(),
|
||||
Platform: player.Platform,
|
||||
LogId: sceneEx.logid,
|
||||
SnId: player.SnId,
|
||||
AutoTime: player.AutoMill.Milliseconds(),
|
||||
HandTime: player.HandMill.Milliseconds(),
|
||||
Ts: time.Now().Unix(),
|
||||
}, mq.BackThirteenAutoLog)
|
||||
}
|
||||
|
||||
// 使用预选牌
|
||||
if player.preCardsO != nil && player.preCardsO.PokerType != -1 && (player.cardsO == nil || player.cardsO.PokerType == -1) {
|
||||
player.cardsO = player.preCardsO
|
||||
|
@ -1120,7 +1169,23 @@ func (this *StateOp) OnLeave(s *base.Scene) {
|
|||
func (this *StateOp) OnTick(s *base.Scene) {
|
||||
this.BaseState.OnTick(s)
|
||||
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
|
||||
if time.Now().Sub(sceneEx.StateStartTime) > sceneEx.GetBaiPai() {
|
||||
now := time.Now()
|
||||
addTime := now.Sub(sceneEx.timestamp)
|
||||
for _, v := range sceneEx.seats {
|
||||
if v != nil && v.IsGameing() {
|
||||
switch v.AutoState {
|
||||
case 2:
|
||||
v.AutoMill += addTime
|
||||
case 1:
|
||||
v.HandMill += addTime
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
sceneEx.timestamp = now
|
||||
|
||||
if now.Sub(sceneEx.StateStartTime) > sceneEx.GetBaiPai() {
|
||||
s.ChangeSceneState(rule.ThirteenWaterSceneStateShowCards)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1298,25 +1298,21 @@ func (this *TienLenSceneData) SendHandCardOdds() {
|
|||
allcs[i], allcs[j] = allcs[j], allcs[i]
|
||||
})
|
||||
|
||||
if len(this.testPokers) > 14 {
|
||||
this.testPokers = this.testPokers[:14]
|
||||
}
|
||||
if len(this.testPokers) < 14 {
|
||||
allcs = common.DelSliceIn32s(allcs, this.testPokers[1:])
|
||||
this.testPokers = append(this.testPokers, allcs[:14-len(this.testPokers)]...)
|
||||
allcs = allcs[14-len(this.testPokers):]
|
||||
}
|
||||
this.testPokers = append(this.testPokers, allcs...)
|
||||
|
||||
allcs = common.DelSliceIn32s(allcs, this.testPokers[1:])
|
||||
for _, seat := range this.seats {
|
||||
if seat != nil && seat.IsGameing() {
|
||||
if seat.SnId == this.testPokers[0] {
|
||||
f1(seat, this.testPokers[1:])
|
||||
} else {
|
||||
f1(seat, allcs[:13])
|
||||
allcs = allcs[13:]
|
||||
if seat != nil && seat.IsGameing() && seat.SnId == this.testPokers[0] {
|
||||
f1(seat, this.testPokers[1:14])
|
||||
this.testPokers = this.testPokers[14:]
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, seat := range this.seats {
|
||||
if seat != nil && seat.IsGameing() && seat.cards[0] == rule.InvalideCard {
|
||||
f1(seat, this.testPokers[:13])
|
||||
this.testPokers = this.testPokers[13:]
|
||||
}
|
||||
}
|
||||
this.testPokers = nil
|
||||
isTestPoker = true
|
||||
|
|
|
@ -8,9 +8,11 @@ type BankruptLog struct {
|
|||
LogId bson.ObjectId `bson:"_id"`
|
||||
SnId int32 //玩家id
|
||||
Channel string // 渠道
|
||||
ChannelId string // 推广渠道
|
||||
Platform string //平台名称
|
||||
GameId int //游戏id
|
||||
GameFreeID int32 //房间id
|
||||
GameDif string // 游戏分组
|
||||
|
||||
CreateTime int64 // 注册时间
|
||||
UseCoin int64 // 消耗金币
|
||||
|
@ -22,12 +24,14 @@ func NewBankruptLog() *BankruptLog {
|
|||
return log
|
||||
}
|
||||
|
||||
func NewBankruptLogEx(snid int32, gamefreeid int32, createtime, usecoin int64, platform, channel string, gameId int) *BankruptLog {
|
||||
func NewBankruptLogEx(snid int32, gamefreeid int32, createtime, usecoin int64, platform, channel, channelId, gamedif string, gameId int) *BankruptLog {
|
||||
cl := NewBankruptLog()
|
||||
cl.SnId = snid
|
||||
cl.Platform = platform
|
||||
cl.Channel = channel
|
||||
cl.ChannelId = channelId
|
||||
cl.GameId = gameId
|
||||
cl.GameDif = gamedif
|
||||
|
||||
cl.GameFreeID = gamefreeid
|
||||
cl.CreateTime = createtime
|
||||
|
|
|
@ -1262,9 +1262,11 @@ func SavePlayerData(pd *PlayerData) bool {
|
|||
}
|
||||
if pd != nil {
|
||||
var ret bool
|
||||
t1 := time.Now()
|
||||
err := rpcCli.CallWithTimeout("PlayerDataSvc.SavePlayerData", pd, &ret, time.Second*30)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("SavePlayerData %v err:%v", pd.SnId, err)
|
||||
logger.Logger.Errorf("SavePlayerData %v cost:%v fail err:%v PlayerData:%+v",
|
||||
pd.SnId, time.Now().Sub(t1), err, *pd)
|
||||
return false
|
||||
}
|
||||
return ret
|
||||
|
|
|
@ -15,6 +15,13 @@ func GenerateOnline(online map[string]map[string]int) *mq.RabbitMQData {
|
|||
return NewRabbitMQData(mq.BackOnline, params)
|
||||
}
|
||||
|
||||
func GenerateOnlineGame(online map[string]map[string]map[string]map[int]map[int]int) *mq.RabbitMQData {
|
||||
params := make(map[string]interface{})
|
||||
params["Online"] = online
|
||||
params["Time"] = time.Now().Unix()
|
||||
return NewRabbitMQData(mq.BackOnlineGame, params)
|
||||
}
|
||||
|
||||
// GenerateLogin 玩家登陆事件
|
||||
func GenerateLogin(o *PlayerLoginEvent) *mq.RabbitMQData {
|
||||
return NewRabbitMQData(mq.BackLogin, o)
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package model
|
||||
|
||||
type ThirteenAutoLog struct {
|
||||
Id string `gorm:"primaryKey"`
|
||||
Platform string `gorm:"-"`
|
||||
LogId string `gorm:"index;column:logid"`
|
||||
SnId int32 `gorm:"index;column:snid"`
|
||||
AutoTime int64 // 自动时长,毫秒
|
||||
HandTime int64 // 手动时长,毫秒
|
||||
Ts int64
|
||||
}
|
19
mq/export.go
19
mq/export.go
|
@ -55,18 +55,18 @@ type RabbitMQData struct {
|
|||
Data interface{}
|
||||
}
|
||||
|
||||
func (c *MessageMgr) Send(data interface{}, name ...string) error {
|
||||
func (c *MessageMgr) Send(data interface{}, name string, options ...broker.PublishOption) error {
|
||||
if msg, ok := data.(*RabbitMQData); ok {
|
||||
return Send(msg.MQName, msg.Data)
|
||||
return Send(msg.MQName, msg.Data, options...)
|
||||
}
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
return Send(name[0], data)
|
||||
if len(name) > 0 {
|
||||
return Send(name, data, options...)
|
||||
}
|
||||
key := c.getName(data)
|
||||
if key == "" {
|
||||
key = "_null_"
|
||||
}
|
||||
return Send(key, data)
|
||||
return Send(key, data, options...)
|
||||
}
|
||||
|
||||
type RegisterHandlerParam struct {
|
||||
|
@ -132,7 +132,14 @@ func RegisterMessage(param *RegisterMessageParam) {
|
|||
// Write 发送消息
|
||||
// 默认队列名称规则:队列前缀_消息结构体名称
|
||||
func Write(data interface{}, name ...string) error {
|
||||
return MessageMgrSingle.Send(data, name...)
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
return MessageMgrSingle.Send(data, name[0])
|
||||
}
|
||||
return MessageMgrSingle.Send(data, "")
|
||||
}
|
||||
|
||||
func WriteWithOptions(data interface{}, name string, opts ...broker.PublishOption) error {
|
||||
return MessageMgrSingle.Send(data, name, opts...)
|
||||
}
|
||||
|
||||
// RegisterHandler 注册消息处理函数
|
||||
|
|
|
@ -18,11 +18,14 @@ const (
|
|||
BackSystemPermitTask = "back_permittask"
|
||||
BackSystemJyb = "back_jyblog"
|
||||
BackActivityLog = "back_activitylog"
|
||||
BackOnlineGame = "back_onlinegame"
|
||||
)
|
||||
|
||||
// mgrsrv
|
||||
// go后端
|
||||
|
||||
const ()
|
||||
const (
|
||||
BackThirteenAutoLog = "b_thirteenautolog"
|
||||
)
|
||||
|
||||
// worldsrv 消息
|
||||
|
||||
|
|
|
@ -386,7 +386,7 @@ type CSThirteenPlayerOp struct {
|
|||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
OpCode int32 `protobuf:"varint,1,opt,name=OpCode,proto3" json:"OpCode,omitempty"` // 1:确定牌 2站起状态 3test 4重新选牌 5加入游戏 6预选
|
||||
OpCode int32 `protobuf:"varint,1,opt,name=OpCode,proto3" json:"OpCode,omitempty"` // 1:确定牌 2站起状态 3test 4重新选牌 5加入游戏 6预选 7自动手动切换(1自动,2手动)
|
||||
// 确定牌时,两种参数规则,都可以
|
||||
// 第一种:玩家从推荐牌型中选择一个,把Poker.IndexType发过来(减少数据传输)
|
||||
// 第二种:按头墩中墩尾墩顺序把牌发过来
|
||||
|
|
|
@ -73,7 +73,7 @@ message SCThirteenPlayerCards {
|
|||
//玩家操作
|
||||
//PACKET_CSThirteenPlayerOp
|
||||
message CSThirteenPlayerOp {
|
||||
int32 OpCode = 1; // 1:确定牌 2站起状态 3test 4重新选牌 5加入游戏 6预选
|
||||
int32 OpCode = 1; // 1:确定牌 2站起状态 3test 4重新选牌 5加入游戏 6预选 7自动手动切换(1自动,2手动)
|
||||
|
||||
// 确定牌时,两种参数规则,都可以
|
||||
// 第一种:玩家从推荐牌型中选择一个,把Poker.IndexType发过来(减少数据传输)
|
||||
|
|
|
@ -25,3 +25,8 @@ update_invite_num: 30
|
|||
update_second_item: 10
|
||||
# 一次最多读取多少道具日志
|
||||
update_item_num: 100
|
||||
|
||||
# rabbitmq配置
|
||||
rabbitmq:
|
||||
url: amqp://win88:123456@127.0.0.1:5672/win99
|
||||
exchange: win99
|
|
@ -15,9 +15,10 @@ import (
|
|||
"mongo.games.com/goserver/core/utils"
|
||||
"mongo.games.com/goserver/core/viperx"
|
||||
|
||||
"mongo.games.com/game/mq"
|
||||
mongomodel "mongo.games.com/game/statistics/modelmongo"
|
||||
mysqlmodel "mongo.games.com/game/statistics/modelmysql"
|
||||
"mongo.games.com/game/statistics/static"
|
||||
_ "mongo.games.com/game/statistics/mq"
|
||||
"mongo.games.com/game/statistics/syn"
|
||||
)
|
||||
|
||||
|
@ -92,26 +93,32 @@ func main() {
|
|||
|
||||
mysqlx.SetAutoMigrateTables(mysqlmodel.Tables)
|
||||
|
||||
// mq
|
||||
mq.StartConsumer(VP.GetString("rabbitmq.url"), VP.GetString("rabbitmq.exchange"), true)
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
// 同步注册和登录日志
|
||||
DoTick(ctx, wg, time.Duration(VP.GetInt64("update_second"))*time.Second, SyncSnId)
|
||||
|
||||
DoTick(ctx, wg, time.Duration(VP.GetInt64("update_second_snid"))*time.Second, func(ctx context.Context) {
|
||||
wg := new(sync.WaitGroup)
|
||||
for _, v := range VP.GetStringSlice("platforms") {
|
||||
platform := v
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
Static(platform)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
})
|
||||
//DoTick(ctx, wg, time.Duration(VP.GetInt64("update_second_snid"))*time.Second, func(ctx context.Context) {
|
||||
// wg := new(sync.WaitGroup)
|
||||
// for _, v := range VP.GetStringSlice("platforms") {
|
||||
// platform := v
|
||||
// wg.Add(1)
|
||||
// go func() {
|
||||
// defer wg.Done()
|
||||
// Static(platform)
|
||||
// }()
|
||||
// }
|
||||
// wg.Wait()
|
||||
//})
|
||||
|
||||
// 同步邀请数据
|
||||
DoTick(ctx, wg, time.Duration(VP.GetInt64("update_second_invite"))*time.Second, SyncInvite)
|
||||
|
||||
// 同步道具日志数据
|
||||
DoTickPlatform(ctx, wg, time.Duration(VP.GetInt64("update_second_item"))*time.Second, VP.GetInt("update_item_num"),
|
||||
func(ctx context.Context, platform string, batchSize int) {
|
||||
err := syn.ItemGainDone(&syn.Data[mongomodel.ItemLog]{
|
||||
|
@ -123,7 +130,7 @@ func main() {
|
|||
}
|
||||
})
|
||||
|
||||
logger.Logger.Info("start")
|
||||
logger.Logger.Info("start success")
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt, os.Kill)
|
||||
|
@ -162,36 +169,36 @@ func SyncSnId(ctx context.Context) {
|
|||
}
|
||||
|
||||
// Static 玩家id触发数据统计
|
||||
func Static(platform string) {
|
||||
// 查询需要更新的玩家id
|
||||
var ids []*mysqlmodel.UserID
|
||||
db, err := mysqlx.GetDatabase(platform)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("GetDatabase error: %v", err)
|
||||
return
|
||||
}
|
||||
if err := db.Limit(VP.GetInt("update_snid_num")).Find(&ids).Error; err != nil {
|
||||
logger.Logger.Warnf("Get UserID error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(ids) == 0 {
|
||||
logger.Logger.Tracef("Static: no need to update")
|
||||
return
|
||||
}
|
||||
|
||||
// 统计玩家跳出记录
|
||||
if err := static.UserLogin(platform, ids); err != nil {
|
||||
logger.Logger.Errorf("StaticUserLogin error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 删除更新过的玩家id
|
||||
if err := db.Delete(ids).Error; err != nil {
|
||||
logger.Logger.Errorf("Delete error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
//func Static(platform string) {
|
||||
// // 查询需要更新的玩家id
|
||||
// var ids []*mysqlmodel.UserID
|
||||
// db, err := mysqlx.GetDatabase(platform)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("GetDatabase error: %v", err)
|
||||
// return
|
||||
// }
|
||||
// if err := db.Limit(VP.GetInt("update_snid_num")).Find(&ids).Error; err != nil {
|
||||
// logger.Logger.Warnf("Get UserID error: %v", err)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// if len(ids) == 0 {
|
||||
// logger.Logger.Tracef("Static: no need to update")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // 统计玩家跳出记录
|
||||
// //if err := static.UserLogin(platform, ids); err != nil {
|
||||
// // logger.Logger.Errorf("StaticUserLogin error: %v", err)
|
||||
// // return
|
||||
// //}
|
||||
//
|
||||
// // 删除更新过的玩家id
|
||||
// if err := db.Delete(ids).Error; err != nil {
|
||||
// logger.Logger.Errorf("Delete error: %v", err)
|
||||
// return
|
||||
// }
|
||||
//}
|
||||
|
||||
// SyncInvite 同步邀请数据
|
||||
func SyncInvite(ctx context.Context) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package modelmysql
|
||||
|
||||
import "mongo.games.com/game/model"
|
||||
|
||||
// 需要自动迁移的表添加在这里 Tables
|
||||
|
||||
var Tables = []interface{}{
|
||||
|
@ -14,4 +16,5 @@ var Tables = []interface{}{
|
|||
&LogMid{},
|
||||
&ItemGain{},
|
||||
&ItemTotalGain{},
|
||||
&model.ThirteenAutoLog{},
|
||||
}
|
||||
|
|
|
@ -1 +1,35 @@
|
|||
package mq
|
||||
|
||||
import (
|
||||
"mongo.games.com/goserver/core/logger"
|
||||
"mongo.games.com/goserver/core/mysqlx"
|
||||
|
||||
"mongo.games.com/game/model"
|
||||
"mongo.games.com/game/mq"
|
||||
)
|
||||
|
||||
func init() {
|
||||
mq.RegisterHandler(&mq.RegisterHandlerParam{
|
||||
Name: mq.BackThirteenAutoLog,
|
||||
Data: &model.ThirteenAutoLog{},
|
||||
Handler: func(data interface{}) (err error) {
|
||||
d, ok := data.(*model.ThirteenAutoLog)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
db, err := mysqlx.GetDatabase(d.Platform)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("mysql: SyncThirteenAutoLog failed to get database: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err = db.Create(d).Error; err != nil {
|
||||
logger.Logger.Errorf("mysql: SyncThirteenAutoLog failed to create thirteen_auto_log: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,371 +1,355 @@
|
|||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"mongo.games.com/goserver/core/logger"
|
||||
|
||||
mymongo "mongo.games.com/goserver/core/mongox"
|
||||
mymysql "mongo.games.com/goserver/core/mysqlx"
|
||||
|
||||
mongomodel "mongo.games.com/game/statistics/modelmongo"
|
||||
mysqlmodel "mongo.games.com/game/statistics/modelmysql"
|
||||
)
|
||||
|
||||
func getAccountTel(platform string, id int) (string, error) {
|
||||
acc := &mongomodel.Account{}
|
||||
cc, err := mymongo.GetUserCollection(platform, mongomodel.UserAccount)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("get collection %s error %v", mongomodel.UserAccount, err)
|
||||
return "", err
|
||||
}
|
||||
dd := cc.FindOne(context.TODO(), bson.M{"snid": id}, options.FindOne().SetProjection(bson.M{"tel": 1}))
|
||||
err = dd.Err()
|
||||
if err != nil {
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
logger.Logger.Tracef("getAccountTel %v not found in user_account", id)
|
||||
return "", nil
|
||||
}
|
||||
logger.Logger.Errorf("getAccountTel %v get user_account err: %v", id, err)
|
||||
return "", err
|
||||
}
|
||||
if err := dd.Decode(acc); err != nil {
|
||||
logger.Logger.Errorf("getAccountTel %v decode user_account err: %v", id, err)
|
||||
return "", err
|
||||
}
|
||||
return acc.Tel, nil
|
||||
}
|
||||
|
||||
// 游戏结束离开
|
||||
func checkGameOver(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) {
|
||||
// 最早的一条掉线记录并且是游戏结束离开
|
||||
a := &mongomodel.LoginLog{}
|
||||
c, err := mymongo.GetLogCollection(platform, mongomodel.LogLogin)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("get collection %s error %v", mongomodel.LogLogin, err)
|
||||
return false, err
|
||||
}
|
||||
d := c.FindOne(context.TODO(), bson.M{"snid": id, "logtype": mongomodel.LogTypeDrop, "gameid": 0, "lastgameid": bson.D{{"$gt", 0}}},
|
||||
options.FindOne().SetSort(bson.D{{"time", 1}}))
|
||||
err = d.Err()
|
||||
if err != nil {
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
logger.Logger.Tracef("checkGameOver %v not found in log_login", id)
|
||||
return false, nil
|
||||
}
|
||||
logger.Logger.Errorf("checkGameOver %v get log_login err: %v", id, err)
|
||||
return false, err
|
||||
}
|
||||
if err := d.Decode(a); err != nil {
|
||||
logger.Logger.Errorf("checkGameOver %v decode log_login err: %v", id, err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
// account tel
|
||||
tel, err := getAccountTel(platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Warnf("get account tel %v err: %v", id, err)
|
||||
}
|
||||
|
||||
update := &mysqlmodel.UserLogin{
|
||||
//OfflineTs: int(a.Ts),
|
||||
OfflineTime: a.Time,
|
||||
OutType: mysqlmodel.OutTypeGameOver,
|
||||
GameID: a.LastGameID,
|
||||
Tel: tel,
|
||||
DeviceName: a.DeviceName,
|
||||
AppVersion: a.AppVersion,
|
||||
BuildVersion: a.BuildVersion,
|
||||
AppChannel: a.AppChannel,
|
||||
ChannelId: a.ChannelId,
|
||||
}
|
||||
|
||||
if err := db.Model(login).Select(
|
||||
"OfflineTime", "OutType", "GameID", "DeviceName", "AppVersion", "BuildVersion", "AppChannel", "Tel",
|
||||
).Updates(update).Error; err != nil {
|
||||
logger.Logger.Errorf("checkLogin %v update user_login err: %v", id, err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// 游戏中离开
|
||||
func checkGaming(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) {
|
||||
// 最早的一条掉线记录并且是游戏中掉线
|
||||
a := &mongomodel.LoginLog{}
|
||||
c, err := mymongo.GetLogCollection(platform, mongomodel.LogLogin)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("get collection %s error %v", mongomodel.LogLogin, err)
|
||||
return false, err
|
||||
}
|
||||
d := c.FindOne(context.TODO(), bson.M{"snid": id, "logtype": mongomodel.LogTypeDrop, "gameid": bson.D{{"$gt", 0}}},
|
||||
options.FindOne().SetSort(bson.D{{"time", 1}}))
|
||||
err = d.Err()
|
||||
if err != nil {
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
logger.Logger.Tracef("checkGaming %v not found in log_login", id)
|
||||
return false, nil
|
||||
}
|
||||
logger.Logger.Errorf("checkGaming %v get log_login err: %v", id, err)
|
||||
return false, err
|
||||
}
|
||||
if err := d.Decode(a); err != nil {
|
||||
logger.Logger.Errorf("checkGaming %v decode log_login err: %v", id, err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
// account tel
|
||||
tel, err := getAccountTel(platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Warnf("get account tel %v err: %v", id, err)
|
||||
}
|
||||
|
||||
update := &mysqlmodel.UserLogin{
|
||||
//OfflineTs: int(a.Ts),
|
||||
OfflineTime: a.Time,
|
||||
OutType: mysqlmodel.OutTypeGaming,
|
||||
GameID: a.GameId,
|
||||
Tel: tel,
|
||||
DeviceName: a.DeviceName,
|
||||
AppVersion: a.AppVersion,
|
||||
BuildVersion: a.BuildVersion,
|
||||
AppChannel: a.AppChannel,
|
||||
ChannelId: a.ChannelId,
|
||||
}
|
||||
|
||||
if err := db.Model(login).Select(
|
||||
"OfflineTime", "OutType", "GameID", "DeviceName", "AppVersion", "BuildVersion", "AppChannel", "Tel",
|
||||
).Updates(update).Error; err != nil {
|
||||
logger.Logger.Errorf("checkLogin %v update user_login err: %v", id, err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// 登录后离开
|
||||
func checkLogin(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) {
|
||||
// 最早的一条掉线记录
|
||||
a := &mongomodel.LoginLog{}
|
||||
c, err := mymongo.GetLogCollection(platform, mongomodel.LogLogin)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("get collection %s error %v", mongomodel.LogLogin, err)
|
||||
return false, err
|
||||
}
|
||||
d := c.FindOne(context.TODO(), bson.M{"snid": id, "logtype": mongomodel.LogTypeDrop}, options.FindOne().SetSort(bson.D{{"time", 1}}))
|
||||
err = d.Err()
|
||||
if err != nil {
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
logger.Logger.Tracef("checkLogin %v not found in log_login", id)
|
||||
return false, nil
|
||||
}
|
||||
logger.Logger.Errorf("checkLogin %v get log_login err: %v", id, err)
|
||||
return false, err
|
||||
}
|
||||
if err := d.Decode(a); err != nil {
|
||||
logger.Logger.Errorf("checkLogin %v decode log_login err: %v", id, err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
// account tel
|
||||
tel, err := getAccountTel(platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Warnf("get account tel %v err: %v", id, err)
|
||||
}
|
||||
|
||||
update := &mysqlmodel.UserLogin{
|
||||
//OfflineTs: int(a.Ts),
|
||||
OfflineTime: a.Time,
|
||||
OutType: mysqlmodel.OutTypeLogin,
|
||||
Tel: tel,
|
||||
DeviceName: a.DeviceName,
|
||||
AppVersion: a.AppVersion,
|
||||
BuildVersion: a.BuildVersion,
|
||||
AppChannel: a.AppChannel,
|
||||
ChannelId: a.ChannelId,
|
||||
}
|
||||
|
||||
if err := db.Model(login).Select(
|
||||
"OfflineTime", "OutType", "DeviceName", "AppVersion", "BuildVersion", "AppChannel", "Tel",
|
||||
).Updates(update).Error; err != nil {
|
||||
logger.Logger.Errorf("checkLogin %v update user_login err: %v", id, err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// 注册后离开
|
||||
func checkRegister(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) {
|
||||
a := &mongomodel.Account{}
|
||||
c, err := mymongo.GetUserCollection(platform, mongomodel.UserAccount)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("get collection %s error %v", mongomodel.UserAccount, err)
|
||||
return false, err
|
||||
}
|
||||
d := c.FindOne(context.TODO(), bson.M{"snid": id})
|
||||
err = d.Err()
|
||||
if err != nil {
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
logger.Logger.Warnf("checkRegister %v not found in user_account", id)
|
||||
return false, nil
|
||||
}
|
||||
logger.Logger.Errorf("checkRegister %v get user_account err: %v", id, err)
|
||||
return false, err
|
||||
}
|
||||
if err := d.Decode(a); err != nil {
|
||||
logger.Logger.Errorf("checkRegister %v decode user_account err: %v", id, err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
// account tel
|
||||
tel, err := getAccountTel(platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Warnf("get account tel %v err: %v", id, err)
|
||||
}
|
||||
|
||||
login.Snid = id
|
||||
//login.OnlineTs = int(a.RegisterTs)
|
||||
login.OnlineTime = a.RegisteTime
|
||||
//login.OfflineTs = int(a.RegisterTs)
|
||||
login.OfflineTime = a.RegisteTime
|
||||
login.OutType = mysqlmodel.OutTypRegister
|
||||
login.Tel = tel
|
||||
login.DeviceName = a.DeviceName
|
||||
login.AppVersion = a.AppVersion
|
||||
login.BuildVersion = a.BuildVersion
|
||||
login.AppChannel = a.AppChannel
|
||||
login.ChannelId = a.ChannelId
|
||||
|
||||
if err := db.Create(login).Error; err != nil {
|
||||
logger.Logger.Errorf("checkRegister create err: %v", err)
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
//func getAccountTel(platform string, id int) (string, error) {
|
||||
// acc := &mongomodel.Account{}
|
||||
// cc, err := mymongo.GetUserCollection(platform, mongomodel.UserAccount)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("get collection %s error %v", mongomodel.UserAccount, err)
|
||||
// return "", err
|
||||
// }
|
||||
// dd := cc.FindOne(context.TODO(), bson.M{"snid": id}, options.FindOne().SetProjection(bson.M{"tel": 1}))
|
||||
// err = dd.Err()
|
||||
// if err != nil {
|
||||
// if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
// logger.Logger.Tracef("getAccountTel %v not found in user_account", id)
|
||||
// return "", nil
|
||||
// }
|
||||
// logger.Logger.Errorf("getAccountTel %v get user_account err: %v", id, err)
|
||||
// return "", err
|
||||
// }
|
||||
// if err := dd.Decode(acc); err != nil {
|
||||
// logger.Logger.Errorf("getAccountTel %v decode user_account err: %v", id, err)
|
||||
// return "", err
|
||||
// }
|
||||
// return acc.Tel, nil
|
||||
//}
|
||||
//
|
||||
//// 游戏结束离开
|
||||
//func checkGameOver(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) {
|
||||
// // 最早的一条掉线记录并且是游戏结束离开
|
||||
// a := &mongomodel.LoginLog{}
|
||||
// c, err := mymongo.GetLogCollection(platform, mongomodel.LogLogin)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("get collection %s error %v", mongomodel.LogLogin, err)
|
||||
// return false, err
|
||||
// }
|
||||
// d := c.FindOne(context.TODO(), bson.M{"snid": id, "logtype": mongomodel.LogTypeDrop, "gameid": 0, "lastgameid": bson.D{{"$gt", 0}}},
|
||||
// options.FindOne().SetSort(bson.D{{"time", 1}}))
|
||||
// err = d.Err()
|
||||
// if err != nil {
|
||||
// if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
// logger.Logger.Tracef("checkGameOver %v not found in log_login", id)
|
||||
// return false, nil
|
||||
// }
|
||||
// logger.Logger.Errorf("checkGameOver %v get log_login err: %v", id, err)
|
||||
// return false, err
|
||||
// }
|
||||
// if err := d.Decode(a); err != nil {
|
||||
// logger.Logger.Errorf("checkGameOver %v decode log_login err: %v", id, err)
|
||||
// return false, err
|
||||
// }
|
||||
//
|
||||
// // account tel
|
||||
// tel, err := getAccountTel(platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Warnf("get account tel %v err: %v", id, err)
|
||||
// }
|
||||
//
|
||||
// update := &mysqlmodel.UserLogin{
|
||||
// //OfflineTs: int(a.Ts),
|
||||
// OfflineTime: a.Time,
|
||||
// OutType: mysqlmodel.OutTypeGameOver,
|
||||
// GameID: a.LastGameID,
|
||||
// Tel: tel,
|
||||
// DeviceName: a.DeviceName,
|
||||
// AppVersion: a.AppVersion,
|
||||
// BuildVersion: a.BuildVersion,
|
||||
// AppChannel: a.AppChannel,
|
||||
// ChannelId: a.ChannelId,
|
||||
// }
|
||||
//
|
||||
// if err := db.Model(login).Select(
|
||||
// "OfflineTime", "OutType", "GameID", "DeviceName", "AppVersion", "BuildVersion", "AppChannel", "Tel",
|
||||
// ).Updates(update).Error; err != nil {
|
||||
// logger.Logger.Errorf("checkLogin %v update user_login err: %v", id, err)
|
||||
// return false, err
|
||||
// }
|
||||
//
|
||||
// return true, nil
|
||||
//}
|
||||
//
|
||||
//// 游戏中离开
|
||||
//func checkGaming(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) {
|
||||
// // 最早的一条掉线记录并且是游戏中掉线
|
||||
// a := &mongomodel.LoginLog{}
|
||||
// c, err := mymongo.GetLogCollection(platform, mongomodel.LogLogin)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("get collection %s error %v", mongomodel.LogLogin, err)
|
||||
// return false, err
|
||||
// }
|
||||
// d := c.FindOne(context.TODO(), bson.M{"snid": id, "logtype": mongomodel.LogTypeDrop, "gameid": bson.D{{"$gt", 0}}},
|
||||
// options.FindOne().SetSort(bson.D{{"time", 1}}))
|
||||
// err = d.Err()
|
||||
// if err != nil {
|
||||
// if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
// logger.Logger.Tracef("checkGaming %v not found in log_login", id)
|
||||
// return false, nil
|
||||
// }
|
||||
// logger.Logger.Errorf("checkGaming %v get log_login err: %v", id, err)
|
||||
// return false, err
|
||||
// }
|
||||
// if err := d.Decode(a); err != nil {
|
||||
// logger.Logger.Errorf("checkGaming %v decode log_login err: %v", id, err)
|
||||
// return false, err
|
||||
// }
|
||||
//
|
||||
// // account tel
|
||||
// tel, err := getAccountTel(platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Warnf("get account tel %v err: %v", id, err)
|
||||
// }
|
||||
//
|
||||
// update := &mysqlmodel.UserLogin{
|
||||
// //OfflineTs: int(a.Ts),
|
||||
// OfflineTime: a.Time,
|
||||
// OutType: mysqlmodel.OutTypeGaming,
|
||||
// GameID: a.GameId,
|
||||
// Tel: tel,
|
||||
// DeviceName: a.DeviceName,
|
||||
// AppVersion: a.AppVersion,
|
||||
// BuildVersion: a.BuildVersion,
|
||||
// AppChannel: a.AppChannel,
|
||||
// ChannelId: a.ChannelId,
|
||||
// }
|
||||
//
|
||||
// if err := db.Model(login).Select(
|
||||
// "OfflineTime", "OutType", "GameID", "DeviceName", "AppVersion", "BuildVersion", "AppChannel", "Tel",
|
||||
// ).Updates(update).Error; err != nil {
|
||||
// logger.Logger.Errorf("checkLogin %v update user_login err: %v", id, err)
|
||||
// return false, err
|
||||
// }
|
||||
//
|
||||
// return true, nil
|
||||
//}
|
||||
//
|
||||
//// 登录后离开
|
||||
//func checkLogin(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) {
|
||||
// // 最早的一条掉线记录
|
||||
// a := &mongomodel.LoginLog{}
|
||||
// c, err := mymongo.GetLogCollection(platform, mongomodel.LogLogin)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("get collection %s error %v", mongomodel.LogLogin, err)
|
||||
// return false, err
|
||||
// }
|
||||
// d := c.FindOne(context.TODO(), bson.M{"snid": id, "logtype": mongomodel.LogTypeDrop}, options.FindOne().SetSort(bson.D{{"time", 1}}))
|
||||
// err = d.Err()
|
||||
// if err != nil {
|
||||
// if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
// logger.Logger.Tracef("checkLogin %v not found in log_login", id)
|
||||
// return false, nil
|
||||
// }
|
||||
// logger.Logger.Errorf("checkLogin %v get log_login err: %v", id, err)
|
||||
// return false, err
|
||||
// }
|
||||
// if err := d.Decode(a); err != nil {
|
||||
// logger.Logger.Errorf("checkLogin %v decode log_login err: %v", id, err)
|
||||
// return false, err
|
||||
// }
|
||||
//
|
||||
// // account tel
|
||||
// tel, err := getAccountTel(platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Warnf("get account tel %v err: %v", id, err)
|
||||
// }
|
||||
//
|
||||
// update := &mysqlmodel.UserLogin{
|
||||
// //OfflineTs: int(a.Ts),
|
||||
// OfflineTime: a.Time,
|
||||
// OutType: mysqlmodel.OutTypeLogin,
|
||||
// Tel: tel,
|
||||
// DeviceName: a.DeviceName,
|
||||
// AppVersion: a.AppVersion,
|
||||
// BuildVersion: a.BuildVersion,
|
||||
// AppChannel: a.AppChannel,
|
||||
// ChannelId: a.ChannelId,
|
||||
// }
|
||||
//
|
||||
// if err := db.Model(login).Select(
|
||||
// "OfflineTime", "OutType", "DeviceName", "AppVersion", "BuildVersion", "AppChannel", "Tel",
|
||||
// ).Updates(update).Error; err != nil {
|
||||
// logger.Logger.Errorf("checkLogin %v update user_login err: %v", id, err)
|
||||
// return false, err
|
||||
// }
|
||||
//
|
||||
// return true, nil
|
||||
//}
|
||||
//
|
||||
//// 注册后离开
|
||||
//func checkRegister(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) {
|
||||
// a := &mongomodel.Account{}
|
||||
// c, err := mymongo.GetUserCollection(platform, mongomodel.UserAccount)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("get collection %s error %v", mongomodel.UserAccount, err)
|
||||
// return false, err
|
||||
// }
|
||||
// d := c.FindOne(context.TODO(), bson.M{"snid": id})
|
||||
// err = d.Err()
|
||||
// if err != nil {
|
||||
// if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
// logger.Logger.Warnf("checkRegister %v not found in user_account", id)
|
||||
// return false, nil
|
||||
// }
|
||||
// logger.Logger.Errorf("checkRegister %v get user_account err: %v", id, err)
|
||||
// return false, err
|
||||
// }
|
||||
// if err := d.Decode(a); err != nil {
|
||||
// logger.Logger.Errorf("checkRegister %v decode user_account err: %v", id, err)
|
||||
// return false, err
|
||||
// }
|
||||
//
|
||||
// // account tel
|
||||
// tel, err := getAccountTel(platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Warnf("get account tel %v err: %v", id, err)
|
||||
// }
|
||||
//
|
||||
// login.Snid = id
|
||||
// //login.OnlineTs = int(a.RegisterTs)
|
||||
// login.OnlineTime = a.RegisteTime
|
||||
// //login.OfflineTs = int(a.RegisterTs)
|
||||
// login.OfflineTime = a.RegisteTime
|
||||
// login.OutType = mysqlmodel.OutTypRegister
|
||||
// login.Tel = tel
|
||||
// login.DeviceName = a.DeviceName
|
||||
// login.AppVersion = a.AppVersion
|
||||
// login.BuildVersion = a.BuildVersion
|
||||
// login.AppChannel = a.AppChannel
|
||||
// login.ChannelId = a.ChannelId
|
||||
//
|
||||
// if err := db.Create(login).Error; err != nil {
|
||||
// logger.Logger.Errorf("checkRegister create err: %v", err)
|
||||
// return false, err
|
||||
// }
|
||||
// return true, nil
|
||||
//}
|
||||
|
||||
// UserLogin 玩家跳出统计
|
||||
func UserLogin(platform string, ids []*mysqlmodel.UserID) error {
|
||||
f := func(id int) error {
|
||||
// 玩家是否已经统计结束,已经是游戏结束状态
|
||||
login := &mysqlmodel.UserLogin{}
|
||||
db, err := mymysql.GetDatabase(platform)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("UserLogin get db err: %v", err)
|
||||
return err
|
||||
}
|
||||
if err = db.Where("snid = ?", id).Find(login).Error; err != nil {
|
||||
logger.Logger.Errorf("UserLogin find %v err: %v", id, err)
|
||||
return err
|
||||
}
|
||||
|
||||
switch login.OutType {
|
||||
case mysqlmodel.OutTypeGameOver:
|
||||
return nil
|
||||
|
||||
case mysqlmodel.OutTypeGaming:
|
||||
_, err := checkGameOver(db, login, platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
case mysqlmodel.OutTypeLogin:
|
||||
ret, err := checkGameOver(db, login, platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err)
|
||||
return err
|
||||
}
|
||||
if ret {
|
||||
return nil
|
||||
}
|
||||
ret, err = checkGaming(db, login, platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("UserLogin checkGaming %v err: %v", id, err)
|
||||
return err
|
||||
}
|
||||
if ret {
|
||||
return nil
|
||||
}
|
||||
|
||||
case mysqlmodel.OutTypRegister:
|
||||
ret, err := checkGameOver(db, login, platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err)
|
||||
return err
|
||||
}
|
||||
if ret {
|
||||
return nil
|
||||
}
|
||||
ret, err = checkGaming(db, login, platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("UserLogin checkGaming %v err: %v", id, err)
|
||||
return err
|
||||
}
|
||||
if ret {
|
||||
return nil
|
||||
}
|
||||
ret, err = checkLogin(db, login, platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("UserLogin checkLogin %v err: %v", id, err)
|
||||
return err
|
||||
}
|
||||
if ret {
|
||||
return nil
|
||||
}
|
||||
|
||||
default:
|
||||
ret, err := checkRegister(db, login, platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("UserLogin checkRegister %v err: %v", id, err)
|
||||
return err
|
||||
}
|
||||
if !ret {
|
||||
logger.Logger.Warnf("UserLogin not found user_account checkRegister %v err: %v", id, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, err = checkGameOver(db, login, platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err)
|
||||
return err
|
||||
}
|
||||
if ret {
|
||||
return nil
|
||||
}
|
||||
ret, err = checkGaming(db, login, platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("UserLogin checkGaming %v err: %v", id, err)
|
||||
return err
|
||||
}
|
||||
if ret {
|
||||
return nil
|
||||
}
|
||||
ret, err = checkLogin(db, login, platform, id)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("UserLogin checkLogin %v err: %v", id, err)
|
||||
return err
|
||||
}
|
||||
if ret {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, v := range ids {
|
||||
if err := f(v.Snid); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
//func UserLogin(platform string, ids []*mysqlmodel.UserID) error {
|
||||
// f := func(id int) error {
|
||||
// // 玩家是否已经统计结束,已经是游戏结束状态
|
||||
// login := &mysqlmodel.UserLogin{}
|
||||
// db, err := mymysql.GetDatabase(platform)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("UserLogin get db err: %v", err)
|
||||
// return err
|
||||
// }
|
||||
// if err = db.Where("snid = ?", id).Find(login).Error; err != nil {
|
||||
// logger.Logger.Errorf("UserLogin find %v err: %v", id, err)
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// switch login.OutType {
|
||||
// case mysqlmodel.OutTypeGameOver:
|
||||
// return nil
|
||||
//
|
||||
// case mysqlmodel.OutTypeGaming:
|
||||
// _, err := checkGameOver(db, login, platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err)
|
||||
// return err
|
||||
// }
|
||||
// return nil
|
||||
//
|
||||
// case mysqlmodel.OutTypeLogin:
|
||||
// ret, err := checkGameOver(db, login, platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err)
|
||||
// return err
|
||||
// }
|
||||
// if ret {
|
||||
// return nil
|
||||
// }
|
||||
// ret, err = checkGaming(db, login, platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("UserLogin checkGaming %v err: %v", id, err)
|
||||
// return err
|
||||
// }
|
||||
// if ret {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// case mysqlmodel.OutTypRegister:
|
||||
// ret, err := checkGameOver(db, login, platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err)
|
||||
// return err
|
||||
// }
|
||||
// if ret {
|
||||
// return nil
|
||||
// }
|
||||
// ret, err = checkGaming(db, login, platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("UserLogin checkGaming %v err: %v", id, err)
|
||||
// return err
|
||||
// }
|
||||
// if ret {
|
||||
// return nil
|
||||
// }
|
||||
// ret, err = checkLogin(db, login, platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("UserLogin checkLogin %v err: %v", id, err)
|
||||
// return err
|
||||
// }
|
||||
// if ret {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// default:
|
||||
// ret, err := checkRegister(db, login, platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("UserLogin checkRegister %v err: %v", id, err)
|
||||
// return err
|
||||
// }
|
||||
// if !ret {
|
||||
// logger.Logger.Warnf("UserLogin not found user_account checkRegister %v err: %v", id, err)
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// ret, err = checkGameOver(db, login, platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err)
|
||||
// return err
|
||||
// }
|
||||
// if ret {
|
||||
// return nil
|
||||
// }
|
||||
// ret, err = checkGaming(db, login, platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("UserLogin checkGaming %v err: %v", id, err)
|
||||
// return err
|
||||
// }
|
||||
// if ret {
|
||||
// return nil
|
||||
// }
|
||||
// ret, err = checkLogin(db, login, platform, id)
|
||||
// if err != nil {
|
||||
// logger.Logger.Errorf("UserLogin checkLogin %v err: %v", id, err)
|
||||
// return err
|
||||
// }
|
||||
// if ret {
|
||||
// return nil
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// for _, v := range ids {
|
||||
// if err := f(v.Snid); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return nil
|
||||
//}
|
||||
|
|
|
@ -9,12 +9,12 @@ import (
|
|||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"gorm.io/gorm"
|
||||
|
||||
mongomodel "mongo.games.com/game/statistics/modelmongo"
|
||||
mysqlmodel "mongo.games.com/game/statistics/modelmysql"
|
||||
"mongo.games.com/goserver/core/logger"
|
||||
mymongo "mongo.games.com/goserver/core/mongox"
|
||||
mymysql "mongo.games.com/goserver/core/mysqlx"
|
||||
|
||||
mongomodel "mongo.games.com/game/statistics/modelmongo"
|
||||
mysqlmodel "mongo.games.com/game/statistics/modelmysql"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -155,19 +155,19 @@ func LogLogin(platform string, batchSize int) ([]*mysqlmodel.LogLogin, error) {
|
|||
return err
|
||||
}
|
||||
|
||||
for _, v := range ls {
|
||||
if err = tx.First(&mysqlmodel.UserID{}, "snid = ?", v.Snid).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
logger.Logger.Errorf("mysql: SyncLogLogin failed to find user_id: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
if err = tx.Create(&mysqlmodel.UserID{Snid: v.Snid}).Error; err != nil {
|
||||
logger.Logger.Errorf("mysql: SyncLogLogin failed to create user_id: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
//for _, v := range ls {
|
||||
// if err = tx.First(&mysqlmodel.UserID{}, "snid = ?", v.Snid).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// logger.Logger.Errorf("mysql: SyncLogLogin failed to find user_id: %v", err)
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// if err = tx.Create(&mysqlmodel.UserID{Snid: v.Snid}).Error; err != nil {
|
||||
// logger.Logger.Errorf("mysql: SyncLogLogin failed to create user_id: %v", err)
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
游戏服mongodb同步到mysql
|
||||
|
||||
datasync.go 同步模型
|
|
@ -1,17 +1,18 @@
|
|||
StartTime: "2024-11-26T00:00:00+08:00"
|
||||
EndTime: "2024-11-27T00:00:00+08:00"
|
||||
StartTime: "2024-12-19T00:00:00+08:00"
|
||||
EndTime: "2024-12-20T00:00:00+08:00"
|
||||
|
||||
Switch: # 1: open, 0: close
|
||||
- 0 # 新用户游戏破产率
|
||||
- 0 # 新用户平均游戏时长
|
||||
- 1 # 用户平均游戏时长
|
||||
- 0 # 新用户平均局数
|
||||
- 0 # 平均倍数
|
||||
- 1 # 活跃破产率
|
||||
- 1 # 控输赢胜率
|
||||
- 1 # 机器人胜率
|
||||
- 1 # 人均获得金币
|
||||
- 1 # 破产后离线
|
||||
- 1 # 充值玩家金币余额
|
||||
- 0 # 活跃破产率
|
||||
- 0 # 控输赢胜率
|
||||
- 0 # 机器人胜率
|
||||
- 0 # 人均获得金币
|
||||
- 0 # 破产后离线
|
||||
- 0 # 充值玩家金币余额
|
||||
|
||||
Gamefreeids:
|
||||
- 2070001
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
const (
|
||||
ExcelTypeNewPlayerBankrupt = iota // 新用户游戏破产率
|
||||
ExcelTypeGameTimeAvg // 新用户平均游戏时长
|
||||
ExcelTypeGameTimeAllAvg // 用户平均游戏时长
|
||||
ExcelTypeGameCountAvg // 新用户平均局数
|
||||
ExcelTypeGameRate // 平均倍数
|
||||
ExcelTypeActiveRate // 活跃破产率
|
||||
|
@ -71,6 +72,7 @@ func main() {
|
|||
mgr := NewExcelMgr()
|
||||
mgr.Register(ExcelTypeNewPlayerBankrupt, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"})
|
||||
mgr.Register(ExcelTypeGameTimeAvg, []string{"日期", "场次id", "参与人数", "平均游戏时长"})
|
||||
mgr.Register(ExcelTypeGameTimeAllAvg, []string{"日期", "场次id", "参与人数", "平均游戏时长"})
|
||||
mgr.Register(ExcelTypeGameCountAvg, []string{"日期", "场次id", "参与人数", "平均局数"})
|
||||
mgr.Register(ExcelTypeGameRate, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"})
|
||||
mgr.Register(ExcelTypeActiveRate, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"})
|
||||
|
@ -99,6 +101,10 @@ func main() {
|
|||
// 新用户平均游戏时长
|
||||
mgr.GenNewPlayerGameTimeAvgExcel("1", startTimeStr, endTimeStr)
|
||||
}
|
||||
if switchArr[ExcelTypeGameTimeAllAvg] == 1 {
|
||||
// 用户平均游戏时长
|
||||
mgr.GenPlayerGameTimeAvgExcel("1", startTimeStr, endTimeStr)
|
||||
}
|
||||
if switchArr[ExcelTypeGameCountAvg] == 1 {
|
||||
// 新用户平均局数
|
||||
mgr.GenGameCountExcel("1", startTimeStr, endTimeStr)
|
||||
|
@ -144,7 +150,10 @@ func (e *ExcelMgr) SaveAll(startTime, endTime string) {
|
|||
e.Save(ExcelTypeNewPlayerBankrupt, fmt.Sprintf("新用户破产率_%s_%s.xlsx", startTime, endTime))
|
||||
}
|
||||
if switchArr[ExcelTypeGameTimeAvg] == 1 {
|
||||
e.Save(ExcelTypeGameTimeAvg, fmt.Sprintf("新用户平局游戏时长_%s_%s.xlsx", startTime, endTime))
|
||||
e.Save(ExcelTypeGameTimeAvg, fmt.Sprintf("新用户平均游戏时长_%s_%s.xlsx", startTime, endTime))
|
||||
}
|
||||
if switchArr[ExcelTypeGameTimeAllAvg] == 1 {
|
||||
e.Save(ExcelTypeGameTimeAllAvg, fmt.Sprintf("用户平均游戏时长_%s_%s.xlsx", startTime, endTime))
|
||||
}
|
||||
if switchArr[ExcelTypeGameCountAvg] == 1 {
|
||||
e.Save(ExcelTypeGameCountAvg, fmt.Sprintf("新用户平均局数_%s_%s.xlsx", startTime, endTime))
|
||||
|
@ -223,6 +232,29 @@ func (e *ExcelMgr) GenNewPlayerGameTimeAvgExcel(plt string, startTime, endTime s
|
|||
}
|
||||
}
|
||||
|
||||
func (e *ExcelMgr) GenPlayerGameTimeAvgExcel(plt string, startTime, endTime string) {
|
||||
for _, v := range VP.GetIntSlice("Gamefreeids") {
|
||||
a, b, err := task.PlayerGameTimeAvg(plt, startTime, endTime, v)
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("PlayerGameTimeAvg get StartTime:%v EndTime:%v GameFreeId:%v err: %v", startTime, endTime, v, err)
|
||||
continue
|
||||
}
|
||||
ex := e.Get(ExcelTypeGameTimeAllAvg)
|
||||
ex.NewLine()
|
||||
ex.SetCell(startTime[:10])
|
||||
ex.SetCell(GetGameFreeName(v))
|
||||
ex.SetCell(a)
|
||||
if a > 0 {
|
||||
avg := float64(b) / float64(a)
|
||||
show := fmt.Sprintf("%v", time.Second*time.Duration(avg))
|
||||
ex.SetCell(show)
|
||||
} else {
|
||||
ex.SetCell(0)
|
||||
}
|
||||
logger.Logger.Tracef("PlayerGameTimeAvg GameFreeId: %v avg: %v", v, float64(b)/float64(a))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *ExcelMgr) GenGameCountExcel(plt string, startTime, endTime string) {
|
||||
for _, v := range VP.GetIntSlice("Gamefreeids") {
|
||||
a, b, err := task.NewPlayerGameCountAvg(plt, startTime, endTime, v)
|
||||
|
|
|
@ -45,6 +45,37 @@ func GetNewPayerIds(plt string, startTime, endTime string) ([]int, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func GetPayerIds(plt string, startTime, endTime string, gamefreeid int) ([]int, error) {
|
||||
s, e := common.StrRFC3339TimeToTime(startTime), common.StrRFC3339TimeToTime(endTime)
|
||||
c, err := mymongo.GetLogCollection(plt, mongomodel.LogGamePlayerListLog)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var res []struct{ Snid int }
|
||||
dd, err := c.Aggregate(context.TODO(), bson.A{
|
||||
bson.M{"$match": bson.M{"time": bson.M{"$gte": s, "$lt": e}, "gamefreeid": gamefreeid}},
|
||||
bson.M{"$group": bson.M{"_id": "$snid", "snid": bson.M{"$first": "$snid"}}},
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
return nil, nil
|
||||
}
|
||||
logger.Logger.Errorf("find game player snid get err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
if err := dd.All(context.TODO(), &res); err != nil {
|
||||
logger.Logger.Errorf("find game player snid decode err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
var ret []int
|
||||
for _, v := range res {
|
||||
ret = append(ret, v.Snid)
|
||||
}
|
||||
logger.Logger.Tracef("find game player snid: %v", ret)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// 场次破产总人数
|
||||
func GameFreeIdBankruptPlayerCount(plt string, ids []int, startTime, endTime string, gamefreeid int) (int, error) {
|
||||
s, e := common.StrRFC3339TimeToTime(startTime), common.StrRFC3339TimeToTime(endTime)
|
||||
|
|
|
@ -36,7 +36,10 @@ func NewPlayerGameTime(plt string, ids []int, startTime, endTime string, gamefre
|
|||
if gamefreeid > 0 {
|
||||
where["gamefreeid"] = gamefreeid
|
||||
}
|
||||
cur, err := c.Find(context.TODO(), where, options.Find().SetProjection(bson.M{"gamedetailedlogid": 1}))
|
||||
cur, err := c.Aggregate(context.Background(), bson.A{
|
||||
bson.M{"$match": where},
|
||||
bson.M{"$group": bson.M{"_id": "$gamedetailedlogid", "gamedetailedlogid": bson.M{"$first": "$gamedetailedlogid"}}},
|
||||
})
|
||||
if err != nil {
|
||||
logger.Logger.Errorf("find player gamedetailedlogid get err: %v", err)
|
||||
return 0, 0, err
|
||||
|
@ -102,3 +105,26 @@ func NewPlayerGameTimeAvg(plt string, startTime, endTime string, gamefreeid int)
|
|||
}
|
||||
return b, a, err
|
||||
}
|
||||
|
||||
func PlayerGameTimeAvg(plt string, startTime, endTime string, gamefreeid int) (int, int, error) {
|
||||
s, e := common.StrRFC3339TimeToTime(startTime), common.StrRFC3339TimeToTime(endTime)
|
||||
if s.IsZero() || e.IsZero() {
|
||||
return 0, 0, fmt.Errorf("time format error")
|
||||
}
|
||||
ids, err := GetPayerIds(plt, startTime, endTime, gamefreeid)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return 0, 0, nil
|
||||
}
|
||||
a, _, err := NewPlayerGameTime(plt, ids, startTime, endTime, gamefreeid)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return 0, 0, nil
|
||||
}
|
||||
|
||||
return len(ids), a, err
|
||||
}
|
||||
|
|
|
@ -180,6 +180,11 @@ func (this *CSEnterRoomHandler) Process(s *netlib.Session, packetid int, data in
|
|||
p.matchCtx = mc
|
||||
}
|
||||
}
|
||||
if scene.IsCustom() {
|
||||
if scene.CustomParam.GetCostType() == 1 {
|
||||
sp.CostPayment(scene, p.SnId)
|
||||
}
|
||||
}
|
||||
|
||||
if !scene.PlayerEnter(p, -1, true) {
|
||||
code = gamehall.OpResultCode_Game_OPRC_Error_Game
|
||||
|
@ -1342,15 +1347,13 @@ func CSCreatePrivateRoomHandler(s *netlib.Session, packetId int, data interface{
|
|||
|
||||
csp.AddScene(scene)
|
||||
|
||||
sp.CostPayment(scene, p.SnId)
|
||||
|
||||
if !scene.PlayerEnter(p, -1, true) {
|
||||
send()
|
||||
return nil
|
||||
}
|
||||
|
||||
if costType == 2 {
|
||||
sp.CostPayment(scene, p.SnId)
|
||||
}
|
||||
|
||||
code = gamehall.OpResultCode_Game_OPRC_Sucess_Game
|
||||
pack = &gamehall.SCCreatePrivateRoom{
|
||||
GameFreeId: msg.GetGameFreeId(),
|
||||
|
|
|
@ -134,7 +134,8 @@ func init() {
|
|||
CostCoin := p.takeCoin - msg.GetReturnCoin()
|
||||
|
||||
logger.Logger.Infof("NewBankruptLogEx: snid:%v GetReturnCoin:%v coin:%v CostCoin:%v", p.SnId, msg.GetReturnCoin(), p.takeCoin, CostCoin)
|
||||
log := model.NewBankruptLogEx(p.SnId, scene.dbGameFree.GetId(), p.CreateTime.Unix(), CostCoin, p.Platform, p.Channel, scene.gameId)
|
||||
log := model.NewBankruptLogEx(p.SnId, scene.dbGameFree.GetId(), p.CreateTime.Unix(), CostCoin,
|
||||
p.Platform, p.Channel, p.ChannelId, scene.dbGameFree.GetGameDif(), scene.gameId)
|
||||
if log != nil {
|
||||
mq.Write(log)
|
||||
}
|
||||
|
|
|
@ -324,8 +324,6 @@ func (this *Player) OnLogined() {
|
|||
|
||||
this.DealShopLog()
|
||||
|
||||
PlayerOnlineSington.Check = true
|
||||
|
||||
this.LoadMessage(tLastLogout.Unix(), isFirstLogin, !inSameWeek)
|
||||
|
||||
//登录次数
|
||||
|
@ -401,7 +399,6 @@ func (this *Player) OnRehold() {
|
|||
if !this.IsRob {
|
||||
TournamentMgr.Quit(this.Platform, this.SnId) // 比赛没有开始,退赛
|
||||
this.SendJackPotInit()
|
||||
PlayerOnlineSington.Check = true
|
||||
|
||||
this.DealShopLog()
|
||||
|
||||
|
@ -1188,7 +1185,6 @@ func (this *Player) DropLine() {
|
|||
|
||||
this.SendPlayerCoin()
|
||||
this.OnlineLogDrop()
|
||||
PlayerOnlineSington.Check = true
|
||||
}
|
||||
|
||||
if this.scene != nil && this.scene.gameSess != nil {
|
||||
|
@ -1222,7 +1218,6 @@ func (this *Player) OnLogoutFinish() {
|
|||
|
||||
if !this.IsRobot() {
|
||||
FriendUnreadMgrSington.SaveFriendUnreadData(this.Platform, this.SnId)
|
||||
PlayerOnlineSington.Check = true
|
||||
|
||||
//登录日志
|
||||
logState := LoginStateMgrSington.GetLoginStateBySid(this.sid)
|
||||
|
@ -1265,6 +1260,7 @@ func (this *Player) UnmarshalData(data []byte, scene *Scene) {
|
|||
strconv.Itoa(int(scene.dbGameFree.GetGameId())),
|
||||
common.GetKeyNoviceGameId(int(scene.dbGameFree.GetGameId())),
|
||||
common.GetKeyGameType(int(scene.dbGameFree.GetGameType())),
|
||||
common.GetKeyGameDif(scene.dbGameFree.GetGameDif()),
|
||||
} {
|
||||
if d, ok := pd.GDatas[v]; ok {
|
||||
this.GDatas[v] = d
|
||||
|
|
|
@ -8,8 +8,40 @@ import (
|
|||
"mongo.games.com/game/common"
|
||||
"mongo.games.com/game/model"
|
||||
"mongo.games.com/game/mq"
|
||||
"mongo.games.com/game/worldsrv/internal"
|
||||
)
|
||||
|
||||
func init() {
|
||||
module.RegisteModule(PlayerOnlineSington, 5*time.Second, 0)
|
||||
|
||||
internal.RegisterPlayerListenerFunc(&internal.PlayerListenerFunc[*Player, *Scene]{
|
||||
OnPlayerLoginedFunc: func(p *Player) {
|
||||
if p == nil || p.IsRob {
|
||||
return
|
||||
}
|
||||
PlayerOnlineSington.Check = true
|
||||
},
|
||||
OnPlayerLogoutedFunc: func(p *Player) {
|
||||
if p == nil || p.IsRob {
|
||||
return
|
||||
}
|
||||
PlayerOnlineSington.Check = true
|
||||
},
|
||||
OnPlayerDropLineFunc: func(p *Player) {
|
||||
if p == nil || p.IsRob {
|
||||
return
|
||||
}
|
||||
PlayerOnlineSington.Check = true
|
||||
},
|
||||
OnPlayerReholdFunc: func(p *Player) {
|
||||
if p == nil || p.IsRob {
|
||||
return
|
||||
}
|
||||
PlayerOnlineSington.Check = true
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
var PlayerOnlineSington = &PlayerOnlineEvent{
|
||||
OnlineCh: make(map[string]map[string]int),
|
||||
}
|
||||
|
@ -66,7 +98,3 @@ here:
|
|||
func (p *PlayerOnlineEvent) Shutdown() {
|
||||
module.UnregisteModule(p)
|
||||
}
|
||||
|
||||
func init() {
|
||||
module.RegisteModule(PlayerOnlineSington, 5*time.Second, 0)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"golang.org/x/exp/maps"
|
||||
"mongo.games.com/goserver/core/logger"
|
||||
"mongo.games.com/goserver/core/module"
|
||||
|
||||
"mongo.games.com/game/common"
|
||||
"mongo.games.com/game/model"
|
||||
"mongo.games.com/game/mq"
|
||||
"mongo.games.com/game/worldsrv/internal"
|
||||
)
|
||||
|
||||
func init() {
|
||||
module.RegisteModule(PlayerOnlineGameSingleton, 10*time.Second, 0)
|
||||
|
||||
internal.RegisterPlayerListenerFunc(&internal.PlayerListenerFunc[*Player, *Scene]{
|
||||
OnPlayerEnterSceneAfterFunc: func(p *Player, s *Scene) {
|
||||
if p == nil || p.IsRob {
|
||||
return
|
||||
}
|
||||
PlayerOnlineGameSingleton.Check = true
|
||||
},
|
||||
OnPlayerLeaveSceneAfterFunc: func(p *Player, s *Scene) {
|
||||
if p == nil || p.IsRob {
|
||||
return
|
||||
}
|
||||
PlayerOnlineGameSingleton.Check = true
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
var PlayerOnlineGameSingleton = &PlayerOnlineGameEvent{
|
||||
Online: make(map[string]map[string]map[string]map[int]map[int]int),
|
||||
}
|
||||
|
||||
type PlayerOnlineGameEvent struct {
|
||||
Online map[string]map[string]map[string]map[int]map[int]int // 平台:推广渠道:游戏组:游戏id:场次id:在线人数
|
||||
Check bool
|
||||
}
|
||||
|
||||
func (p *PlayerOnlineGameEvent) ModuleName() string {
|
||||
return "PlayerOnlineGameEvent"
|
||||
}
|
||||
|
||||
func (p *PlayerOnlineGameEvent) Init() {
|
||||
}
|
||||
|
||||
func (p *PlayerOnlineGameEvent) Update() {
|
||||
if !p.Check {
|
||||
return
|
||||
}
|
||||
p.Check = false
|
||||
|
||||
onlineCh := make(map[string]map[string]map[string]map[int]map[int]int)
|
||||
|
||||
for _, v := range SceneMgrSingleton.scenes {
|
||||
if v == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
plt := SceneMgrSingleton.GetPlatformBySceneId(v.sceneId)
|
||||
// 平台
|
||||
if _, ok := onlineCh[plt]; !ok {
|
||||
onlineCh[plt] = map[string]map[string]map[int]map[int]int{}
|
||||
}
|
||||
|
||||
for _, player := range v.players {
|
||||
if player == nil || player.IsRob || player.Platform == common.Platform_Rob && player.Channel == common.Channel_Rob {
|
||||
continue
|
||||
}
|
||||
|
||||
// 渠道
|
||||
if _, ok := onlineCh[plt][player.ChannelId]; !ok {
|
||||
onlineCh[plt][player.ChannelId] = map[string]map[int]map[int]int{}
|
||||
}
|
||||
// 游戏组
|
||||
if _, ok := onlineCh[plt][player.ChannelId][v.dbGameFree.GetGameDif()]; !ok {
|
||||
onlineCh[plt][player.ChannelId][v.dbGameFree.GetGameDif()] = map[int]map[int]int{}
|
||||
}
|
||||
// 游戏id
|
||||
if _, ok := onlineCh[plt][player.ChannelId][v.dbGameFree.GetGameDif()][int(v.dbGameFree.GetGameId())]; !ok {
|
||||
onlineCh[plt][player.ChannelId][v.dbGameFree.GetGameDif()][int(v.dbGameFree.GetGameId())] = map[int]int{}
|
||||
}
|
||||
onlineCh[plt][player.ChannelId][v.dbGameFree.GetGameDif()][int(v.dbGameFree.GetGameId())][int(v.dbGameFree.GetId())] += 1
|
||||
}
|
||||
}
|
||||
|
||||
// 判断差异
|
||||
if !slices.Equal(maps.Keys(p.Online), maps.Keys(onlineCh)) {
|
||||
goto here
|
||||
}
|
||||
for k, v := range p.Online {
|
||||
if !slices.Equal(maps.Keys(v), maps.Keys(onlineCh[k])) {
|
||||
goto here
|
||||
}
|
||||
for k1, v1 := range v {
|
||||
if !slices.Equal(maps.Keys(v1), maps.Keys(onlineCh[k][k1])) {
|
||||
goto here
|
||||
}
|
||||
for k2, v2 := range v1 {
|
||||
if !slices.Equal(maps.Keys(v2), maps.Keys(onlineCh[k][k1][k2])) {
|
||||
goto here
|
||||
}
|
||||
for k3, v3 := range v2 {
|
||||
if !slices.Equal(maps.Keys(v3), maps.Keys(onlineCh[k][k1][k2][k3])) {
|
||||
goto here
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
here:
|
||||
p.Online = onlineCh
|
||||
mq.Write(model.GenerateOnlineGame(p.Online))
|
||||
logger.Logger.Trace("PlayerOnlineGameEvent", p.Online)
|
||||
}
|
||||
|
||||
func (p *PlayerOnlineGameEvent) Shutdown() {
|
||||
module.UnregisteModule(p)
|
||||
}
|
|
@ -162,6 +162,10 @@ func NewScene(args *CreateSceneParam) *Scene {
|
|||
return s
|
||||
}
|
||||
|
||||
func (this *Scene) GetPlatform() *Platform {
|
||||
return this.platform
|
||||
}
|
||||
|
||||
func (this *Scene) RobotIsLimit() bool {
|
||||
if this.robotLimit != 0 {
|
||||
if this.robotNum >= this.robotLimit {
|
||||
|
|
|
@ -57,11 +57,6 @@ func (spd *ScenePolicyData) OnTick(s *Scene) {
|
|||
|
||||
func (spd *ScenePolicyData) OnPlayerEnter(s *Scene, snid int32) {
|
||||
s.NotifyPrivateRoom(common.ListModify)
|
||||
if s.IsCustom() {
|
||||
if s.CustomParam.GetCostType() == 1 { // AA
|
||||
spd.CostPayment(s, snid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (spd *ScenePolicyData) OnPlayerLeave(s *Scene, snid int32) {
|
||||
|
|
|
@ -2257,11 +2257,13 @@ func init() {
|
|||
|
||||
state = msg.GetState()
|
||||
player := PlayerMgrSington.GetPlayerBySnId(info.SnId)
|
||||
if player == nil {
|
||||
logger.Logger.Info("CallbackPayment player", player)
|
||||
if player == nil || (player != nil && player.IsOffline()) {
|
||||
if msg.State == 1 {
|
||||
state = 3
|
||||
}
|
||||
}
|
||||
logger.Logger.Info("------------CallbackPayment state----------", state)
|
||||
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
|
||||
err := model.UpdateDbShopState(msg.Platform, msg.OrderId, state)
|
||||
if err != nil {
|
||||
|
@ -2274,7 +2276,7 @@ func init() {
|
|||
retFail("购买记录状态修改失败")
|
||||
return
|
||||
}
|
||||
if player != nil {
|
||||
if player != nil || (player != nil && player.IsOffline()) {
|
||||
player.DoShopInfo(info, false)
|
||||
// 邀请积分
|
||||
InviteTask(msg.Platform, player.PSnId, info.SnId, common.InviteScoreTypePay, int64(info.ConsumeNum))
|
||||
|
|
Loading…
Reference in New Issue