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 /robot/robot
/ranksrv/ranksrv /ranksrv/ranksrv
/schedulesrv/schedulesrv /schedulesrv/schedulesrv
/machine/machine /machine/machine
/statistics/statistics
/statistics/task/task*

View File

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

View File

@ -1,8 +1,8 @@
@echo off @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 echo go build %%i
go build -o ./%%i/%%i.exe ../%%i/ go build -o ./%%i/%%i.exe ../%%i/
) )

View File

@ -250,6 +250,7 @@ func RegisterClockFunc(fs *ClockFunc) {
if fs == nil { if fs == nil {
return return
} }
if fs.OnSecTimerFunc != nil { if fs.OnSecTimerFunc != nil {
fs.event = fs.event | 1<<ClockEventSecond fs.event = fs.event | 1<<ClockEventSecond
} }
@ -272,5 +273,9 @@ func RegisterClockFunc(fs *ClockFunc) {
fs.event = fs.event | 1<<ClockEventShutdown fs.event = fs.event | 1<<ClockEventShutdown
} }
if fs.event == 0 {
return
}
ClockMgrSingleton.RegisterSinker(fs) ClockMgrSingleton.RegisterSinker(fs)
} }

View File

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

View File

@ -2,13 +2,15 @@ package common
import ( import (
"fmt" "fmt"
rawproto "google.golang.org/protobuf/proto" 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/logger"
"mongo.games.com/goserver/core/netlib" "mongo.games.com/goserver/core/netlib"
"mongo.games.com/goserver/core/profile" "mongo.games.com/goserver/core/profile"
"mongo.games.com/goserver/core/utils" "mongo.games.com/goserver/core/utils"
"mongo.games.com/game/proto"
"mongo.games.com/game/protocol/server"
) )
var ( 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 return false
} }
func InSameDayNoZero(tNow, tPre time.Time) bool { func InSameDayNoZero(tNow, tPre time.Time) bool {
if tNow.Day() != tPre.Day() { if tNow.Day() != tPre.Day() {
@ -110,7 +111,7 @@ func DiffMonth(tNow, tPre time.Time) int {
return int(diffMonth) 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 { return timer.StartTimer(timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool {
if method != nil { if method != nil {
method() method()
@ -126,6 +127,7 @@ func StrTimeToTs(strTime string) int64 {
} }
return rTime.Unix() return rTime.Unix()
} }
func TsToStrTime(tc int64) string { func TsToStrTime(tc int64) string {
//return time.Now().Format("2018-07-02 19:14:00") //return time.Now().Format("2018-07-02 19:14:00")
return time.Unix(tc, 0).Format("2006-01-02 15:04:05") 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": { "Compound": {
"71002": 10 "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") logger.Logger.Error("UpdateDbShopState == nil")
return 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}}) err = clog.UpdateId(args.Log.LogId, bson.M{"$set": bson.M{"state": args.Log.State}})
if err != nil { if err != nil {
logger.Logger.Error("DbShopLogSvc.UpdateDbShopState error:", err) logger.Logger.Error("DbShopLogSvc.UpdateDbShopState error:", err, "LogId = ", args.Log.LogId)
return nil return nil
} }
*ret = true *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{"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{"-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 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{"-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{"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{"ts", "cycleid"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"gamedif"}, Background: true, Sparse: true})
} }
return c_gameplayerlistlog 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{"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{"-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 return c_itemlog
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2057,6 +2057,7 @@ func (this *Scene) IsControl(hasRobotGaming bool) bool {
// Statistics 玩家游戏数据统计 // Statistics 玩家游戏数据统计
// 包含水池统计,黑白名单统计,新手调控统计,个人水池统计 // 包含水池统计,黑白名单统计,新手调控统计,个人水池统计
// 拉霸游戏数据统计,一次下注记录一次 StaticsLaba
func (this *Scene) Statistics(param *StaticParam) { func (this *Scene) Statistics(param *StaticParam) {
if param == nil { if param == nil {
return return
@ -2110,6 +2111,7 @@ func (this *Scene) Statistics(param *StaticParam) {
var statics []*model.PlayerGameStatics var statics []*model.PlayerGameStatics
keyGameId := strconv.Itoa(this.GetGameId()) keyGameId := strconv.Itoa(this.GetGameId())
keyGameFreeId := strconv.Itoa(int(this.GetGameFreeId())) keyGameFreeId := strconv.Itoa(int(this.GetGameFreeId()))
keyGameDif := common.GetKeyGameDif(this.GetDBGameFree().GetGameDif())
// 当天数据统计 // 当天数据统计
// 按场次分 // 按场次分
if data, ok := p.TodayGameData.CtrlData[keyGameFreeId]; ok { if data, ok := p.TodayGameData.CtrlData[keyGameFreeId]; ok {
@ -2127,6 +2129,14 @@ func (this *Scene) Statistics(param *StaticParam) {
p.TodayGameData.CtrlData[keyGameId] = data p.TodayGameData.CtrlData[keyGameId] = data
statics = append(statics, 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, ok := p.GDatas[keyGameFreeId]; ok {
if data.FirstTime.IsZero() { if data.FirstTime.IsZero() {
@ -2149,6 +2159,27 @@ func (this *Scene) Statistics(param *StaticParam) {
p.GDatas[keyGameId] = data p.GDatas[keyGameId] = data
statics = append(statics, &data.Statics) 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 { 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 var statics []*model.PlayerGameStatics
keyGameId := strconv.Itoa(this.GetGameId()) keyGameId := strconv.Itoa(this.GetGameId())
keyGameFreeId := strconv.Itoa(int(this.GetGameFreeId())) keyGameFreeId := strconv.Itoa(int(this.GetGameFreeId()))
keyGameDif := common.GetKeyGameDif(this.GetDBGameFree().GetGameDif())
// 当天数据统计 // 当天数据统计
// 按场次分 // 按场次分
if data, ok := p.TodayGameData.CtrlData[keyGameFreeId]; ok { if data, ok := p.TodayGameData.CtrlData[keyGameFreeId]; ok {
@ -2336,6 +2368,14 @@ func (this *Scene) StaticsLaba(param *StaticLabaParam) {
p.TodayGameData.CtrlData[keyGameId] = data p.TodayGameData.CtrlData[keyGameId] = data
statics = append(statics, 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, ok := p.GDatas[keyGameFreeId]; ok {
if data.FirstTime.IsZero() { if data.FirstTime.IsZero() {
@ -2358,6 +2398,27 @@ func (this *Scene) StaticsLaba(param *StaticLabaParam) {
p.GDatas[keyGameId] = data p.GDatas[keyGameId] = data
statics = append(statics, &data.Statics) 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 { for _, data := range statics {
if data != nil { if data != nil {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,6 +8,7 @@ import (
type FortuneDragonPlayerData struct { type FortuneDragonPlayerData struct {
*base.Player *base.Player
base.LabaLog
leaveTime int32 //离开时间 leaveTime int32 //离开时间
SlotsSession *base.SlotsSession SlotsSession *base.SlotsSession
@ -31,6 +32,7 @@ func (p *FortuneDragonPlayerData) Clear() {
p.taxCoin = 0 p.taxCoin = 0
p.winCoin = 0 p.winCoin = 0
p.currentLogId = "" p.currentLogId = ""
p.LabaLog.Clear()
} }
// 需要带到world上进行数据处理 // 需要带到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) logger.Logger.Trace("(this *ScenePolicyFortuneDragon) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId)
if playerEx, ok := p.ExtraData.(*FortuneDragonPlayerData); ok { if playerEx, ok := p.ExtraData.(*FortuneDragonPlayerData); ok {
playerEx.Save(2)
m := playerEx.PushPlayer() m := playerEx.PushPlayer()
if m != nil && len(m) > 0 { if m != nil && len(m) > 0 {
b, err := json.Marshal(m) b, err := json.Marshal(m)
@ -476,6 +477,8 @@ func (this *SceneStateStartFortuneDragon) OnPlayerOp(s *base.Scene, p *base.Play
// 记录本次操作 // 记录本次操作
FortuneDragonAndSaveLog(sceneEx, playerEx, data) FortuneDragonAndSaveLog(sceneEx, playerEx, data)
case 1000:
playerEx.Save(0)
} }
} }
} }
@ -520,11 +523,6 @@ func FortuneDragonAndSaveLog(sceneEx *FortuneDragonSceneData, playerEx *FortuneD
if err == nil { if err == nil {
logid, _ := model.AutoIncGameLogId() logid, _ := model.AutoIncGameLogId()
playerEx.currentLogId = logid playerEx.currentLogId = logid
sceneEx.SaveGameDetailedLog(&base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
GameTime: 2,
})
var totalin, totalout int64 var totalin, totalout int64
if data.Results[0].FreeStatus == 1 || data.Results[0].FreeNumMax == 0 { if data.Results[0].FreeStatus == 1 || data.Results[0].FreeNumMax == 0 {
totalin = playerEx.totalBet totalin = playerEx.totalBet
@ -532,13 +530,14 @@ func FortuneDragonAndSaveLog(sceneEx *FortuneDragonSceneData, playerEx *FortuneD
if data.Results[0].FreeStatus == 3 || data.Results[0].FreeNumMax == 0 { if data.Results[0].FreeStatus == 3 || data.Results[0].FreeNumMax == 0 {
totalout = int64(data.RoundReward) + playerEx.taxCoin totalout = int64(data.RoundReward) + playerEx.taxCoin
} }
sceneEx.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{ playerEx.Cache(sceneEx.Scene, &base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
}, &base.SaveGamePlayerListLogParam{
LogId: logid, LogId: logid,
Platform: playerEx.Platform, Platform: playerEx.Platform,
Snid: playerEx.SnId, Snid: playerEx.SnId,
PlayerName: playerEx.Name, PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin, TotalIn: totalin,
TotalOut: totalout, TotalOut: totalout,
TaxCoin: playerEx.taxCoin, TaxCoin: playerEx.taxCoin,
@ -546,7 +545,6 @@ func FortuneDragonAndSaveLog(sceneEx *FortuneDragonSceneData, playerEx *FortuneD
WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin, WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin,
IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player), IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player),
IsFree: playerEx.isFree, IsFree: playerEx.isFree,
GameTime: 2,
}) })
} }
} }

View File

@ -8,6 +8,7 @@ import (
type FortuneMousePlayerData struct { type FortuneMousePlayerData struct {
*base.Player *base.Player
base.LabaLog
leaveTime int32 //离开时间 leaveTime int32 //离开时间
SlotsSession *base.SlotsSession SlotsSession *base.SlotsSession
@ -37,6 +38,7 @@ func (p *FortuneMousePlayerData) Clear() {
p.taxCoin = 0 p.taxCoin = 0
p.winCoin = 0 p.winCoin = 0
p.currentLogId = "" p.currentLogId = ""
p.LabaLog.Clear()
} }
// 需要带到world上进行数据处理 // 需要带到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) logger.Logger.Trace("(this *ScenePolicyFortuneMouse) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId)
if playerEx, ok := p.ExtraData.(*FortuneMousePlayerData); ok { if playerEx, ok := p.ExtraData.(*FortuneMousePlayerData); ok {
playerEx.Save(2)
m := playerEx.PushPlayer() m := playerEx.PushPlayer()
if m != nil && len(m) > 0 { if m != nil && len(m) > 0 {
b, err := json.Marshal(m) b, err := json.Marshal(m)
@ -480,6 +481,8 @@ func (this *SceneStateStartFortuneMouse) OnPlayerOp(s *base.Scene, p *base.Playe
// 记录本次操作 // 记录本次操作
FortuneMouseAndSaveLog(sceneEx, playerEx, data) FortuneMouseAndSaveLog(sceneEx, playerEx, data)
case 1000:
playerEx.Save(0)
} }
} }
} }
@ -524,18 +527,13 @@ func FortuneMouseAndSaveLog(sceneEx *FortuneMouseSceneData, playerEx *FortuneMou
json.Unmarshal(sp, &spinLock) json.Unmarshal(sp, &spinLock)
respinStatus = spinLock.ReSpinStatus respinStatus = spinLock.ReSpinStatus
} }
if respinStatus == 0 || respinStatus == 1 { if respinStatus != 0 && respinStatus != 1 {
data.TotalBet = 0 data.TotalBet = 0
} }
info, err := model.MarshalGameNoteByROLL(data) info, err := model.MarshalGameNoteByROLL(data)
if err == nil { if err == nil {
logid, _ := model.AutoIncGameLogId() logid, _ := model.AutoIncGameLogId()
playerEx.currentLogId = logid playerEx.currentLogId = logid
sceneEx.SaveGameDetailedLog(&base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
GameTime: 2,
})
var totalin, totalout int64 var totalin, totalout int64
if respinStatus == 0 || respinStatus == 1 { if respinStatus == 0 || respinStatus == 1 {
totalin = playerEx.totalBet totalin = playerEx.totalBet
@ -543,21 +541,21 @@ func FortuneMouseAndSaveLog(sceneEx *FortuneMouseSceneData, playerEx *FortuneMou
if respinStatus == 0 || respinStatus == 3 { if respinStatus == 0 || respinStatus == 3 {
totalout = int64(data.RoundReward) + playerEx.taxCoin totalout = int64(data.RoundReward) + playerEx.taxCoin
} }
sceneEx.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{ playerEx.Cache(sceneEx.Scene, &base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
}, &base.SaveGamePlayerListLogParam{
LogId: logid, LogId: logid,
Platform: playerEx.Platform, Platform: playerEx.Platform,
Snid: playerEx.SnId, Snid: playerEx.SnId,
PlayerName: playerEx.Name, PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin, TotalIn: totalin,
TotalOut: totalout, TotalOut: totalout,
TaxCoin: playerEx.taxCoin, TaxCoin: playerEx.taxCoin,
BetAmount: playerEx.totalBet, BetAmount: totalin,
WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin, WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin,
IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player), IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player),
IsFree: totalin == 0, IsFree: totalin == 0,
GameTime: 2,
}) })
} }
} }

View File

@ -8,6 +8,7 @@ import (
type FortuneOxPlayerData struct { type FortuneOxPlayerData struct {
*base.Player *base.Player
base.LabaLog
leaveTime int32 //离开时间 leaveTime int32 //离开时间
SlotsSession *base.SlotsSession SlotsSession *base.SlotsSession
@ -37,6 +38,7 @@ func (p *FortuneOxPlayerData) Clear() {
p.taxCoin = 0 p.taxCoin = 0
p.winCoin = 0 p.winCoin = 0
p.currentLogId = "" p.currentLogId = ""
p.LabaLog.Clear()
} }
// 需要带到world上进行数据处理 // 需要带到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) logger.Logger.Trace("(this *ScenePolicyFortuneOx) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId)
if playerEx, ok := p.ExtraData.(*FortuneOxPlayerData); ok { if playerEx, ok := p.ExtraData.(*FortuneOxPlayerData); ok {
playerEx.Save(2)
m := playerEx.PushPlayer() m := playerEx.PushPlayer()
if m != nil && len(m) > 0 { if m != nil && len(m) > 0 {
b, err := json.Marshal(m) b, err := json.Marshal(m)
@ -480,6 +481,8 @@ func (this *SceneStateStartFortuneOx) OnPlayerOp(s *base.Scene, p *base.Player,
// 记录本次操作 // 记录本次操作
FortuneOxAndSaveLog(sceneEx, playerEx, data) FortuneOxAndSaveLog(sceneEx, playerEx, data)
case 1000:
playerEx.Save(0)
} }
} }
} }
@ -527,16 +530,10 @@ func FortuneOxAndSaveLog(sceneEx *FortuneOxSceneData, playerEx *FortuneOxPlayerD
if respinStatus != 0 && respinStatus != 1 { if respinStatus != 0 && respinStatus != 1 {
data.TotalBet = 0 data.TotalBet = 0
} }
info, err := model.MarshalGameNoteByROLL(data) info, err := model.MarshalGameNoteByROLL(data)
if err == nil { if err == nil {
logid, _ := model.AutoIncGameLogId() logid, _ := model.AutoIncGameLogId()
playerEx.currentLogId = logid playerEx.currentLogId = logid
sceneEx.SaveGameDetailedLog(&base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
GameTime: 2,
})
var totalin, totalout int64 var totalin, totalout int64
if respinStatus == 0 || respinStatus == 1 { if respinStatus == 0 || respinStatus == 1 {
totalin = playerEx.totalBet totalin = playerEx.totalBet
@ -544,13 +541,14 @@ func FortuneOxAndSaveLog(sceneEx *FortuneOxSceneData, playerEx *FortuneOxPlayerD
if respinStatus == 0 || respinStatus == 3 { if respinStatus == 0 || respinStatus == 3 {
totalout = int64(data.RoundReward) + playerEx.taxCoin totalout = int64(data.RoundReward) + playerEx.taxCoin
} }
sceneEx.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{ playerEx.Cache(sceneEx.Scene, &base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
}, &base.SaveGamePlayerListLogParam{
LogId: logid, LogId: logid,
Platform: playerEx.Platform, Platform: playerEx.Platform,
Snid: playerEx.SnId, Snid: playerEx.SnId,
PlayerName: playerEx.Name, PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin, TotalIn: totalin,
TotalOut: totalout, TotalOut: totalout,
TaxCoin: playerEx.taxCoin, TaxCoin: playerEx.taxCoin,
@ -558,7 +556,6 @@ func FortuneOxAndSaveLog(sceneEx *FortuneOxSceneData, playerEx *FortuneOxPlayerD
WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin, WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin,
IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player), IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player),
IsFree: totalin == 0, IsFree: totalin == 0,
GameTime: 2,
}) })
} }
} }

View File

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

View File

@ -8,6 +8,7 @@ import (
type FortuneTigerPlayerData struct { type FortuneTigerPlayerData struct {
*base.Player *base.Player
base.LabaLog
leaveTime int32 //离开时间 leaveTime int32 //离开时间
SlotsSession *base.SlotsSession SlotsSession *base.SlotsSession
@ -40,6 +41,7 @@ func (p *FortuneTigerPlayerData) Clear() {
p.taxCoin = 0 p.taxCoin = 0
p.winCoin = 0 p.winCoin = 0
p.currentLogId = "" p.currentLogId = ""
p.LabaLog.Clear()
} }
// 需要带到world上进行数据处理 // 需要带到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) logger.Logger.Trace("(this *ScenePolicyFortuneTiger) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId)
if playerEx, ok := p.ExtraData.(*FortuneTigerPlayerData); ok { if playerEx, ok := p.ExtraData.(*FortuneTigerPlayerData); ok {
playerEx.LabaLog.Save(2) // 没有收到结束消息算2秒游戏时长
m := playerEx.PushPlayer() m := playerEx.PushPlayer()
if m != nil && len(m) > 0 { if m != nil && len(m) > 0 {
b, err := json.Marshal(m) b, err := json.Marshal(m)
@ -480,6 +481,9 @@ func (this *SceneStateStartFortuneTiger) OnPlayerOp(s *base.Scene, p *base.Playe
// 记录本次操作 // 记录本次操作
FortuneTigerAndSaveLog(sceneEx, playerEx, data) 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) { func FortuneTigerAndSaveLog(sceneEx *FortuneTigerSceneData, playerEx *FortuneTigerPlayerData, data assemble.GameEnd) {
if !playerEx.IsRob { if !playerEx.IsRob {
data.SnId = playerEx.SnId 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 data.TotalBet = 0
} }
info, err := model.MarshalGameNoteByROLL(data) info, err := model.MarshalGameNoteByROLL(data)
if err == nil { if err == nil {
logid, _ := model.AutoIncGameLogId() logid, _ := model.AutoIncGameLogId()
playerEx.currentLogId = logid playerEx.currentLogId = logid
sceneEx.SaveGameDetailedLog(&base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
GameTime: 2,
})
var totalin, totalout int64 var totalin, totalout int64
if data.Results[0].FreeStatus == 1 || data.Results[0].FreeNumMax == 0 { if data.Results[0].FreeStatus == 1 || data.Results[0].FreeNumMax == 0 {
totalin = playerEx.totalBet totalin = playerEx.totalBet
@ -536,13 +542,14 @@ func FortuneTigerAndSaveLog(sceneEx *FortuneTigerSceneData, playerEx *FortuneTig
if data.Results[0].FreeStatus == 3 || data.Results[0].FreeNumMax == 0 { if data.Results[0].FreeStatus == 3 || data.Results[0].FreeNumMax == 0 {
totalout = int64(data.RoundReward) + playerEx.taxCoin totalout = int64(data.RoundReward) + playerEx.taxCoin
} }
sceneEx.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{ playerEx.Cache(sceneEx.Scene, &base.SaveGameDetailedParam{
LogId: logid,
Detail: info,
}, &base.SaveGamePlayerListLogParam{
LogId: logid, LogId: logid,
Platform: playerEx.Platform, Platform: playerEx.Platform,
Snid: playerEx.SnId, Snid: playerEx.SnId,
PlayerName: playerEx.Name, PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin, TotalIn: totalin,
TotalOut: totalout, TotalOut: totalout,
TaxCoin: playerEx.taxCoin, TaxCoin: playerEx.taxCoin,
@ -550,7 +557,6 @@ func FortuneTigerAndSaveLog(sceneEx *FortuneTigerSceneData, playerEx *FortuneTig
WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin, WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin,
IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player), IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player),
IsFree: totalin == 0, IsFree: totalin == 0,
GameTime: 2,
}) })
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,8 @@
package thirteen package thirteen
import ( import (
"time"
"mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/logger"
"mongo.games.com/game/gamerule/thirteen" "mongo.games.com/game/gamerule/thirteen"
@ -25,7 +27,10 @@ type PlayerEx struct {
odds int32 odds int32
totalScore int64 totalScore int64
defGroup *thirteen.Group defGroup *thirteen.Group
playerPool int // 个人水池分 playerPool int // 个人水池分
AutoState int // 是否自动模式
AutoMill time.Duration // 自动时长
HandMill time.Duration // 手动时长
} }
func (this *PlayerEx) Clear() { func (this *PlayerEx) Clear() {
@ -42,6 +47,9 @@ func (this *PlayerEx) Clear() {
this.gainCoin = 0 this.gainCoin = 0
this.taxCoin = 0 this.taxCoin = 0
this.deterMine = false 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.score = [7]int64{0, 0, 0, 0, 0, 0, 0}
this.tableScore = [6]int64{} this.tableScore = [6]int64{}
this.winThreePos = make(map[int]int64) this.winThreePos = make(map[int]int64)

View File

@ -86,6 +86,7 @@ type SceneEx struct {
ctrlType int // 1控赢 2控输 0不控 ctrlType int // 1控赢 2控输 0不控
cardsArr [][13]int cardsArr [][13]int
cardsGroup []map[int]*rule.Group cardsGroup []map[int]*rule.Group
timestamp time.Time
} }
func NewThirteenWaterSceneData(s *base.Scene) *SceneEx { func NewThirteenWaterSceneData(s *base.Scene) *SceneEx {

View File

@ -4,6 +4,7 @@ import (
"strconv" "strconv"
"time" "time"
"go.mongodb.org/mongo-driver/bson/primitive"
"mongo.games.com/goserver/core" "mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/logger"
@ -11,6 +12,7 @@ import (
rule "mongo.games.com/game/gamerule/thirteen" rule "mongo.games.com/game/gamerule/thirteen"
"mongo.games.com/game/gamesrv/base" "mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model" "mongo.games.com/game/model"
"mongo.games.com/game/mq"
"mongo.games.com/game/proto" "mongo.games.com/game/proto"
"mongo.games.com/game/protocol/thirteen" "mongo.games.com/game/protocol/thirteen"
) )
@ -188,8 +190,6 @@ func (this *PolicyThirteen) OnPlayerLeave(s *base.Scene, p *base.Player, reason
Platform: playerEx.Platform, Platform: playerEx.Platform,
Snid: playerEx.SnId, Snid: playerEx.SnId,
PlayerName: playerEx.Name, PlayerName: playerEx.Name,
Channel: playerEx.Channel,
ChannelId: playerEx.ChannelId,
TotalIn: totalin, TotalIn: totalin,
TotalOut: totalout, TotalOut: totalout,
TaxCoin: playerEx.taxCoin, TaxCoin: playerEx.taxCoin,
@ -810,6 +810,11 @@ func (this *StateOp) OnEnter(s *base.Scene) {
logger.Logger.Tracef("(this *StateOp) OnEnter, sceneid=%v", s.GetSceneId()) logger.Logger.Tracef("(this *StateOp) OnEnter, sceneid=%v", s.GetSceneId())
this.BaseState.OnEnter(s) this.BaseState.OnEnter(s)
ThirteenWaterBroadcastRoomState(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 return false
} }
returnFunc := func(code thirteen.OpResultCode) { returnFunc := func(code thirteen.OpResultCode, broadcast bool) {
pack := &thirteen.SCThirteenPlayerOp{ pack := &thirteen.SCThirteenPlayerOp{
OpRetCode: code, OpRetCode: code,
OpCode: int32(opcode), OpCode: int32(opcode),
OpParam: params, OpParam: params,
Pos: int32(playerEx.GetPos()), Pos: int32(playerEx.GetPos()),
} }
if code == thirteen.OpResultCode_OPRC_Error { if broadcast {
proto.SetDefaults(pack) playerEx.Broadcast(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack, 0)
logger.Logger.Trace("SCThirteenPlayerOp:", pack) } else {
playerEx.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack) playerEx.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack)
return
} }
logger.Logger.Trace("SCThirteenPlayerOp:", pack)
} }
if !playerEx.IsGameing() { if !playerEx.IsGameing() {
returnFunc(thirteen.OpResultCode_OPRC_Error) returnFunc(thirteen.OpResultCode_OPRC_Error, false)
return true return true
} }
switch opcode { switch opcode {
case rule.ThirteenWaterPlayerOpMS: //确定牌 case rule.ThirteenWaterPlayerOpMS: //确定牌
//if playerEx.deterMine { // 确认牌型
// returnFunc(thirteen.OpResultCode_OPRC_Error)
// return false
//}
if len(params) == 13 { if len(params) == 13 {
//校验牌 //校验牌
a := rule.DelCards(playerEx.cards[:], common.Int64Toint(params)) a := rule.DelCards(playerEx.cards[:], common.Int64Toint(params))
if len(a) != 0 { if len(a) != 0 {
logger.Logger.Error("the cards is error.") logger.Logger.Error("the cards is error.")
returnFunc(thirteen.OpResultCode_OPRC_Error) returnFunc(thirteen.OpResultCode_OPRC_Error, false)
return true return true
} }
//牌赋值 //牌赋值
@ -875,6 +876,7 @@ func (this *StateOp) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, param
playerEx.Trusteeship = 0 playerEx.Trusteeship = 0
playerEx.UnmarkFlag(base.PlayerState_Auto) playerEx.UnmarkFlag(base.PlayerState_Auto)
playerEx.deterMine = true playerEx.deterMine = true
playerEx.AutoState = 0
//如果所有玩家都确认牌之后 可以直接开始下一阶段 //如果所有玩家都确认牌之后 可以直接开始下一阶段
a := true a := true
for _, v := range sceneEx.players { 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.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.Trusteeship = 0
playerEx.UnmarkFlag(base.PlayerState_Auto) 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 { if len(params) == 13 {
//校验牌 //校验牌
a := rule.DelCards(playerEx.cards[:], common.Int64Toint(params)) remain := len(playerEx.cards)
if len(a) != 0 { remainCards := make([]int, remain)
logger.Logger.Error("the cards is error.") copy(remainCards, playerEx.cards[:])
returnFunc(thirteen.OpResultCode_OPRC_Error) for _, v := range params {
return true 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.Head[:], common.Int64Toint(params[:3]))
copy(playerEx.preCardsO.Mid[:], common.Int64Toint(params[3:8])) copy(playerEx.preCardsO.Mid[:], common.Int64Toint(params[3:8]))
copy(playerEx.preCardsO.End[:], common.Int64Toint(params[8:])) copy(playerEx.preCardsO.End[:], common.Int64Toint(params[8:]))
playerEx.preCardsO.PokerType = 0 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: case rule.ThirteenWaterPlayerOpReset:
// 取消确认 // 取消确认
playerEx.deterMine = false playerEx.deterMine = false
pack := &thirteen.SCThirteenPlayerOp{ returnFunc(thirteen.OpResultCode_OPRC_Sucess, true)
OpRetCode: thirteen.OpResultCode_OPRC_Sucess,
OpCode: int32(opcode), case rule.ThirteenWaterPlayerOpAuto:
OpParam: params, if len(params) == 0 {
Pos: int32(playerEx.GetPos()), return true
} }
playerEx.Broadcast(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack, 0)
playerEx.AutoState = int(params[0])
default: default:
return false return false
@ -943,6 +977,19 @@ func (this *StateOp) OnLeave(s *base.Scene) {
for _, player := range sceneEx.players { for _, player := range sceneEx.players {
if player != nil && player.IsGameing() { 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) { if player.preCardsO != nil && player.preCardsO.PokerType != -1 && (player.cardsO == nil || player.cardsO.PokerType == -1) {
player.cardsO = player.preCardsO player.cardsO = player.preCardsO
@ -1122,7 +1169,23 @@ func (this *StateOp) OnLeave(s *base.Scene) {
func (this *StateOp) OnTick(s *base.Scene) { func (this *StateOp) OnTick(s *base.Scene) {
this.BaseState.OnTick(s) this.BaseState.OnTick(s)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok { 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) s.ChangeSceneState(rule.ThirteenWaterSceneStateShowCards)
} }
} }
@ -1438,8 +1501,6 @@ func (this *StateBilled) OnEnter(s *base.Scene) {
Platform: o_player.Platform, Platform: o_player.Platform,
Snid: o_player.SnId, Snid: o_player.SnId,
PlayerName: o_player.Name, PlayerName: o_player.Name,
Channel: o_player.Channel,
ChannelId: o_player.ChannelId,
TotalIn: totalin, TotalIn: totalin,
TotalOut: totalout, TotalOut: totalout,
TaxCoin: o_player.taxCoin, TaxCoin: o_player.taxCoin,

View File

@ -1302,24 +1302,20 @@ func (this *TienLenSceneData) SendHandCardOdds() {
allcs[i], allcs[j] = allcs[j], allcs[i] 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:]) allcs = common.DelSliceIn32s(allcs, this.testPokers[1:])
this.testPokers = append(this.testPokers, allcs...)
for _, seat := range this.seats { for _, seat := range this.seats {
if seat != nil && seat.IsGameing() { if seat != nil && seat.IsGameing() && seat.SnId == this.testPokers[0] {
if seat.SnId == this.testPokers[0] { f1(seat, this.testPokers[1:14])
f1(seat, this.testPokers[1:]) this.testPokers = this.testPokers[14:]
} else { break
f1(seat, allcs[:13]) }
allcs = allcs[13:] }
} 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 this.testPokers = nil

View File

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

13
go.mod
View File

@ -19,6 +19,7 @@ require (
github.com/jinzhu/now v1.1.5 github.com/jinzhu/now v1.1.5
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/mojocn/base64Captcha v1.3.6 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/cast v1.7.0
github.com/spf13/viper v1.19.0 github.com/spf13/viper v1.19.0
github.com/tealeg/xlsx v1.0.5 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/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/xtaci/kcp-go v5.4.20+incompatible // 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/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
go.etcd.io/etcd/api/v3 v3.5.16 // 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/automaxprocs v1.6.0 // indirect
go.uber.org/multierr v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect
go.uber.org/zap v1.24.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/image v0.18.0 // indirect
golang.org/x/net v0.30.0 // indirect golang.org/x/net v0.33.0 // indirect
golang.org/x/sync v0.8.0 // indirect golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.26.0 // indirect golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.19.0 // indirect golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.7.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/api v0.0.0-20240814211410-ddb44dafa142 // indirect
google.golang.org/genproto/googleapis/rpc 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/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 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= 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/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 h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 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-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 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-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 h1:1tgOaEq92IOEumR1/JfYS/eR0KHOCsRv/rYXXh6YJQE=
github.com/xuri/excelize/v2 v2.9.0/go.mod h1:uqey4QBZ9gdMeWApPLdhm9x+9o2lq4iVmjiLfBS5hdE= github.com/xuri/excelize/v2 v2.9.0/go.mod h1:uqey4QBZ9gdMeWApPLdhm9x+9o2lq4iVmjiLfBS5hdE=
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A= 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.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 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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-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 h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= 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.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 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= 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-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 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= 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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= 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.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-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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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.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 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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-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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 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.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 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 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.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 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 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"` LogId bson.ObjectId `bson:"_id"`
SnId int32 //玩家id SnId int32 //玩家id
Channel string // 渠道 Channel string // 渠道
ChannelId string // 推广渠道
Platform string //平台名称 Platform string //平台名称
GameId int //游戏id GameId int //游戏id
GameFreeID int32 //房间id GameFreeID int32 //房间id
GameDif string // 游戏分组
CreateTime int64 // 注册时间 CreateTime int64 // 注册时间
UseCoin int64 // 消耗金币 UseCoin int64 // 消耗金币
@ -22,12 +24,14 @@ func NewBankruptLog() *BankruptLog {
return log 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 := NewBankruptLog()
cl.SnId = snid cl.SnId = snid
cl.Platform = platform cl.Platform = platform
cl.Channel = channel cl.Channel = channel
cl.ChannelId = channelId
cl.GameId = gameId cl.GameId = gameId
cl.GameDif = gamedif
cl.GameFreeID = gamefreeid cl.GameFreeID = gamefreeid
cl.CreateTime = createtime cl.CreateTime = createtime

View File

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

View File

@ -23,9 +23,33 @@ type CoinPoolCtx struct {
Controlled bool //被水池控制了 Controlled bool //被水池控制了
} }
type GameDetailedLogRet struct { type GameDetailedLog struct {
Gplt GameDetailedLogType 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 { type GameDetailedLogType struct {
PageNo int //当前页码 PageNo int //当前页码
PageSize int //每页数量 PageSize int //每页数量
@ -33,64 +57,8 @@ type GameDetailedLogType struct {
Data []*GameDetailedLog //当页数据 Data []*GameDetailedLog //当页数据
} }
type GameDetailedLog struct { type GameDetailedLogRet struct {
Id bson.ObjectId `bson:"_id"` //记录ID Gplt GameDetailedLogType
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
} }
func InsertGameDetailedLog(log *GameDetailedLog) (err error) { func InsertGameDetailedLog(log *GameDetailedLog) (err error) {

View File

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

View File

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

View File

@ -1262,9 +1262,11 @@ func SavePlayerData(pd *PlayerData) bool {
} }
if pd != nil { if pd != nil {
var ret bool var ret bool
t1 := time.Now()
err := rpcCli.CallWithTimeout("PlayerDataSvc.SavePlayerData", pd, &ret, time.Second*30) err := rpcCli.CallWithTimeout("PlayerDataSvc.SavePlayerData", pd, &ret, time.Second*30)
if err != nil { 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 false
} }
return ret return ret

View File

@ -15,6 +15,13 @@ func GenerateOnline(online map[string]map[string]int) *mq.RabbitMQData {
return NewRabbitMQData(mq.BackOnline, params) 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 玩家登陆事件 // GenerateLogin 玩家登陆事件
func GenerateLogin(o *PlayerLoginEvent) *mq.RabbitMQData { func GenerateLogin(o *PlayerLoginEvent) *mq.RabbitMQData {
return NewRabbitMQData(mq.BackLogin, o) 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{} 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 { 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] != "" { if len(name) > 0 {
return Send(name[0], data) return Send(name, data, options...)
} }
key := c.getName(data) key := c.getName(data)
if key == "" { if key == "" {
key = "_null_" key = "_null_"
} }
return Send(key, data) return Send(key, data, options...)
} }
type RegisterHandlerParam struct { type RegisterHandlerParam struct {
@ -132,7 +132,14 @@ func RegisterMessage(param *RegisterMessageParam) {
// Write 发送消息 // Write 发送消息
// 默认队列名称规则队列前缀_消息结构体名称 // 默认队列名称规则队列前缀_消息结构体名称
func Write(data interface{}, name ...string) error { 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 注册消息处理函数 // RegisterHandler 注册消息处理函数

View File

@ -18,11 +18,14 @@ const (
BackSystemPermitTask = "back_permittask" BackSystemPermitTask = "back_permittask"
BackSystemJyb = "back_jyblog" BackSystemJyb = "back_jyblog"
BackActivityLog = "back_activitylog" BackActivityLog = "back_activitylog"
BackOnlineGame = "back_onlinegame"
) )
// mgrsrv // go后端
const () const (
BackThirteenAutoLog = "b_thirteenautolog"
)
// worldsrv 消息 // 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; 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 { message DB_GameCoinPool {
int32 Id = 1; int32 Id = 1;

View File

@ -386,7 +386,7 @@ type CSThirteenPlayerOp struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields 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发过来减少数据传输 // 第一种玩家从推荐牌型中选择一个把Poker.IndexType发过来减少数据传输
// 第二种:按头墩中墩尾墩顺序把牌发过来 // 第二种:按头墩中墩尾墩顺序把牌发过来

View File

@ -73,7 +73,7 @@ message SCThirteenPlayerCards {
// //
//PACKET_CSThirteenPlayerOp //PACKET_CSThirteenPlayerOp
message 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发过来 // 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 OrderType = 6;// 0, 1
int32 GameFreeId = 7; int32 GameFreeId = 7;
string Channel = 8; string Channel = 8;
string GameDif = 9; //
string ChannelId = 10; // 广ID
} }
message SAQueryOnlineReportList{ message SAQueryOnlineReportList{
TagCode Tag = 1; // 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_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/utils"
"mongo.games.com/goserver/core/viperx" "mongo.games.com/goserver/core/viperx"
"mongo.games.com/game/mq"
mongomodel "mongo.games.com/game/statistics/modelmongo" mongomodel "mongo.games.com/game/statistics/modelmongo"
mysqlmodel "mongo.games.com/game/statistics/modelmysql" 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" "mongo.games.com/game/statistics/syn"
) )
@ -68,9 +69,9 @@ func DoTickPlatform(ctx context.Context, wg *sync.WaitGroup, duration time.Durat
} }
func main() { func main() {
VP = viperx.GetViper("config", "yaml") VP = viperx.GetViper("config.yaml")
// mongo // mongo
vp := viperx.GetViper("mongo", "yaml") vp := viperx.GetViper("mongo.yaml")
// mongo初始化 // mongo初始化
conf := &mongox.Config{} conf := &mongox.Config{}
err := vp.Unmarshal(conf) err := vp.Unmarshal(conf)
@ -81,7 +82,7 @@ func main() {
defer mongox.Close() defer mongox.Close()
// mysql // mysql
vp = viperx.GetViper("mysql", "yaml") vp = viperx.GetViper("mysql.yaml")
myConf := &mysqlx.Config{} myConf := &mysqlx.Config{}
err = vp.Unmarshal(myConf) err = vp.Unmarshal(myConf)
if err != nil { if err != nil {
@ -92,26 +93,32 @@ func main() {
mysqlx.SetAutoMigrateTables(mysqlmodel.Tables) mysqlx.SetAutoMigrateTables(mysqlmodel.Tables)
// mq
mq.StartConsumer(VP.GetString("rabbitmq.url"), VP.GetString("rabbitmq.exchange"), true)
wg := &sync.WaitGroup{} wg := &sync.WaitGroup{}
ctx, cancel := context.WithCancel(context.Background()) 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"))*time.Second, SyncSnId)
DoTick(ctx, wg, time.Duration(VP.GetInt64("update_second_snid"))*time.Second, func(ctx context.Context) { //DoTick(ctx, wg, time.Duration(VP.GetInt64("update_second_snid"))*time.Second, func(ctx context.Context) {
wg := new(sync.WaitGroup) // wg := new(sync.WaitGroup)
for _, v := range VP.GetStringSlice("platforms") { // for _, v := range VP.GetStringSlice("platforms") {
platform := v // platform := v
wg.Add(1) // wg.Add(1)
go func() { // go func() {
defer wg.Done() // defer wg.Done()
Static(platform) // Static(platform)
}() // }()
} // }
wg.Wait() // wg.Wait()
}) //})
// 同步邀请数据
DoTick(ctx, wg, time.Duration(VP.GetInt64("update_second_invite"))*time.Second, SyncInvite) 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"), 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) { func(ctx context.Context, platform string, batchSize int) {
err := syn.ItemGainDone(&syn.Data[mongomodel.ItemLog]{ 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) c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill) signal.Notify(c, os.Interrupt, os.Kill)
@ -162,36 +169,36 @@ func SyncSnId(ctx context.Context) {
} }
// Static 玩家id触发数据统计 // Static 玩家id触发数据统计
func Static(platform string) { //func Static(platform string) {
// 查询需要更新的玩家id // // 查询需要更新的玩家id
var ids []*mysqlmodel.UserID // var ids []*mysqlmodel.UserID
db, err := mysqlx.GetDatabase(platform) // db, err := mysqlx.GetDatabase(platform)
if err != nil { // if err != nil {
logger.Logger.Errorf("GetDatabase error: %v", err) // logger.Logger.Errorf("GetDatabase error: %v", err)
return // return
} // }
if err := db.Limit(VP.GetInt("update_snid_num")).Find(&ids).Error; err != nil { // if err := db.Limit(VP.GetInt("update_snid_num")).Find(&ids).Error; err != nil {
logger.Logger.Warnf("Get UserID error: %v", err) // logger.Logger.Warnf("Get UserID error: %v", err)
return // return
} // }
//
if len(ids) == 0 { // if len(ids) == 0 {
logger.Logger.Tracef("Static: no need to update") // logger.Logger.Tracef("Static: no need to update")
return // return
} // }
//
// 统计玩家跳出记录 // // 统计玩家跳出记录
if err := static.UserLogin(platform, ids); err != nil { // //if err := static.UserLogin(platform, ids); err != nil {
logger.Logger.Errorf("StaticUserLogin error: %v", err) // // logger.Logger.Errorf("StaticUserLogin error: %v", err)
return // // return
} // //}
//
// 删除更新过的玩家id // // 删除更新过的玩家id
if err := db.Delete(ids).Error; err != nil { // if err := db.Delete(ids).Error; err != nil {
logger.Logger.Errorf("Delete error: %v", err) // logger.Logger.Errorf("Delete error: %v", err)
return // return
} // }
} //}
// SyncInvite 同步邀请数据 // SyncInvite 同步邀请数据
func SyncInvite(ctx context.Context) { func SyncInvite(ctx context.Context) {

View File

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

View File

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

View File

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

View File

@ -1 +1,35 @@
package mq 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 package static
import ( //func getAccountTel(platform string, id int) (string, error) {
"context" // acc := &mongomodel.Account{}
"errors" // cc, err := mymongo.GetUserCollection(platform, mongomodel.UserAccount)
// if err != nil {
"go.mongodb.org/mongo-driver/bson" // logger.Logger.Errorf("get collection %s error %v", mongomodel.UserAccount, err)
"go.mongodb.org/mongo-driver/mongo" // return "", err
"go.mongodb.org/mongo-driver/mongo/options" // }
"mongo.games.com/goserver/core/logger" // dd := cc.FindOne(context.TODO(), bson.M{"snid": id}, options.FindOne().SetProjection(bson.M{"tel": 1}))
// err = dd.Err()
mymongo "mongo.games.com/goserver/core/mongox" // if err != nil {
mymysql "mongo.games.com/goserver/core/mysqlx" // if errors.Is(err, mongo.ErrNoDocuments) {
// logger.Logger.Tracef("getAccountTel %v not found in user_account", id)
mongomodel "mongo.games.com/game/statistics/modelmongo" // return "", nil
mysqlmodel "mongo.games.com/game/statistics/modelmysql" // }
) // logger.Logger.Errorf("getAccountTel %v get user_account err: %v", id, err)
// return "", err
func getAccountTel(platform string, id int) (string, error) { // }
acc := &mongomodel.Account{} // if err := dd.Decode(acc); err != nil {
cc, err := mymongo.GetUserCollection(platform, mongomodel.UserAccount) // logger.Logger.Errorf("getAccountTel %v decode user_account err: %v", id, err)
if err != nil { // return "", err
logger.Logger.Errorf("get collection %s error %v", mongomodel.UserAccount, err) // }
return "", err // return acc.Tel, nil
} //}
dd := cc.FindOne(context.TODO(), bson.M{"snid": id}, options.FindOne().SetProjection(bson.M{"tel": 1})) //
err = dd.Err() //// 游戏结束离开
if err != nil { //func checkGameOver(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) {
if errors.Is(err, mongo.ErrNoDocuments) { // // 最早的一条掉线记录并且是游戏结束离开
logger.Logger.Tracef("getAccountTel %v not found in user_account", id) // a := &mongomodel.LoginLog{}
return "", nil // c, err := mymongo.GetLogCollection(platform, mongomodel.LogLogin)
} // if err != nil {
logger.Logger.Errorf("getAccountTel %v get user_account err: %v", id, err) // logger.Logger.Errorf("get collection %s error %v", mongomodel.LogLogin, err)
return "", err // return false, err
} // }
if err := dd.Decode(acc); err != nil { // d := c.FindOne(context.TODO(), bson.M{"snid": id, "logtype": mongomodel.LogTypeDrop, "gameid": 0, "lastgameid": bson.D{{"$gt", 0}}},
logger.Logger.Errorf("getAccountTel %v decode user_account err: %v", id, err) // options.FindOne().SetSort(bson.D{{"time", 1}}))
return "", err // err = d.Err()
} // if err != nil {
return acc.Tel, nil // if errors.Is(err, mongo.ErrNoDocuments) {
} // logger.Logger.Tracef("checkGameOver %v not found in log_login", id)
// return false, nil
// 游戏结束离开 // }
func checkGameOver(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) { // logger.Logger.Errorf("checkGameOver %v get log_login err: %v", id, err)
// 最早的一条掉线记录并且是游戏结束离开 // return false, err
a := &mongomodel.LoginLog{} // }
c, err := mymongo.GetLogCollection(platform, mongomodel.LogLogin) // if err := d.Decode(a); err != nil {
if err != nil { // logger.Logger.Errorf("checkGameOver %v decode log_login err: %v", id, err)
logger.Logger.Errorf("get collection %s error %v", mongomodel.LogLogin, err) // return false, err
return false, err // }
} //
d := c.FindOne(context.TODO(), bson.M{"snid": id, "logtype": mongomodel.LogTypeDrop, "gameid": 0, "lastgameid": bson.D{{"$gt", 0}}}, // // account tel
options.FindOne().SetSort(bson.D{{"time", 1}})) // tel, err := getAccountTel(platform, id)
err = d.Err() // if err != nil {
if err != nil { // logger.Logger.Warnf("get account tel %v err: %v", id, err)
if errors.Is(err, mongo.ErrNoDocuments) { // }
logger.Logger.Tracef("checkGameOver %v not found in log_login", id) //
return false, nil // update := &mysqlmodel.UserLogin{
} // //OfflineTs: int(a.Ts),
logger.Logger.Errorf("checkGameOver %v get log_login err: %v", id, err) // OfflineTime: a.Time,
return false, err // OutType: mysqlmodel.OutTypeGameOver,
} // GameID: a.LastGameID,
if err := d.Decode(a); err != nil { // Tel: tel,
logger.Logger.Errorf("checkGameOver %v decode log_login err: %v", id, err) // DeviceName: a.DeviceName,
return false, err // AppVersion: a.AppVersion,
} // BuildVersion: a.BuildVersion,
// AppChannel: a.AppChannel,
// account tel // ChannelId: a.ChannelId,
tel, err := getAccountTel(platform, id) // }
if err != nil { //
logger.Logger.Warnf("get account tel %v err: %v", id, err) // if err := db.Model(login).Select(
} // "OfflineTime", "OutType", "GameID", "DeviceName", "AppVersion", "BuildVersion", "AppChannel", "Tel",
// ).Updates(update).Error; err != nil {
update := &mysqlmodel.UserLogin{ // logger.Logger.Errorf("checkLogin %v update user_login err: %v", id, err)
//OfflineTs: int(a.Ts), // return false, err
OfflineTime: a.Time, // }
OutType: mysqlmodel.OutTypeGameOver, //
GameID: a.LastGameID, // return true, nil
Tel: tel, //}
DeviceName: a.DeviceName, //
AppVersion: a.AppVersion, //// 游戏中离开
BuildVersion: a.BuildVersion, //func checkGaming(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) {
AppChannel: a.AppChannel, // // 最早的一条掉线记录并且是游戏中掉线
ChannelId: a.ChannelId, // a := &mongomodel.LoginLog{}
} // c, err := mymongo.GetLogCollection(platform, mongomodel.LogLogin)
// if err != nil {
if err := db.Model(login).Select( // logger.Logger.Errorf("get collection %s error %v", mongomodel.LogLogin, err)
"OfflineTime", "OutType", "GameID", "DeviceName", "AppVersion", "BuildVersion", "AppChannel", "Tel", // return false, err
).Updates(update).Error; err != nil { // }
logger.Logger.Errorf("checkLogin %v update user_login err: %v", id, err) // d := c.FindOne(context.TODO(), bson.M{"snid": id, "logtype": mongomodel.LogTypeDrop, "gameid": bson.D{{"$gt", 0}}},
return false, err // options.FindOne().SetSort(bson.D{{"time", 1}}))
} // err = d.Err()
// if err != nil {
return true, nil // if errors.Is(err, mongo.ErrNoDocuments) {
} // logger.Logger.Tracef("checkGaming %v not found in log_login", id)
// return false, nil
// 游戏中离开 // }
func checkGaming(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) { // logger.Logger.Errorf("checkGaming %v get log_login err: %v", id, err)
// 最早的一条掉线记录并且是游戏中掉线 // return false, err
a := &mongomodel.LoginLog{} // }
c, err := mymongo.GetLogCollection(platform, mongomodel.LogLogin) // if err := d.Decode(a); err != nil {
if err != nil { // logger.Logger.Errorf("checkGaming %v decode log_login err: %v", id, err)
logger.Logger.Errorf("get collection %s error %v", mongomodel.LogLogin, err) // return false, err
return false, err // }
} //
d := c.FindOne(context.TODO(), bson.M{"snid": id, "logtype": mongomodel.LogTypeDrop, "gameid": bson.D{{"$gt", 0}}}, // // account tel
options.FindOne().SetSort(bson.D{{"time", 1}})) // tel, err := getAccountTel(platform, id)
err = d.Err() // if err != nil {
if err != nil { // logger.Logger.Warnf("get account tel %v err: %v", id, err)
if errors.Is(err, mongo.ErrNoDocuments) { // }
logger.Logger.Tracef("checkGaming %v not found in log_login", id) //
return false, nil // update := &mysqlmodel.UserLogin{
} // //OfflineTs: int(a.Ts),
logger.Logger.Errorf("checkGaming %v get log_login err: %v", id, err) // OfflineTime: a.Time,
return false, err // OutType: mysqlmodel.OutTypeGaming,
} // GameID: a.GameId,
if err := d.Decode(a); err != nil { // Tel: tel,
logger.Logger.Errorf("checkGaming %v decode log_login err: %v", id, err) // DeviceName: a.DeviceName,
return false, err // AppVersion: a.AppVersion,
} // BuildVersion: a.BuildVersion,
// AppChannel: a.AppChannel,
// account tel // ChannelId: a.ChannelId,
tel, err := getAccountTel(platform, id) // }
if err != nil { //
logger.Logger.Warnf("get account tel %v err: %v", id, err) // if err := db.Model(login).Select(
} // "OfflineTime", "OutType", "GameID", "DeviceName", "AppVersion", "BuildVersion", "AppChannel", "Tel",
// ).Updates(update).Error; err != nil {
update := &mysqlmodel.UserLogin{ // logger.Logger.Errorf("checkLogin %v update user_login err: %v", id, err)
//OfflineTs: int(a.Ts), // return false, err
OfflineTime: a.Time, // }
OutType: mysqlmodel.OutTypeGaming, //
GameID: a.GameId, // return true, nil
Tel: tel, //}
DeviceName: a.DeviceName, //
AppVersion: a.AppVersion, //// 登录后离开
BuildVersion: a.BuildVersion, //func checkLogin(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) {
AppChannel: a.AppChannel, // // 最早的一条掉线记录
ChannelId: a.ChannelId, // a := &mongomodel.LoginLog{}
} // c, err := mymongo.GetLogCollection(platform, mongomodel.LogLogin)
// if err != nil {
if err := db.Model(login).Select( // logger.Logger.Errorf("get collection %s error %v", mongomodel.LogLogin, err)
"OfflineTime", "OutType", "GameID", "DeviceName", "AppVersion", "BuildVersion", "AppChannel", "Tel", // return false, err
).Updates(update).Error; err != nil { // }
logger.Logger.Errorf("checkLogin %v update user_login err: %v", id, err) // d := c.FindOne(context.TODO(), bson.M{"snid": id, "logtype": mongomodel.LogTypeDrop}, options.FindOne().SetSort(bson.D{{"time", 1}}))
return false, err // err = d.Err()
} // if err != nil {
// if errors.Is(err, mongo.ErrNoDocuments) {
return true, nil // 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)
func checkLogin(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) { // return false, err
// 最早的一条掉线记录 // }
a := &mongomodel.LoginLog{} // if err := d.Decode(a); err != nil {
c, err := mymongo.GetLogCollection(platform, mongomodel.LogLogin) // logger.Logger.Errorf("checkLogin %v decode log_login err: %v", id, err)
if err != nil { // return false, err
logger.Logger.Errorf("get collection %s error %v", mongomodel.LogLogin, err) // }
return false, err //
} // // account tel
d := c.FindOne(context.TODO(), bson.M{"snid": id, "logtype": mongomodel.LogTypeDrop}, options.FindOne().SetSort(bson.D{{"time", 1}})) // tel, err := getAccountTel(platform, id)
err = d.Err() // if err != nil {
if err != nil { // logger.Logger.Warnf("get account tel %v err: %v", id, err)
if errors.Is(err, mongo.ErrNoDocuments) { // }
logger.Logger.Tracef("checkLogin %v not found in log_login", id) //
return false, nil // update := &mysqlmodel.UserLogin{
} // //OfflineTs: int(a.Ts),
logger.Logger.Errorf("checkLogin %v get log_login err: %v", id, err) // OfflineTime: a.Time,
return false, err // OutType: mysqlmodel.OutTypeLogin,
} // Tel: tel,
if err := d.Decode(a); err != nil { // DeviceName: a.DeviceName,
logger.Logger.Errorf("checkLogin %v decode log_login err: %v", id, err) // AppVersion: a.AppVersion,
return false, err // BuildVersion: a.BuildVersion,
} // AppChannel: a.AppChannel,
// ChannelId: a.ChannelId,
// account tel // }
tel, err := getAccountTel(platform, id) //
if err != nil { // if err := db.Model(login).Select(
logger.Logger.Warnf("get account tel %v err: %v", id, err) // "OfflineTime", "OutType", "DeviceName", "AppVersion", "BuildVersion", "AppChannel", "Tel",
} // ).Updates(update).Error; err != nil {
// logger.Logger.Errorf("checkLogin %v update user_login err: %v", id, err)
update := &mysqlmodel.UserLogin{ // return false, err
//OfflineTs: int(a.Ts), // }
OfflineTime: a.Time, //
OutType: mysqlmodel.OutTypeLogin, // return true, nil
Tel: tel, //}
DeviceName: a.DeviceName, //
AppVersion: a.AppVersion, //// 注册后离开
BuildVersion: a.BuildVersion, //func checkRegister(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) {
AppChannel: a.AppChannel, // a := &mongomodel.Account{}
ChannelId: a.ChannelId, // c, err := mymongo.GetUserCollection(platform, mongomodel.UserAccount)
} // if err != nil {
// logger.Logger.Errorf("get collection %s error %v", mongomodel.UserAccount, err)
if err := db.Model(login).Select( // return false, err
"OfflineTime", "OutType", "DeviceName", "AppVersion", "BuildVersion", "AppChannel", "Tel", // }
).Updates(update).Error; err != nil { // d := c.FindOne(context.TODO(), bson.M{"snid": id})
logger.Logger.Errorf("checkLogin %v update user_login err: %v", id, err) // err = d.Err()
return false, err // if err != nil {
} // if errors.Is(err, mongo.ErrNoDocuments) {
// logger.Logger.Warnf("checkRegister %v not found in user_account", id)
return true, nil // return false, nil
} // }
// logger.Logger.Errorf("checkRegister %v get user_account err: %v", id, err)
// 注册后离开 // return false, err
func checkRegister(db *mymysql.Database, login *mysqlmodel.UserLogin, platform string, id int) (bool, error) { // }
a := &mongomodel.Account{} // if err := d.Decode(a); err != nil {
c, err := mymongo.GetUserCollection(platform, mongomodel.UserAccount) // logger.Logger.Errorf("checkRegister %v decode user_account err: %v", id, err)
if err != nil { // return false, err
logger.Logger.Errorf("get collection %s error %v", mongomodel.UserAccount, err) // }
return false, err //
} // // account tel
d := c.FindOne(context.TODO(), bson.M{"snid": id}) // tel, err := getAccountTel(platform, id)
err = d.Err() // if err != nil {
if err != nil { // logger.Logger.Warnf("get account tel %v err: %v", id, err)
if errors.Is(err, mongo.ErrNoDocuments) { // }
logger.Logger.Warnf("checkRegister %v not found in user_account", id) //
return false, nil // login.Snid = id
} // //login.OnlineTs = int(a.RegisterTs)
logger.Logger.Errorf("checkRegister %v get user_account err: %v", id, err) // login.OnlineTime = a.RegisteTime
return false, err // //login.OfflineTs = int(a.RegisterTs)
} // login.OfflineTime = a.RegisteTime
if err := d.Decode(a); err != nil { // login.OutType = mysqlmodel.OutTypRegister
logger.Logger.Errorf("checkRegister %v decode user_account err: %v", id, err) // login.Tel = tel
return false, err // login.DeviceName = a.DeviceName
} // login.AppVersion = a.AppVersion
// login.BuildVersion = a.BuildVersion
// account tel // login.AppChannel = a.AppChannel
tel, err := getAccountTel(platform, id) // login.ChannelId = a.ChannelId
if err != nil { //
logger.Logger.Warnf("get account tel %v err: %v", id, err) // if err := db.Create(login).Error; err != nil {
} // logger.Logger.Errorf("checkRegister create err: %v", err)
// return false, err
login.Snid = id // }
//login.OnlineTs = int(a.RegisterTs) // return true, nil
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 玩家跳出统计 // UserLogin 玩家跳出统计
func UserLogin(platform string, ids []*mysqlmodel.UserID) error { //func UserLogin(platform string, ids []*mysqlmodel.UserID) error {
f := func(id int) error { // f := func(id int) error {
// 玩家是否已经统计结束,已经是游戏结束状态 // // 玩家是否已经统计结束,已经是游戏结束状态
login := &mysqlmodel.UserLogin{} // login := &mysqlmodel.UserLogin{}
db, err := mymysql.GetDatabase(platform) // db, err := mymysql.GetDatabase(platform)
if err != nil { // if err != nil {
logger.Logger.Errorf("UserLogin get db err: %v", err) // logger.Logger.Errorf("UserLogin get db err: %v", err)
return err // return err
} // }
if err = db.Where("snid = ?", id).Find(login).Error; err != nil { // if err = db.Where("snid = ?", id).Find(login).Error; err != nil {
logger.Logger.Errorf("UserLogin find %v err: %v", id, err) // logger.Logger.Errorf("UserLogin find %v err: %v", id, err)
return err // return err
} // }
//
switch login.OutType { // switch login.OutType {
case mysqlmodel.OutTypeGameOver: // case mysqlmodel.OutTypeGameOver:
return nil // return nil
//
case mysqlmodel.OutTypeGaming: // case mysqlmodel.OutTypeGaming:
_, err := checkGameOver(db, login, platform, id) // _, err := checkGameOver(db, login, platform, id)
if err != nil { // if err != nil {
logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err) // logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err)
return err // return err
} // }
return nil // return nil
//
case mysqlmodel.OutTypeLogin: // case mysqlmodel.OutTypeLogin:
ret, err := checkGameOver(db, login, platform, id) // ret, err := checkGameOver(db, login, platform, id)
if err != nil { // if err != nil {
logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err) // logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err)
return err // return err
} // }
if ret { // if ret {
return nil // return nil
} // }
ret, err = checkGaming(db, login, platform, id) // ret, err = checkGaming(db, login, platform, id)
if err != nil { // if err != nil {
logger.Logger.Errorf("UserLogin checkGaming %v err: %v", id, err) // logger.Logger.Errorf("UserLogin checkGaming %v err: %v", id, err)
return err // return err
} // }
if ret { // if ret {
return nil // return nil
} // }
//
case mysqlmodel.OutTypRegister: // case mysqlmodel.OutTypRegister:
ret, err := checkGameOver(db, login, platform, id) // ret, err := checkGameOver(db, login, platform, id)
if err != nil { // if err != nil {
logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err) // logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err)
return err // return err
} // }
if ret { // if ret {
return nil // return nil
} // }
ret, err = checkGaming(db, login, platform, id) // ret, err = checkGaming(db, login, platform, id)
if err != nil { // if err != nil {
logger.Logger.Errorf("UserLogin checkGaming %v err: %v", id, err) // logger.Logger.Errorf("UserLogin checkGaming %v err: %v", id, err)
return err // return err
} // }
if ret { // if ret {
return nil // return nil
} // }
ret, err = checkLogin(db, login, platform, id) // ret, err = checkLogin(db, login, platform, id)
if err != nil { // if err != nil {
logger.Logger.Errorf("UserLogin checkLogin %v err: %v", id, err) // logger.Logger.Errorf("UserLogin checkLogin %v err: %v", id, err)
return err // return err
} // }
if ret { // if ret {
return nil // return nil
} // }
//
default: // default:
ret, err := checkRegister(db, login, platform, id) // ret, err := checkRegister(db, login, platform, id)
if err != nil { // if err != nil {
logger.Logger.Errorf("UserLogin checkRegister %v err: %v", id, err) // logger.Logger.Errorf("UserLogin checkRegister %v err: %v", id, err)
return err // return err
} // }
if !ret { // if !ret {
logger.Logger.Warnf("UserLogin not found user_account checkRegister %v err: %v", id, err) // logger.Logger.Warnf("UserLogin not found user_account checkRegister %v err: %v", id, err)
return nil // return nil
} // }
//
ret, err = checkGameOver(db, login, platform, id) // ret, err = checkGameOver(db, login, platform, id)
if err != nil { // if err != nil {
logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err) // logger.Logger.Errorf("UserLogin checkGameOver %v err: %v", id, err)
return err // return err
} // }
if ret { // if ret {
return nil // return nil
} // }
ret, err = checkGaming(db, login, platform, id) // ret, err = checkGaming(db, login, platform, id)
if err != nil { // if err != nil {
logger.Logger.Errorf("UserLogin checkGaming %v err: %v", id, err) // logger.Logger.Errorf("UserLogin checkGaming %v err: %v", id, err)
return err // return err
} // }
if ret { // if ret {
return nil // return nil
} // }
ret, err = checkLogin(db, login, platform, id) // ret, err = checkLogin(db, login, platform, id)
if err != nil { // if err != nil {
logger.Logger.Errorf("UserLogin checkLogin %v err: %v", id, err) // logger.Logger.Errorf("UserLogin checkLogin %v err: %v", id, err)
return err // return err
} // }
if ret { // if ret {
return nil // return nil
} // }
return nil // return nil
} // }
//
return nil // return nil
} // }
//
for _, v := range ids { // for _, v := range ids {
if err := f(v.Snid); err != nil { // if err := f(v.Snid); err != nil {
return err // return err
} // }
} // }
//
return nil // return nil
} //}

View File

@ -9,12 +9,12 @@ import (
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/options"
"gorm.io/gorm" "gorm.io/gorm"
mongomodel "mongo.games.com/game/statistics/modelmongo"
mysqlmodel "mongo.games.com/game/statistics/modelmysql"
"mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/logger"
mymongo "mongo.games.com/goserver/core/mongox" mymongo "mongo.games.com/goserver/core/mongox"
mymysql "mongo.games.com/goserver/core/mysqlx" 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 { if n == 0 {
e = &mysqlmodel.LogLogin{ e = &mysqlmodel.LogLogin{
Snid: int(v.SnId), Snid: int(v.SnId),
OnlineType: onlineType, OnlineType: onlineType,
//OnlineTs: int(v.Ts), OnlineTs: v.Time.Unix(),
OnlineTime: v.Time, OnlineTime: v.Time,
OfflineType: 0, OfflineType: 0,
//OfflineTs: 0, OfflineTs: 0,
OfflineTime: v.Time, OfflineTime: v.Time,
DeviceName: v.DeviceName, DeviceName: v.DeviceName,
AppVersion: v.AppVersion, AppVersion: v.AppVersion,
@ -132,7 +132,7 @@ func LogLogin(platform string, batchSize int) ([]*mysqlmodel.LogLogin, error) {
} }
e.OfflineType = mysqlmodel.LogTypeOffline e.OfflineType = mysqlmodel.LogTypeOffline
//e.OfflineTs = int(v.Ts) e.OfflineTs = v.Time.Unix()
e.OfflineTime = v.Time e.OfflineTime = v.Time
if err = db.Model(e).Select("OfflineType", "OfflineTime").Updates(e).Error; err != nil { 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) 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 return err
} }
for _, v := range ls { //for _, v := range ls {
if err = tx.First(&mysqlmodel.UserID{}, "snid = ?", v.Snid).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { // 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) // logger.Logger.Errorf("mysql: SyncLogLogin failed to find user_id: %v", err)
return err // return err
} // }
//
if errors.Is(err, gorm.ErrRecordNotFound) { // if errors.Is(err, gorm.ErrRecordNotFound) {
if err = tx.Create(&mysqlmodel.UserID{Snid: v.Snid}).Error; err != nil { // if err = tx.Create(&mysqlmodel.UserID{Snid: v.Snid}).Error; err != nil {
logger.Logger.Errorf("mysql: SyncLogLogin failed to create user_id: %v", err) // logger.Logger.Errorf("mysql: SyncLogLogin failed to create user_id: %v", err)
return err // return err
} // }
} // }
} //}
return nil 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 { for _, v := range accounts {
logger.Logger.Tracef("mongo account: %+v", *v) logger.Logger.Tracef("mongo account: %+v", *v)
a := &mysqlmodel.UserAccount{ a := &mysqlmodel.UserAccount{
MID: v.AccountId.Hex(), MID: v.AccountId.Hex(),
Snid: int(v.SnId), Snid: int(v.SnId),
//RegisterTs: int(v.RegisterTs), RegisterTs: v.RegisteTime.Unix(),
RegisterTime: v.RegisteTime, RegisterTime: v.RegisteTime,
Tel: v.Tel, Tel: v.Tel,
ChannelId: v.ChannelId, ChannelId: v.ChannelId,
@ -81,17 +81,17 @@ func UserAccount(platform string, batchSize int) ([]*mysqlmodel.UserAccount, err
return err return err
} }
if err = tx.First(&mysqlmodel.UserID{}, "snid = ?", v.SnId).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { //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) // logger.Logger.Errorf("mysql: UserAccount failed to find user_id: %v", err)
return err // return err
} //}
//
if errors.Is(err, gorm.ErrRecordNotFound) { //if errors.Is(err, gorm.ErrRecordNotFound) {
if err = tx.Create(&mysqlmodel.UserID{Snid: int(v.SnId)}).Error; err != nil { // 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) // logger.Logger.Errorf("mysql: UserAccount failed to create user_id: %v", err)
return err // return err
} // }
} //}
as = append(as, a) as = append(as, a)
} }

View File

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

View File

@ -2,7 +2,14 @@ package main
import ( import (
"fmt" "fmt"
"golang.org/x/exp/maps"
"strings"
"github.com/mozillazg/go-pinyin"
"github.com/xuri/excelize/v2" "github.com/xuri/excelize/v2"
"gorm.io/gorm"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/mysqlx"
) )
type ExcelData struct { type ExcelData struct {
@ -10,6 +17,10 @@ type ExcelData struct {
Head []string Head []string
Index int Index int
IndexCell int IndexCell int
TableName string
TableHead []string
DataName string
} }
func (e *ExcelData) SetHead(head []string) *ExcelData { 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{ e.List[id] = &ExcelData{
File: excelize.NewFile(), File: excelize.NewFile(),
Head: head, Head: head,
Index: 0, 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") e.List[id].NewSheet("Sheet1")
if len(head) > 0 { if len(head) > 0 {
@ -79,10 +103,180 @@ func (e *ExcelMgr) Get(id int) *ExcelData {
return e.List[id] 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] d := e.List[id]
if d == nil { if d == nil {
return 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 ( import (
"fmt" "fmt"
"mongo.games.com/goserver/core/utils"
"net/http"
"os"
"os/signal"
"sort" "sort"
"time" "time"
@ -11,6 +15,7 @@ import (
"mongo.games.com/goserver/core/mysqlx" "mongo.games.com/goserver/core/mysqlx"
"mongo.games.com/goserver/core/viperx" "mongo.games.com/goserver/core/viperx"
"mongo.games.com/game/common"
"mongo.games.com/game/statistics/task/gamefree" "mongo.games.com/game/statistics/task/gamefree"
"mongo.games.com/game/statistics/task/task" "mongo.games.com/game/statistics/task/task"
) )
@ -18,6 +23,7 @@ import (
const ( const (
ExcelTypeNewPlayerBankrupt = iota // 新用户游戏破产率 ExcelTypeNewPlayerBankrupt = iota // 新用户游戏破产率
ExcelTypeGameTimeAvg // 新用户平均游戏时长 ExcelTypeGameTimeAvg // 新用户平均游戏时长
ExcelTypeGameTimeAllAvg // 用户平均游戏时长
ExcelTypeGameCountAvg // 新用户平均局数 ExcelTypeGameCountAvg // 新用户平均局数
ExcelTypeGameRate // 平均倍数 ExcelTypeGameRate // 平均倍数
ExcelTypeActiveRate // 活跃破产率 ExcelTypeActiveRate // 活跃破产率
@ -29,33 +35,13 @@ const (
) )
var VP *viper.Viper var VP *viper.Viper
var ExcelMgrSingle *ExcelMgr
func main() { func run() {
defer func() { if VP.GetBool("IsDatabaseMode") {
logger.Logger.Flush() VP.Set("StartTime", common.HMSToTime(0, 0, 0).Format(time.RFC3339))
logger.Logger.Close() VP.Set("EndTime", common.HMSToTime(0, 0, 0).AddDate(0, 0, 1).Format(time.RFC3339))
}()
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()
startTime, err := time.Parse(time.RFC3339, VP.GetString("StartTime")) startTime, err := time.Parse(time.RFC3339, VP.GetString("StartTime"))
if err != nil { if err != nil {
@ -68,18 +54,6 @@ func main() {
return 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") switchArr := VP.GetIntSlice("Switch")
for { for {
@ -93,83 +67,161 @@ func main() {
if switchArr[ExcelTypeNewPlayerBankrupt] == 1 { if switchArr[ExcelTypeNewPlayerBankrupt] == 1 {
// 新用户游戏破产率 // 新用户游戏破产率
mgr.GenNewPlayerBankruptRateExcel("1", startTimeStr, endTimeStr) ExcelMgrSingle.GenNewPlayerBankruptRateExcel("1", startTimeStr, endTimeStr)
} }
if switchArr[ExcelTypeGameTimeAvg] == 1 { 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 { if switchArr[ExcelTypeGameCountAvg] == 1 {
// 新用户平均局数 // 新用户平均局数
mgr.GenGameCountExcel("1", startTimeStr, endTimeStr) ExcelMgrSingle.GenGameCountExcel("1", startTimeStr, endTimeStr)
} }
if switchArr[ExcelTypeGameRate] == 1 { if switchArr[ExcelTypeGameRate] == 1 {
// 平均倍数 // 平均倍数
mgr.GenGameRateExcel("1", startTimeStr, endTimeStr) ExcelMgrSingle.GenGameRateExcel("1", startTimeStr, endTimeStr)
} }
if switchArr[ExcelTypeActiveRate] == 1 { if switchArr[ExcelTypeActiveRate] == 1 {
// 活跃破产率 // 活跃破产率
mgr.GenActiveBankruptRateExcel("1", startTimeStr, endTimeStr) ExcelMgrSingle.GenActiveBankruptRateExcel("1", startTimeStr, endTimeStr)
} }
if switchArr[ExcelTypeCtrlWinRate] == 1 { if switchArr[ExcelTypeCtrlWinRate] == 1 {
// 控赢胜率 // 控赢胜率
mgr.GenCtrlWinRateExcel("1", startTimeStr, endTimeStr) ExcelMgrSingle.GenCtrlWinRateExcel("1", startTimeStr, endTimeStr)
} }
if switchArr[ExcelTypeRobotWinRate] == 1 { if switchArr[ExcelTypeRobotWinRate] == 1 {
// 机器人胜率 // 机器人胜率
mgr.GenRobotWinRateExcel("1", startTimeStr, endTimeStr) ExcelMgrSingle.GenRobotWinRateExcel("1", startTimeStr, endTimeStr)
} }
if switchArr[ExcelTypeCoinAvg] == 1 { if switchArr[ExcelTypeCoinAvg] == 1 {
// 人均获得金币 // 人均获得金币
mgr.GenCoinAvgExcel("1", startTimeStr, endTimeStr) ExcelMgrSingle.GenCoinAvgExcel("1", startTimeStr, endTimeStr)
} }
if switchArr[ExcelTypeBankruptOffline] == 1 { if switchArr[ExcelTypeBankruptOffline] == 1 {
// 破产后离线 // 破产后离线
mgr.GenBankruptOfflineExcel("1", startTimeStr, endTimeStr) ExcelMgrSingle.GenBankruptOfflineExcel("1", startTimeStr, endTimeStr)
} }
if switchArr[ExcelTypeOfflineCoin] == 1 { if switchArr[ExcelTypeOfflineCoin] == 1 {
// 离线金币 // 离线金币
mgr.GenOfflineCoinExcel("1", startTimeStr, endTimeStr) ExcelMgrSingle.GenOfflineCoinExcel("1", startTimeStr, endTimeStr)
} }
startTime = et 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) { func (e *ExcelMgr) SaveAll(startTime, endTime string) {
switchArr := VP.GetIntSlice("Switch") switchArr := VP.GetIntSlice("Switch")
if switchArr[ExcelTypeNewPlayerBankrupt] == 1 { if switchArr[ExcelTypeNewPlayerBankrupt] == 1 {
e.Save(ExcelTypeNewPlayerBankrupt, fmt.Sprintf("新用户破产率_%s_%s.xlsx", startTime, endTime)) e.Save(ExcelTypeNewPlayerBankrupt, startTime, endTime)
} }
if switchArr[ExcelTypeGameTimeAvg] == 1 { 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 { if switchArr[ExcelTypeGameCountAvg] == 1 {
e.Save(ExcelTypeGameCountAvg, fmt.Sprintf("新用户平均局数_%s_%s.xlsx", startTime, endTime)) e.Save(ExcelTypeGameCountAvg, startTime, endTime)
} }
if switchArr[ExcelTypeGameRate] == 1 { if switchArr[ExcelTypeGameRate] == 1 {
e.Save(ExcelTypeGameRate, fmt.Sprintf("平均倍数_%s_%s.xlsx", startTime, endTime)) e.Save(ExcelTypeGameRate, startTime, endTime)
} }
if switchArr[ExcelTypeActiveRate] == 1 { if switchArr[ExcelTypeActiveRate] == 1 {
e.Save(ExcelTypeActiveRate, fmt.Sprintf("活跃破产率_%s_%s.xlsx", startTime, endTime)) e.Save(ExcelTypeActiveRate, startTime, endTime)
} }
if switchArr[ExcelTypeCtrlWinRate] == 1 { if switchArr[ExcelTypeCtrlWinRate] == 1 {
e.Save(ExcelTypeCtrlWinRate, fmt.Sprintf("控赢胜率_%s_%s.xlsx", startTime, endTime)) e.Save(ExcelTypeCtrlWinRate, startTime, endTime)
e.Save(ExcelTypeCtrlWinRate*10, fmt.Sprintf("控输胜率_%s_%s.xlsx", startTime, endTime)) e.Save(ExcelTypeCtrlWinRate*10, startTime, endTime)
} }
if switchArr[ExcelTypeRobotWinRate] == 1 { if switchArr[ExcelTypeRobotWinRate] == 1 {
e.Save(ExcelTypeRobotWinRate, fmt.Sprintf("机器人输率_%s_%s.xlsx", startTime, endTime)) e.Save(ExcelTypeRobotWinRate, startTime, endTime)
} }
if switchArr[ExcelTypeCoinAvg] == 1 { if switchArr[ExcelTypeCoinAvg] == 1 {
e.Save(ExcelTypeCoinAvg, fmt.Sprintf("人均获得金币_%s_%s.xlsx", startTime, endTime)) e.Save(ExcelTypeCoinAvg, startTime, endTime)
} }
if switchArr[ExcelTypeBankruptOffline] == 1 { if switchArr[ExcelTypeBankruptOffline] == 1 {
e.Save(ExcelTypeBankruptOffline, fmt.Sprintf("破产后离线_%s_%s.xlsx", startTime, endTime)) e.Save(ExcelTypeBankruptOffline, startTime, endTime)
} }
if switchArr[ExcelTypeOfflineCoin] == 1 { 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) { func (e *ExcelMgr) GenGameCountExcel(plt string, startTime, endTime string) {
for _, v := range VP.GetIntSlice("Gamefreeids") { for _, v := range VP.GetIntSlice("Gamefreeids") {
a, b, err := task.NewPlayerGameCountAvg(plt, startTime, endTime, v) 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 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) { func GameFreeIdBankruptPlayerCount(plt string, ids []int, startTime, endTime string, gamefreeid int) (int, error) {
s, e := common.StrRFC3339TimeToTime(startTime), common.StrRFC3339TimeToTime(endTime) 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 { if gamefreeid > 0 {
where["gamefreeid"] = gamefreeid 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 { if err != nil {
logger.Logger.Errorf("find player gamedetailedlogid get err: %v", err) logger.Logger.Errorf("find player gamedetailedlogid get err: %v", err)
return 0, 0, err return 0, 0, err
@ -102,3 +105,26 @@ func NewPlayerGameTimeAvg(plt string, startTime, endTime string, gamefreeid int)
} }
return b, a, err 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工具 参考 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