Compare commits

...

92 Commits

Author SHA1 Message Date
sk d8bee4bd73 update excel 2024-12-27 11:03:39 +08:00
sk 1d0ce09952 update ci 2024-12-27 11:00:54 +08:00
sk caee9f1aff Merge branch 'release' into develop 2024-12-27 09:01:42 +08:00
skeleton ae3622c587 更新.gitlab-ci.yml文件 2024-12-26 10:06:27 +00:00
sk 5368460ad3 add 各游戏破产金额 2024-12-26 11:01:17 +08:00
sk 0cc66a8b28 statistics文件下载 2024-12-26 08:26:00 +08:00
sk 82887c39c1 update excel 2024-12-26 08:25:12 +08:00
sk 6d1fe0c89b add 数据统计到mysql 2024-12-25 13:57:19 +08:00
sk 70f8ef26e0 modify 允许游戏中顶号 2024-12-25 09:51:18 +08:00
sk fe3f0a185d fix tienlen过牌 2024-12-25 09:27:41 +08:00
sk 6804bf6641 Merge branch 'develop' of git.pogorockgames.com:mango-games/server/game into develop 2024-12-24 17:12:35 +08:00
sk 51767e9c6a no message 2024-12-24 10:47:36 +08:00
tomas f15ce4ef8f Merge branch 'develop' of https://git.pogorockgames.com/mango-games/server/game into develop 2024-12-23 13:23:41 +08:00
tomas 4b8093d09e Merge remote-tracking branch 'origin/develop' into dev_slots 2024-12-23 13:22:33 +08:00
tomas 9ef70ecc23 up pe rabbit 2024-12-23 13:12:58 +08:00
sk 292a5ea563 解决冲突 2024-12-23 11:29:59 +08:00
sk daa13d58e1 modify 比赛日志 2024-12-23 09:14:49 +08:00
sk 68f51d0c5d add 拉霸游戏时长 2024-12-21 16:45:25 +08:00
sk 142b2f0ba5 no message 2024-12-21 15:21:26 +08:00
sk 696267d954 Merge branch 'develop' of git.pogorockgames.com:mango-games/server/game into develop 2024-12-21 11:48:32 +08:00
sk bbe6c99209 modify 在线玩家列表 2024-12-21 11:47:30 +08:00
tomas 71bc527f96 del free betlimit 2024-12-21 10:12:16 +08:00
sk 1235383c87 no message 2024-12-21 09:46:34 +08:00
sk 8177397b26 add 统计十三张自动手动摆牌时间 2024-12-21 09:13:01 +08:00
sk 694e8a5992 modify 十三张手动摆牌 2024-12-21 09:05:08 +08:00
sk b186967189 add 十三张记录分别自动手动摆牌时长 2024-12-20 16:09:26 +08:00
sk d82c5ed055 modify mq 2024-12-20 10:43:12 +08:00
sk e044a590d4 Merge branch 'develop' of git.pogorockgames.com:mango-games/server/game into develop 2024-12-20 09:21:40 +08:00
sk 39890efbfa add:破产记录添加游戏组id 2024-12-20 09:21:24 +08:00
by 09a609b1b3 Merge branch 'develop' of https://git.pogorockgames.com/mango-games/server/game into develop 2024-12-19 18:03:03 +08:00
by e2095d6878 后台补单 2024-12-19 18:02:51 +08:00
sk bb8af52a6b modify:平均游戏时长查询优化 2024-12-19 17:52:33 +08:00
sk 08023bcdea fix:游戏分组统计数据 2024-12-19 17:50:49 +08:00
sk 893bc4cbbb modify:房费扣除 2024-12-19 17:23:46 +08:00
sk a9efaed491 fix:tienlen调试发牌修改 2024-12-19 14:40:00 +08:00
sk 88b4c08740 fix:tienlen调试发牌修改 2024-12-19 14:36:42 +08:00
sk 167e1e9c10 add:tienlen调试发牌修改 2024-12-19 14:07:18 +08:00
sk 1ed0d5b4d7 Merge branch 'develop' of git.pogorockgames.com:mango-games/server/game into develop 2024-12-19 13:47:49 +08:00
sk 7a7baa9568 modify:十三张牌型预选
支持清空预选
空位随机补牌
2024-12-19 13:47:29 +08:00
sk 30d3ba1cc0 add:查询平均游戏时长 2024-12-19 11:48:56 +08:00
by 9b59039d4b 后台补单 2024-12-18 09:31:49 +08:00
by 7d0d5e9509 后台补单log 2024-12-18 09:19:57 +08:00
sk 93792b3e38 add:添加日志 2024-12-17 14:25:11 +08:00
sk f4964a57a2 fix:统计游戏组数据 2024-12-17 14:12:52 +08:00
sk 0c65af22ea add:对局中玩家人数上报 2024-12-17 13:29:50 +08:00
sk 1f24dd29b6 no message 2024-12-17 10:35:21 +08:00
sk 4b29c43709 modify:.gitignore 2024-12-17 10:34:55 +08:00
sk 4e59c6600c 道具记录记录gamedif 2024-12-16 17:51:21 +08:00
sk 442801fc9a 游戏记录添加游戏组首次游戏时间和游戏次数 2024-12-16 16:33:41 +08:00
sk 490576b1dc 游戏记录添加gamedif 2024-12-16 15:47:26 +08:00
sk 2c48adeca7 Merge branch 'develop' into sk 2024-12-16 15:33:06 +08:00
sk bcbc162549 解决冲突 2024-12-16 11:17:11 +08:00
by 4d65851083 后台补单BUG修改 2024-12-16 10:16:55 +08:00
by 8b40eb3c49 后台补单BUG修改 2024-12-16 10:10:45 +08:00
by d791c4d02c 后台补单BUG修改 2024-12-16 10:03:36 +08:00
by d6bfa73d70 充值增加log 2024-12-13 17:55:37 +08:00
by a4ebed8fc9 充值增加log 2024-12-13 17:54:41 +08:00
by db24cf0620 充值增加log 2024-12-13 17:53:13 +08:00
by 7d6ee4c3bd 充值增加log 2024-12-13 17:51:59 +08:00
by 5c64d97728 报错修改 2024-12-13 17:42:45 +08:00
sk 5ca1048b18 Merge branch 'release' into develop 2024-12-13 11:16:09 +08:00
sk cab63a8bf9 add:游戏记录上报数据添加唯一id 2024-12-12 16:08:22 +08:00
sk 500fed59dd modify:游戏记录上报 2024-12-12 16:03:11 +08:00
sk bf636de73a fix:机器人离场金币 2024-12-12 09:34:13 +08:00
sk 95650519e8 fix:etcd配置 2024-12-12 08:43:43 +08:00
sk 8021f554f2 Merge branch 'release' into develop 2024-12-12 08:42:06 +08:00
tomas d672b91174 fix totalbet mouse tiger 2024-12-11 11:15:03 +08:00
tomas d6989f42ea Merge branch 'dev_slots' into develop 2024-12-10 20:43:26 +08:00
tomas 684d05642e fix idx 2024-12-10 20:42:55 +08:00
tomas 72b287ebfa fix index 2024-12-10 20:40:50 +08:00
sk 3104e68bb9 Merge branch 'release' into develop 2024-12-10 15:20:21 +08:00
sk 43c3d3571b Merge branch 'develop' into sk 2024-12-10 10:40:27 +08:00
sk 779d8a64a4 拉霸缓存游戏记录 2024-12-09 16:51:53 +08:00
sk ccd3481b06 Merge branch 'develop' of git.pogorockgames.com:mango-games/server/game into develop 2024-12-09 13:12:35 +08:00
sk c8b7647695 Merge branch 'sk' into develop 2024-12-09 13:11:57 +08:00
sk b342e0ad61 十三张手动摆牌不算特殊牌型 2024-12-09 11:56:46 +08:00
by 4671d33f67 娃娃机调整 2024-12-09 10:30:37 +08:00
sk 886bf444c3 十三张花色比牌添加单元测试 2024-12-09 09:55:15 +08:00
sk 945bf3c829 Merge branch 'develop' of git.pogorockgames.com:mango-games/server/game into develop 2024-12-07 18:06:00 +08:00
sk ea41d7f379 十三张调试发牌 2024-12-07 18:05:37 +08:00
DESKTOP-45ANQ2C\unis 2f8123333c Merge branch 'develop' of git.pogorockgames.com:mango-games/server/game into develop 2024-12-07 17:19:52 +08:00
DESKTOP-45ANQ2C\unis 51b946bc0b 十三水测试牌型比率 2024-12-07 17:18:25 +08:00
sk 690a5f1a08 十三张比牌包含花色 2024-12-07 17:09:19 +08:00
sk 52b4994de3 修改十三张全垒打分数 2024-12-07 10:20:06 +08:00
sk 766d30d7ca Merge branch 'develop' into sk 2024-12-06 17:07:45 +08:00
sk 4fc2019770 update statistics 2024-12-06 10:15:17 +08:00
sk 6923ed95f1 系统赠送记录破产补助 2024-12-06 09:59:10 +08:00
sk 027b4caf81 Merge branch 'dev_slots' into develop 2024-12-05 13:46:25 +08:00
sk 2ea5226a14 no message 2024-12-04 17:40:39 +08:00
DESKTOP-45ANQ2C\unis 86bbeb8c9b Merge branch 'develop' of git.pogorockgames.com:mango-games/server/game into develop 2024-11-29 13:55:09 +08:00
DESKTOP-45ANQ2C\unis 1c800d794f Merge branch 'develop' of git.pogorockgames.com:mango-games/server/game into develop 2024-11-26 17:20:45 +08:00
DESKTOP-45ANQ2C\unis 70ddc7e6b2 道具表格更新 2024-11-25 11:39:42 +08:00
114 changed files with 4370 additions and 10254 deletions

4
.gitignore vendored
View File

@ -46,4 +46,6 @@ tools/xlsx2binary/agc.go
/robot/robot
/ranksrv/ranksrv
/schedulesrv/schedulesrv
/machine/machine
/machine/machine
/statistics/statistics
/statistics/task/task*

View File

@ -1,12 +1,12 @@
stages:
- lock
- build
- save
- sync
- unlock
variables:
ProjectPath: "mongo.games.com/game" # 项目相对于GOPATH的路径
GOPROXY: "https://goproxy.cn,direct"
GOPATH: "/home/gopath"
GoServerSrcPath: "mongo.games.com/goserver" # 项目相对于GOPATH/src的路径
BetaBinPath: "/home/game/" # beta环境部署路径
DevelopBinPath: "/home/game/" # develop环境部署路径
@ -25,12 +25,12 @@ lock_job:
stage: lock
script:
- |
if [ -f /tmp/ci_lock ]; then
echo "流水线已在运行,等待..."
if [ -f /tmp/ci_lock_$CI_COMMIT_REF_NAME ]; then
echo "流水线($CI_COMMIT_REF_NAME)已在运行,等待..."
exit 1
else
touch /tmp/ci_lock
echo "获得锁定,开始流水线。"
touch /tmp/ci_lock_$CI_COMMIT_REF_NAME
echo "获得锁定,开始流水线($CI_COMMIT_REF_NAME)。"
fi
build-job:
@ -39,20 +39,21 @@ build-job:
- develop
- release
script:
# 拉取代码
- git checkout $CI_COMMIT_REF_NAME
- git pull origin $CI_COMMIT_REF_NAME
# 替换 go.mod 中的 ../goserver
- sed -i "s|mongo.games.com/goserver => .*|mongo.games.com/goserver => $GOPATH/src/$GoServerSrcPath|" go.mod
- if [ ! -z "$(git status --porcelain go.mod go.sum)" ]; then
GOMODTIDY=1;
fi
# 拷贝到GOPATH
- echo '拷贝到GOPATH'
- rsync -rvc --no-perms --delete ./* $GOPATH/src/$ProjectPath
# 进入项目目录
- cd $GOPATH/src/$ProjectPath
# 编译
- echo '编译'
- if [ "$GOMODTIDY" == 1 ]; then
go mod tidy;
go mod tidy;
fi
- |
while IFS= read -r line || [[ -n $line ]]
@ -63,19 +64,13 @@ build-job:
cd ..
done < ./programs.txt
save-job:
stage: save
only:
- develop
- release
script:
- cd $GOPATH/src/$ProjectPath
# 拷贝文件
- echo '拷贝文件'
- rm -rf ./temp
- mkdir ./temp
- mkdir ./temp/data
- cp -rfp ./data/* ./temp/data
# 删除自定义配置
- echo '删除自定义配置'
- |
@ -84,6 +79,7 @@ save-job:
echo "删除 $line 配置"
rm ./temp/data/$line
done < ./exclude.txt
# 拷贝可执行程序
- echo '拷贝可执行程序'
- |
@ -93,13 +89,7 @@ save-job:
mv ./$line/$line ./temp/$line
done < ./programs.txt
sync_job:
stage: sync
only:
- develop
- release
script:
- cd $GOPATH/src/$ProjectPath
# 获取部署环境信息
- if [ "$CI_COMMIT_BRANCH" == "develop" ]; then
SSH_PRIVATE_KEY="$SSH_PRIVATE_KEY_DEVELOP";
REMOTE_HOST="$REMOTE_HOST_DEVELOP";
@ -128,7 +118,7 @@ sync_job:
- echo "同步到服务器"
- echo "Deploying to remote server using rsync... $BinPath"
- rsync -rvz --delete ./temp/ $REMOTE_USER@$REMOTE_HOST:$BinPath
# 触发部署
- "curl -X POST --fail -F token=$SERVER_CI_TOKEN -F ref=release -F variables[ServerName]=$ServerName https://git.pogorockgames.com/api/v4/projects/31/trigger/pipeline"
@ -136,6 +126,6 @@ sync_job:
unlock_job:
stage: unlock
script:
- rm -f /tmp/ci_lock
- echo "释放锁定,流水线结束。"
- rm -f /tmp/ci_lock_$CI_COMMIT_REF_NAME
- echo "释放锁定,流水线结束(/$CI_COMMIT_REF_NAME)。"
when: always

View File

@ -1,8 +1,8 @@
@echo off
xcopy ..\data\* .\data\ /s /e /y /exclude:..\shell\exclude.txt
xcopy ..\data\* .\data\ /s /e /y /exclude:..\exclude.txt
for /f %%i in (../shell/programs.txt) do (
for /f %%i in (../programs.txt) do (
echo go build %%i
go build -o ./%%i/%%i.exe ../%%i/
)

View File

@ -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)
}

View File

@ -898,3 +898,7 @@ var GuideIdToGainWay = map[int]int{
GuideIdNewPlayer: GainWayGuide,
GuideIdCustom: GainWayGuide2,
}
func GetKeyGameDif(gamedif string) string {
return fmt.Sprintf("gamedif-%v", gamedif)
}

View File

@ -2,13 +2,15 @@ package common
import (
"fmt"
rawproto "google.golang.org/protobuf/proto"
"mongo.games.com/game/proto"
"mongo.games.com/game/protocol/server"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/goserver/core/profile"
"mongo.games.com/goserver/core/utils"
"mongo.games.com/game/proto"
"mongo.games.com/game/protocol/server"
)
var (

View File

@ -1,7 +0,0 @@
package common
// 系统消息编号
const (
SYSMSG_BEGIN int = iota
SYSMSG_PASSHU //因过胡规则,此牌不能胡
)

View File

@ -1,30 +0,0 @@
GainWay_NewPlayer int32 = iota //0.新建角色 新建账号,系统赠送房卡%s张|新建账号,系统赠送金币%s个 remark:无
GainWay_Pay //1.后台增加(主要是充值) %s获得d%张房卡剩余d%张 remark:充值X元
GainWay_Transfer_In //2.俱乐部转移(转入) s%赠送您房卡d%张剩余d%张 remark:玩家名称
GainWay_AgentReturn //3.代创房间返还 -
GainWay_DrawPrize //4.领取奖励 领取奖励房卡d%张,剩余%d张 remark:无
GainWay_Share //5.每日分享 每日分享活动奖励d%房卡剩余d%房卡 remark:无
GainWay_Activty //6.活动获得 s%活动奖励d%金币剩余d%金币 remark:活动名称
GainWay_Game //7.玩游戏消耗 开房间房卡-d%张剩余d%张 remark:无
GainWay_Task //8.任务 完成%s任务奖励房卡d%张剩余d%张 remark:任务名称
GainWay_ByPMCmd //9.pm命令 -
GainWay_MatchSignup //10.比赛报名 -
GainWay_MatchPlay //11.比赛回兑 -
GainWay_MatchAdd //12.比赛补充 -
GainWay_MatchBreakBack //13.退赛退还 -
GainWay_MatchSystemSupply //14.系统补给 -
GainWay_Exchange //15.兑换 兑换%s红包%d分剩余红包%d分 remark:房卡x张
GainWay_Contribute //16.贡献 -
GainWay_ClubMoneySceneFee //17.俱乐部钻石场房费 -
GainWay_Transfer_Out //18.俱乐部转移(转出) 赠送给s%房卡d%张剩余d%张 remark:玩家名称
GainWay_ServiceFee //19.桌费 扣除桌费d%金币剩余d%金币 remark:无
GainWay_CoinSceneWin //20.金豆场赢取 参与游戏赢取d%金币剩余d%金币 remark:无
GainWay_CoinSceneLost //21.金豆场输 参与游戏输掉d%金币剩余d%金币 remark:无
GainWay_BindTel //22.绑定手机 绑定手机,获得房卡%d张剩余%d张 remark:无
GainWay_PlayerShare //23.隶属玩家每日分享 每日分享活动,领取房卡%d张剩余%d张 remark:无
GainWay_Invite //24.邀请玩家 邀请玩家,获得红包%d分剩余%d分 remark:无
GainWay_LoginSign //25.签到奖励
GainWay_OnlineGift //26.签到奖励
GainWay_CoinSceneEnter //27.进入金币场预扣
GainWay_ShopBuy //28.商城购买或者兑换 使用%s购买金币%d剩余%d remark:房卡x张
GainWay_CoinSceneLeave //29.离开金币场回兑

View File

@ -28,6 +28,7 @@ func InSameDay(tNow, tPre time.Time) bool {
}
return false
}
func InSameDayNoZero(tNow, tPre time.Time) bool {
if tNow.Day() != tPre.Day() {
@ -110,7 +111,7 @@ func DiffMonth(tNow, tPre time.Time) int {
return int(diffMonth)
}
func DelayInvake(method func(), ud interface{}, delay time.Duration, times int) (timer.TimerHandle, bool) {
func DelayInvoke(method func(), ud interface{}, delay time.Duration, times int) (timer.TimerHandle, bool) {
return timer.StartTimer(timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool {
if method != nil {
method()
@ -126,6 +127,7 @@ func StrTimeToTs(strTime string) int64 {
}
return rTime.Unix()
}
func TsToStrTime(tc int64) string {
//return time.Now().Format("2018-07-02 19:14:00")
return time.Unix(tc, 0).Format("2006-01-02 15:04:05")

View File

@ -0,0 +1,23 @@
Tienlen207 Àš
 欢ä¹<C3A4>æ<EFBFBD>•é±¼401 Àš
 高棉象棋521 Àš
 å<><C3A5>三水211 Àš
愤æ€çš„大å<C2A7>606 Àš
 å°<C3A5>ç<EFBFBD>«ç®­607 Àš
 è´¢è¿<C3A8>神301 à§
å¤<C3A5>仇者è<E280A6>”çŸ302 à§
  å¤<C3A5>æ´»èŠå²303 à§

 冰河世纪304 à§
  百战æˆ<C3A6>神305 à§
  水果拉霸306 à§
  多ç¦<C3A7>多财307 à§
 FortuneTiger308 à§
 FortuneDragon309 à§
 FortuneRabbit310 à§
 FortuneOx311 à§
 FortuneMouse312 à§
 CashMania313 à§
GatesOfOlympus314 à§
 娃娃机608

129
data/DB_GameBankruptcy.json Normal file
View File

@ -0,0 +1,129 @@
{
"Arr": [
{
"Id": 1,
"GameName": "Tienlen",
"GameDif": "207",
"LimitNum": 200000
},
{
"Id": 2,
"GameName": "欢乐捕鱼",
"GameDif": "401",
"LimitNum": 200000
},
{
"Id": 3,
"GameName": "高棉象棋",
"GameDif": "521",
"LimitNum": 200000
},
{
"Id": 4,
"GameName": "十三水",
"GameDif": "211",
"LimitNum": 200000
},
{
"Id": 5,
"GameName": "愤怒的大叔",
"GameDif": "606",
"LimitNum": 200000
},
{
"Id": 6,
"GameName": "小火箭",
"GameDif": "607",
"LimitNum": 200000
},
{
"Id": 7,
"GameName": "财运神",
"GameDif": "301",
"LimitNum": 300000
},
{
"Id": 8,
"GameName": "复仇者联盟",
"GameDif": "302",
"LimitNum": 300000
},
{
"Id": 9,
"GameName": "复活节岛",
"GameDif": "303",
"LimitNum": 300000
},
{
"Id": 10,
"GameName": "冰河世纪",
"GameDif": "304",
"LimitNum": 300000
},
{
"Id": 11,
"GameName": "百战成神",
"GameDif": "305",
"LimitNum": 300000
},
{
"Id": 12,
"GameName": "水果拉霸",
"GameDif": "306",
"LimitNum": 300000
},
{
"Id": 13,
"GameName": "多福多财",
"GameDif": "307",
"LimitNum": 300000
},
{
"Id": 14,
"GameName": "FortuneTiger",
"GameDif": "308",
"LimitNum": 300000
},
{
"Id": 15,
"GameName": "FortuneDragon",
"GameDif": "309",
"LimitNum": 300000
},
{
"Id": 16,
"GameName": "FortuneRabbit",
"GameDif": "310",
"LimitNum": 300000
},
{
"Id": 17,
"GameName": "FortuneOx",
"GameDif": "311",
"LimitNum": 300000
},
{
"Id": 18,
"GameName": "FortuneMouse",
"GameDif": "312",
"LimitNum": 300000
},
{
"Id": 19,
"GameName": "CashMania",
"GameDif": "313",
"LimitNum": 300000
},
{
"Id": 20,
"GameName": "GatesOfOlympus",
"GameDif": "314",
"LimitNum": 300000
},
{
"Id": 21,
"GameName": "娃娃机",
"GameDif": "608"
}
]
}

Binary file not shown.

View File

@ -7154,6 +7154,78 @@
"Compound": {
"71002": 10
}
},
{
"Id": 40005,
"Name": "金币赛门票",
"ShowLocation": [
1,
1,
0
],
"Classify": [
1,
1,
0
],
"Type": 4,
"Effect0": [
0,
0,
0,
0,
0,
0
],
"Effect": [
0,
0,
0,
0,
0,
0
],
"SaleGold": 100000,
"Composition": 1,
"CompositionMax": 1,
"Location": "0",
"Describe": "作用:用于报名特殊钻石赛事;\n产出途径存钱罐"
},
{
"Id": 40006,
"Name": "钻石赛门票",
"ShowLocation": [
1,
1,
0
],
"Classify": [
1,
1,
0
],
"Type": 4,
"Effect0": [
0,
0,
0,
0,
0,
0
],
"Effect": [
0,
0,
0,
0,
0,
0
],
"SaleGold": 100000,
"Composition": 1,
"CompositionMax": 1,
"Location": "0",
"Describe": "作用:用于报名特殊钻石赛事;\n产出途径存钱罐"
}
]
}

Binary file not shown.

Binary file not shown.

View File

@ -1,16 +0,0 @@
{
"Id":5,
"Name":"51活动",
"Desc":"对局领福袋",
"StartTime":"2018-04-20 00:00:00",
"EndTime":"2018-05-02 23:59:59",
"TaskIds":[],
"IsDelTaskWhenEnd":true,
"IsDelActIdWhenEnd":true,
"Data":[
{"Name":"PerDayLimit", "IntVal":3 },
{"Name":"CostTimes", "IntArr":[5,3] },
{"Name":"Prize1", "IntArr":[1,1500,60,1,2000,20,1,3000,10,4,100,6,4,200,3,4,500,1] },
{"Name":"Prize2", "IntArr":[1,200,40,1,300,25,1,500,15,1,800,10,1,1000,5,4,100,5] }
]
}

View File

@ -1,20 +0,0 @@
{
"Id":3,
"Name":"元宵猜灯谜",
"Desc":"元宵猜灯谜",
"StartTime":"2018-03-02 00:00:00",
"EndTime":"2018-03-02 23:59:59",
"TaskIds":[],
"IsDelTaskWhenEnd":true,
"IsDelActIdWhenEnd":true,
"Data":[
{"Name":"Count", "IntVal":6 },
{"Name":"Prize", "IntArr":[1,2000,50,1,3000,30,3,20,15,3,50,5] },
{"Name":"1", "StrArr":["2018-03-02 00:00:00","1","弟兄五六个,围着圆柱坐,大家一分手,衣服都扯破。","A:花生","B:大蒜","C:向日葵","D:糖葫芦"] },
{"Name":"2", "StrArr":["2018-03-02 04:00:00","2","红公鸡,绿尾巴,身体钻到地底下,又甜又脆营养大。","A:番茄","B:红薯","C:红萝卜","D:花生"] },
{"Name":"3", "StrArr":["2018-03-02 08:00:00","3","纸老虎(打一成语)","A:狐假虎威","B:狗仗人势","C:仗势欺人","D:外强中干"] },
{"Name":"4", "StrArr":["2018-03-02 12:00:00","0","笑死人(打一成语)","A:乐极生悲","B:笑里藏刀","C:哭笑不得","D:强颜欢笑"] },
{"Name":"5", "StrArr":["2018-03-02 16:00:00","3","兔子请老虎(打一成语)","A:狐假虎威","B:为虎作伥","C:与虎谋皮","D:寅吃卯粮"] },
{"Name":"6", "StrArr":["2018-03-02 20:00:00","1", "白又方,嫩又香,能做菜,能煮汤,豆子是它爹和妈,它和爹妈不一样。","A:土豆","B:豆腐","C:大米","D:萝卜"] }
]
}

View File

@ -1,11 +0,0 @@
{
"Id":4,
"Name":"邀请新人",
"Desc":"邀请新人",
"StartTime":"2018-03-23 00:00:00",
"EndTime":"2018-05-31 23:59:59",
"TaskIds":[],
"IsDelTaskWhenEnd":true,
"IsDelActIdWhenEnd":true,
"Data":[]
}

View File

@ -1,14 +0,0 @@
{
"Id":1,
"Name":"新人注册领红包",
"Desc":"新人注册领红包",
"StartTime":"2018-02-05 12:00:00",
"EndTime":"2020-05-30 12:00:00",
"TaskIds":[1,2,3,4,5,6,7,8,9,10],
"IsDelTaskWhenEnd":false,
"IsDelActIdWhenEnd":false,
"Data":[
{"Name":"MaxNum", "IntVal":2000 },
{"Name":"AcceptRate", "IntArr":[1001,100,2001,20] }
]
}

View File

@ -1,11 +0,0 @@
{
"Id":6,
"Name":"投资返利",
"Desc":"投资返利",
"StartTime":"2018-04-20 00:00:00",
"EndTime":"2025-05-02 23:59:59",
"TaskIds":[],
"IsDelTaskWhenEnd":true,
"IsDelActIdWhenEnd":true,
"Data":[]
}

View File

@ -1,21 +0,0 @@
{
"Id":2,
"Name":"对暗号拿红包",
"Desc":"对暗号拿红包",
"StartTime":"2018-02-16 00:00:00",
"EndTime":"2018-02-23 00:00:00",
"TaskIds":[],
"IsDelTaskWhenEnd":false,
"IsDelActIdWhenEnd":false,
"Data":[
{"Name":"Count", "IntVal":7 },
{"Name":"UnOpenTip", "StrVal":"0" },
{"Name":"1", "StrVal":"2018-02-16 19:00:00|1" },
{"Name":"2", "StrVal":"2018-02-17 19:00:00|2" },
{"Name":"3", "StrVal":"2018-02-18 19:00:00|3" },
{"Name":"4", "StrVal":"2018-02-19 19:00:00|4" },
{"Name":"5", "StrVal":"2018-02-20 19:00:00|5" },
{"Name":"6", "StrVal":"2018-02-21 19:00:00|6" },
{"Name":"7", "StrVal":"2018-02-22 19:00:00|7" }
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
{"count":3,"pools":[{"id":-1,"type":2,"scatter":0,"s_obj":{"helix":0,"h_obj":{"offset":0},"custom":0,"c_obj":{"start":0,"offset":0}},"move":0,"m_obj":{"sx":0,"sy":0,"ex":0,"ey":0,"sp":0},"points":[{"x":-464,"y":-77,"stay":0},{"x":354,"y":1175,"stay":100},{"x":1352,"y":1038,"stay":50},{"x":897,"y":-374,"stay":50}],"stay":200,"length":3986}],"maxId":3,"lastEdit":1}

View File

@ -64,10 +64,10 @@ func (svc *DbShopLogSvc) UpdateDbShopState(args *model.DbShopLogArgs, ret *bool)
logger.Logger.Error("UpdateDbShopState == nil")
return nil
}
logger.Logger.Trace("DbShopLogSvc.UpdateDbShopState")
logger.Logger.Info("DbShopLogSvc.UpdateDbShopState", args.Log.LogId)
err = clog.UpdateId(args.Log.LogId, bson.M{"$set": bson.M{"state": args.Log.State}})
if err != nil {
logger.Logger.Error("DbShopLogSvc.UpdateDbShopState error:", err)
logger.Logger.Error("DbShopLogSvc.UpdateDbShopState error:", err, "LogId = ", args.Log.LogId)
return nil
}
*ret = true

View File

@ -33,6 +33,7 @@ func GameDetailedLogsCollection(plt string) *mongo.Collection {
c_gamedetailed.EnsureIndex(mgo.Index{Key: []string{"ts", "cycleid"}, Background: true, Sparse: true})
c_gamedetailed.EnsureIndex(mgo.Index{Key: []string{"time", "cycleid"}, Background: true, Sparse: true})
c_gamedetailed.EnsureIndex(mgo.Index{Key: []string{"-time", "cycleid"}, Background: true, Sparse: true})
c_gamedetailed.EnsureIndex(mgo.Index{Key: []string{"gamedif"}, Background: true, Sparse: true})
}
return c_gamedetailed
}

View File

@ -44,6 +44,7 @@ func GamePlayerListLogsCollection(plt string) *mongo.Collection {
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"-ts", "cycleid"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"cycleid"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"ts", "cycleid"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"gamedif"}, Background: true, Sparse: true})
}
return c_gameplayerlistlog
}

View File

@ -30,6 +30,7 @@ func ItemLogsCollection(plt string) *mongo.Collection {
c_itemlog.EnsureIndex(mgo.Index{Key: []string{"typeid", "roomconfigid"}, Background: true, Sparse: true})
c_itemlog.EnsureIndex(mgo.Index{Key: []string{"ts"}, Background: true, Sparse: true})
c_itemlog.EnsureIndex(mgo.Index{Key: []string{"-ts"}, Background: true, Sparse: true})
c_itemlog.EnsureIndex(mgo.Index{Key: []string{"gamedif"}, Background: true, Sparse: true})
}
return c_itemlog
}

View File

@ -42,8 +42,8 @@ const (
ETCDKEY_MACHINE = "/game/machine_config" //娃娃机配置
ETCDKEY_MatchAudience = "/game/match_audience" //比赛观众
ETCDKEY_Spirit = "/game/spirit" // 小精灵配置
ETCDKEY_RoomType = "/game/room_type" // 房间类型配置
ETCDKEY_RoomConfig = "/game/room_config" // 房间配置
ETCDKEY_RoomType = "/game/room_type/" // 房间类型配置
ETCDKEY_RoomConfig = "/game/room_config/" // 房间配置
ETCDKEY_RoomConfigSystem = "/game/room_system" // 系统房间配置
ETCDKEY_ClientUpgrade = "/game/client_upgrade" // 客户端升级奖励配置
ETCDKEY_PopUpWindow = "/game/PopUpWindowConfig" //弹窗配置

View File

@ -35,6 +35,7 @@ const (
ThirteenWaterPlayerOpReset = 4 // 重新选牌
ThirteenWaterPlayerJoin = 5 // 加入游戏
ThirteenWaterPlayerOpSelect = 6 // 预选牌
ThirteenWaterPlayerOpAuto = 7 // 自动摆牌 1自动 2手动
)
const (
ThirteenWaterSceneWaitTimeout = time.Second * 2 //等待倒计时

View File

@ -945,8 +945,6 @@ func AvengersCheckAndSaveLog(sceneEx *AvengersSceneData, playerEx *AvengersPlaye
LogId: logid,
Platform: playerEx.Platform,
Snid: playerEx.SnId,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,

View File

@ -44,13 +44,16 @@ func (this *Scene) SaveGameDetailedLog(param *SaveGameDetailedParam) *SaveGameDe
f := func(plt string) {
log := &model.GameDetailedLog{
Id: bson.NewObjectId(),
LogId: param.LogId,
GameId: this.GameId,
Platform: plt,
LogId: param.LogId,
GameDif: this.GetDBGameFree().GetGameDif(),
GameId: this.GetDBGameFree().GetGameId(),
GameClass: this.GetDBGameFree().GetGameClass(),
GameMode: this.GetDBGameFree().GetGameMode(),
GameType: this.GetDBGameFree().GetGameType(),
GameFreeId: this.GetDBGameFree().GetId(),
MatchId: this.GetMatch().GetMatchSortId(),
SceneId: this.SceneId,
GameMode: this.GameMode,
GameFreeid: this.GetGameFreeId(),
PlayerCount: int32(len(this.Players)),
GameTiming: int32(param.GameTime),
GameBaseBet: this.GetBaseScore(),
@ -98,8 +101,6 @@ type SaveGamePlayerListLogParam struct {
Platform string // 平台
Snid int32 // 玩家id
PlayerName string // 玩家名字
Channel string // 渠道
ChannelId string // 推广渠道
TotalIn int64 // 总投入
TotalOut int64 // 总产出(税前)
TaxCoin int64 // 总税收
@ -155,33 +156,35 @@ func (this *Scene) SaveGamePlayerListLog(param *SaveGamePlayerListLogParam) *Sav
now := time.Now()
log := &model.GamePlayerListLog{
LogId: bson.NewObjectId(),
Platform: param.Platform,
GameDif: this.GetDBGameFree().GetGameDif(),
GameId: this.GetDBGameFree().GetGameId(),
GameClass: this.GetDBGameFree().GetGameClass(),
GameMode: this.GetDBGameFree().GetGameMode(),
GameType: this.GetDBGameFree().GetGameType(),
GameFreeId: this.GetGameFreeId(),
BaseScore: baseScore,
GameDetailedLogId: param.LogId,
Channel: p.Channel,
ChannelId: p.ChannelId,
RoomType: this.SceneMode,
Ts: now.Unix(),
Time: now,
CycleId: this.CycleID,
SnId: p.SnId,
Name: param.PlayerName,
GameId: this.GameId,
BaseScore: baseScore,
TaxCoin: param.TaxCoin,
Platform: param.Platform,
Channel: param.Channel,
SceneId: this.SceneId,
GameMode: this.GameMode,
GameFreeid: this.GetGameFreeId(),
GameDetailedLogId: param.LogId,
IsFirstGame: param.IsFirstGame,
BetAmount: param.BetAmount,
WinAmountNoAnyTax: param.WinAmountNoAnyTax,
TotalIn: param.TotalIn,
TotalOut: param.TotalOut,
Time: now,
RoomType: this.SceneMode,
GameDif: this.GetDBGameFree().GetGameDif(),
GameClass: this.GetDBGameFree().GetGameClass(),
MatchId: this.GetMatch().GetMatchSortId(),
MatchType: int64(this.GetMatch().GetMatchType()),
Ts: now.Unix(),
WinAmountNoAnyTax: param.WinAmountNoAnyTax,
TaxCoin: param.TaxCoin,
BetAmount: param.BetAmount,
IsFirstGame: param.IsFirstGame,
TotalIn: param.TotalIn,
TotalOut: param.TotalOut,
IsFree: param.IsFree,
WinSmallGame: param.WinSmallGame,
WinTotal: param.WinTotal,
CycleId: this.CycleID,
}
if param.OnlyLog {
ret.Log = append(ret.Log, log)
@ -223,10 +226,12 @@ func (s *SaveGameDetailedCopy) Save() {
}
}
// LabaLog 拉霸缓存游戏记录
// LabaLog 拉霸缓存游戏记录,为了统计游戏时长
type LabaLog struct {
PlayerListLog *SaveGamePlayerListLogCopy
GameDetailLog *SaveGameDetailedCopy
CacheTime time.Time // 缓存时间
noEmpty bool
}
// Cache 临时缓存
@ -234,22 +239,55 @@ func (l *LabaLog) Cache(s *Scene, detailLog *SaveGameDetailedParam, playerListLo
if s == nil {
return
}
l.Save(2) // 如果没有收到结束消息算2秒游戏时长
detailLog.OnlyLog = true
playerListLog.OnlyLog = true
l.GameDetailLog = s.SaveGameDetailedLog(detailLog)
l.PlayerListLog = s.SaveGamePlayerListLog(playerListLog)
l.CacheTime = time.Now()
l.noEmpty = true
}
// Save 保存
func (l *LabaLog) Save(f func(log *LabaLog)) {
f(l)
l.PlayerListLog.Save()
l.GameDetailLog.Save()
// second 为0时自动计算时间,从开始转动计时
func (l *LabaLog) Save(second int32) {
if !l.noEmpty {
return
}
if second <= 0 {
sub := time.Now().Sub(l.CacheTime).Milliseconds()
if sub <= 1000 {
second = 1
} else {
second = int32(sub / 1000)
}
}
if l.PlayerListLog != nil {
if l.PlayerListLog.UpLog != nil {
for _, v := range l.PlayerListLog.UpLog.Log {
v.GamingTime = second
}
}
l.PlayerListLog.Save()
}
if l.GameDetailLog != nil {
for _, v := range l.GameDetailLog.Log {
v.GameTiming = second
}
l.GameDetailLog.Save()
}
l.Clear()
}
// Clear 清空
func (l *LabaLog) Clear() {
l.noEmpty = false
l.PlayerListLog = nil
l.GameDetailLog = nil
l.CacheTime = time.Time{}
}

View File

@ -7,6 +7,7 @@ import (
"math/rand"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
rawproto "google.golang.org/protobuf/proto"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
@ -637,19 +638,25 @@ type ReportGameEventOnly struct {
func (this *Player) ReportGameEvent(param *ReportGameEventParam) *ReportGameEventOnly {
// 记录玩家 首次参与该场次的游戏时间 游戏次数
var gameFirstTime, gameFreeFirstTime time.Time
var gameTimes, gameFreeTimes int64
var gameFirstTime, gameFreeFirstTime, gamedifFirstTime time.Time
var gameTimes, gameFreeTimes, gamedifTimes int64
data, ok := this.GDatas[this.scene.KeyGamefreeId]
if ok {
gameFirstTime = data.FirstTime
gameTimes = data.Statics.GameTimes
gameFreeFirstTime = data.FirstTime
gameFreeTimes = data.Statics.GameTimes
}
// 记录玩家 首次参与该游戏时间 游戏次数(不区分场次)
dataGame, ok := this.GDatas[this.scene.KeyGameId]
if ok {
gameFreeFirstTime = dataGame.FirstTime
gameFreeTimes = dataGame.Statics.GameTimes
gameFirstTime = dataGame.FirstTime
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)
@ -668,30 +675,32 @@ func (this *Player) ReportGameEvent(param *ReportGameEventParam) *ReportGameEven
var ret ReportGameEventOnly
ret.Param = param
log := &model.PlayerGameRecEvent{
Platform: this.Platform,
RecordId: this.scene.GetRecordId(),
SnId: this.GetSnId(),
Channel: this.Channel,
ChannelId: this.ChannelId,
City: this.City,
OS: this.DeviceOS,
GameId: this.scene.GameId,
ModeId: this.scene.GameMode,
Tax: param.Tax,
Amount: param.Change,
CreateTime: time.Now().Unix(),
CreateDayTime: tCreateDay.Unix(),
Out: param.Out,
In: param.In,
IsNew: isNew,
GameFreeID: this.scene.GetGameFreeId(),
GamingTime: int32(param.GameTime),
FirstTime: gameFirstTime.Unix(),
PlayTimes: gameTimes,
FirstGameTime: gameFreeFirstTime.Unix(),
PlayGameTimes: gameFreeTimes,
LastLoginTime: this.LastLoginTime.Unix(),
DeviceId: this.DeviceId,
Id: primitive.NewObjectID().Hex(),
RecordId: this.scene.GetRecordId(),
SnId: this.GetSnId(),
Channel: this.Channel,
Platform: this.Platform,
OS: this.DeviceOS,
GameId: this.scene.GameId,
ModeId: this.scene.GameMode,
Tax: param.Tax,
Amount: param.Change,
CreateTime: time.Now().Unix(),
CreateDayTime: tCreateDay.Unix(),
Out: param.Out,
In: param.In,
IsNew: isNew,
GameFreeID: this.scene.GetGameFreeId(),
GamingTime: int32(param.GameTime),
GameDif: this.scene.GetDBGameFree().GetGameDif(),
FirstGameDifTime: gamedifFirstTime.Unix(),
GameDifTimes: gamedifTimes,
FirstTime: gameFreeFirstTime.Unix(),
PlayTimes: gameFreeTimes,
FirstGameTime: gameFirstTime.Unix(),
PlayGameTimes: gameTimes,
LastLoginTime: this.LastLoginTime.Unix(),
ChannelId: this.ChannelId,
}
if param.OnlyLog {
ret.Log = append(ret.Log, log)

View File

@ -2057,6 +2057,7 @@ func (this *Scene) IsControl(hasRobotGaming bool) bool {
// Statistics 玩家游戏数据统计
// 包含水池统计,黑白名单统计,新手调控统计,个人水池统计
// 拉霸游戏数据统计,一次下注记录一次 StaticsLaba
func (this *Scene) Statistics(param *StaticParam) {
if param == nil {
return
@ -2110,6 +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.GetKeyGameDif(this.GetDBGameFree().GetGameDif())
// 当天数据统计
// 按场次分
if data, ok := p.TodayGameData.CtrlData[keyGameFreeId]; ok {
@ -2127,6 +2129,14 @@ func (this *Scene) Statistics(param *StaticParam) {
p.TodayGameData.CtrlData[keyGameId] = data
statics = append(statics, data)
}
// 按游戏组分
if data, ok := p.TodayGameData.CtrlData[keyGameDif]; ok {
statics = append(statics, data)
} else {
data = model.NewPlayerGameStatics()
p.TodayGameData.CtrlData[keyGameDif] = data
statics = append(statics, data)
}
// 按场次分
if data, ok := p.GDatas[keyGameFreeId]; ok {
if data.FirstTime.IsZero() {
@ -2149,6 +2159,27 @@ func (this *Scene) Statistics(param *StaticParam) {
p.GDatas[keyGameId] = data
statics = append(statics, &data.Statics)
}
//按游戏组分
getMinTime := func() time.Time {
var minTime = time.Now()
for _, v := range srvdata.GameFreeMgr.GetGameId(this.GetDBGameFree().GetGameDif()) {
vv := p.GDatas[strconv.Itoa(int(v))]
if vv != nil && vv.FirstTime.Before(minTime) {
minTime = vv.FirstTime
}
}
return minTime
}
if data, ok := p.GDatas[keyGameDif]; ok {
if data.FirstTime.IsZero() {
data.FirstTime = getMinTime()
}
statics = append(statics, &data.Statics)
} else {
data = &model.PlayerGameInfo{FirstTime: getMinTime()}
p.GDatas[keyGameDif] = data
statics = append(statics, &data.Statics)
}
// 新手输赢统计
if !model.GameParamData.CloseNovice && !common.InSliceInt(model.GameParamData.CloseNoviceGame, int(this.GameId)) && isControl && wbLevel == 0 && isNovice {
@ -2319,6 +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.GetKeyGameDif(this.GetDBGameFree().GetGameDif())
// 当天数据统计
// 按场次分
if data, ok := p.TodayGameData.CtrlData[keyGameFreeId]; ok {
@ -2336,6 +2368,14 @@ func (this *Scene) StaticsLaba(param *StaticLabaParam) {
p.TodayGameData.CtrlData[keyGameId] = data
statics = append(statics, data)
}
// 按游戏组
if data, ok := p.TodayGameData.CtrlData[keyGameDif]; ok {
statics = append(statics, data)
} else {
data = model.NewPlayerGameStatics()
p.TodayGameData.CtrlData[keyGameDif] = data
statics = append(statics, data)
}
// 按场次分
if data, ok := p.GDatas[keyGameFreeId]; ok {
if data.FirstTime.IsZero() {
@ -2358,6 +2398,27 @@ func (this *Scene) StaticsLaba(param *StaticLabaParam) {
p.GDatas[keyGameId] = data
statics = append(statics, &data.Statics)
}
// 按游戏组
getMinTime := func() time.Time {
var minTime = time.Now()
for _, v := range srvdata.GameFreeMgr.GetGameId(this.GetDBGameFree().GetGameDif()) {
vv := p.GDatas[strconv.Itoa(int(v))]
if vv != nil && vv.FirstTime.Before(minTime) {
minTime = vv.FirstTime
}
}
return minTime
}
if data, ok := p.GDatas[keyGameDif]; ok {
if data.FirstTime.IsZero() {
data.FirstTime = getMinTime()
}
statics = append(statics, &data.Statics)
} else {
data = &model.PlayerGameInfo{FirstTime: getMinTime()}
p.GDatas[keyGameDif] = data
statics = append(statics, &data.Statics)
}
for _, data := range statics {
if data != nil {

View File

@ -1035,8 +1035,6 @@ func CaiShenCheckAndSaveLog(sceneEx *CaiShenSceneData, playerEx *CaiShenPlayerDa
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,

View File

@ -1315,8 +1315,6 @@ func (this *SceneStateBilled) OnEnter(s *base.Scene) {
Platform: o_player.Platform,
Snid: o_player.UserId,
PlayerName: "",
Channel: o_player.Channel,
ChannelId: o_player.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: o_player.GainTaxCoin,

View File

@ -795,8 +795,6 @@ func (this *StateBilled) OnEnter(s *base.Scene) {
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,

View File

@ -904,8 +904,6 @@ func EasterIslandCheckAndSaveLog(sceneEx *EasterIslandSceneData, playerEx *Easte
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,

View File

@ -267,8 +267,6 @@ func (this *FishingPlayerData) SaveDetailedLog(s *base.Scene) {
Platform: this.Platform,
Snid: this.SnId,
PlayerName: this.Name,
Channel: this.Channel,
ChannelId: this.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: int64(this.sTaxCoin),

View File

@ -281,7 +281,7 @@ func (this *SceneBaseStateFishing) OnPlayerOp(s *base.Scene, p *base.Player, opc
// start 检测当前房间是否处于基本的关闭状态
if s.CheckNeedDestroy() {
if sceneEx.hDestroy == timer.InvalidTimerHandle {
if hNext, ok := common.DelayInvake(func() {
if hNext, ok := common.DelayInvoke(func() {
sceneEx.hDestroy = timer.InvalidTimerHandle
sceneEx.SceneDestroy(true)
}, nil, time.Second*10, 1); ok {

View File

@ -8,6 +8,7 @@ import (
type FortuneDragonPlayerData struct {
*base.Player
base.LabaLog
leaveTime int32 //离开时间
SlotsSession *base.SlotsSession
@ -31,6 +32,7 @@ func (p *FortuneDragonPlayerData) Clear() {
p.taxCoin = 0
p.winCoin = 0
p.currentLogId = ""
p.LabaLog.Clear()
}
// 需要带到world上进行数据处理

View File

@ -112,6 +112,7 @@ func (this *ScenePolicyFortuneDragon) OnPlayerLeave(s *base.Scene, p *base.Playe
}
logger.Logger.Trace("(this *ScenePolicyFortuneDragon) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId)
if playerEx, ok := p.ExtraData.(*FortuneDragonPlayerData); ok {
playerEx.Save(2)
m := playerEx.PushPlayer()
if m != nil && len(m) > 0 {
b, err := json.Marshal(m)
@ -476,6 +477,8 @@ func (this *SceneStateStartFortuneDragon) OnPlayerOp(s *base.Scene, p *base.Play
// 记录本次操作
FortuneDragonAndSaveLog(sceneEx, playerEx, data)
case 1000:
playerEx.Save(0)
}
}
}
@ -520,11 +523,6 @@ func FortuneDragonAndSaveLog(sceneEx *FortuneDragonSceneData, playerEx *FortuneD
if err == nil {
logid, _ := model.AutoIncGameLogId()
playerEx.currentLogId = logid
sceneEx.SaveGameDetailedLog(&base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
GameTime: 2,
})
var totalin, totalout int64
if data.Results[0].FreeStatus == 1 || data.Results[0].FreeNumMax == 0 {
totalin = playerEx.totalBet
@ -532,13 +530,14 @@ func FortuneDragonAndSaveLog(sceneEx *FortuneDragonSceneData, playerEx *FortuneD
if data.Results[0].FreeStatus == 3 || data.Results[0].FreeNumMax == 0 {
totalout = int64(data.RoundReward) + playerEx.taxCoin
}
sceneEx.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{
playerEx.Cache(sceneEx.Scene, &base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
}, &base.SaveGamePlayerListLogParam{
LogId: logid,
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,
@ -546,7 +545,6 @@ func FortuneDragonAndSaveLog(sceneEx *FortuneDragonSceneData, playerEx *FortuneD
WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin,
IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player),
IsFree: playerEx.isFree,
GameTime: 2,
})
}
}

View File

@ -8,6 +8,7 @@ import (
type FortuneMousePlayerData struct {
*base.Player
base.LabaLog
leaveTime int32 //离开时间
SlotsSession *base.SlotsSession
@ -37,6 +38,7 @@ func (p *FortuneMousePlayerData) Clear() {
p.taxCoin = 0
p.winCoin = 0
p.currentLogId = ""
p.LabaLog.Clear()
}
// 需要带到world上进行数据处理

View File

@ -111,6 +111,7 @@ func (this *ScenePolicyFortuneMouse) OnPlayerLeave(s *base.Scene, p *base.Player
}
logger.Logger.Trace("(this *ScenePolicyFortuneMouse) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId)
if playerEx, ok := p.ExtraData.(*FortuneMousePlayerData); ok {
playerEx.Save(2)
m := playerEx.PushPlayer()
if m != nil && len(m) > 0 {
b, err := json.Marshal(m)
@ -480,6 +481,8 @@ func (this *SceneStateStartFortuneMouse) OnPlayerOp(s *base.Scene, p *base.Playe
// 记录本次操作
FortuneMouseAndSaveLog(sceneEx, playerEx, data)
case 1000:
playerEx.Save(0)
}
}
}
@ -524,18 +527,13 @@ func FortuneMouseAndSaveLog(sceneEx *FortuneMouseSceneData, playerEx *FortuneMou
json.Unmarshal(sp, &spinLock)
respinStatus = spinLock.ReSpinStatus
}
if respinStatus == 0 || respinStatus == 1 {
if respinStatus != 0 && respinStatus != 1 {
data.TotalBet = 0
}
info, err := model.MarshalGameNoteByROLL(data)
if err == nil {
logid, _ := model.AutoIncGameLogId()
playerEx.currentLogId = logid
sceneEx.SaveGameDetailedLog(&base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
GameTime: 2,
})
var totalin, totalout int64
if respinStatus == 0 || respinStatus == 1 {
totalin = playerEx.totalBet
@ -543,21 +541,21 @@ func FortuneMouseAndSaveLog(sceneEx *FortuneMouseSceneData, playerEx *FortuneMou
if respinStatus == 0 || respinStatus == 3 {
totalout = int64(data.RoundReward) + playerEx.taxCoin
}
sceneEx.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{
playerEx.Cache(sceneEx.Scene, &base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
}, &base.SaveGamePlayerListLogParam{
LogId: logid,
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,
BetAmount: playerEx.totalBet,
BetAmount: totalin,
WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin,
IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player),
IsFree: totalin == 0,
GameTime: 2,
})
}
}

View File

@ -8,6 +8,7 @@ import (
type FortuneOxPlayerData struct {
*base.Player
base.LabaLog
leaveTime int32 //离开时间
SlotsSession *base.SlotsSession
@ -37,6 +38,7 @@ func (p *FortuneOxPlayerData) Clear() {
p.taxCoin = 0
p.winCoin = 0
p.currentLogId = ""
p.LabaLog.Clear()
}
// 需要带到world上进行数据处理

View File

@ -111,6 +111,7 @@ func (this *ScenePolicyFortuneOx) OnPlayerLeave(s *base.Scene, p *base.Player, r
}
logger.Logger.Trace("(this *ScenePolicyFortuneOx) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId)
if playerEx, ok := p.ExtraData.(*FortuneOxPlayerData); ok {
playerEx.Save(2)
m := playerEx.PushPlayer()
if m != nil && len(m) > 0 {
b, err := json.Marshal(m)
@ -480,6 +481,8 @@ func (this *SceneStateStartFortuneOx) OnPlayerOp(s *base.Scene, p *base.Player,
// 记录本次操作
FortuneOxAndSaveLog(sceneEx, playerEx, data)
case 1000:
playerEx.Save(0)
}
}
}
@ -527,16 +530,10 @@ func FortuneOxAndSaveLog(sceneEx *FortuneOxSceneData, playerEx *FortuneOxPlayerD
if respinStatus != 0 && respinStatus != 1 {
data.TotalBet = 0
}
info, err := model.MarshalGameNoteByROLL(data)
if err == nil {
logid, _ := model.AutoIncGameLogId()
playerEx.currentLogId = logid
sceneEx.SaveGameDetailedLog(&base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
GameTime: 2,
})
var totalin, totalout int64
if respinStatus == 0 || respinStatus == 1 {
totalin = playerEx.totalBet
@ -544,13 +541,14 @@ func FortuneOxAndSaveLog(sceneEx *FortuneOxSceneData, playerEx *FortuneOxPlayerD
if respinStatus == 0 || respinStatus == 3 {
totalout = int64(data.RoundReward) + playerEx.taxCoin
}
sceneEx.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{
playerEx.Cache(sceneEx.Scene, &base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
}, &base.SaveGamePlayerListLogParam{
LogId: logid,
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,
@ -558,7 +556,6 @@ func FortuneOxAndSaveLog(sceneEx *FortuneOxSceneData, playerEx *FortuneOxPlayerD
WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin,
IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player),
IsFree: totalin == 0,
GameTime: 2,
})
}
}

View File

@ -8,6 +8,7 @@ import (
type FortuneRabbitPlayerData struct {
*base.Player
base.LabaLog
leaveTime int32 //离开时间
SlotsSession *base.SlotsSession
@ -31,6 +32,7 @@ func (p *FortuneRabbitPlayerData) Clear() {
p.taxCoin = 0
p.winCoin = 0
p.currentLogId = ""
p.LabaLog.Clear()
}
// 需要带到world上进行数据处理

View File

@ -111,6 +111,7 @@ func (this *ScenePolicyFortuneRabbit) OnPlayerLeave(s *base.Scene, p *base.Playe
}
logger.Logger.Trace("(this *ScenePolicyFortuneRabbit) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId)
if playerEx, ok := p.ExtraData.(*FortuneRabbitPlayerData); ok {
playerEx.LabaLog.Save(2) // 没有收到结束消息算2秒游戏时长
m := playerEx.PushPlayer()
if m != nil && len(m) > 0 {
b, err := json.Marshal(m)
@ -474,6 +475,9 @@ func (this *SceneStateStartFortuneRabbit) OnPlayerOp(s *base.Scene, p *base.Play
// 记录本次操作
FortuneRabbitAndSaveLog(sceneEx, playerEx, data)
case 1000:
playerEx.Save(0)
}
}
}
@ -518,11 +522,6 @@ func FortuneRabbitAndSaveLog(sceneEx *FortuneRabbitSceneData, playerEx *FortuneR
if err == nil {
logid, _ := model.AutoIncGameLogId()
playerEx.currentLogId = logid
sceneEx.SaveGameDetailedLog(&base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
GameTime: 2,
})
var totalin, totalout int64
if data.Results[0].FreeStatus == 1 || data.Results[0].FreeNumMax == 0 {
totalin = playerEx.totalBet
@ -530,13 +529,14 @@ func FortuneRabbitAndSaveLog(sceneEx *FortuneRabbitSceneData, playerEx *FortuneR
if data.Results[0].FreeStatus == 3 || data.Results[0].FreeNumMax == 0 {
totalout = int64(data.RoundReward) + playerEx.taxCoin
}
sceneEx.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{
playerEx.Cache(sceneEx.Scene, &base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
}, &base.SaveGamePlayerListLogParam{
LogId: logid,
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,
@ -544,7 +544,6 @@ func FortuneRabbitAndSaveLog(sceneEx *FortuneRabbitSceneData, playerEx *FortuneR
WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin,
IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player),
IsFree: playerEx.isFree,
GameTime: 2,
})
}
}

View File

@ -8,6 +8,7 @@ import (
type FortuneTigerPlayerData struct {
*base.Player
base.LabaLog
leaveTime int32 //离开时间
SlotsSession *base.SlotsSession
@ -40,6 +41,7 @@ func (p *FortuneTigerPlayerData) Clear() {
p.taxCoin = 0
p.winCoin = 0
p.currentLogId = ""
p.LabaLog.Clear()
}
// 需要带到world上进行数据处理

View File

@ -111,6 +111,7 @@ func (this *ScenePolicyFortuneTiger) OnPlayerLeave(s *base.Scene, p *base.Player
}
logger.Logger.Trace("(this *ScenePolicyFortuneTiger) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId)
if playerEx, ok := p.ExtraData.(*FortuneTigerPlayerData); ok {
playerEx.LabaLog.Save(2) // 没有收到结束消息算2秒游戏时长
m := playerEx.PushPlayer()
if m != nil && len(m) > 0 {
b, err := json.Marshal(m)
@ -480,6 +481,9 @@ func (this *SceneStateStartFortuneTiger) OnPlayerOp(s *base.Scene, p *base.Playe
// 记录本次操作
FortuneTigerAndSaveLog(sceneEx, playerEx, data)
case 1000:
playerEx.Save(0)
}
}
}
@ -517,18 +521,20 @@ func (this *ScenePolicyFortuneTiger) GetSceneState(s *base.Scene, stateid int) b
func FortuneTigerAndSaveLog(sceneEx *FortuneTigerSceneData, playerEx *FortuneTigerPlayerData, data assemble.GameEnd) {
if !playerEx.IsRob {
data.SnId = playerEx.SnId
if data.Results[0].FreeStatus != 1 && data.Results[0].FreeNumMax != 0 {
var respinStatus int
if data.Results[0].ArrSpins[0].Special != nil {
sp, _ := json.Marshal(data.Results[0].ArrSpins[0].Special)
var spinLock SpinLock
json.Unmarshal(sp, &spinLock)
respinStatus = spinLock.ReSpinStatus
}
if respinStatus != 0 && respinStatus != 1 {
data.TotalBet = 0
}
info, err := model.MarshalGameNoteByROLL(data)
if err == nil {
logid, _ := model.AutoIncGameLogId()
playerEx.currentLogId = logid
sceneEx.SaveGameDetailedLog(&base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
GameTime: 2,
})
var totalin, totalout int64
if data.Results[0].FreeStatus == 1 || data.Results[0].FreeNumMax == 0 {
totalin = playerEx.totalBet
@ -536,13 +542,14 @@ func FortuneTigerAndSaveLog(sceneEx *FortuneTigerSceneData, playerEx *FortuneTig
if data.Results[0].FreeStatus == 3 || data.Results[0].FreeNumMax == 0 {
totalout = int64(data.RoundReward) + playerEx.taxCoin
}
sceneEx.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{
playerEx.Cache(sceneEx.Scene, &base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
}, &base.SaveGamePlayerListLogParam{
LogId: logid,
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,
@ -550,7 +557,6 @@ func FortuneTigerAndSaveLog(sceneEx *FortuneTigerSceneData, playerEx *FortuneTig
WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin,
IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player),
IsFree: totalin == 0,
GameTime: 2,
})
}
}

View File

@ -345,8 +345,6 @@ func (s *FruitsSceneData) SaveLog(p *FruitsPlayerData, isOffline int) {
Platform: p.Platform,
Snid: p.SnId,
PlayerName: p.Name,
Channel: p.Channel,
ChannelId: p.ChannelId,
TotalIn: totalIn,
TotalOut: totalOut,
TaxCoin: p.taxCoin,

View File

@ -954,8 +954,6 @@ func IceAgeCheckAndSaveLog(sceneEx *IceAgeSceneData, playerEx *IceAgePlayerData)
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,

View File

@ -367,8 +367,6 @@ func (s *RichBlessedSceneData) SaveLog(p *RichBlessedPlayerData, isOffline int)
Platform: p.Platform,
Snid: p.SnId,
PlayerName: p.Name,
Channel: p.Channel,
ChannelId: p.ChannelId,
TotalIn: totalIn,
TotalOut: totalOut,
TaxCoin: p.taxCoin,

View File

@ -1179,8 +1179,6 @@ func (this *StateBilled) OnEnter(s *base.Scene) {
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,
@ -1258,8 +1256,6 @@ func (this *StateBilled) OnEnter(s *base.Scene) {
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,

View File

@ -790,8 +790,6 @@ func TamQuocCheckAndSaveLog(sceneEx *TamQuocSceneData, playerEx *TamQuocPlayerDa
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,

View File

@ -1,6 +1,8 @@
package thirteen
import (
"time"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/game/gamerule/thirteen"
@ -25,7 +27,10 @@ type PlayerEx struct {
odds int32
totalScore int64
defGroup *thirteen.Group
playerPool int // 个人水池分
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)

View File

@ -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 {

View File

@ -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"
)
@ -188,8 +190,6 @@ func (this *PolicyThirteen) OnPlayerLeave(s *base.Scene, p *base.Player, reason
Platform: playerEx.Platform,
Snid: playerEx.SnId,
PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: playerEx.taxCoin,
@ -810,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()
}
// 玩家操作
@ -828,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
}
//牌赋值
@ -875,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 {
@ -894,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 {
logger.Logger.Error("the cards is error.")
returnFunc(thirteen.OpResultCode_OPRC_Error)
return true
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, 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:]
}
}
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:]
}
}
}
playerEx.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack)
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
@ -943,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
@ -1122,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)
}
}
@ -1438,8 +1501,6 @@ func (this *StateBilled) OnEnter(s *base.Scene) {
Platform: o_player.Platform,
Snid: o_player.SnId,
PlayerName: o_player.Name,
Channel: o_player.Channel,
ChannelId: o_player.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: o_player.taxCoin,

View File

@ -1302,24 +1302,20 @@ 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):]
}
allcs = common.DelSliceIn32s(allcs, this.testPokers[1:])
this.testPokers = append(this.testPokers, allcs...)
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

View File

@ -1383,7 +1383,7 @@ func (this *ScenePlayerOpStateTienLen) OnPlayerOp(s *base.Scene, p *base.Player,
case rule.TienLenPlayerOpPass: //过牌
//当前操作者和上一个操作者是同一个人,必出牌,不能过牌
if int32(playerEx.GetPos()) == sceneEx.lastOpPos || sceneEx.lastOpPos != rule.InvalidePos {
if int32(playerEx.GetPos()) == sceneEx.lastOpPos || sceneEx.lastOpPos == rule.InvalidePos {
finishFunc()
return true
}
@ -2789,8 +2789,6 @@ func (this *SceneBilledStateTienLen) OnEnter(s *base.Scene) {
LogId: sceneEx.recordId,
Platform: o_player.Platform,
Snid: o_player.UserId,
Channel: o_player.Channel,
ChannelId: o_player.ChannelId,
TotalIn: totalin,
TotalOut: totalout,
TaxCoin: o_player.BillTaxCoin,

13
go.mod
View File

@ -19,6 +19,7 @@ require (
github.com/jinzhu/now v1.1.5
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/mojocn/base64Captcha v1.3.6
github.com/mozillazg/go-pinyin v0.20.0
github.com/spf13/cast v1.7.0
github.com/spf13/viper v1.19.0
github.com/tealeg/xlsx v1.0.5
@ -91,7 +92,7 @@ require (
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/xtaci/kcp-go v5.4.20+incompatible // indirect
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect
github.com/xuri/efp v0.0.0-20241211021726-c4e992084aa6 // indirect
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
go.etcd.io/etcd/api/v3 v3.5.16 // indirect
@ -102,12 +103,12 @@ require (
go.uber.org/automaxprocs v1.6.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/image v0.18.0 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.7.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect

13
go.sum
View File

@ -226,6 +226,8 @@ github.com/mojocn/base64Captcha v1.3.6 h1:gZEKu1nsKpttuIAQgWHO+4Mhhls8cAKyiV2Ew0
github.com/mojocn/base64Captcha v1.3.6/go.mod h1:i5CtHvm+oMbj1UzEPXaA8IH/xHFZ3DGY3Wh3dBpZ28E=
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+GnMFQ=
github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@ -386,6 +388,8 @@ github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2
github.com/xuri/efp v0.0.0-20200605144744-ba689101faaf/go.mod h1:uBiSUepVYMhGTfDeBKKasV4GpgBlzJ46gXUBAqV8qLk=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/efp v0.0.0-20241211021726-c4e992084aa6 h1:8m6DWBG+dlFNbx5ynvrE7NgI+Y7OlZVMVTpayoW+rCc=
github.com/xuri/efp v0.0.0-20241211021726-c4e992084aa6/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/excelize/v2 v2.9.0 h1:1tgOaEq92IOEumR1/JfYS/eR0KHOCsRv/rYXXh6YJQE=
github.com/xuri/excelize/v2 v2.9.0/go.mod h1:uqey4QBZ9gdMeWApPLdhm9x+9o2lq4iVmjiLfBS5hdE=
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A=
@ -439,6 +443,8 @@ golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
@ -475,6 +481,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -487,6 +495,7 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -516,6 +525,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@ -528,6 +539,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=

View File

@ -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

View File

@ -245,34 +245,36 @@ func CreatePlayerLoginEvent(snid int32, channel, promoter, platform, city, os, i
// 玩家游戏记录
type PlayerGameRecEvent struct {
RecordId string //游戏记录ID
SnId int32 //用户ID
Channel string //包类型
Promoter string //推广
Platform string //平台
City string //城市
OS string //操作系统
TelephonePromoter int32 //电销标记
GameId int32 //游戏id
ModeId int32 //游戏模式
Tax int64 //税收
Amount int64 //金币变化(正值为赢;负值为输)
CreateTime int64 //创建时间
CreateDayTime int64 //账号创建时间0点
ValidBet int64 //有效下注数量
ValidFlow int64 //有效流水数量
Out int64 //产出
In int64 //投入
IsNew int32 //是否是新人
GameFreeID int32 //游戏freeid
GamingTime int32 //游戏开始到玩家结算的时长 单位:秒
FirstTime int64 //首次玩该场次游戏时间
PlayTimes int64 //该场次游戏次数
FirstGameTime int64 //首次玩游戏时间
PlayGameTimes int64 //该游戏总次数
LastLoginTime int64 //最后登录时间
DeviceId string //设备id
ChannelId string //推广渠道id
Id string //id
RecordId string //游戏记录ID
SnId int32 //用户ID
Channel string //包类型
Platform string //平台
OS string //操作系统
GameId int32 //游戏id
ModeId int32 //游戏模式
Tax int64 //税收
Amount int64 //金币变化,税后(正值为赢;负值为输)
CreateTime int64 //创建时间
CreateDayTime int64 //账号创建时间0点
Out int64 //产出
In int64 //投入
IsNew int32 //是否是新人
GameFreeID int32 //游戏freeid
GamingTime int32 //游戏开始到玩家结算的时长 单位:秒
GameDif string // 游戏分组
FirstGameDifTime int64 // 首次游戏分组时间
GameDifTimes int64 // 游戏分组游戏次数
FirstTime int64 //首次玩该场次游戏时间
PlayTimes int64 //该场次游戏次数
FirstGameTime int64 //首次玩游戏时间
PlayGameTimes int64 //该游戏总次数
LastLoginTime int64 //最后登录时间
ChannelId string //推广渠道id
}
// 玩家游戏记录

View File

@ -23,9 +23,33 @@ type CoinPoolCtx struct {
Controlled bool //被水池控制了
}
type GameDetailedLogRet struct {
Gplt GameDetailedLogType
type GameDetailedLog struct {
Id bson.ObjectId `bson:"_id"`
Platform string // 平台
LogId string // 记录ID每局游戏唯一
GameDif string // 游戏组
GameId int32 // 游戏id
GameClass int32 // 游戏类型
GameMode int32 // 游戏模式,弃用
GameType int32 // 游戏类型
GameFreeId int32 // 场次id
CycleId string // 房卡场id多轮有相同的id
MatchId int64 // 比赛ID应该用字符串的
SceneId int32 // 房间id会重复
PlayerCount int32 // 玩家数量
GameTiming int32 // 游戏用时,秒
GameBaseBet int32 // 游戏底分
Ts int64 // 时间戳
Time time.Time // 记录时间
GameDetailedNote string // 游戏详情
GameDetailVer int32 // 游戏详情版本
CpCtx CoinPoolCtx // 水池上下文信息
Trend20Lately string // 最近游戏走势
CtrlType int // 1控赢 2控输 0不控
PlayerPool map[int]int // 个人水池分 玩家id:分
}
type GameDetailedLogType struct {
PageNo int //当前页码
PageSize int //每页数量
@ -33,64 +57,8 @@ type GameDetailedLogType struct {
Data []*GameDetailedLog //当页数据
}
type GameDetailedLog struct {
Id bson.ObjectId `bson:"_id"` //记录ID
LogId string //记录ID每局游戏唯一
GameId int32 //游戏id
ClubId int32 //俱乐部Id
ClubRoom string //俱乐部包间
Platform string //平台id
Channel string //渠道
Promoter string //推广员
MatchId int64 //比赛ID应该用字符串的
SceneId int32 //房间id会重复
GameMode int32 //游戏类型
GameFreeid int32 //游戏类型房间号
PlayerCount int32 //玩家数量
GameTiming int32 //本局游戏用时(mm)
GameBaseBet int32 //游戏单位低分
GameDetailedNote string //游戏详情
GameDetailVer int32 //游戏详情版本
CpCtx CoinPoolCtx //水池上下文信息
Time time.Time //记录时间
Trend20Lately string //最近游戏走势
Ts int64 //时间戳
CtrlType int // 1控赢 2控输 0不控
PlayerPool map[int]int // 个人水池分
CycleId string // 本轮id打一轮有多局
}
func NewGameDetailedLog() *GameDetailedLog {
log := &GameDetailedLog{Id: bson.NewObjectId()}
return log
}
func NewGameDetailedLogEx(logid string, gameid, sceneid, gamemode, gamefreeid, playercount, gametiming, gamebasebet int32,
gamedetailednote string, platform string, clubId int32, clubRoom string, cpCtx CoinPoolCtx, ver int32,
trend20Lately string, ctrlType int, playerPool map[int]int, cycleId string) *GameDetailedLog {
cl := NewGameDetailedLog()
cl.LogId = logid
cl.GameId = gameid
cl.ClubId = clubId
cl.ClubRoom = clubRoom
cl.SceneId = sceneid
cl.GameMode = gamemode
cl.GameFreeid = gamefreeid
cl.PlayerCount = playercount
cl.GameTiming = gametiming
cl.GameBaseBet = gamebasebet
cl.GameDetailedNote = gamedetailednote
cl.Platform = platform
tNow := time.Now()
cl.Time = tNow
cl.CpCtx = cpCtx
cl.GameDetailVer = ver
cl.Trend20Lately = trend20Lately
cl.Ts = time.Now().Unix()
cl.CtrlType = ctrlType
cl.PlayerPool = playerPool
cl.CycleId = cycleId
return cl
type GameDetailedLogRet struct {
Gplt GameDetailedLogType
}
func InsertGameDetailedLog(log *GameDetailedLog) (err error) {

View File

@ -21,86 +21,36 @@ type GameTotalRecord struct {
type GamePlayerListLog struct {
LogId bson.ObjectId `bson:"_id"` //记录ID
SnId int32 //用户Id
Name string //名称
GameId int32 //游戏id
BaseScore int32 //游戏底注
ClubId int32 //俱乐部Id
ClubRoom string //俱乐部包间
TaxCoin int64 //税收
ClubPumpCoin int64 //俱乐部额外抽水
Platform string //平台id
Channel string //渠道
Promoter string //推广员
PackageTag string //包标识
SceneId int32 //场景ID
GameMode int32 //游戏类型
GameFreeid int32 //游戏类型房间号
GameDetailedLogId string //游戏记录Id
IsFirstGame bool //是否第一次游戏
//对于拉霸类BetAmount=100 WinAmountNoAnyTax=0 (表示投入多少、收益多少,值>=0
//拉霸类小游戏会是BetAmount=0 WinAmountNoAnyTax=100 投入0、收益多少值>=0
//对战场BetAmount=0 WinAmountNoAnyTax=100 投入会有是0、收益有正负WinAmountNoAnyTax=100则盈利WinAmountNoAnyTax=-100则输100
BetAmount int64 //下注金额
WinAmountNoAnyTax int64 //盈利金额,不包含任何税
TotalIn int64 //本局投入
TotalOut int64 //本局产出
Time time.Time //记录时间
RoomType int32 //房间类型
GameDif string //游戏标识
GameClass int32 //游戏类型 1棋牌 2电子 3百人 4捕鱼 5视讯 6彩票 7体育
MatchId int64
MatchType int64 //0.普通场 1.锦标赛 2.冠军赛 3.vip专属
Ts int64
IsFree bool //拉霸专用 是否免费
WinSmallGame int64 //拉霸专用 小游戏奖励
WinTotal int64 //拉霸专用 输赢
CycleId string // 本轮id打一轮有多局
}
Platform string // 平台
GameDif string // 游戏组
GameId int32 // 游戏id
GameClass int32 // 游戏类型
GameMode int32 // 游戏模式,弃用
GameType int32 // 游戏类型
GameFreeId int32 // 场次id
BaseScore int32 // 游戏底注
GameDetailedLogId string // 游戏记录Id
Channel string // 包类型
ChannelId string // 推广渠道
RoomType int32 // 房间类型
Ts int64 // 记录时间
Time time.Time // 记录时间
CycleId string // 本轮id打一轮有多局
func NewGamePlayerListLog() *GamePlayerListLog {
log := &GamePlayerListLog{LogId: bson.NewObjectId()}
return log
}
func NewGamePlayerListLogEx(snid int32, gamedetailedlogid string, platform, channel, promoter, packageTag string, gameid, baseScore,
sceneid, gamemode, gamefreeid int32, totalin, totalout int64, clubId int32, clubRoom string, taxCoin, pumpCoin int64, roomType int32,
betAmount, winAmountNoAnyTax int64, key, name string, gameClass int32, isFirst bool, matchid, matchType int64,
isFree bool, winSmallGame, winTotal int64, cycleId string) *GamePlayerListLog {
cl := NewGamePlayerListLog()
cl.SnId = snid
cl.GameDetailedLogId = gamedetailedlogid
cl.Platform = platform
cl.Name = name
cl.Channel = channel
cl.Promoter = promoter
cl.PackageTag = packageTag
cl.GameFreeid = gamefreeid
cl.GameId = gameid
cl.BaseScore = baseScore
cl.ClubId = clubId
cl.GameMode = gamemode
cl.SceneId = sceneid
cl.TotalIn = totalin
cl.TotalOut = totalout
cl.ClubRoom = clubRoom
cl.TaxCoin = taxCoin
cl.IsFirstGame = isFirst
cl.ClubPumpCoin = pumpCoin
cl.RoomType = roomType
cl.BetAmount = betAmount
cl.WinAmountNoAnyTax = winAmountNoAnyTax
cl.GameDif = key
cl.GameClass = gameClass
cl.IsFree = isFree
cl.WinSmallGame = winSmallGame
cl.WinTotal = winTotal
tNow := time.Now()
cl.Ts = tNow.Unix()
cl.Time = tNow
cl.MatchId = matchid
cl.MatchType = matchType
cl.CycleId = cycleId
return cl
SnId int32 // 用户Id
Name string // 名称
SceneId int32 // 房间id会重复
MatchId int64 // 比赛ID应该用字符串的
MatchType int64 // 0.普通场 1.锦标赛 2.冠军赛 3.vip专属
WinAmountNoAnyTax int64 // 盈利金额,不包含任何税
TaxCoin int64 // 税收
BetAmount int64 // 下注金额
IsFirstGame bool // 是否第一次游戏
TotalIn int64 // 本局投入
TotalOut int64 // 本局产出
IsFree bool // 拉霸专用 是否免费
WinSmallGame int64 // 拉霸专用 小游戏奖励
WinTotal int64 // 拉霸专用 输赢
}
type GamePlayerListRet struct {

View File

@ -28,6 +28,7 @@ type ItemLog struct {
TypeId int32 // 变化类型
GameId int64 // 游戏id,游戏中获得时有值
GameFreeId int64 // 场次id,游戏中获得时有值
GameDif string // 游戏分组
Cost []*Item // 消耗的道具
Id string // 撤销的id兑换失败
RoomConfigId int32 // 房间配置id
@ -50,6 +51,7 @@ type ItemParam struct {
TypeId int32 // 变化类型
GameId int64 // 游戏id,游戏中获得时有值
GameFreeId int64 // 场次id,游戏中获得时有值
GameDif string // 游戏分组
Cost []*Item // 消耗的道具
LogId string // 撤销的id兑换失败
RoomConfigId int32 // 房间配置id
@ -71,6 +73,7 @@ func NewItemLogEx(param ItemParam) *ItemLog {
itemLog.TypeId = param.TypeId
itemLog.GameId = param.GameId
itemLog.GameFreeId = param.GameFreeId
itemLog.GameDif = param.GameDif
itemLog.Cost = param.Cost
itemLog.Id = param.LogId
itemLog.RoomConfigId = param.RoomConfigId
@ -246,7 +249,7 @@ type InsertItemLogReq struct {
Logs []*ItemLog
}
func InsertItemLog(configItems map[int32]*server.DB_GameItem, param *AddItemParam, isOffline bool) error {
func InsertItemLog(configItems map[int32]*server.DB_GameItem, param *AddItemParam, gamedif string, isOffline bool) error {
if rpcCli == nil {
logger.Logger.Warnf("rpcCli is nil")
return errors.New("rpcCli is nil")
@ -280,6 +283,7 @@ func InsertItemLog(configItems map[int32]*server.DB_GameItem, param *AddItemPara
TypeId: param.GainWay,
GameId: param.GameId,
GameFreeId: param.GameFreeId,
GameDif: gamedif,
Cost: param.Cost,
LogId: param.LogId,
RoomConfigId: param.RoomConfigId,

View File

@ -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

View File

@ -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)

11
model/thirteen.go Normal file
View File

@ -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
}

View File

@ -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 注册消息处理函数

View File

@ -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 消息

File diff suppressed because it is too large Load Diff

View File

@ -659,6 +659,22 @@ message DB_GamMatchLVArray {
repeated DB_GamMatchLV Arr = 1;
}
message DB_GameBankruptcy {
int32 Id = 1;
string GameName = 2;
string GameDif = 3;
int32 LimitNum = 4;
}
message DB_GameBankruptcyArray {
repeated DB_GameBankruptcy Arr = 1;
}
message DB_GameCoinPool {
int32 Id = 1;

View File

@ -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发过来减少数据传输
// 第二种:按头墩中墩尾墩顺序把牌发过来

View File

@ -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(12)
// ,
// Poker.IndexType发过来

File diff suppressed because it is too large Load Diff

View File

@ -513,6 +513,8 @@ message ASQueryOnlineReportList{
int32 OrderType = 6;// 0, 1
int32 GameFreeId = 7;
string Channel = 8;
string GameDif = 9; //
string ChannelId = 10; // 广ID
}
message SAQueryOnlineReportList{
TagCode Tag = 1; //

View File

@ -0,0 +1,77 @@
// Code generated by xlsx2proto.
// DO NOT EDIT!
package srvdata
import (
"google.golang.org/protobuf/proto"
"mongo.games.com/game/protocol/server"
)
var PBDB_GameBankruptcyMgr = &DB_GameBankruptcyMgr{
Datas: &server.DB_GameBankruptcyArray{},
pool: make(map[int32]*server.DB_GameBankruptcy),
}
type DB_GameBankruptcyMgr struct {
Datas *server.DB_GameBankruptcyArray
pool map[int32]*server.DB_GameBankruptcy
}
func (this *DB_GameBankruptcyMgr) unmarshal(data []byte) error {
err := proto.Unmarshal(data, this.Datas)
if err == nil {
this.arrangeData()
}
return err
}
func (this *DB_GameBankruptcyMgr) reunmarshal(data []byte) error {
newDatas := &server.DB_GameBankruptcyArray{}
err := proto.Unmarshal(data, newDatas)
if err == nil {
for _, item := range newDatas.Arr {
existItem := this.GetData(item.GetId())
if existItem == nil {
this.pool[item.GetId()] = item
this.Datas.Arr = append(this.Datas.Arr, item)
} else {
*existItem = *item
}
}
}
return err
}
func (this *DB_GameBankruptcyMgr) arrangeData() {
if this.Datas == nil {
return
}
dataArr := this.Datas.GetArr()
if dataArr == nil {
return
}
for _, data := range dataArr {
this.pool[data.GetId()] = data
}
}
func (this *DB_GameBankruptcyMgr) GetData(id int32) *server.DB_GameBankruptcy {
if data, ok := this.pool[id]; ok {
return data
}
return nil
}
func init() {
DataMgr.register("DB_GameBankruptcy.dat", &ProtobufDataLoader{dh: PBDB_GameBankruptcyMgr})
}

View File

@ -24,4 +24,9 @@ update_invite_num: 30
# 几秒读取一次道具日志
update_second_item: 10
# 一次最多读取多少道具日志
update_item_num: 100
update_item_num: 100
# rabbitmq配置
rabbitmq:
url: amqp://win88:123456@127.0.0.1:5672/win99
exchange: win99

View File

@ -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"
)
@ -68,9 +69,9 @@ func DoTickPlatform(ctx context.Context, wg *sync.WaitGroup, duration time.Durat
}
func main() {
VP = viperx.GetViper("config", "yaml")
VP = viperx.GetViper("config.yaml")
// mongo
vp := viperx.GetViper("mongo", "yaml")
vp := viperx.GetViper("mongo.yaml")
// mongo初始化
conf := &mongox.Config{}
err := vp.Unmarshal(conf)
@ -81,7 +82,7 @@ func main() {
defer mongox.Close()
// mysql
vp = viperx.GetViper("mysql", "yaml")
vp = viperx.GetViper("mysql.yaml")
myConf := &mysqlx.Config{}
err = vp.Unmarshal(myConf)
if err != nil {
@ -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) {

View File

@ -9,13 +9,13 @@ const (
)
type LogLogin struct {
ID uint `gorm:"primaryKey"`
Snid int `gorm:"index"`
OnlineType int `gorm:"index"`
//OnlineTs int `gorm:"index"`
ID uint `gorm:"primaryKey"`
Snid int `gorm:"index"`
OnlineType int `gorm:"index"`
OnlineTs int64 `gorm:"index"`
OnlineTime time.Time `gorm:"index"`
OfflineType int `gorm:"index"`
//OfflineTs int `gorm:"index"`
OfflineTs int64 `gorm:"index"`
OfflineTime time.Time `gorm:"index"`
ChannelId string `gorm:"index"` // 推广渠道

View File

@ -1,17 +1,20 @@
package modelmysql
import "mongo.games.com/game/model"
// 需要自动迁移的表添加在这里 Tables
var Tables = []interface{}{
&LogLogin{},
&LogLoginMid{},
&UserAccount{},
&UserLogin{},
&UserID{},
//&UserLogin{},
//&UserID{},
&LogInviteScoreMid{},
&LogInviteScore{},
&LogInviteUser{},
&LogMid{},
&ItemGain{},
&ItemTotalGain{},
&model.ThirteenAutoLog{},
}

View File

@ -8,6 +8,7 @@ type UserAccount struct {
Snid int `gorm:"index"`
//RegisterTs int `gorm:"index"`
RegisterTime time.Time `gorm:"index"`
RegisterTs int64 `gorm:"index"`
ChannelId string `gorm:"index"` // 推广渠道
DeviceName string `gorm:"index"`

View File

@ -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
},
})
}

View File

@ -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
//}

View File

@ -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"
)
/*
@ -91,12 +91,12 @@ func LogLogin(platform string, batchSize int) ([]*mysqlmodel.LogLogin, error) {
if n == 0 {
e = &mysqlmodel.LogLogin{
Snid: int(v.SnId),
OnlineType: onlineType,
//OnlineTs: int(v.Ts),
OnlineTime: v.Time,
OfflineType: 0,
//OfflineTs: 0,
Snid: int(v.SnId),
OnlineType: onlineType,
OnlineTs: v.Time.Unix(),
OnlineTime: v.Time,
OfflineType: 0,
OfflineTs: 0,
OfflineTime: v.Time,
DeviceName: v.DeviceName,
AppVersion: v.AppVersion,
@ -132,7 +132,7 @@ func LogLogin(platform string, batchSize int) ([]*mysqlmodel.LogLogin, error) {
}
e.OfflineType = mysqlmodel.LogTypeOffline
//e.OfflineTs = int(v.Ts)
e.OfflineTs = v.Time.Unix()
e.OfflineTime = v.Time
if err = db.Model(e).Select("OfflineType", "OfflineTime").Updates(e).Error; err != nil {
logger.Logger.Errorf("mysql: SyncLogLogin failed to update log_login: %v", err)
@ -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
})

View File

@ -1 +1,3 @@
游戏服mongodb同步到mysql
游戏服mongodb同步到mysql
datasync.go 同步模型

View File

@ -68,9 +68,9 @@ func UserAccount(platform string, batchSize int) ([]*mysqlmodel.UserAccount, err
for _, v := range accounts {
logger.Logger.Tracef("mongo account: %+v", *v)
a := &mysqlmodel.UserAccount{
MID: v.AccountId.Hex(),
Snid: int(v.SnId),
//RegisterTs: int(v.RegisterTs),
MID: v.AccountId.Hex(),
Snid: int(v.SnId),
RegisterTs: v.RegisteTime.Unix(),
RegisterTime: v.RegisteTime,
Tel: v.Tel,
ChannelId: v.ChannelId,
@ -81,17 +81,17 @@ func UserAccount(platform string, batchSize int) ([]*mysqlmodel.UserAccount, err
return err
}
if err = tx.First(&mysqlmodel.UserID{}, "snid = ?", v.SnId).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
logger.Logger.Errorf("mysql: UserAccount failed to find user_id: %v", err)
return err
}
if errors.Is(err, gorm.ErrRecordNotFound) {
if err = tx.Create(&mysqlmodel.UserID{Snid: int(v.SnId)}).Error; err != nil {
logger.Logger.Errorf("mysql: UserAccount failed to create user_id: %v", err)
return err
}
}
//if err = tx.First(&mysqlmodel.UserID{}, "snid = ?", v.SnId).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
// logger.Logger.Errorf("mysql: UserAccount failed to find user_id: %v", err)
// return err
//}
//
//if errors.Is(err, gorm.ErrRecordNotFound) {
// if err = tx.Create(&mysqlmodel.UserID{Snid: int(v.SnId)}).Error; err != nil {
// logger.Logger.Errorf("mysql: UserAccount failed to create user_id: %v", err)
// return err
// }
//}
as = append(as, a)
}

View File

@ -1,17 +1,21 @@
StartTime: "2024-11-26T00:00:00+08:00"
EndTime: "2024-11-27T00:00:00+08:00"
StartTime: "2024-12-25T00:00:00+08:00"
EndTime: "2024-12-26T00:00:00+08:00"
IsDatabaseMode: true
ListenPort: 8888
Switch: # 1: open, 0: close
- 0 # 新用户游戏破产率
- 0 # 新用户平均游戏时长
- 0 # 新用户平均局数
- 0 # 平均倍数
- 1 # 新用户游戏破产率
- 1 # 新用户平均游戏时长
- 1 # 用户平均游戏时长
- 1 # 新用户平均局数
- 1 # 平均倍数
- 1 # 活跃破产率
- 1 # 控输赢胜率
- 1 # 机器人胜率
- 1 # 人均获得金币
- 1 # 破产后离线
- 1 # 充值玩家金币余额
- 0 # 控输赢胜率
- 0 # 机器人胜率
- 0 # 人均获得金币
- 0 # 破产后离线
- 0 # 充值玩家金币余额
Gamefreeids:
- 2070001

View File

@ -2,7 +2,14 @@ package main
import (
"fmt"
"golang.org/x/exp/maps"
"strings"
"github.com/mozillazg/go-pinyin"
"github.com/xuri/excelize/v2"
"gorm.io/gorm"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/mysqlx"
)
type ExcelData struct {
@ -10,6 +17,10 @@ type ExcelData struct {
Head []string
Index int
IndexCell int
TableName string
TableHead []string
DataName string
}
func (e *ExcelData) SetHead(head []string) *ExcelData {
@ -59,13 +70,26 @@ func NewExcelMgr() *ExcelMgr {
}
}
func (e *ExcelMgr) Register(id int, head []string) *ExcelData {
func (e *ExcelMgr) Register(id int, head []string, filename string) *ExcelData {
e.List[id] = &ExcelData{
File: excelize.NewFile(),
Head: head,
Index: 0,
}
name := ChineseToPinYin([]string{filename})
if len(name) == 0 {
return nil
}
tableName := fmt.Sprintf("task_%s", name[0])
e.List[id].TableName = tableName
for _, v := range head {
cl := ChineseToPinYin([]string{v})[0]
e.List[id].TableHead = append(e.List[id].TableHead, cl)
}
e.List[id].DataName = filename
e.List[id].NewSheet("Sheet1")
if len(head) > 0 {
@ -79,10 +103,180 @@ func (e *ExcelMgr) Get(id int) *ExcelData {
return e.List[id]
}
func (e *ExcelMgr) Save(id int, fileName string) error {
func (e *ExcelMgr) Save(id int, startTime, endTime string) error {
d := e.List[id]
if d == nil {
return nil
}
return d.SaveAs(fileName)
filename := fmt.Sprintf("%s_%s_%s.xlsx", d.DataName, startTime, endTime)
if VP.GetBool("IsDatabaseMode") {
rows, err := d.GetRows("Sheet1")
if err != nil {
return err
}
db, err := mysqlx.GetDatabase("1")
if err != nil {
logger.Logger.Errorf("GetDatabase error: %v", err)
return err
}
files := make(map[string]string)
index := make(map[string]string)
for _, v := range d.Head {
cl := ChineseToPinYin([]string{v})[0]
d.TableHead = append(d.TableHead, cl)
files[cl] = v
if strings.Contains(v, "*") {
index[cl] = "INDEX"
}
}
createSQL := buildCreateTableSQLWithIndices(d.TableName, d.DataName, files, index)
if err = db.Exec(createSQL).Error; err != nil {
logger.Logger.Errorf("createTable error: %v", err)
return err
}
if err = insertData(db.DB, d.TableName, maps.Keys(files), rows); err != nil {
logger.Logger.Errorf("insertData error: %v", err)
return err
}
return nil
}
return d.SaveAs(filename)
}
func (e *ExcelMgr) Pull(id int, startTime, endTime string) (*excelize.File, string, error) {
d := e.List[id]
if d == nil {
return nil, "", nil
}
db, err := mysqlx.GetDatabase("1")
if err != nil {
logger.Logger.Errorf("GetDatabase error: %v", err)
return nil, "", err
}
rows, err := db.Table(d.TableName).Where("ri_qi between ? and ?", startTime, endTime).Select(d.TableHead).Rows()
if err != nil {
logger.Logger.Errorf("Pull error: %v", err)
return nil, "", err
}
defer rows.Close()
f := excelize.NewFile()
f.NewSheet("Sheet1")
f.SetSheetRow("Sheet1", "A1", &d.Head)
index := 2
for rows.Next() {
data := make([]interface{}, len(d.TableHead))
scanArgs := make([]interface{}, len(d.TableHead))
for i := range data {
scanArgs[i] = &data[i]
}
err = rows.Scan(scanArgs...)
if err != nil {
logger.Logger.Errorf("Pull error: %v", err)
return nil, "", err
}
f.SetSheetRow("Sheet1", "A"+fmt.Sprintf("%d", index), &data)
index++
}
return f, fmt.Sprintf("%s_%s_%s", d.DataName, startTime, endTime), nil
}
// 构建创建表的 SQL 语句,支持中文描述和索引
func buildCreateTableSQLWithIndices(tableName string, comment string, fields map[string]string, indices map[string]string) string {
var columns []string
var indexDefs []string
// 遍历字段定义
for field, comment := range fields {
column := fmt.Sprintf("`%s` VARCHAR(255) COMMENT '%s'", field, comment)
columns = append(columns, column)
// 根据索引类型添加索引定义
if indexType, ok := indices[field]; ok {
switch strings.ToUpper(indexType) {
case "PRIMARY":
indexDefs = append(indexDefs, fmt.Sprintf("PRIMARY KEY (`%s`)", field))
case "UNIQUE":
indexDefs = append(indexDefs, fmt.Sprintf("UNIQUE KEY `idx_%s` (`%s`)", field, field))
case "INDEX":
indexDefs = append(indexDefs, fmt.Sprintf("KEY `idx_%s` (`%s`)", field, field))
}
}
}
// 拼接字段和索引部分
allDefs := append(columns, indexDefs...)
ret := fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n%s\n) COMMENT='%s';",
tableName,
strings.Join(allDefs, ",\n"), comment)
logger.Logger.Tracef("createTableSQL: %s", ret)
// 拼接最终的 SQL
return ret
}
func insertData(db *gorm.DB, tableName string, header []string, rows [][]string) error {
placeholders := strings.Repeat("?,", len(header))
placeholders = placeholders[:len(placeholders)-1] // 移除多余的逗号
insertSQL := fmt.Sprintf("INSERT INTO `%s` (%s) VALUES (%s)", tableName, "`"+strings.Join(header, "`,`")+"`", placeholders)
for _, row := range rows {
// 确保每行数据长度和表头一致
if len(row) < len(header) {
for len(row) < len(header) {
row = append(row, "") // 填充缺失列
}
}
err := db.Exec(insertSQL, interfaceSlice(row)...).Error
if err != nil {
return err
}
}
return nil
}
func interfaceSlice(slice []string) []interface{} {
result := make([]interface{}, len(slice))
for i, v := range slice {
result[i] = v
}
return result
}
var args = pinyin.NewArgs()
func init() {
args.Style = pinyin.Normal
}
func joinPinyin(py [][]string) string {
var result []string
for _, word := range py {
if len(word) > 0 {
result = append(result, word[0]) // 每个字的拼音取第一个候选
}
}
return strings.Join(result, "_")
}
func ChineseToPinYin(param []string) []string {
var ret []string
for _, v := range param {
ret = append(ret, joinPinyin(pinyin.Pinyin(v, args)))
}
return ret
}

View File

@ -0,0 +1,51 @@
package main
import (
"net/http"
"strconv"
)
/*
下载
GET http://127.0.0.1:8888/statistics/task?data_type=0&start_time=2024-12-26&end_time=2024-12-26
请求参数
data_type 数据类型
0新用户游戏破产率
1新用户平均游戏时长
2用户平均游戏时长
3新用户平均局数
4平均倍数
5活跃破产率
start_time 开始时间
end_time 结束时间
*/
// Download 下载
func Download(w http.ResponseWriter, r *http.Request) {
// 请求参数
// data_type 数据类型
// start_time 开始时间
// end_time 结束时间
// Request parameters
dataType, err := strconv.Atoi(r.URL.Query().Get("data_type"))
if err != nil {
http.Error(w, "Invalid data_type", http.StatusBadRequest)
return
}
startTime := r.URL.Query().Get("start_time")
endTime := r.URL.Query().Get("end_time")
f, name, err := ExcelMgrSingle.Pull(dataType, startTime, endTime)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer f.Close()
w.Header().Set("Content-Type", "application/octet-stream;charset=UTF-8")
w.Header().Set("Content-Disposition", "attachment; filename=\""+name+".xlsx\"")
f.Write(w)
}

View File

@ -2,6 +2,10 @@ package main
import (
"fmt"
"mongo.games.com/goserver/core/utils"
"net/http"
"os"
"os/signal"
"sort"
"time"
@ -11,6 +15,7 @@ import (
"mongo.games.com/goserver/core/mysqlx"
"mongo.games.com/goserver/core/viperx"
"mongo.games.com/game/common"
"mongo.games.com/game/statistics/task/gamefree"
"mongo.games.com/game/statistics/task/task"
)
@ -18,6 +23,7 @@ import (
const (
ExcelTypeNewPlayerBankrupt = iota // 新用户游戏破产率
ExcelTypeGameTimeAvg // 新用户平均游戏时长
ExcelTypeGameTimeAllAvg // 用户平均游戏时长
ExcelTypeGameCountAvg // 新用户平均局数
ExcelTypeGameRate // 平均倍数
ExcelTypeActiveRate // 活跃破产率
@ -29,33 +35,13 @@ const (
)
var VP *viper.Viper
var ExcelMgrSingle *ExcelMgr
func main() {
defer func() {
logger.Logger.Flush()
logger.Logger.Close()
}()
VP = viperx.GetViper("config", "yaml")
// mongo
vp := viperx.GetViper("mongo", "yaml")
// mongo初始化
conf := &mongox.Config{}
err := vp.Unmarshal(conf)
if err != nil {
panic(fmt.Errorf("mongo config error: %v", err))
func run() {
if VP.GetBool("IsDatabaseMode") {
VP.Set("StartTime", common.HMSToTime(0, 0, 0).Format(time.RFC3339))
VP.Set("EndTime", common.HMSToTime(0, 0, 0).AddDate(0, 0, 1).Format(time.RFC3339))
}
mongox.Init(conf)
defer mongox.Close()
// mysql
vp = viperx.GetViper("mysql", "yaml")
myConf := &mysqlx.Config{}
err = vp.Unmarshal(myConf)
if err != nil {
panic(fmt.Errorf("mysql config error: %v", err))
}
mysqlx.Init(myConf)
defer mysqlx.Close()
startTime, err := time.Parse(time.RFC3339, VP.GetString("StartTime"))
if err != nil {
@ -68,18 +54,6 @@ func main() {
return
}
mgr := NewExcelMgr()
mgr.Register(ExcelTypeNewPlayerBankrupt, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"})
mgr.Register(ExcelTypeGameTimeAvg, []string{"日期", "场次id", "参与人数", "平均游戏时长"})
mgr.Register(ExcelTypeGameCountAvg, []string{"日期", "场次id", "参与人数", "平均局数"})
mgr.Register(ExcelTypeGameRate, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"})
mgr.Register(ExcelTypeActiveRate, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"})
mgr.Register(ExcelTypeCtrlWinRate, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"})
mgr.Register(ExcelTypeCtrlWinRate*10, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"})
mgr.Register(ExcelTypeRobotWinRate, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"})
mgr.Register(ExcelTypeCoinAvg, []string{"日期", "场次id", "参与人数", "人均获得金币"})
mgr.Register(ExcelTypeBankruptOffline, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"})
mgr.Register(ExcelTypeOfflineCoin, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"})
switchArr := VP.GetIntSlice("Switch")
for {
@ -93,83 +67,161 @@ func main() {
if switchArr[ExcelTypeNewPlayerBankrupt] == 1 {
// 新用户游戏破产率
mgr.GenNewPlayerBankruptRateExcel("1", startTimeStr, endTimeStr)
ExcelMgrSingle.GenNewPlayerBankruptRateExcel("1", startTimeStr, endTimeStr)
}
if switchArr[ExcelTypeGameTimeAvg] == 1 {
// 新用户平均游戏时长
mgr.GenNewPlayerGameTimeAvgExcel("1", startTimeStr, endTimeStr)
ExcelMgrSingle.GenNewPlayerGameTimeAvgExcel("1", startTimeStr, endTimeStr)
}
if switchArr[ExcelTypeGameTimeAllAvg] == 1 {
// 用户平均游戏时长
ExcelMgrSingle.GenPlayerGameTimeAvgExcel("1", startTimeStr, endTimeStr)
}
if switchArr[ExcelTypeGameCountAvg] == 1 {
// 新用户平均局数
mgr.GenGameCountExcel("1", startTimeStr, endTimeStr)
ExcelMgrSingle.GenGameCountExcel("1", startTimeStr, endTimeStr)
}
if switchArr[ExcelTypeGameRate] == 1 {
// 平均倍数
mgr.GenGameRateExcel("1", startTimeStr, endTimeStr)
ExcelMgrSingle.GenGameRateExcel("1", startTimeStr, endTimeStr)
}
if switchArr[ExcelTypeActiveRate] == 1 {
// 活跃破产率
mgr.GenActiveBankruptRateExcel("1", startTimeStr, endTimeStr)
ExcelMgrSingle.GenActiveBankruptRateExcel("1", startTimeStr, endTimeStr)
}
if switchArr[ExcelTypeCtrlWinRate] == 1 {
// 控赢胜率
mgr.GenCtrlWinRateExcel("1", startTimeStr, endTimeStr)
ExcelMgrSingle.GenCtrlWinRateExcel("1", startTimeStr, endTimeStr)
}
if switchArr[ExcelTypeRobotWinRate] == 1 {
// 机器人胜率
mgr.GenRobotWinRateExcel("1", startTimeStr, endTimeStr)
ExcelMgrSingle.GenRobotWinRateExcel("1", startTimeStr, endTimeStr)
}
if switchArr[ExcelTypeCoinAvg] == 1 {
// 人均获得金币
mgr.GenCoinAvgExcel("1", startTimeStr, endTimeStr)
ExcelMgrSingle.GenCoinAvgExcel("1", startTimeStr, endTimeStr)
}
if switchArr[ExcelTypeBankruptOffline] == 1 {
// 破产后离线
mgr.GenBankruptOfflineExcel("1", startTimeStr, endTimeStr)
ExcelMgrSingle.GenBankruptOfflineExcel("1", startTimeStr, endTimeStr)
}
if switchArr[ExcelTypeOfflineCoin] == 1 {
// 离线金币
mgr.GenOfflineCoinExcel("1", startTimeStr, endTimeStr)
ExcelMgrSingle.GenOfflineCoinExcel("1", startTimeStr, endTimeStr)
}
startTime = et
}
mgr.SaveAll(VP.GetString("StartTime")[:10], endTime.AddDate(0, 0, -1).Format(time.DateOnly))
ExcelMgrSingle.SaveAll(VP.GetString("StartTime")[:10], endTime.AddDate(0, 0, -1).Format(time.DateOnly))
}
func main() {
defer func() {
logger.Logger.Flush()
logger.Logger.Close()
}()
VP = viperx.GetViper("config.yaml")
// mongo
vp := viperx.GetViper("mongo.yaml")
// mongo初始化
conf := &mongox.Config{}
err := vp.Unmarshal(conf)
if err != nil {
panic(fmt.Errorf("mongo config error: %v", err))
}
mongox.Init(conf)
defer mongox.Close()
// mysql
vp = viperx.GetViper("mysql.yaml")
myConf := &mysqlx.Config{}
err = vp.Unmarshal(myConf)
if err != nil {
panic(fmt.Errorf("mysql config error: %v", err))
}
mysqlx.Init(myConf)
defer mysqlx.Close()
mgr := NewExcelMgr()
ExcelMgrSingle = mgr
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", "破产人数", "参与人数", "破产率"}, "活跃破产率")
mgr.Register(ExcelTypeCtrlWinRate, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}, "控赢胜率")
mgr.Register(ExcelTypeCtrlWinRate*10, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}, "控数胜率")
mgr.Register(ExcelTypeRobotWinRate, []string{"日期", "场次id", "总局数", "平均倍数", "有炸弹分局数", "炸弹分平均倍数", "2留在手里的局数"}, "机器人输率")
mgr.Register(ExcelTypeCoinAvg, []string{"日期", "场次id", "参与人数", "人均获得金币"}, "人均获得金币")
mgr.Register(ExcelTypeBankruptOffline, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"}, "破产后离线")
mgr.Register(ExcelTypeOfflineCoin, []string{"日期", "场次id", "破产人数", "参与人数", "破产率"}, "离线金币")
if VP.GetBool("IsDatabaseMode") {
// 每天凌晨执行一次 run方法
var f func()
f = func() {
nextTime := common.HMSToTime(0, 0, 0).AddDate(0, 0, 1)
time.AfterFunc(nextTime.Sub(time.Now())+time.Second*10, func() {
go utils.RepeatUntilPanicless(run)
f()
})
}
f()
//run()
listenPort := VP.GetString("ListenPort")
http.HandleFunc("/statistics/task", Download)
go http.ListenAndServe(fmt.Sprintf(":%v", listenPort), nil)
logger.Logger.Infof("start server 0.0.0.0:%v", listenPort)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill)
sig := <-c
logger.Logger.Infof("closing down (signal: %v)", sig)
} else {
run()
}
}
func (e *ExcelMgr) SaveAll(startTime, endTime string) {
switchArr := VP.GetIntSlice("Switch")
if switchArr[ExcelTypeNewPlayerBankrupt] == 1 {
e.Save(ExcelTypeNewPlayerBankrupt, fmt.Sprintf("新用户破产率_%s_%s.xlsx", startTime, endTime))
e.Save(ExcelTypeNewPlayerBankrupt, startTime, endTime)
}
if switchArr[ExcelTypeGameTimeAvg] == 1 {
e.Save(ExcelTypeGameTimeAvg, fmt.Sprintf("新用户平局游戏时长_%s_%s.xlsx", startTime, endTime))
e.Save(ExcelTypeGameTimeAvg, startTime, endTime)
}
if switchArr[ExcelTypeGameTimeAllAvg] == 1 {
e.Save(ExcelTypeGameTimeAllAvg, startTime, endTime)
}
if switchArr[ExcelTypeGameCountAvg] == 1 {
e.Save(ExcelTypeGameCountAvg, fmt.Sprintf("新用户平均局数_%s_%s.xlsx", startTime, endTime))
e.Save(ExcelTypeGameCountAvg, startTime, endTime)
}
if switchArr[ExcelTypeGameRate] == 1 {
e.Save(ExcelTypeGameRate, fmt.Sprintf("平均倍数_%s_%s.xlsx", startTime, endTime))
e.Save(ExcelTypeGameRate, startTime, endTime)
}
if switchArr[ExcelTypeActiveRate] == 1 {
e.Save(ExcelTypeActiveRate, fmt.Sprintf("活跃破产率_%s_%s.xlsx", startTime, endTime))
e.Save(ExcelTypeActiveRate, startTime, endTime)
}
if switchArr[ExcelTypeCtrlWinRate] == 1 {
e.Save(ExcelTypeCtrlWinRate, fmt.Sprintf("控赢胜率_%s_%s.xlsx", startTime, endTime))
e.Save(ExcelTypeCtrlWinRate*10, fmt.Sprintf("控输胜率_%s_%s.xlsx", startTime, endTime))
e.Save(ExcelTypeCtrlWinRate, startTime, endTime)
e.Save(ExcelTypeCtrlWinRate*10, startTime, endTime)
}
if switchArr[ExcelTypeRobotWinRate] == 1 {
e.Save(ExcelTypeRobotWinRate, fmt.Sprintf("机器人输率_%s_%s.xlsx", startTime, endTime))
e.Save(ExcelTypeRobotWinRate, startTime, endTime)
}
if switchArr[ExcelTypeCoinAvg] == 1 {
e.Save(ExcelTypeCoinAvg, fmt.Sprintf("人均获得金币_%s_%s.xlsx", startTime, endTime))
e.Save(ExcelTypeCoinAvg, startTime, endTime)
}
if switchArr[ExcelTypeBankruptOffline] == 1 {
e.Save(ExcelTypeBankruptOffline, fmt.Sprintf("破产后离线_%s_%s.xlsx", startTime, endTime))
e.Save(ExcelTypeBankruptOffline, startTime, endTime)
}
if switchArr[ExcelTypeOfflineCoin] == 1 {
e.Save(ExcelTypeOfflineCoin, fmt.Sprintf("离线金币_%s_%s.xlsx", startTime, endTime))
e.Save(ExcelTypeOfflineCoin, startTime, endTime)
}
}
@ -223,6 +275,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)

View File

@ -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)

View File

@ -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
}

5
todo
View File

@ -7,4 +7,7 @@ dbproxy优化:
参考 https://go-zero.dev/ 中的goctl工具
消息队列数据恢复发送:
发送失败的消息会写入本地文件等mq正常后尝试重新发送
发送失败的消息会写入本地文件等mq正常后尝试重新发送
代理业务需要重构支持worldsrv的滚动更新
dbproxy/mq/c_invite.go

Some files were not shown because too many files have changed in this diff Show More