From 8eb9a7c7a1fcab2626ae06e23b9552727e4fba03 Mon Sep 17 00:00:00 2001 From: sk <123456@qq.com> Date: Fri, 21 Jun 2024 10:12:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E7=89=88=E9=82=80=E8=AF=B7=E6=B4=BB?= =?UTF-8?q?=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/constant.go | 25 +- common/time.go | 36 +++ data/DB_GameItem.dat | Bin 7952 -> 8437 bytes data/DB_GameItem.json | 112 +++++++ data/DB_Game_Drop.dat | 107 ++++--- data/DB_Game_Drop.json | 166 +++++----- data/DB_PropExchange.dat | Bin 384 -> 384 bytes data/DB_Task.dat | Bin 2198 -> 2161 bytes data/DB_Task.json | 190 +++++------ data/gameparam.json | 2 +- dbproxy/mq/c_invite.go | 195 ++++++++++-- dbproxy/svc/l_invitescore.go | 326 +++++++++++++++++++ dbproxy/svc/l_rankinvite.go | 55 ++++ dbproxy/svc/l_rankplayercoin.go | 2 +- dbproxy/svc/l_rankplayerlevel.go | 2 +- dbproxy/svc/l_rankseasion.go | 2 +- dbproxy/svc/u_invitecode.go | 15 +- dbproxy/svc/u_invitescore.go | 429 ------------------------- dbproxy/svc/u_player.go | 227 +++++++++----- etcd/keyconf.go | 1 + model/baginfo.go | 8 +- model/config.go | 2 + model/invitecode.go | 94 ++---- model/player.go | 35 +-- model/rank.go | 8 +- mq/keyconf.go | 1 - protocol/rank/rank.pb.go | 48 +-- protocol/rank/rank.proto | 3 +- protocol/webapi/common.pb.go | 274 ++++++++++++++-- protocol/webapi/common.proto | 18 ++ protocol/welfare/welfare.pb.go | 519 ++++++++++++++++++++----------- protocol/welfare/welfare.proto | 14 + public | 2 +- worldsrv/action_player.go | 5 +- worldsrv/action_welfare.go | 114 ++++--- worldsrv/bagmgr.go | 4 +- worldsrv/etcd.go | 5 +- worldsrv/invitecode.go | 128 ++------ worldsrv/logchannel.go | 3 +- worldsrv/mq_coinlog.go | 33 +- worldsrv/player.go | 100 ++---- worldsrv/taskmgr.go | 6 +- worldsrv/trascate_webapi.go | 4 +- xlsx/DB_GameItem.xlsx | Bin 22751 -> 23215 bytes xlsx/DB_Game_Drop.xlsx | Bin 12821 -> 12807 bytes xlsx/DB_Task.xlsx | Bin 20527 -> 20513 bytes 46 files changed, 1955 insertions(+), 1365 deletions(-) create mode 100644 dbproxy/svc/l_invitescore.go create mode 100644 dbproxy/svc/l_rankinvite.go delete mode 100644 dbproxy/svc/u_invitescore.go diff --git a/common/constant.go b/common/constant.go index ec91584..3076249 100644 --- a/common/constant.go +++ b/common/constant.go @@ -660,15 +660,15 @@ const ( TaskTypePay = 7 // 充值金额 TaskTypeWinOrLose = 8 // 游戏输赢金币数量 TaskTypeTienlenCount = 9 // tienlen游戏场次 - TaskTypeBindInviter = 10 // 绑定邀请人数量 + TaskTypeBindInviter = 10 // 绑定邀请人数量* TaskTypeWinCoin = 11 // 赢取金币数量 TaskTypeTienlenWinTimes = 12 // tienlen游戏赢取次数 - TaskTypeInviteScore = 13 // 邀请积分 + TaskTypeInviteScore = 13 // 邀请积分* TaskTypeActivityScore = 14 // 周活跃积分数量 TaskTypeFirstLogin = 15 // 每日首次登录 - TaskTypeInviteNum = 16 // 邀请绑定数量 + TaskTypeInviteNum = 16 // 邀请绑定数量* TaskTypeTurnplate = 17 // 转盘抽奖次数 - TaskTypeInviteRecharge = 18 // 被邀请人充值金额 + TaskTypeInviteRecharge = 18 // 被邀请人充值金额* ) const ( @@ -689,17 +689,12 @@ const ( const HeadRange = 3 // 机器人头像id范围 const ( - InviteScoreTypeBind = 1 // 绑定邀请码 - InviteScoreTypeLogin = 2 // 每日登录 - InviteScoreTypePlayTimes = 3 // 每日参与任意游戏 - InviteScoreTypeRecharge = 4 // 充值 - InviteScoreTypeGameTimes = 5 // 每局游戏 + InviteScoreCheckWeek = -1 // 跨周 + InviteScoreTypeBind = 1 // 绑定邀请码 + InviteScoreTypePay = 2 // 充值 + InviteScoreTypeRecharge = 3 // 充值完成 ) -const TaskIDInvitePlayGame = 1000001 -const TaskIDInviteRecharge = 1000002 -const TaskIDInviteFirstLogin = 1000003 - func InMatchChannel(ls []string, n string) bool { if n == "" || len(ls) == 0 { return false @@ -749,10 +744,6 @@ const ( var PetIDs = []int32{PetIDChicken} -const ( - InviteScoreRecharge = 10000 // 用户每充值$1邀请人获得积分 -) - const ( ChannelSwitchExchange = 1 ChannelSwitchDropItem = 2 diff --git a/common/time.go b/common/time.go index d6156c0..64f93df 100644 --- a/common/time.go +++ b/common/time.go @@ -143,3 +143,39 @@ func InTimeRange(beginHour, beginMinute, endHour, endMinute, checkHour, checkMin checkTime := checkHour*100 + checkMinute return beginTime <= checkTime && checkTime <= endTime } + +func GetWeekTimestamp() []int64 { + now := time.Now().Local() + year, month, day := now.Date() + today := time.Date(year, month, day, 0, 0, 0, 0, time.Local) + // 本周起始日期(周日) + st := today.AddDate(0, 0, -int(today.Weekday())).Unix() + et := today.AddDate(0, 0, 7-int(today.Weekday())).Unix() + return []int64{st, et} +} + +func GetWeekStartTs(ts int64) int64 { + now := time.Unix(ts, 0).Local() + year, month, day := now.Date() + today := time.Date(year, month, day, 0, 0, 0, 0, time.Local) + // 本周起始日期(周日) + st := today.AddDate(0, 0, -int(today.Weekday())).Unix() + return st +} + +func GetMonthTimestamp() []int64 { + now := time.Now().Local() + year, month, _ := now.Date() + // 本月起始日期 + st := time.Date(year, month, 1, 0, 0, 0, 0, time.Local).Unix() + // 计算下个月的年和月 + if month == time.December { + year = year + 1 + month = time.January + } else { + month = month + 1 + } + // 构建下个月的第一天的时间 + et := time.Date(year, month, 1, 0, 0, 0, 0, now.Location()).Unix() + return []int64{st, et} +} diff --git a/data/DB_GameItem.dat b/data/DB_GameItem.dat index 28afb8c5ebd28f2a214d1cc9c3d7a3cfdbdf0537..f49b1b26b397acfb24f99a92d29ec0eda4a11c6a 100644 GIT binary patch delta 353 zcmbPW_tkNOfV??ZImeDyj6%YOPg|Q`te^X0%g*Psw>)i~__Sk(6cZz(5;Fq>gNC3H zGb00o6^Mvn%wjYsa+rLcStIbtj^=06mp81wZbSo=Y1;=insUn63q#G-R(^xJ5eiNE> delta 7 OcmezBIKgg%fII*WR|4b! diff --git a/data/DB_GameItem.json b/data/DB_GameItem.json index d142ae9..8c618d7 100644 --- a/data/DB_GameItem.json +++ b/data/DB_GameItem.json @@ -2503,6 +2503,118 @@ "Location": "0", "Describe": "可联系客服兑换实物奖励", "Entity": 9 + }, + { + "Id": 30008, + "Name": "1元话费直兑券", + "ShowLocation": [ + 1, + 1 + ], + "Classify": [ + 0, + 0, + 0 + ], + "Type": 17, + "Effect0": [ + 1, + 0, + 0 + ], + "Effect": [ + 1, + 0, + 0 + ], + "CompositionMax": 1, + "Location": "0", + "Describe": "用途:话费兑换码\n产出途径:七日累签进阶奖励", + "Num": 1 + }, + { + "Id": 30009, + "Name": "2元话费直兑券", + "ShowLocation": [ + 1, + 1 + ], + "Classify": [ + 0, + 0, + 0 + ], + "Type": 17, + "Effect0": [ + 1, + 0, + 0 + ], + "Effect": [ + 1, + 0, + 0 + ], + "CompositionMax": 1, + "Location": "0", + "Describe": "用途:话费兑换码\n产出途径:七日累签进阶奖励", + "Num": 2 + }, + { + "Id": 30010, + "Name": "5元话费直兑券", + "ShowLocation": [ + 1, + 1 + ], + "Classify": [ + 0, + 0, + 0 + ], + "Type": 17, + "Effect0": [ + 1, + 0, + 0 + ], + "Effect": [ + 1, + 0, + 0 + ], + "CompositionMax": 1, + "Location": "0", + "Describe": "用途:话费兑换码\n产出途径:七日累签进阶奖励", + "Num": 5 + }, + { + "Id": 30011, + "Name": "10元话费直兑券", + "ShowLocation": [ + 1, + 1 + ], + "Classify": [ + 0, + 0, + 0 + ], + "Type": 17, + "Effect0": [ + 1, + 0, + 0 + ], + "Effect": [ + 1, + 0, + 0 + ], + "CompositionMax": 1, + "Location": "0", + "Describe": "用途:话费兑换码\n产出途径:七日累签进阶奖励", + "Num": 10 } ] } \ No newline at end of file diff --git a/data/DB_Game_Drop.dat b/data/DB_Game_Drop.dat index 8fb0166..d510ec8 100644 --- a/data/DB_Game_Drop.dat +++ b/data/DB_Game_Drop.dat @@ -1,56 +1,55 @@ - (2 -' (J2 -N (2 -u (2 - (2 - (2 - (2 - (2 -  (2 + (2 +' (12 +N (c2 +u (2 + (2 + (2 + (2 + (2 +  (2  - (2 - І (2 - ح (2 -  (2 - (2 - (2 - (2 - ( 2 - ( 2 - ( -2 - ( 2 - ( 2 - (2 - (2 - (2 - ("2 - ((2 - (.2 -л (42 - (:2 -! (?2 -$ (E2 - ' (K2 -!* (N2 -"- (N2 -#0 (N2 -$3 (N2 -%6 (N2 -&9 (N2 -'= (N2 -(z (N2 -) (N2 -* (N2  -+Ó (N2 -, (N2 -- (N2#' -. (N2+/ -/ (N226 -0 (N29= -1ʺ (N2AE -2 (N2HL -3/ (N2 -4G (N2 -5_ (N2 \ No newline at end of file + (2 + І (2 + ح (2 +  (2 + (2 + (2 + (2 + (2 + (2 + (2 + (2 + (2 + ( 2 + (2 + (2 + (2 + (2 + (2 +л ("2 + (&2 +! (*2 +$ (.2 + ' (22 +!* (32 +"- (52 +#0 (62 +$3 (82 +%6 (:2 +&9 (;2 +'= (=2 +(z (>2 +) (@2 +* (N2 ++Ó (N2 +, (N2 +- (N2 +. (N2$ +/ (N2$* +0 (N2)0 +1ʺ (N2.6 +2 (N23< +3/ (N2e{ +4G (N2 +5_ (N2 \ No newline at end of file diff --git a/data/DB_Game_Drop.json b/data/DB_Game_Drop.json index c1f90b4..121160a 100644 --- a/data/DB_Game_Drop.json +++ b/data/DB_Game_Drop.json @@ -4,7 +4,7 @@ "Id": 1, "Bet": 2000, "ItemId1": 30001, - "Rate1": 30, + "Rate1": 20, "Amount1": [ 1, 1 @@ -14,7 +14,7 @@ "Id": 2, "Bet": 5000, "ItemId1": 30001, - "Rate1": 74, + "Rate1": 49, "Amount1": [ 1, 1 @@ -24,7 +24,7 @@ "Id": 3, "Bet": 10000, "ItemId1": 30001, - "Rate1": 149, + "Rate1": 99, "Amount1": [ 1, 1 @@ -34,7 +34,7 @@ "Id": 4, "Bet": 15000, "ItemId1": 30001, - "Rate1": 223, + "Rate1": 149, "Amount1": [ 1, 1 @@ -44,7 +44,7 @@ "Id": 5, "Bet": 20000, "ItemId1": 30001, - "Rate1": 297, + "Rate1": 198, "Amount1": [ 1, 1 @@ -54,7 +54,7 @@ "Id": 6, "Bet": 25000, "ItemId1": 30001, - "Rate1": 371, + "Rate1": 247, "Amount1": [ 1, 1 @@ -64,7 +64,7 @@ "Id": 7, "Bet": 30000, "ItemId1": 30001, - "Rate1": 446, + "Rate1": 297, "Amount1": [ 1, 1 @@ -74,7 +74,7 @@ "Id": 8, "Bet": 35000, "ItemId1": 30001, - "Rate1": 520, + "Rate1": 347, "Amount1": [ 1, 1 @@ -84,7 +84,7 @@ "Id": 9, "Bet": 40000, "ItemId1": 30001, - "Rate1": 594, + "Rate1": 396, "Amount1": [ 1, 1 @@ -94,7 +94,7 @@ "Id": 10, "Bet": 45000, "ItemId1": 30001, - "Rate1": 668, + "Rate1": 445, "Amount1": [ 1, 1 @@ -104,7 +104,7 @@ "Id": 11, "Bet": 50000, "ItemId1": 30001, - "Rate1": 743, + "Rate1": 495, "Amount1": [ 1, 1 @@ -114,7 +114,7 @@ "Id": 12, "Bet": 55000, "ItemId1": 30001, - "Rate1": 817, + "Rate1": 545, "Amount1": [ 1, 1 @@ -124,7 +124,7 @@ "Id": 13, "Bet": 60000, "ItemId1": 30001, - "Rate1": 891, + "Rate1": 594, "Amount1": [ 1, 1 @@ -134,7 +134,7 @@ "Id": 14, "Bet": 65000, "ItemId1": 30001, - "Rate1": 965, + "Rate1": 643, "Amount1": [ 1, 1 @@ -144,7 +144,7 @@ "Id": 15, "Bet": 70000, "ItemId1": 30001, - "Rate1": 1040, + "Rate1": 693, "Amount1": [ 1, 1 @@ -154,7 +154,7 @@ "Id": 16, "Bet": 75000, "ItemId1": 30001, - "Rate1": 1114, + "Rate1": 743, "Amount1": [ 1, 1 @@ -164,7 +164,7 @@ "Id": 17, "Bet": 80000, "ItemId1": 30001, - "Rate1": 1188, + "Rate1": 792, "Amount1": [ 1, 1 @@ -174,7 +174,7 @@ "Id": 18, "Bet": 85000, "ItemId1": 30001, - "Rate1": 1262, + "Rate1": 841, "Amount1": [ 1, 1 @@ -184,7 +184,7 @@ "Id": 19, "Bet": 90000, "ItemId1": 30001, - "Rate1": 1337, + "Rate1": 891, "Amount1": [ 1, 1 @@ -194,7 +194,7 @@ "Id": 20, "Bet": 95000, "ItemId1": 30001, - "Rate1": 1411, + "Rate1": 941, "Amount1": [ 1, 1 @@ -204,7 +204,7 @@ "Id": 21, "Bet": 100000, "ItemId1": 30001, - "Rate1": 1485, + "Rate1": 990, "Amount1": [ 1, 1 @@ -214,7 +214,7 @@ "Id": 22, "Bet": 150000, "ItemId1": 30001, - "Rate1": 2228, + "Rate1": 1485, "Amount1": [ 1, 1 @@ -224,7 +224,7 @@ "Id": 23, "Bet": 200000, "ItemId1": 30001, - "Rate1": 2970, + "Rate1": 1980, "Amount1": [ 1, 1 @@ -234,7 +234,7 @@ "Id": 24, "Bet": 250000, "ItemId1": 30001, - "Rate1": 3713, + "Rate1": 2475, "Amount1": [ 1, 1 @@ -244,170 +244,170 @@ "Id": 25, "Bet": 300000, "ItemId1": 30001, - "Rate1": 4455, + "Rate1": 2970, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 26, "Bet": 350000, "ItemId1": 30001, - "Rate1": 5198, + "Rate1": 3465, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 27, "Bet": 400000, "ItemId1": 30001, - "Rate1": 5940, + "Rate1": 3960, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 28, "Bet": 450000, "ItemId1": 30001, - "Rate1": 6683, + "Rate1": 4455, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 29, "Bet": 500000, "ItemId1": 30001, - "Rate1": 7425, + "Rate1": 4950, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 30, "Bet": 550000, "ItemId1": 30001, - "Rate1": 8168, + "Rate1": 5445, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 31, "Bet": 600000, "ItemId1": 30001, - "Rate1": 8910, + "Rate1": 5940, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 32, "Bet": 650000, "ItemId1": 30001, - "Rate1": 9653, + "Rate1": 6435, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 33, "Bet": 700000, "ItemId1": 30001, - "Rate1": 10000, + "Rate1": 6635, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 34, "Bet": 750000, "ItemId1": 30001, - "Rate1": 10000, + "Rate1": 6835, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 35, "Bet": 800000, "ItemId1": 30001, - "Rate1": 10000, + "Rate1": 7035, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 36, "Bet": 850000, "ItemId1": 30001, - "Rate1": 10000, + "Rate1": 7235, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 37, "Bet": 900000, "ItemId1": 30001, - "Rate1": 10000, + "Rate1": 7435, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 38, "Bet": 950000, "ItemId1": 30001, - "Rate1": 10000, + "Rate1": 7635, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 39, "Bet": 1000000, "ItemId1": 30001, - "Rate1": 10000, + "Rate1": 7835, "Amount1": [ 1, - 2 + 1 ] }, { "Id": 40, "Bet": 2000000, "ItemId1": 30001, - "Rate1": 10000, + "Rate1": 8035, "Amount1": [ 1, - 5 + 3 ] }, { "Id": 41, "Bet": 5000000, "ItemId1": 30001, - "Rate1": 10000, + "Rate1": 8235, "Amount1": [ - 5, - 9 + 4, + 6 ] }, { @@ -416,8 +416,8 @@ "ItemId1": 30001, "Rate1": 10000, "Amount1": [ - 13, - 17 + 11, + 13 ] }, { @@ -426,8 +426,8 @@ "ItemId1": 30001, "Rate1": 10000, "Amount1": [ - 20, - 24 + 16, + 18 ] }, { @@ -436,8 +436,8 @@ "ItemId1": 30001, "Rate1": 10000, "Amount1": [ - 28, - 32 + 21, + 24 ] }, { @@ -446,8 +446,8 @@ "ItemId1": 30001, "Rate1": 10000, "Amount1": [ - 35, - 39 + 24, + 29 ] }, { @@ -456,8 +456,8 @@ "ItemId1": 30001, "Rate1": 10000, "Amount1": [ - 43, - 47 + 31, + 36 ] }, { @@ -466,8 +466,8 @@ "ItemId1": 30001, "Rate1": 10000, "Amount1": [ - 50, - 54 + 36, + 42 ] }, { @@ -476,8 +476,8 @@ "ItemId1": 30001, "Rate1": 10000, "Amount1": [ - 57, - 61 + 41, + 48 ] }, { @@ -486,8 +486,8 @@ "ItemId1": 30001, "Rate1": 10000, "Amount1": [ - 65, - 69 + 46, + 54 ] }, { @@ -496,8 +496,8 @@ "ItemId1": 30001, "Rate1": 10000, "Amount1": [ - 72, - 76 + 51, + 60 ] }, { @@ -506,8 +506,8 @@ "ItemId1": 30001, "Rate1": 10000, "Amount1": [ - 147, - 151 + 101, + 123 ] }, { @@ -516,8 +516,8 @@ "ItemId1": 30001, "Rate1": 10000, "Amount1": [ - 221, - 225 + 150, + 164 ] }, { @@ -526,8 +526,8 @@ "ItemId1": 30001, "Rate1": 10000, "Amount1": [ - 295, - 299 + 199, + 246 ] } ] diff --git a/data/DB_PropExchange.dat b/data/DB_PropExchange.dat index 13a118614580b018a035d3533c99f93ed9ecce2b..76bd54381623e0ee0f9f8c8c1ae160b5be25a5f5 100644 GIT binary patch delta 73 zcmZo*ZeV8NGUH&J$fGo|j$@*pv-0IOW&uViHjXP$`WlqJ3Z<{NF;BEnp156jG83cd O#Pi0CS0@WI<^lk9XcBw? literal 384 zcmd-w<6snElw#w!-o^~3FGJ}oQ2HvAz6PR|I5-yevI!h$vE|a^U;?YZ0hPZArEfv$ z+i2>;IUwevn1^I9Odq=a=;lMrEhutRVe3^U*k)M4lrV0Sn>$0DFd Lzc6z#&=vv!W5PT& diff --git a/data/DB_Task.dat b/data/DB_Task.dat index 096091711a38b82ad8f6d8dcf91e0619d3a02910..1ba525b6021b289ee9e48561a266723839b2fbcc 100644 GIT binary patch literal 2161 zcmaKtO;1xn6o$R`_O_?f(hj9SK`ocIV0RjqBqXkh>96otxMD$wE}B$DVu*`^pe{59 zzv2=>3DFHAek8h3{D{#lKfrg+oz9&qy{ntddFIS{-#K%xsE{L_k`p*}=ZrIzq}66p z`cp*9`0mboGp^%^3c1n+<62BnGwo(_#y#eUGI`Pi<5^5T$|C|w$OPgED=wn=IR}I< zeGqZnrthh&QP`(}S@Ij>c_h!0ERxK+VsS;rHImt>mrUpR9A7>!85aW*q7 zaChyzP9Pw0RAw0Xl|qK_9@?*ObV@9WG3tlIiJ-6EYM3)3i(RBBz+wfUZ4D8*pojrj ztcZ=JtRc`H+9zL(QxQ%xF*j}MQ2n40A!>A`fkJ$BQJWu5n>0}=4lZPZt~TH(Qwx7S zTlFkubt;#!YYo{KVmlAo6DHf2I|Yq-z$R&-AqPTi_tVy)>R{aldVoTm|JYfv5;#otTj&>E;6GCu0qQ<9hmB)Z=;LtR$8SMFvJYso$kIaomIL8 zD96yHQ|7d8l~q~=RAk7$<1UFcS_3r7(9!p-1lH&_sDLSyYYzNZ-uiC`9pU3;^_KS# zOq!V(d5-|)8H$nj7|yr-bXnTnJ5{F#e(_AxJe%i9Dan2C|M1xPX! zBku*EA%VQ7_;}j9ffmVm$fGJKNm>X-`dNe*4bzJnzg~Q6x)RdCRkW>%27?r{!8) zx|2kU_}!j!rftg-MY5$0#x|I2z%**{Y5SBV3gk!!jAJmFsE+U`CS%x-8T%sIzhHrI zr3=FKMX00@ox((1#zDlnhSrGl1Jzj&IZD8d?WO%KWk(~`%NIpI5iF>UyEa#UJ?BVU zQxK_^Kg4)>2{{$uz6<9%o-mX(XQ%L) z+86NFjpLobo0etlL-`=3p~Uf0e)ZnIDjh=jI0GpTqEo?y>#gGWc$g$qIiB<*7phDP zfxdnu=XkwFiTYwDu%!wN$OIQ~L$h`eN8{BE1>__#pfp4|1r=fd@-oRM%!GjYG5~D2 z7?gqm4pf(D{Q2t!gbHa$rkMDV2x~Nd{Z0i$7Kij8=9t&**DD~7N0AjH)Qg-IfV&&k zFrrXMAA(j$^JZ6seB4Ol7}c!_AXx;?$m|ply*?AzuI?S=M2W6cAjMVvT6=%)1Tg}A z8KbKeQwv-Y%gdI8)x%~xcf=C(hrAL^UT znvIq)c)cPAHCTVSvzZPn8d1yu^l70Yhc(!kU#XpqKov-W1KF}b7HRR8g=}5iVb$T| z*(Bj;TG!PTB8D{0hQ=Bpfp35#!*Q_g_Z+YW@;H!mMQM_kt@fRL5f;MgXPD~faT8dPu}&UKdRT)?1pg)K!nFQvFn9T1twcK*=_#h7B#f8IRGHp@ z>S4+pOGYaLZWmmRxi-yYZk*nNJIh=;D&tA@L1Jfe~ZMn?naf;yaiUGe)3Q HbKd*|CHvk9 diff --git a/data/DB_Task.json b/data/DB_Task.json index 2480fa0..998d30a 100644 --- a/data/DB_Task.json +++ b/data/DB_Task.json @@ -146,8 +146,8 @@ "TargetTimes": 1, "FinishTimes": 1, "Award": { - "100001": 1000000, - "100002": 10 + "100001": 100000, + "100002": 1 } }, { @@ -158,8 +158,8 @@ "TargetTimes": 10, "FinishTimes": 1, "Award": { - "100001": 1000000, - "100002": 10 + "100001": 100000, + "100002": 1 }, "GameType": 1 }, @@ -171,7 +171,7 @@ "TargetTimes": 10000000, "FinishTimes": 1, "Award": { - "100001": 1000000 + "100001": 100000 } }, { @@ -182,8 +182,8 @@ "TargetTimes": 10, "FinishTimes": 1, "Award": { - "100001": 1000000, - "100002": 10 + "100001": 100000, + "100002": 1 }, "GameType": 1 }, @@ -195,8 +195,8 @@ "TargetTimes": 3, "FinishTimes": 1, "Award": { - "100001": 10000000, - "100002": 10 + "100001": 1000000, + "100002": 1 } }, { @@ -207,7 +207,7 @@ "TargetTimes": 10, "FinishTimes": 1, "Award": { - "100001": 250000, + "100001": 25000, "50001": 1 } }, @@ -219,7 +219,7 @@ "TargetTimes": 5, "FinishTimes": 1, "Award": { - "100001": 2500000, + "100001": 250000, "50001": 2 } }, @@ -231,7 +231,7 @@ "TargetTimes": 10, "FinishTimes": 1, "Award": { - "100001": 5000000, + "100001": 500000, "50001": 4 } }, @@ -243,7 +243,7 @@ "TargetTimes": 100, "FinishTimes": 1, "Award": { - "100001": 2500000, + "100001": 250000, "50001": 2 } }, @@ -255,7 +255,7 @@ "TargetTimes": 500, "FinishTimes": 1, "Award": { - "100001": 12500000, + "100001": 1250000, "50001": 10 } }, @@ -267,7 +267,7 @@ "TargetTimes": 1000, "FinishTimes": 1, "Award": { - "100001": 25000000, + "100001": 2500000, "50001": 20 } }, @@ -279,8 +279,8 @@ "TargetTimes": 10000, "FinishTimes": 1, "Award": { - "100001": 1000000, - "100002": 20 + "100001": 100000, + "100002": 2 } }, { @@ -291,8 +291,8 @@ "TargetTimes": 50000, "FinishTimes": 1, "Award": { - "100001": 10000000, - "100002": 20 + "100001": 1000000, + "100002": 2 } }, { @@ -303,8 +303,8 @@ "TargetTimes": 200000, "FinishTimes": 1, "Award": { - "100001": 20000000, - "100002": 50 + "100001": 2000000, + "100002": 5 } }, { @@ -315,8 +315,8 @@ "TargetTimes": 1000000, "FinishTimes": 1, "Award": { - "100001": 50000000, - "100002": 100 + "100001": 5000000, + "100002": 10 } }, { @@ -327,8 +327,8 @@ "TargetTimes": 100000000, "FinishTimes": 1, "Award": { - "100001": 1000000, - "100002": 10 + "100001": 100000, + "100002": 1 }, "GameType": 1 }, @@ -340,8 +340,8 @@ "TargetTimes": 1000000000, "FinishTimes": 1, "Award": { - "100001": 2000000, - "100002": 20 + "100001": 200000, + "100002": 2 }, "GameType": 1 }, @@ -353,8 +353,8 @@ "TargetTimes": 10000000000, "FinishTimes": 1, "Award": { - "100001": 3000000, - "100002": 30 + "100001": 300000, + "100002": 3 }, "GameType": 1 }, @@ -366,8 +366,8 @@ "TargetTimes": 100000000000, "FinishTimes": 1, "Award": { - "100001": 5000000, - "100002": 50 + "100001": 500000, + "100002": 5 }, "GameType": 1 }, @@ -379,8 +379,8 @@ "TargetTimes": 500000000000, "FinishTimes": 1, "Award": { - "100001": 10000000, - "100002": 100 + "100001": 1000000, + "100002": 10 }, "GameType": 1 }, @@ -392,8 +392,8 @@ "TargetTimes": 1000000000000, "FinishTimes": 1, "Award": { - "100001": 20000000, - "100002": 200 + "100001": 2000000, + "100002": 20 }, "GameType": 1 }, @@ -405,8 +405,8 @@ "TargetTimes": 100, "FinishTimes": 1, "Award": { - "100001": 1000000, - "100002": 10 + "100001": 100000, + "100002": 1 }, "GameType": 1 }, @@ -418,8 +418,8 @@ "TargetTimes": 1000, "FinishTimes": 1, "Award": { - "100001": 2000000, - "100002": 20 + "100001": 200000, + "100002": 2 }, "GameType": 1 }, @@ -431,8 +431,8 @@ "TargetTimes": 5000, "FinishTimes": 1, "Award": { - "100001": 3000000, - "100002": 30 + "100001": 300000, + "100002": 3 }, "GameType": 1 }, @@ -444,8 +444,8 @@ "TargetTimes": 10000, "FinishTimes": 1, "Award": { - "100001": 5000000, - "100002": 50 + "100001": 500000, + "100002": 5 }, "GameType": 1 }, @@ -457,8 +457,8 @@ "TargetTimes": 50000, "FinishTimes": 1, "Award": { - "100001": 10000000, - "100002": 100 + "100001": 1000000, + "100002": 10 }, "GameType": 1 }, @@ -470,8 +470,8 @@ "TargetTimes": 100000, "FinishTimes": 1, "Award": { - "100001": 20000000, - "100002": 200 + "100001": 2000000, + "100002": 20 }, "GameType": 1 }, @@ -483,8 +483,8 @@ "TargetTimes": 100, "FinishTimes": 1, "Award": { - "100001": 1000000, - "100002": 10 + "100001": 100000, + "100002": 1 }, "GameType": 1 }, @@ -496,8 +496,8 @@ "TargetTimes": 1000, "FinishTimes": 1, "Award": { - "100001": 2000000, - "100002": 20 + "100001": 200000, + "100002": 2 }, "GameType": 1 }, @@ -509,8 +509,8 @@ "TargetTimes": 5000, "FinishTimes": 1, "Award": { - "100001": 3000000, - "100002": 30 + "100001": 300000, + "100002": 3 }, "GameType": 1 }, @@ -522,8 +522,8 @@ "TargetTimes": 10000, "FinishTimes": 1, "Award": { - "100001": 5000000, - "100002": 50 + "100001": 500000, + "100002": 5 }, "GameType": 1 }, @@ -535,8 +535,8 @@ "TargetTimes": 50000, "FinishTimes": 1, "Award": { - "100001": 10000000, - "100002": 100 + "100001": 1000000, + "100002": 10 }, "GameType": 1 }, @@ -548,8 +548,8 @@ "TargetTimes": 100000, "FinishTimes": 1, "Award": { - "100001": 20000000, - "100002": 200 + "100001": 2000000, + "100002": 20 }, "GameType": 1 }, @@ -561,8 +561,8 @@ "TargetTimes": 100, "FinishTimes": 1, "Award": { - "100001": 1000000, - "100002": 10 + "100001": 100000, + "100002": 1 }, "GameType": 1 }, @@ -574,8 +574,8 @@ "TargetTimes": 1000, "FinishTimes": 1, "Award": { - "100001": 2000000, - "100002": 20 + "100001": 200000, + "100002": 2 }, "GameType": 1 }, @@ -587,8 +587,8 @@ "TargetTimes": 5000, "FinishTimes": 1, "Award": { - "100001": 3000000, - "100002": 30 + "100001": 300000, + "100002": 3 }, "GameType": 1 }, @@ -600,8 +600,8 @@ "TargetTimes": 10000, "FinishTimes": 1, "Award": { - "100001": 5000000, - "100002": 50 + "100001": 500000, + "100002": 5 }, "GameType": 1 }, @@ -613,8 +613,8 @@ "TargetTimes": 50000, "FinishTimes": 1, "Award": { - "100001": 10000000, - "100002": 100 + "100001": 1000000, + "100002": 10 }, "GameType": 1 }, @@ -626,8 +626,8 @@ "TargetTimes": 100000, "FinishTimes": 1, "Award": { - "100001": 20000000, - "100002": 200 + "100001": 2000000, + "100002": 20 }, "GameType": 1 }, @@ -639,8 +639,8 @@ "TargetTimes": 10, "FinishTimes": 1, "Award": { - "100001": 1000000, - "100002": 10 + "100001": 100000, + "100002": 1 }, "Position": [ 1, @@ -655,8 +655,8 @@ "TargetTimes": 100, "FinishTimes": 1, "Award": { - "100001": 2000000, - "100002": 20 + "100001": 200000, + "100002": 2 }, "Position": [ 1, @@ -671,8 +671,8 @@ "TargetTimes": 1000, "FinishTimes": 1, "Award": { - "100001": 3000000, - "100002": 30 + "100001": 300000, + "100002": 3 }, "Position": [ 1, @@ -687,8 +687,8 @@ "TargetTimes": 10000, "FinishTimes": 1, "Award": { - "100001": 5000000, - "100002": 50 + "100001": 500000, + "100002": 5 }, "Position": [ 1, @@ -703,8 +703,8 @@ "TargetTimes": 50000, "FinishTimes": 1, "Award": { - "100001": 10000000, - "100002": 100 + "100001": 1000000, + "100002": 10 }, "Position": [ 1, @@ -719,8 +719,8 @@ "TargetTimes": 100000, "FinishTimes": 1, "Award": { - "100001": 20000000, - "100002": 200 + "100001": 2000000, + "100002": 20 }, "Position": [ 1, @@ -735,8 +735,8 @@ "TargetTimes": 10, "FinishTimes": 1, "Award": { - "100001": 1000000, - "100002": 10 + "100001": 100000, + "100002": 1 } }, { @@ -747,8 +747,8 @@ "TargetTimes": 20, "FinishTimes": 1, "Award": { - "100001": 2000000, - "100002": 20 + "100001": 200000, + "100002": 2 } }, { @@ -759,8 +759,8 @@ "TargetTimes": 50, "FinishTimes": 1, "Award": { - "100001": 3000000, - "100002": 30 + "100001": 300000, + "100002": 3 } }, { @@ -771,8 +771,8 @@ "TargetTimes": 100, "FinishTimes": 1, "Award": { - "100001": 5000000, - "100002": 50 + "100001": 500000, + "100002": 5 } }, { @@ -783,8 +783,8 @@ "TargetTimes": 500, "FinishTimes": 1, "Award": { - "100001": 10000000, - "100002": 100 + "100001": 1000000, + "100002": 10 } }, { @@ -795,8 +795,8 @@ "TargetTimes": 1000, "FinishTimes": 1, "Award": { - "100001": 20000000, - "100002": 200 + "100001": 2000000, + "100002": 20 } } ] diff --git a/data/gameparam.json b/data/gameparam.json index b0d94cd..ac32d61 100644 --- a/data/gameparam.json +++ b/data/gameparam.json @@ -23,5 +23,5 @@ "ClosePreCreateRoom": true, "AgoraAddress": "http://47.105.78.29:8081", "InviteUrl": "http://47.105.78.29:8000/", - "RankTimeout": 5 + "RankTimeout": 2 } \ No newline at end of file diff --git a/dbproxy/mq/c_invite.go b/dbproxy/mq/c_invite.go index 053ed4b..3369430 100644 --- a/dbproxy/mq/c_invite.go +++ b/dbproxy/mq/c_invite.go @@ -2,65 +2,204 @@ package mq import ( "encoding/json" - "fmt" + "errors" "time" - "github.com/astaxie/beego/cache" "mongo.games.com/goserver/core/broker" "mongo.games.com/goserver/core/broker/rabbitmq" "mongo.games.com/goserver/core/logger" + "mongo.games.com/game/common" "mongo.games.com/game/dbproxy/svc" "mongo.games.com/game/model" "mongo.games.com/game/mq" - rankproto "mongo.games.com/game/protocol/rank" ) -var InviteNumCache = cache.NewMemoryCache() - func init() { - mq.RegisterSubscriber(model.EvtBindInvite, func(e broker.Event) (err error) { + mq.RegisterSubscriber(model.EvtInvite, func(e broker.Event) (err error) { msg := e.Message() if msg != nil { defer func() { e.Ack() }() - var log model.BindInvite + var log model.EvtInviteMsg err = json.Unmarshal(msg.Body, &log) if err != nil { + logger.Logger.Errorf("EvtInvite json.Unmarshal error:%v msg:%v", err, string(msg.Body)) return } + logger.Logger.Tracef("EvtInvite log:%+v", log) - // 绑定 - err = svc.BindInviteSnId(log.Platform, log.SnId, log.InviteSnId, log.Ts) - if err != nil { - logger.Logger.Errorf("BindInviteSnId error:%v", err) - return err + now := time.Unix(log.Ts, 0).Local() // 数据创建时间 + + get := func(snid int32) (*model.EvtInviteAckMsg, error) { + if snid == 0 { + return nil, errors.New("not found") + } + n := new(model.EvtInviteAckMsg) + n.Platform = log.Platform + n.Snid = snid + n.Score, n.Num, n.Money, _, err = svc.GetInviteData(log.Platform, snid) + return n, err } - name := fmt.Sprintf("%v", log.InviteSnId) - b := InviteNumCache.Get(name) - n, _ := b.(int32) - if n > 0 { - n++ - } else { - n, err = svc.GetInviteNum(log.Platform, log.InviteSnId, int32(rankproto.RankInvite_InviteType_Total)) + // 增加积分 + add := func(snid int32, score, money, rate int64) error { + if snid == 0 { + return nil + } + err = svc.AddInviteScore(log.Platform, snid, score*rate/10000, money, now) if err != nil { - logger.Logger.Errorf("BindInviteSnId error:%v", err) + logger.Logger.Errorf("EvtInvite add error:%v snid:%v score:%v rate:%v", err, snid, score, rate) + return err + } + msg, err := get(snid) + if err != nil { + logger.Logger.Errorf("EvtInvite add find error:%v snid:%v score:%v rate:%v", err, snid, score, rate) + return err + } + mq.Send(model.EvtInviteAck, msg) + return nil + } + + // 重置积分 + reset := func(snid int32) error { + if snid == 0 { + return nil + } + _, _, _, ts, err := svc.GetInviteData(log.Platform, snid) // 上次更新时间 + if err != nil { + logger.Logger.Errorf("EvtInvite GetInviteData error:%v snid:%v", err, snid) + return err + } + inSameWeek := common.InSameWeek(ts, now) + if !inSameWeek { + err = svc.ClearInviteScore(log.Platform, snid, now) + if err != nil { + logger.Logger.Errorf("EvtInvite ClearInviteScore error:%v snid:%v", err, snid) + return err + } + msg, err := get(snid) + if err != nil { + logger.Logger.Errorf("EvtInvite get error:%v snid:%v", err, snid) + return err + } + msg.Score = 0 + mq.Send(model.EvtInviteAck, msg) + } + return nil + } + + // 当前玩家积分是否跨周重置 + err = reset(log.SnId) + if err != nil { + logger.Logger.Errorf("EvtInvite reset 1 error:%v snid:%v", err, log.SnId) + return err + } + // 父节点积分是否跨周重置 + // 一级 + err = reset(log.InviteSnId) + if err != nil { + logger.Logger.Errorf("EvtInvite reset 2 error:%v snid:%v", err, log.InviteSnId) + return err + } + // 二级 + ppsnid, err := svc.GetPSnId(log.Platform, log.InviteSnId) + if err != nil { + logger.Logger.Errorf("EvtInvite GetPSnId 1 error:%v snid:%v", err, log.InviteSnId) + return err + } + if ppsnid > 0 { + err = reset(ppsnid) + if err != nil { + logger.Logger.Errorf("EvtInvite reset 3 error:%v snid:%v", err, ppsnid) return err } } - InviteNumCache.Put(name, n, int64(time.Hour.Seconds())) - // 更新绑定数量 - mq.Send(model.AckBindNum, &model.BindNum{ - SnId: log.InviteSnId, - Num: n, - }) + if log.Tp != common.InviteScoreCheckWeek { + err = svc.SaveInviteScore(&log.InviteScore, log.RechargeScore) + if err != nil { + logger.Logger.Errorf("EvtInvite SaveInviteScore error:%v msg:%+v %+v", err, log.InviteScore, log) + return err + } + } - return + switch log.Tp { + case common.InviteScoreTypeBind: + code, err := svc.GetCodeBySnId(log.Platform, log.InviteSnId) + if err != nil { + logger.Logger.Errorf("EvtInvite GetCodeBySnId error:%v %v", err, log.InviteSnId) + return err + } + // 绑定关系 + err = svc.BindInviteSnId(log.Platform, log.SnId, log.InviteSnId, code) + if err != nil { + logger.Logger.Errorf("EvtInvite BindInviteSnId error:%v msg:%+v", err, log.InviteScore) + return err + } + // 更新绑定数量 + // 更新邀请积分 + // 1.邀请人增加积分 + add(log.InviteSnId, log.Score, 0, 10000) + // 2.上级增加积分 + var psnid int32 + if len(log.Rate) > 0 { + psnid, err = svc.GetPSnId(log.Platform, log.InviteSnId) + if err != nil { + logger.Logger.Errorf("EvtInvite GetPSnId 2 error:%v snid:%v", err, log.InviteSnId) + return err + } + if psnid > 0 { + add(psnid, log.Score, 0, log.Rate[0]) + } + } + if len(log.Rate) > 1 && psnid > 0 { + psnid, err = svc.GetPSnId(log.Platform, psnid) + if err != nil { + logger.Logger.Errorf("EvtInvite GetPSnId 2 error:%v snid:%v", err, log.InviteSnId) + return err + } + if psnid > 0 { + add(psnid, log.Score, 0, log.Rate[1]) + } + } + + case common.InviteScoreTypePay: + // 更新充值积分,上级积分增加 + var psnid int32 + if len(log.Rate) > 0 { + add(log.InviteSnId, log.Score, log.Money, log.Rate[0]) + psnid, err = svc.GetPSnId(log.Platform, log.InviteSnId) + if err != nil { + logger.Logger.Errorf("EvtInvite GetPSnId 3 error:%v snid:%v", err, log.InviteSnId) + return err + } + } + if len(log.Rate) > 1 && psnid > 0 { + add(psnid, log.Score, 0, log.Rate[1]) + psnid, err = svc.GetPSnId(log.Platform, psnid) + if err != nil { + logger.Logger.Errorf("EvtInvite GetPSnId 4 error:%v snid:%v", err, psnid) + return err + } + } + if len(log.Rate) > 2 && psnid > 0 { + add(psnid, log.Score, 0, log.Rate[2]) + } + + case common.InviteScoreTypeRecharge: + // 更新自己的积分 + add(log.SnId, log.Score, log.Money, 10000) + + case common.InviteScoreCheckWeek: + + default: + logger.Logger.Errorf("EvtInvite tp error, %v", log.Tp) + return err + } } return nil - }, broker.Queue(model.EvtBindInvite), broker.DisableAutoAck(), rabbitmq.DurableQueue()) + }, broker.Queue(model.EvtInvite), broker.DisableAutoAck(), rabbitmq.DurableQueue()) } diff --git a/dbproxy/svc/l_invitescore.go b/dbproxy/svc/l_invitescore.go new file mode 100644 index 0000000..2e1cba5 --- /dev/null +++ b/dbproxy/svc/l_invitescore.go @@ -0,0 +1,326 @@ +package svc + +import ( + "errors" + "net/rpc" + "sort" + "time" + + "github.com/globalsign/mgo" + "github.com/globalsign/mgo/bson" + "mongo.games.com/goserver/core/logger" + + "mongo.games.com/game/common" + "mongo.games.com/game/dbproxy/mongo" + "mongo.games.com/game/model" +) + +var ( + InviteScoreDBName = "log" + InviteScoreCollName = "log_invitescore" + InviteScoreColError = errors.New("InviteScore collection open failed") +) + +func InviteScoreCollection(plt string) *mongo.Collection { + s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, InviteScoreDBName) + if s != nil { + c, first := s.DB().C(InviteScoreCollName) + if first { + c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"invitesnid"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"tp"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"ts"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"-ts"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"money"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"score"}, Background: true, Sparse: true}) + } + return c + } + + return nil +} + +type BindScoreSvc struct { +} + +func SaveInviteScore(req *model.InviteScore, rechargeScore int64) error { + logger.Logger.Tracef("SaveInviteScore req:%+v", *req) + if req.InviteSnId == 0 || req.SnId == 0 { + return nil + } + + req.Id = bson.NewObjectId() + u := PlayerDataCollection(req.Platform) + if u == nil { + return PlayerColError + } + + c := InviteScoreCollection(req.Platform) + if c == nil { + return InviteScoreColError + } + + // 不能重复绑定 + var err error + if req.Tp == common.InviteScoreTypeBind { + a := &model.InviteScore{} + err = c.Find(bson.M{"snid": req.SnId, "tp": common.InviteScoreTypeBind}).One(a) + if err != nil && !errors.Is(err, mgo.ErrNotFound) { + return errors.New("find error") + } + if err == nil && a.InviteSnId > 0 { + // 已经绑定 + return errors.New("already bind") + } + } + + // 必须已经绑定 + if req.Tp != common.InviteScoreTypeBind { + a := &model.InviteScore{} + err = c.Find(bson.M{"snid": req.SnId, "tp": common.InviteScoreTypeBind}).One(a) + if err != nil { + // 还没有绑定上级 + logger.Logger.Errorf("GetInviteScore Find BindTime error:%v", err) + return err + } + } + + // 充值成功记录 + if req.Tp == common.InviteScoreTypePay || req.Tp == common.InviteScoreTypeRecharge { + // 是否已经记录过 + a := &model.InviteScore{} + err = c.Find(bson.M{"snid": req.SnId, "tp": common.InviteScoreTypeRecharge}).One(a) + if err != nil && !errors.Is(err, mgo.ErrNotFound) { + return errors.New("find error") + } + if err == nil && a.InviteSnId > 0 { + // 已有记录 + if req.Tp == common.InviteScoreTypeRecharge { + + } else { + err = c.Insert(req) + if err != nil { + logger.Logger.Errorf("SaveInviteScore Insert 1 error:%v", err) + return err + } + } + } else { + // 没有充值成功记录 + err = c.Insert(req) + if err != nil { + logger.Logger.Errorf("SaveInviteScore Insert 2 error:%v", err) + return err + } + + req.Tp = common.InviteScoreTypeRecharge + req.Score = rechargeScore + err = c.Insert(req) + if err != nil { + logger.Logger.Errorf("SaveInviteScore InviteScoreTypeRecharge Insert error:%v", err) + return err + } + } + } else { + err = c.Insert(req) + if err != nil { + logger.Logger.Errorf("SaveInviteScore Insert 3 error:%v", err) + return err + } + } + + return nil +} + +// GetInviteRankList 获取周榜 +func (b *BindScoreSvc) GetInviteRankList(req *model.FindPlayerRankInviteListArgs, ret *model.FindPlayerRankInviteListReply) error { + c := RankInviteCollection(req.Platform) + if c == nil { + return RankInviteColError + } + + ret.RankType = req.RankType + + var st int64 + switch req.RankType { + case 1: //todo 总榜 + return nil + case 2: // 本周榜 + st = common.GetWeekStartTs(time.Now().Unix()) + case 3: //todo 月榜 + return nil + case 4: // 上周榜 + st = common.GetWeekStartTs(time.Now().Unix()) + st -= 7 * 24 * 3600 + } + var list []*model.RankInvite + err := c.Find(bson.M{"week": st}).Sort("-score").Limit(int(model.GameParamData.RankInviteMaxNum)).All(&list) + if err != nil { + logger.Logger.Errorf("GetInviteRankList error: %v", err) + return err + } + + var conds []int32 + if len(list) > 0 { + type PInfo struct { + SnId int32 + Name string // 昵称 + Roles *model.RolePetInfo + } + var retPlayerList []PInfo + cplayerdata := PlayerDataCollection(req.Platform) + if cplayerdata == nil { + return err + } + + for i := 0; i < len(list); i++ { + conds = append(conds, list[i].SnId) + } + + selecter := bson.M{"snid": bson.M{"$in": conds}} + err = cplayerdata.Find(selecter).Select(bson.M{"snid": 1, "name": 1, "roles": 1}).All(&retPlayerList) + if err != nil { + logger.Logger.Error("GetInviteRankList find player is error", err) + return err + } + + for _, inviteInfo := range list { + for _, playerData := range retPlayerList { + if inviteInfo.SnId == playerData.SnId { + var RankInvite model.PlayerRankInvite + RankInvite.Name = playerData.Name + RankInvite.Score = inviteInfo.Score + RankInvite.SnId = inviteInfo.SnId + + // 头像模型ID + roleId := common.DefaultRoleId + if playerData.Roles != nil { + roleId = int(playerData.Roles.ModId) + } + RankInvite.ModId = int32(roleId) + + RankInvite.InviteNum = int32(inviteInfo.Num) + ret.List = append(ret.List, &RankInvite) + break + } + } + } + } + + return nil +} + +// GetInviteScoreByType 获取玩家排行信息 +func (b *BindScoreSvc) GetInviteScoreByType(req *model.FindPlayerRankInviteScoreArgs, ret *model.FindPlayerRankInviteScoreReply) error { + c := RankInviteCollection(req.Platform) + if c == nil { + return RankInviteColError + } + + ret.RankType = req.RankType + + var st int64 + switch req.RankType { + case 1: //todo 总榜 + return nil + case 2: // 本周榜 + st = common.GetWeekStartTs(time.Now().Unix()) + case 3: //todo 月榜 + return nil + case 4: // 上周榜 + st = common.GetWeekStartTs(time.Now().Unix()) + st -= 7 * 24 * 3600 + } + res := new(model.RankInvite) + err := c.Find(bson.M{"week": st, "snid": req.SnId}).One(res) + if err != nil && !errors.Is(err, mgo.ErrNotFound) { + logger.Logger.Warnf("GetInviteScoreByType error: %v", err) + return err + } + + type PInfo struct { + SnId int32 + Name string // 昵称 + Roles *model.RolePetInfo + } + + var retPlayer PInfo + u := PlayerDataCollection(req.Platform) + if u == nil { + return PlayerColError + } + err = u.Find(bson.M{"snid": req.SnId}).Select(bson.M{"snid": 1, "name": 1, "roles": 1}).One(&retPlayer) + if err != nil { + logger.Logger.Error("GetInviteScoreByType find player is error", err) + return err + } + + // 头像模型ID + roleId := common.DefaultRoleId + if retPlayer.Roles != nil { + roleId = int(retPlayer.Roles.ModId) + } + ret.Data = model.PlayerRankInvite{ + SnId: req.SnId, + Score: res.Score, + InviteNum: int32(res.Num), + Name: retPlayer.Name, + ModId: int32(roleId), + } + return nil +} + +// GetInviteList 获取邀请列表 +func (b *BindScoreSvc) GetInviteList(req *model.InviteLisArgs, ret *model.InviteListRet) error { + c := PlayerDataCollection(req.Platform) + if c == nil { + return InviteScoreColError + } + + type M struct { + Name string + Roles *model.RolePetInfo + CreateTime time.Time + SnId int32 + IScore int64 + IScoreTs time.Time + } + + var res []*M + + err := c.Find(bson.M{"psnid": req.SnId}).Select(bson.M{"snid": 1, "iscore": 1, "iscorets": 1, "name": 1, "createtime": 1, "roles": 1}).All(&res) + if err != nil { + logger.Logger.Errorf("GetInviteList error:%v", err) + return err + } + + now := time.Now().Local() + for _, v := range res { + if !common.InSameWeek(now, v.IScoreTs) { + v.IScore = 0 + } + roleId := common.DefaultRoleId + if v.Roles != nil && v.Roles.ModId != 0 { + roleId = int(v.Roles.ModId) + } + ret.List = append(ret.List, &model.InviteInfo{ + Name: v.Name, + SnId: v.SnId, + CreateTs: v.CreateTime.Unix(), + Score: v.IScore, + ModId: int32(roleId), + }) + } + sort.Slice(ret.List, func(i, j int) bool { + return ret.List[i].Score > ret.List[j].Score + }) + + return nil +} + +//todo 每周清理数据,绑定关系不能删除 + +var GlobalBindScoreSvc = new(BindScoreSvc) + +func init() { + rpc.Register(GlobalBindScoreSvc) +} diff --git a/dbproxy/svc/l_rankinvite.go b/dbproxy/svc/l_rankinvite.go new file mode 100644 index 0000000..36a30b6 --- /dev/null +++ b/dbproxy/svc/l_rankinvite.go @@ -0,0 +1,55 @@ +package svc + +import ( + "errors" + + "github.com/globalsign/mgo" + "github.com/globalsign/mgo/bson" + "mongo.games.com/goserver/core/logger" + + "mongo.games.com/game/common" + "mongo.games.com/game/dbproxy/mongo" + "mongo.games.com/game/model" +) + +var ( + RankInviteDBName = "log" + RankInviteCollName = "log_rankinvite" + RankInviteColError = errors.New("RankInvite collection open failed") +) + +func RankInviteCollection(plt string) *mongo.Collection { + s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, RankInviteDBName) + if s != nil { + c, first := s.DB().C(RankInviteCollName) + if first { + c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"num"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"-score"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"score"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"ts"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"week", "-score"}, Background: true, Sparse: true}) + } + return c + } + + return nil +} + +func SaveRankInvite(data *model.RankInvite) error { + c := RankInviteCollection(data.Platform) + if c == nil { + return RankInviteColError + } + + data.Week = common.GetWeekStartTs(data.Ts) + + _, err := c.Upsert(bson.M{"snid": data.SnId, "week": data.Week}, data) + if err != nil { + logger.Logger.Tracef("SaveRankInvite error:%v", err) + return err + } + return nil +} + +//todo 每周清理数据 diff --git a/dbproxy/svc/l_rankplayercoin.go b/dbproxy/svc/l_rankplayercoin.go index 5050030..d3da869 100644 --- a/dbproxy/svc/l_rankplayercoin.go +++ b/dbproxy/svc/l_rankplayercoin.go @@ -23,7 +23,7 @@ func RankPlayerCoinCollection(plt string) *mongo.Collection { c, first := s.DB().C(RankPlayerCoinCollName) if first { c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true}) - c.EnsureIndex(mgo.Index{Key: []string{"coin"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"-coin"}, Background: true, Sparse: true}) } return c } diff --git a/dbproxy/svc/l_rankplayerlevel.go b/dbproxy/svc/l_rankplayerlevel.go index 006746f..42699ab 100644 --- a/dbproxy/svc/l_rankplayerlevel.go +++ b/dbproxy/svc/l_rankplayerlevel.go @@ -22,7 +22,7 @@ func RankPlayerLevelCollection(plt string) *mongo.Collection { c, first := s.DB().C(RankPlayerLevelCollName) if first { c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true}) - c.EnsureIndex(mgo.Index{Key: []string{"exp"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"-exp"}, Background: true, Sparse: true}) } return c } diff --git a/dbproxy/svc/l_rankseasion.go b/dbproxy/svc/l_rankseasion.go index 3e8364f..1cdaf16 100644 --- a/dbproxy/svc/l_rankseasion.go +++ b/dbproxy/svc/l_rankseasion.go @@ -26,7 +26,7 @@ func RankSeasonCollection(plt string, rankType int32) *mongo.Collection { c, first := s.DB().C(fmt.Sprintf("%s_%d", RankSeasonCollName, rankType)) if first { c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true}) - c.EnsureIndex(mgo.Index{Key: []string{"isrobot", "seasonid", "score"}, Background: true, Sparse: true}) + c.EnsureIndex(mgo.Index{Key: []string{"isrobot", "seasonid", "-score"}, Background: true, Sparse: true}) } return c } diff --git a/dbproxy/svc/u_invitecode.go b/dbproxy/svc/u_invitecode.go index d2f0beb..b303c58 100644 --- a/dbproxy/svc/u_invitecode.go +++ b/dbproxy/svc/u_invitecode.go @@ -21,7 +21,7 @@ import ( var ( InviteCodeDBName = "user" - InviteCodeCollName = "user_invitecode" + InviteCodeCollName = "user_icode" InviteCodeColError = errors.New("InviteCode collection open failed") InviteCodeMutex = sync.Mutex{} ) @@ -105,6 +105,19 @@ func (i *InviteCodeSvc) GetSnIdByCode(req *model.InviteSnIdReq, ret *model.Invit return nil } +func GetCodeBySnId(platform string, snid int32) (string, error) { + c := InviteCodeCollection(platform) + if c == nil { + return "", InviteCodeColError + } + col := new(model.InviteCode) + err := c.Find(bson.M{"snid": snid}).One(col) + if err != nil && !errors.Is(err, mgo.ErrNotFound) { + return "", err + } + return col.Code, err +} + func init() { rpc.Register(new(InviteCodeSvc)) } diff --git a/dbproxy/svc/u_invitescore.go b/dbproxy/svc/u_invitescore.go deleted file mode 100644 index c8eca1f..0000000 --- a/dbproxy/svc/u_invitescore.go +++ /dev/null @@ -1,429 +0,0 @@ -package svc - -import ( - "errors" - "net/rpc" - "time" - - "github.com/globalsign/mgo" - "github.com/globalsign/mgo/bson" - "mongo.games.com/goserver/core/logger" - - "mongo.games.com/game/common" - "mongo.games.com/game/dbproxy/mongo" - "mongo.games.com/game/model" - rankproto "mongo.games.com/game/protocol/rank" -) - -var ( - InviteScoreDBName = "user" - InviteScoreCollName = "user_invitescore" - InviteScoreColError = errors.New("InviteScore collection open failed") -) - -func InviteScoreCollection(plt string) *mongo.Collection { - s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, InviteScoreDBName) - if s != nil { - c, first := s.DB().C(InviteScoreCollName) - if first { - c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true}) - c.EnsureIndex(mgo.Index{Key: []string{"invitesnid"}, Background: true, Sparse: true}) - c.EnsureIndex(mgo.Index{Key: []string{"tp"}, Background: true, Sparse: true}) - c.EnsureIndex(mgo.Index{Key: []string{"ts"}, Background: true, Sparse: true}) - c.EnsureIndex(mgo.Index{Key: []string{"-ts"}, Background: true, Sparse: true}) - c.EnsureIndex(mgo.Index{Key: []string{"weekindex"}, Background: true, Sparse: true}) - c.EnsureIndex(mgo.Index{Key: []string{"monthindex"}, Background: true, Sparse: true}) - } - return c - } - - return nil -} - -type BindScoreSvc struct { -} - -func (b *BindScoreSvc) GetInviteScore(req *model.InviteScoreReq, ret *model.InviteScoreRet) error { - c := InviteScoreCollection(req.Platform) - if c == nil { - return InviteScoreColError - } - - type M struct { - Score int64 - Money int64 - } - - var tc []M - err := c.Pipe([]bson.M{ - {"$match": bson.M{ - "invitesnid": req.SnId, - }}, - {"$group": bson.M{ - "_id": nil, - "score": bson.M{"$sum": "$score"}, - "money": bson.M{"$sum": "$money"}, - }}, - }).AllowDiskUse().All(&tc) - if err != nil { - logger.Logger.Error("GetInviteScore AllowDiskUse is error", err) - return err - } - - if len(tc) > 0 { - ret.Score = tc[0].Score - ret.Money = tc[0].Money - c := PlayerDataCollection(req.Platform) - if c == nil { - return PlayerColError - } - err = c.Update(bson.M{"snid": req.SnId}, bson.M{"$set": bson.M{"invitescore": tc[0].Score}}) - if err != nil { - logger.Logger.Error("GetInviteScore update invitescore is error", err) - return err - } - } - - tc = tc[:0] - err = c.Pipe([]bson.M{ - {"$match": bson.M{ - "invitesnid": req.SnId, - "score": bson.M{"$gt": 0}, - }}, - {"$group": bson.M{ - "_id": nil, - "score": bson.M{"$sum": "$score"}, - }}, - }).AllowDiskUse().All(&tc) - if err != nil { - logger.Logger.Error("GetInviteScore z AllowDiskUse is error", err) - return err - } - - if len(tc) > 0 { - ret.ZScore = tc[0].Score - } - - return nil -} - -func (b *BindScoreSvc) SaveInviteScore(req *model.InviteScore, ret *bool) error { - logger.Logger.Tracef("SaveInviteScore req:%+v", *req) - if req.InviteSnId == 0 { - return nil - } - req.Id = bson.NewObjectId() - u := PlayerDataCollection(req.Platform) - if u == nil { - return PlayerColError - } - - type M struct { - InviteScore int64 - } - r := new(M) - err := u.Find(bson.M{"snid": req.InviteSnId}).Select(bson.M{"invitescore": 1}).One(r) - if err != nil && !errors.Is(err, mgo.ErrNotFound) { - logger.Logger.Errorf("GetInviteScore Find error:%v", err) - return err - } - - if req.Score < 0 { - if -req.Score > r.InviteScore { - req.Score = -r.InviteScore - } - } - - c := InviteScoreCollection(req.Platform) - if c == nil { - return InviteScoreColError - } - - ts := req.Ts - if req.Tp != common.InviteScoreTypeBind { - a := &model.InviteScore{} - err = c.Find(bson.M{"snid": req.SnId, "tp": common.InviteScoreTypeBind}).One(a) - if err != nil && !errors.Is(err, mgo.ErrNotFound) { - logger.Logger.Errorf("GetInviteScore Find BindTime error:%v", err) - return err - } - ts = a.Ts - } - - bindTime := time.Unix(0, ts).Local() - year, month, day := bindTime.Date() - today := time.Date(year, month, day, 0, 0, 0, 0, time.Local) - // 本周起始日期(周日) - req.WeekIndex = today.AddDate(0, 0, -int(today.Weekday())).Unix() - // 本月起始日期 - req.MonthIndex = time.Date(year, month, 1, 0, 0, 0, 0, time.Local).Unix() - - err = c.Insert(req) - if err != nil { - logger.Logger.Errorf("SaveInviteScore Insert error:%v", err) - return err - } - - err = u.Update(bson.M{"snid": req.InviteSnId}, bson.M{"$inc": bson.M{"invitescore": req.Score}}) - if err != nil { - logger.Logger.Errorf("inc InviteScore error:%v", err) - return err - } - - *ret = true - return nil -} - -func (b *BindScoreSvc) GetInviteRankList(req *model.FindPlayerRankInviteListArgs, ret *model.FindPlayerRankInviteListReply) error { - c := InviteScoreCollection(req.Platform) - if c == nil { - return InviteScoreColError - } - - matchParam := bson.M{ - "score": bson.M{"$gt": 0}, - } - now := time.Now().Local() - startTime := now.AddDate(-100, 0, 0).UnixNano() - year, month, day := now.Date() - today := time.Date(year, month, day, 0, 0, 0, 0, time.Local) - if req.RankType == int32(rankproto.RankInvite_InviteType_Week) { - // 本周起始日期(周日) - matchParam["weekindex"] = today.AddDate(0, 0, -int(today.Weekday())).Unix() - } else if req.RankType == int32(rankproto.RankInvite_InviteType_Month) { - // 本月起始日期 - matchParam["monthindex"] = time.Date(year, month, 1, 0, 0, 0, 0, time.Local).Unix() - } else { - matchParam["ts"] = bson.M{"$gte": startTime, "$lte": now.UnixNano()} - } - - type M struct { - InviteSnId int32 // 邀请人id - Score int64 // 积分 - } - - var tc []M - err := c.Pipe([]bson.M{ - {"$match": matchParam}, - {"$group": bson.M{ - "_id": bson.M{ - "invitesnid": "$invitesnid", - }, - "invitesnid": bson.M{"$first": "$invitesnid"}, - "score": bson.M{"$sum": "$score"}, - }}, - { - "$sort": bson.M{"ts": -1}, - }, - { - "$sort": bson.M{"score": -1}, - }, - { - "$limit": model.GameParamData.RankInviteMaxNum, - }, - }).AllowDiskUse().All(&tc) - if err != nil { - logger.Logger.Error("GetInviteRankList z AllowDiskUse is error", err) - return err - } - - var conds []int32 - if len(tc) > 0 { - - type PInfo struct { - SnId int32 - Name string // 昵称 - Roles *model.RolePetInfo - } - - var retPlayerList []PInfo - - cplayerdata := PlayerDataCollection(req.Platform) - if cplayerdata == nil { - return err - } - - for i := 0; i < len(tc); i++ { - conds = append(conds, tc[i].InviteSnId) - } - - selecter := bson.M{"snid": bson.M{"$in": conds}} - //err = cplayerdata.Find(selecter).Select(bson.M{"snid": 1, "name": 1, "roles": 1}).All(&retPlayerList) - err = cplayerdata.Find(selecter).Select(bson.M{"snid": 1, "name": 1, "roles": 1}).All(&retPlayerList) - if err != nil { - logger.Logger.Error("svc.FindInvitePlayerList is error", err) - return nil - } - - for _, inviteInfo := range tc { - for _, playerData := range retPlayerList { - if inviteInfo.InviteSnId == playerData.SnId { - var RankInvite model.PlayerRankInvite - RankInvite.Name = playerData.Name - RankInvite.Score = inviteInfo.Score - RankInvite.SnId = inviteInfo.InviteSnId - - // 头像模型ID - roleId := common.DefaultRoleId - if playerData.Roles != nil { - roleId = int(playerData.Roles.ModId) - } - RankInvite.ModId = int32(roleId) - - RankInvite.InviteNum, _ = GetInviteNum(req.Platform, inviteInfo.InviteSnId, req.RankType) - ret.List = append(ret.List, &RankInvite) - - break - } - } - } - ret.RankType = req.RankType - } - - return nil -} - -func (b *BindScoreSvc) GetInviteScoreByType(req *model.FindPlayerRankInviteScoreArgs, ret *model.FindPlayerRankInviteScoreReply) error { - c := InviteScoreCollection(req.Platform) - if c == nil { - return InviteScoreColError - } - - matchParam := bson.M{ - "invitesnid": req.SnId, - "score": bson.M{"$gt": 0}, - } - now := time.Now().Local() - startTime := now.AddDate(-100, 0, 0).UnixNano() - year, month, day := now.Date() - today := time.Date(year, month, day, 0, 0, 0, 0, time.Local) - if req.RankType == int32(rankproto.RankInvite_InviteType_Week) { - // 本周起始日期(周日) - matchParam["weekindex"] = today.AddDate(0, 0, -int(today.Weekday())).Unix() - } else if req.RankType == int32(rankproto.RankInvite_InviteType_Month) { - // 本月起始日期 - matchParam["monthindex"] = time.Date(year, month, 1, 0, 0, 0, 0, time.Local).Unix() - } else { - matchParam["ts"] = bson.M{"$gte": startTime, "$lte": now.UnixNano()} - } - - type M struct { - InviteSnId int32 // 邀请人id - Score int64 // 积分 - } - - var tc []M - err := c.Pipe([]bson.M{ - {"$match": matchParam}, - {"$group": bson.M{ - "_id": nil, - "invitesnid": bson.M{"$first": "$invitesnid"}, - "score": bson.M{"$sum": "$score"}, - }}, - }).AllowDiskUse().All(&tc) - if err != nil { - logger.Logger.Error("GetInviteScoreByType z AllowDiskUse is error", err) - return err - } - - type PInfo struct { - SnId int32 - Name string // 昵称 - Roles *model.RolePetInfo - } - - var retPlayer PInfo - u := PlayerDataCollection(req.Platform) - if u == nil { - return err - } - err = u.Find(bson.M{"snid": req.SnId}).Select(bson.M{"snid": 1, "name": 1, "roles": 1}).One(&retPlayer) - if err != nil { - logger.Logger.Error("svc.GetInviteScoreByType is error", err) - return nil - } - - var rankInvite model.PlayerRankInvite - rankInvite.Name = retPlayer.Name - if len(tc) > 0 { - rankInvite.Score = tc[0].Score - } - rankInvite.SnId = req.SnId - // 头像模型ID - roleId := common.DefaultRoleId - if retPlayer.Roles != nil { - roleId = int(retPlayer.Roles.ModId) - } - rankInvite.ModId = int32(roleId) - rankInvite.InviteNum, _ = GetInviteNum(req.Platform, req.SnId, req.RankType) - ret.Data = rankInvite - - ret.RankType = req.RankType - - return nil -} - -func (b *BindScoreSvc) GetInviteList(req *model.InviteLisArgs, ret *model.InviteListRet) error { - c := InviteScoreCollection(req.Platform) - if c == nil { - return InviteScoreColError - } - - type M struct { - SnId int32 - Score int64 - } - - var tc []M - err := c.Pipe([]bson.M{ - {"$match": bson.M{ - "invitesnid": req.SnId, - }}, - {"$group": bson.M{ - "_id": bson.M{ - "snid": "$snid", - }, - "snid": bson.M{"$first": "$snid"}, - "score": bson.M{"$sum": "$score"}, - }}, - { - "$sort": bson.M{ - "score": -1, - }, - }, - }).AllowDiskUse().All(&tc) - if err != nil { - logger.Logger.Error("GetInviteList AllowDiskUse is error", err) - return err - } - - u := PlayerDataCollection(req.Platform) - if u == nil { - return PlayerColError - } - - for _, v := range tc { - d := &model.PlayerBaseInfo2{} - err = u.Find(bson.M{"snid": v.SnId}).Select(bson.M{"name": 1, "createtime": 1, "roles": 1}).One(d) - if err != nil { - logger.Logger.Warnf("GetInviteList Find player is error:%v", err) - } - roleId := common.DefaultRoleId - if d.Roles != nil && d.Roles.ModId != 0 { - roleId = int(d.Roles.ModId) - } - ret.List = append(ret.List, &model.InviteInfo{ - Name: d.Name, - SnId: v.SnId, - CreateTs: d.CreateTime.Unix(), - Score: v.Score, - ModId: int32(roleId), - }) - } - - return nil -} - -func init() { - rpc.Register(new(BindScoreSvc)) -} diff --git a/dbproxy/svc/u_player.go b/dbproxy/svc/u_player.go index 360a28c..b590a2e 100644 --- a/dbproxy/svc/u_player.go +++ b/dbproxy/svc/u_player.go @@ -21,7 +21,6 @@ import ( "mongo.games.com/game/common" "mongo.games.com/game/dbproxy/mongo" "mongo.games.com/game/model" - rankproto "mongo.games.com/game/protocol/rank" ) var ( @@ -40,12 +39,12 @@ func PlayerDataCollection(plt string) *mongo.Collection { c_playerdata.EnsureIndex(mgo.Index{Key: []string{"snid"}, Unique: true, Background: true, Sparse: true}) c_playerdata.EnsureIndex(mgo.Index{Key: []string{"channel"}, Background: true, Sparse: true}) c_playerdata.EnsureIndex(mgo.Index{Key: []string{"tel"}, Background: true, Sparse: true}) - c_playerdata.EnsureIndex(mgo.Index{Key: []string{"invitecode"}, Background: true, Sparse: true}) - c_playerdata.EnsureIndex(mgo.Index{Key: []string{"invitesnid"}, Background: true, Sparse: true}) c_playerdata.EnsureIndex(mgo.Index{Key: []string{"name"}, Background: true, Sparse: true}) c_playerdata.EnsureIndex(mgo.Index{Key: []string{"createtime"}, Background: true, Sparse: true}) c_playerdata.EnsureIndex(mgo.Index{Key: []string{"-createtime"}, Background: true, Sparse: true}) - c_playerdata.EnsureIndex(mgo.Index{Key: []string{"othercode"}, Background: true, Sparse: true}) + c_playerdata.EnsureIndex(mgo.Index{Key: []string{"icode"}, Background: true, Sparse: true}) + c_playerdata.EnsureIndex(mgo.Index{Key: []string{"psnid"}, Background: true, Sparse: true}) + c_playerdata.EnsureIndex(mgo.Index{Key: []string{"pcode"}, Background: true, Sparse: true}) } return c_playerdata } @@ -247,7 +246,7 @@ func (svc *PlayerDataSvc) CreatePlayerDataByThird(args *model.CreatePlayer, ret func (svc *PlayerDataSvc) CreatePlayerDataOnRegister(args *model.PlayerDataArg, ret *model.PlayerDataRet) (err error) { cplayerdata := PlayerDataCollection(args.Plt) if cplayerdata == nil { - return + return PlayerColError } acc := args.AccId pd := &model.PlayerData{} @@ -267,13 +266,13 @@ func (svc *PlayerDataSvc) CreatePlayerDataOnRegister(args *model.PlayerDataArg, if !bson.IsObjectIdHex(acc) { logger.Logger.Warn("NewPlayer failed: acc is illeage ", acc) - return + return errors.New("acc is illeage") } var a *model.Account a, err = _AccountSvc.getAccount(args.Plt, args.AccId) if err != nil { logger.Logger.Warnf("_AccountSvc.getAccount(%v,%v) failed:%v", args.Plt, args.AccId, err) - return + return err } id := a.SnId @@ -281,7 +280,7 @@ func (svc *PlayerDataSvc) CreatePlayerDataOnRegister(args *model.PlayerDataArg, id, err = GetOnePlayerIdFromBucket() if err != nil { logger.Logger.Warn("NewPlayer failed:", err) - return + return err } } @@ -298,21 +297,26 @@ func (svc *PlayerDataSvc) CreatePlayerDataOnRegister(args *model.PlayerDataArg, dataParams.Ip, int64(args.AddCoin), "", a.DeviceInfo, a.TagKey, a.AccountType) pd.HeadUrl = args.HeadUrl if pd != nil { + if pd.ICode == "" { + code, _ := GetInviteCode(pd.Platform, pd.SnId) + pd.ICode = code + pd.IScoreTs = time.Now() + } err = cplayerdata.Insert(pd) if err != nil { logger.Logger.Trace("CreatePlayerDataOnRegister Insert failed:", err) - return + return err } ret.Pd = pd ret.IsNew = true - return + return nil } - return + return nil } if CorrectData(pd) { } ret.Pd = pd - return + return nil } func (svc *PlayerDataSvc) GetPlayerDataBySnId(args *model.GetPlayerDataBySnIdArgs, ret *model.PlayerDataRet) (err error) { @@ -321,6 +325,30 @@ func (svc *PlayerDataSvc) GetPlayerDataBySnId(args *model.GetPlayerDataBySnIdArg return nil } + f := func(p *model.PlayerData) { + // 更新一下绑定关系 + if p.PSnId > 0 && p.PCode != "" { + return + } + c := InviteScoreCollection(args.Plt) + if c == nil { + return + } + res := new(model.InviteScore) + c.Find(bson.M{"snid": args.SnId, "tp": common.InviteScoreTypeBind}).One(res) + param := bson.M{} + if res.InviteSnId > 0 { + p.PSnId = res.InviteSnId + param["psnid"] = res.InviteSnId + code, _ := GetCodeBySnId(args.Plt, res.InviteSnId) + if code != "" { + p.PCode = code + param["pcode"] = code + } + cplayerdata.Update(bson.M{"snid": args.SnId}, bson.M{"$set": param}) + } + } + var code string err = cplayerdata.Find(bson.M{"snid": args.SnId}).One(&ret.Pd) if err != nil { @@ -346,15 +374,16 @@ func (svc *PlayerDataSvc) GetPlayerDataBySnId(args *model.GetPlayerDataBySnIdArg pd := model.NewPlayerData(a.AccountId.Hex(), name, a.SnId, a.Channel, a.Platform, a.Params, a.Tel, a.PackegeTag, dataParams.Ip, 0, dataParams.UnionId, a.DeviceInfo, a.TagKey, a.AccountType) if pd != nil { + if pd.ICode == "" { + code, _ = GetInviteCode(pd.Platform, pd.SnId) + pd.ICode = code + pd.IScoreTs = time.Now() + } err = cplayerdata.Insert(pd) if err != nil { logger.Logger.Errorf("GetPlayerDataBySnId Insert err:%v acc:%v snid:%v", err, a.AccountId.Hex(), a.SnId) return err } - if pd.InviteCode == "" { - code, err = GetInviteCode(pd.Platform, pd.SnId) - pd.InviteCode = code - } ret.IsNew = true ret.Pd = pd return nil @@ -362,10 +391,13 @@ func (svc *PlayerDataSvc) GetPlayerDataBySnId(args *model.GetPlayerDataBySnIdArg } return err } - if ret.Pd.InviteCode == "" { - code, err = GetInviteCode(ret.Pd.Platform, ret.Pd.SnId) - ret.Pd.InviteCode = code + if ret.Pd.ICode == "" { + code, _ = GetInviteCode(ret.Pd.Platform, ret.Pd.SnId) + ret.Pd.ICode = code + ret.Pd.IScoreTs = time.Now() + cplayerdata.Update(bson.M{"snid": args.SnId}, bson.M{"icode": code, "iscorets": ret.Pd.IScoreTs}) } + f(ret.Pd) if args.CorrectData && ret.Pd != nil { CorrectData(ret.Pd) } @@ -459,6 +491,12 @@ func SavePlayerData(pd *model.PlayerData) (err error) { } if pd != nil { model.RecalcuPlayerCheckSum(pd) + //todo 排除字段更新,有没有更新好的方法 + pd.IScore, pd.INum, pd.IMoney, pd.IScoreTs, err = GetInviteData(pd.Platform, pd.SnId) + if err != nil { + logger.Logger.Errorf("model.SavePlayerData GetInviteData %v err:%v", pd.SnId, err) + return + } _, err = cplayerdata.Upsert(bson.M{"_id": pd.Id}, pd) if err != nil { logger.Logger.Errorf("model.SavePlayerData %v err:%v", pd.SnId, err) @@ -1495,87 +1533,126 @@ func (svc *PlayerDataSvc) GetPlayerInviteSnid(req *model.PlayerIsExistBySnIdArgs } type t struct { - InviteSnId int32 + PSnId int32 } res := &t{} - err := c.Find(bson.M{"snid": req.SnId}).Select(bson.M{"invitesnid": 1}).One(res) + err := c.Find(bson.M{"snid": req.SnId}).Select(bson.M{"psnid": 1}).One(res) if err != nil && errors.Is(err, mgo.ErrNotFound) { return err } - *resp = res.InviteSnId + *resp = res.PSnId return nil } -func (svc *PlayerDataSvc) GetInviteNum(req *model.PlayerIsExistBySnIdArgs, resp *int32) error { - n, err := GetInviteNum(req.Plt, req.SnId, int32(rankproto.RankInvite_InviteType_Total)) - if err != nil { - return err - } - *resp = n - return nil -} - -func GetInviteNum(platform string, snId int32, rankType int32) (int32, error) { - var err error - var n int - switch rankType { - case int32(rankproto.RankInvite_InviteType_Week), int32(rankproto.RankInvite_InviteType_Month): - matchParam := bson.M{ - "invitesnid": snId, - "tp": common.InviteScoreTypeBind, - } - now := time.Now().Local() - year, month, day := now.Date() - today := time.Date(year, month, day, 0, 0, 0, 0, time.Local) - if rankType == int32(rankproto.RankInvite_InviteType_Week) { - // 本周起始日期(周日) - matchParam["weekindex"] = today.AddDate(0, 0, -int(today.Weekday())).Unix() - } else if rankType == int32(rankproto.RankInvite_InviteType_Month) { - // 本月起始日期 - matchParam["monthindex"] = time.Date(year, month, 1, 0, 0, 0, 0, time.Local).Unix() - } - c := InviteScoreCollection(platform) - if c == nil { - return 0, InviteScoreColError - } - n, err = c.Find(matchParam).Count() - if err != nil { - return 0, err - } - - default: - c := PlayerDataCollection(platform) - if c == nil { - return 0, PlayerColError - } - n, err = c.Find(bson.M{"invitesnid": snId}).Count() - if err != nil { - return 0, err - } - } - - return int32(n), nil -} - -func BindInviteSnId(platform string, snId, inviteSnId int32, ts int64) error { +func BindInviteSnId(platform string, snId, inviteSnId int32, code string) error { c := PlayerDataCollection(platform) if c == nil { return PlayerColError } - err := c.Update(bson.M{"snid": snId}, bson.M{"$set": bson.M{"invitesnid": inviteSnId}}) + err := c.Update(bson.M{"snid": snId}, bson.M{"$set": bson.M{"psnid": inviteSnId, "pcode": code}}) if err != nil { logger.Logger.Error("BindInviteSnId error ", err) return err } + err = c.Update(bson.M{"snid": inviteSnId}, bson.M{"$inc": bson.D{{"inum", 1}}}) + if err != nil { + logger.Logger.Error("BindInviteSnId inc error ", err) + return err + } + return nil +} + +func ClearInviteScore(platform string, snId int32, now time.Time) error { + c := PlayerDataCollection(platform) + if c == nil { + return PlayerColError + } + + err := c.Update(bson.M{"snid": snId}, bson.M{"$set": bson.M{"iscore": 0, "iscorets": now}}) + if err != nil { + logger.Logger.Error("ClearInviteScore error ", err) + return err + } return nil } +func AddInviteScore(platform string, snId int32, num, money int64, now time.Time) error { + c := PlayerDataCollection(platform) + if c == nil { + return PlayerColError + } + + err := c.Update(bson.M{"snid": snId}, bson.M{"$inc": bson.M{"iscore": num, "imoney": money}, "$set": bson.M{"iscorets": now}}) + if err != nil { + logger.Logger.Error("AddInviteScore error ", err) + return err + } + + // 更新排行榜 + type m struct { + IScore int64 + INum int64 + } + res := &m{} + err = c.Find(bson.M{"snid": snId}).Select(bson.M{"iscore": 1, "inum": 1}).One(res) + if err != nil { + logger.Logger.Error("AddInviteScore find error ", err) + return err + } + + SaveRankInvite(&model.RankInvite{ + Platform: platform, + SnId: snId, + Num: res.INum, + Score: res.IScore, + Ts: now.Unix(), + }) + + return nil +} + +func GetInviteData(platform string, snId int32) (iscore, inum, imoney int64, iscorets time.Time, err error) { + c := PlayerDataCollection(platform) + if c == nil { + err = PlayerColError + return + } + type M struct { + IScore, Imoney, Inum int64 + IScoreTs time.Time + } + res := &M{} + err = c.Find(bson.M{"snid": snId}).Select(bson.M{"iscore": 1, "inum": 1, "imoney": 1, "iscorets": 1}).One(res) + if err != nil && !errors.Is(err, mgo.ErrNotFound) { + return + } + res.IScoreTs = res.IScoreTs.Local() + return res.IScore, res.Inum, res.Imoney, res.IScoreTs, nil +} + +func GetPSnId(platform string, snId int32) (psnId int32, err error) { + c := PlayerDataCollection(platform) + if c == nil { + err = PlayerColError + return + } + type M struct { + PSnId int32 + } + res := &M{} + err = c.Find(bson.M{"snid": snId}).Select(bson.M{"psnid": 1}).One(res) + if err != nil && !errors.Is(err, mgo.ErrNotFound) { + return 0, err + } + return res.PSnId, nil +} + func CorrectData(pd *model.PlayerData) bool { //var coinTotal int64 dirty := false diff --git a/etcd/keyconf.go b/etcd/keyconf.go index 51c1434..1ddc523 100644 --- a/etcd/keyconf.go +++ b/etcd/keyconf.go @@ -31,4 +31,5 @@ const ( ETCDKEY_GAME_CONFIG = "/game/plt/gameconfig/" // 游戏管理/全局配置 ETCDKEY_ACT_PHONELOTTERY = "/game/act_phoneLottery" ETCDKEY_ChannelSwitch = "/game/channel/switch" // 渠道开关 + ETCDKEY_ACT_Invite = "/game/act_invite" // 邀请活动配置 ) diff --git a/model/baginfo.go b/model/baginfo.go index 84e994b..6591384 100644 --- a/model/baginfo.go +++ b/model/baginfo.go @@ -29,9 +29,9 @@ func NewBagInfo(sid int32, plt string) *BagInfo { return &BagInfo{BagId: bson.NewObjectId(), SnId: sid, Platform: plt, BagItem: make(map[int32]*Item)} } -func GetBagInfo(sid int32, plt string) *BagInfo { +func GetBagInfo(sid int32, plt string) (*BagInfo, error) { if rpcCli == nil { - return nil + return nil, ErrRPClientNoConn } ret := &BagInfo{} args := &GetBagInfoArgs{ @@ -41,9 +41,9 @@ func GetBagInfo(sid int32, plt string) *BagInfo { err := rpcCli.CallWithTimeout("BagSvc.GetBagItem", args, ret, time.Second*30) if err != nil { logger.Logger.Error("GetBagInfo err:%v SnId:%v ", err, args.SnId) - return nil + return nil, err } - return ret + return ret, nil } func UpBagItem(args *BagInfo) error { diff --git a/model/config.go b/model/config.go index a2523ac..547b542 100644 --- a/model/config.go +++ b/model/config.go @@ -117,6 +117,8 @@ type AllConfig struct { ShopInfos map[int32]*ShopInfo // 商品id:商品信息 // 渠道开关 ChannelSwitch map[int32]*webapi.ChannelSwitchConfig + // 邀请活动 + *webapi.ActInviteConfig } type GlobalConfig struct { diff --git a/model/invitecode.go b/model/invitecode.go index 4ab55c8..b0dfde0 100644 --- a/model/invitecode.go +++ b/model/invitecode.go @@ -24,6 +24,7 @@ type InviteSnIdRet struct { SnId int32 } +// GetSnIdByCode 根据邀请码获取被邀请人id func GetSnIdByCode(platform string, code string) (int32, error) { if rpcCli == nil { logger.Logger.Warnf("rpcCli is nil") @@ -47,81 +48,30 @@ func GetSnIdByCode(platform string, code string) (int32, error) { // InviteScore 积分记录 type InviteScore struct { Id bson.ObjectId `bson:"_id"` - Platform string // 平台id + Platform string `bson:"-"` // 平台id SnId int32 // 被邀请人id InviteSnId int32 // 邀请人id - Tp int32 // 积分类型 common.InviteScoreType~ + Tp int32 // 积分类型 common.InviteScoreType ~ Score int64 // 积分 Ts int64 // 时间戳 Money int64 // 充值金额 - WeekIndex int64 // 所在周 - MonthIndex int64 // 所在月 + Rate []int64 // 返佣比例 } -type InviteScoreReq struct { +// 邀请消息 +const EvtInvite = "evt_invite" // 绑定邀请人 worldsrv -> dbproxy +type EvtInviteMsg struct { + InviteScore + RechargeScore int64 // 充值成功积分 +} + +const EvtInviteAck = "evt_invite_ack" // 绑定邀请人 dbproxy -> worldsrv +type EvtInviteAckMsg struct { Platform string - SnId int32 -} - -type InviteScoreRet struct { - Score int64 // 包含扣积分 - ZScore int64 // 只包含大于0的积分 - Money int64 // 充值金额 -} - -// GetInviteScore 查询总积分 -// 下级玩家所有积分 -// 返回 包含扣积分,只包含大于0的积分,充值金额 -func GetInviteScore(plt string, snid int32) (int64, int64, int64, error) { - if rpcCli == nil { - logger.Logger.Warnf("rpcCli is nil") - return 0, 0, 0, errors.New("rpcCli is nil") - } - - req := &InviteScoreReq{ - Platform: plt, - SnId: snid, - } - ret := &InviteScoreRet{} - err := rpcCli.CallWithTimeout("BindScoreSvc.GetInviteScore", req, ret, time.Second*30) - if err != nil { - logger.Logger.Warnf("GetInviteScore err:%v", err) - return 0, 0, 0, err - } - - return ret.Score, ret.ZScore, ret.Money, err -} - -// SaveInviteScore 保存积分变更记录 -func SaveInviteScore(b *InviteScore) error { - if rpcCli == nil { - logger.Logger.Warnf("rpcCli is nil") - return errors.New("rpcCli is nil") - } - - ret := false - err := rpcCli.CallWithTimeout("BindScoreSvc.SaveInviteScore", b, &ret, time.Second*30) - if err != nil { - logger.Logger.Warnf("SaveInviteScore err:%v", err) - return err - } - return nil -} - -const EvtBindInvite = "evt_bind_invite" -const AckBindNum = "ack_bind_num" -const EvtInviteScore = "evt_invitescore" - -type BindInvite struct { - Platform string - SnId int32 - InviteSnId int32 - Ts int64 -} - -type BindNum struct { - SnId int32 - Num int32 + Snid int32 + Score int64 + Money int64 + Num int64 } type InviteLisArgs struct { @@ -141,6 +91,7 @@ type InviteListRet struct { List []*InviteInfo } +// GetInviteList 获取邀请人列表 func GetInviteList(platform string, snid int32) ([]*InviteInfo, error) { if rpcCli == nil { logger.Logger.Error("model.GetInviteList rpcCli == nil") @@ -159,3 +110,12 @@ func GetInviteList(platform string, snid int32) ([]*InviteInfo, error) { } return ret.List, nil } + +type RankInvite struct { + Platform string `bson:"-"` + SnId int32 + Num int64 + Score int64 + Ts int64 + Week int64 +} diff --git a/model/player.go b/model/player.go index d3b13bd..8b6533a 100644 --- a/model/player.go +++ b/model/player.go @@ -449,16 +449,19 @@ type PlayerData struct { LotteryCount int32 //抽奖次数 InitLotteryStatus bool //抽奖初始化状态 Delete int // 是否删除 - InviteCode string // 邀请码 - InviteSnId int32 // 邀请人 - InviteScore int64 // 邀请积分 - OtherCode string // 绑定的邀请码 WeekCardTime map[int32]int64 // 周卡结束时间 key:类型 value:结束时间 WeekCardAward map[int32]bool // 周卡奖励领取状态false-未领取,true已领取 ItemRecExpireTime int64 // 记牌器到期时间 RequestAddFriend map[int32]int64 // 玩家申请好友记录 IsTakeExpireItem bool // 是否领取 LastChannel string // 最后包类型 + ICode string // 邀请码 + IScore int64 // 邀请积分 + PSnId int32 // 邀请人 + PCode string // 绑定的邀请码 + INum int64 // 邀请人数 + IMoney int64 // 邀请人充值金额 + IScoreTs time.Time // 邀请积分更新时间 } // 七日签到数据 @@ -655,9 +658,9 @@ func ConvertPlayerDataToWebData(param *WebPlayerDataParam) *webapi.PlayerData { pdfw.VipExp = param.VipExp pdfw.ShopId = common.IntSliceToInt32(param.ShopID) pdfw.Delete = int64(param.Delete) - pdfw.InviteCode = param.InviteCode - pdfw.InviteSnId = param.InviteSnId - pdfw.InviteScore = param.InviteScore + pdfw.InviteCode = param.ICode + pdfw.InviteSnId = param.PSnId + pdfw.InviteScore = param.IScore pdfw.Channel = param.Channel pdfw.LastChannel = param.LastChannel for _, v := range param.Items { @@ -1061,6 +1064,7 @@ func GetPlayerDataBySnId(plt string, snid int32, correctData, createIfNotExist b ret.Pd.CreateTime = ret.Pd.CreateTime.Local() ret.Pd.LastLoginTime = ret.Pd.LastLoginTime.Local() ret.Pd.LastLogoutTime = ret.Pd.LastLogoutTime.Local() + ret.Pd.IScoreTs = ret.Pd.IScoreTs.Local() return ret.Pd, ret.IsNew } @@ -2685,23 +2689,6 @@ func GetPlayerInviteSnid(plt string, snid int32) (int32, error) { return ret, nil } -func GetInviteNum(plt string, snid int32) (int32, error) { - if rpcCli == nil { - return 0, errors.New("rpcCli is nil") - } - args := &PlayerIsExistBySnIdArgs{ - Plt: plt, - SnId: snid, - } - var ret int32 - err := rpcCli.CallWithTimeout("PlayerDataSvc.GetInviteNum", args, &ret, time.Second*30) - if err != nil { - logger.Logger.Error("model.GetPlayerInviteSnid error ", err) - return 0, err - } - return ret, nil -} - // 所有游戏都要加上当天统计数据 func (this *PlayerData) GetDaliyGameData(id int) (*PlayerGameStatics, *PlayerGameStatics) { gameId := strconv.Itoa(id) diff --git a/model/rank.go b/model/rank.go index 69841e2..95213d0 100644 --- a/model/rank.go +++ b/model/rank.go @@ -131,11 +131,11 @@ type PlayerRankInvite struct { type FindPlayerRankInviteListArgs struct { Platform string - RankType int32 // 邀请榜时间类型: 总榜 周榜 月榜 + RankType int32 // 邀请榜时间类型: 总榜 周榜 月榜 上周榜 } type FindPlayerRankInviteListReply struct { - RankType int32 // 邀请榜时间类型: 总榜 周榜 月榜 + RankType int32 // 邀请榜时间类型: 总榜 周榜 月榜 上周榜 List []*PlayerRankInvite } @@ -156,12 +156,12 @@ func FindPlayerRankInviteList(args *FindPlayerRankInviteListArgs) (*FindPlayerRa type FindPlayerRankInviteScoreArgs struct { Platform string - RankType int32 // 邀请榜时间类型: 总榜 周榜 月榜 + RankType int32 // 邀请榜时间类型: 总榜 周榜 月榜 上周榜 SnId int32 } type FindPlayerRankInviteScoreReply struct { - RankType int32 // 邀请榜时间类型: 总榜 周榜 月榜 + RankType int32 // 邀请榜时间类型: 总榜 周榜 月榜 上周榜 Data PlayerRankInvite } diff --git a/mq/keyconf.go b/mq/keyconf.go index 827af8b..7183046 100644 --- a/mq/keyconf.go +++ b/mq/keyconf.go @@ -5,7 +5,6 @@ const ( BackBankrupt = "log_bankrupt" BackClientLog = "log_clientlog_mysql" BackGameRecord = "evt_gamerec" - BackInviteScore = "evt_invitescore" BackLogin = "evt_login" BackOnline = "evt_online" BackPhoneLottery = "evt_phonelottery" diff --git a/protocol/rank/rank.pb.go b/protocol/rank/rank.pb.go index db71dcd..00a0c60 100644 --- a/protocol/rank/rank.pb.go +++ b/protocol/rank/rank.pb.go @@ -108,11 +108,12 @@ func (Rank) EnumDescriptor() ([]byte, []int) { type RankInvite int32 const ( - RankInvite_InviteType_None RankInvite = 0 - RankInvite_InviteType_Total RankInvite = 1 //总榜 - RankInvite_InviteType_Week RankInvite = 2 //周榜 - RankInvite_InviteType_Month RankInvite = 3 //月榜 - RankInvite_InviteType_Max RankInvite = 4 + RankInvite_InviteType_None RankInvite = 0 + RankInvite_InviteType_Total RankInvite = 1 //总榜 + RankInvite_InviteType_Week RankInvite = 2 //周榜 + RankInvite_InviteType_Month RankInvite = 3 //月榜 + RankInvite_InviteType_UpWeek RankInvite = 4 //上周榜 + RankInvite_InviteType_Max RankInvite = 5 ) // Enum value maps for RankInvite. @@ -122,14 +123,16 @@ var ( 1: "InviteType_Total", 2: "InviteType_Week", 3: "InviteType_Month", - 4: "InviteType_Max", + 4: "InviteType_UpWeek", + 5: "InviteType_Max", } RankInvite_value = map[string]int32{ - "InviteType_None": 0, - "InviteType_Total": 1, - "InviteType_Week": 2, - "InviteType_Month": 3, - "InviteType_Max": 4, + "InviteType_None": 0, + "InviteType_Total": 1, + "InviteType_Week": 2, + "InviteType_Month": 3, + "InviteType_UpWeek": 4, + "InviteType_Max": 5, } ) @@ -1730,17 +1733,18 @@ var file_rank_proto_rawDesc = []byte{ 0x13, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x52, 0x41, 0x4e, 0x4b, 0x5f, 0x43, 0x53, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x10, 0x9a, 0x4e, 0x12, 0x18, 0x0a, 0x13, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x52, 0x41, 0x4e, 0x4b, 0x5f, 0x53, 0x43, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x10, 0x9b, - 0x4e, 0x2a, 0x76, 0x0a, 0x0a, 0x52, 0x61, 0x6e, 0x6b, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x12, - 0x13, 0x0a, 0x0f, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x6f, - 0x6e, 0x65, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x5f, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x57, 0x65, 0x65, 0x6b, 0x10, 0x02, 0x12, - 0x14, 0x0a, 0x10, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, - 0x6e, 0x74, 0x68, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x61, 0x78, 0x10, 0x04, 0x42, 0x24, 0x5a, 0x22, 0x6d, 0x6f, 0x6e, - 0x67, 0x6f, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x6d, - 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x72, 0x61, 0x6e, 0x6b, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x4e, 0x2a, 0x8d, 0x01, 0x0a, 0x0a, 0x52, 0x61, 0x6e, 0x6b, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, + 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, + 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x5f, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x49, + 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x57, 0x65, 0x65, 0x6b, 0x10, 0x02, + 0x12, 0x14, 0x0a, 0x10, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, + 0x6f, 0x6e, 0x74, 0x68, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x5f, 0x55, 0x70, 0x57, 0x65, 0x65, 0x6b, 0x10, 0x04, 0x12, 0x12, 0x0a, + 0x0e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x61, 0x78, 0x10, + 0x05, 0x42, 0x24, 0x5a, 0x22, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x73, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x6d, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x2f, 0x72, 0x61, 0x6e, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protocol/rank/rank.proto b/protocol/rank/rank.proto index eb0177a..f879d5d 100644 --- a/protocol/rank/rank.proto +++ b/protocol/rank/rank.proto @@ -110,7 +110,8 @@ enum RankInvite{ InviteType_Total = 1;//总榜 InviteType_Week = 2; //周榜 InviteType_Month = 3;//月榜 - InviteType_Max = 4; + InviteType_UpWeek = 4;//上周榜 + InviteType_Max = 5; } message GateTransmit { diff --git a/protocol/webapi/common.pb.go b/protocol/webapi/common.pb.go index a44dde2..4bd447a 100644 --- a/protocol/webapi/common.pb.go +++ b/protocol/webapi/common.pb.go @@ -5949,6 +5949,173 @@ func (x *ChannelSwitchConfig) GetOnChannelName() []string { return nil } +type RankAward struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Start int64 `protobuf:"varint,1,opt,name=Start,proto3" json:"Start,omitempty"` // 开始积分 + End int64 `protobuf:"varint,2,opt,name=End,proto3" json:"End,omitempty"` // 结束积分 + Num int64 `protobuf:"varint,3,opt,name=Num,proto3" json:"Num,omitempty"` // 奖励 +} + +func (x *RankAward) Reset() { + *x = RankAward{} + if protoimpl.UnsafeEnabled { + mi := &file_common_proto_msgTypes[58] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RankAward) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RankAward) ProtoMessage() {} + +func (x *RankAward) ProtoReflect() protoreflect.Message { + mi := &file_common_proto_msgTypes[58] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RankAward.ProtoReflect.Descriptor instead. +func (*RankAward) Descriptor() ([]byte, []int) { + return file_common_proto_rawDescGZIP(), []int{58} +} + +func (x *RankAward) GetStart() int64 { + if x != nil { + return x.Start + } + return 0 +} + +func (x *RankAward) GetEnd() int64 { + if x != nil { + return x.End + } + return 0 +} + +func (x *RankAward) GetNum() int64 { + if x != nil { + return x.Num + } + return 0 +} + +// etcd /game/act_invite +type ActInviteConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Platform string `protobuf:"bytes,1,opt,name=Platform,proto3" json:"Platform,omitempty"` + BindScore int64 `protobuf:"varint,2,opt,name=BindScore,proto3" json:"BindScore,omitempty"` // 绑定积分 + RechargeScore int64 `protobuf:"varint,3,opt,name=RechargeScore,proto3" json:"RechargeScore,omitempty"` // 充值积分,一个玩家最多给上级贡献一次 + PayScore map[int64]int64 `protobuf:"bytes,4,rep,name=PayScore,proto3" json:"PayScore,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` // 充值积分;充值金额:获得积分 + Rates []int64 `protobuf:"varint,5,rep,packed,name=Rates,proto3" json:"Rates,omitempty"` // 返佣比例;多级按顺序给 + Awards1 []*RankAward `protobuf:"bytes,6,rep,name=Awards1,proto3" json:"Awards1,omitempty"` // 周榜奖励列表 + Awards2 []*RankAward `protobuf:"bytes,7,rep,name=Awards2,proto3" json:"Awards2,omitempty"` // 周榜奖励列表 + Awards3 []*RankAward `protobuf:"bytes,8,rep,name=Awards3,proto3" json:"Awards3,omitempty"` // 周榜奖励列表 +} + +func (x *ActInviteConfig) Reset() { + *x = ActInviteConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_common_proto_msgTypes[59] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ActInviteConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ActInviteConfig) ProtoMessage() {} + +func (x *ActInviteConfig) ProtoReflect() protoreflect.Message { + mi := &file_common_proto_msgTypes[59] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ActInviteConfig.ProtoReflect.Descriptor instead. +func (*ActInviteConfig) Descriptor() ([]byte, []int) { + return file_common_proto_rawDescGZIP(), []int{59} +} + +func (x *ActInviteConfig) GetPlatform() string { + if x != nil { + return x.Platform + } + return "" +} + +func (x *ActInviteConfig) GetBindScore() int64 { + if x != nil { + return x.BindScore + } + return 0 +} + +func (x *ActInviteConfig) GetRechargeScore() int64 { + if x != nil { + return x.RechargeScore + } + return 0 +} + +func (x *ActInviteConfig) GetPayScore() map[int64]int64 { + if x != nil { + return x.PayScore + } + return nil +} + +func (x *ActInviteConfig) GetRates() []int64 { + if x != nil { + return x.Rates + } + return nil +} + +func (x *ActInviteConfig) GetAwards1() []*RankAward { + if x != nil { + return x.Awards1 + } + return nil +} + +func (x *ActInviteConfig) GetAwards2() []*RankAward { + if x != nil { + return x.Awards2 + } + return nil +} + +func (x *ActInviteConfig) GetAwards3() []*RankAward { + if x != nil { + return x.Awards3 + } + return nil +} + var File_common_proto protoreflect.FileDescriptor var file_common_proto_rawDesc = []byte{ @@ -6908,9 +7075,39 @@ var file_common_proto_rawDesc = []byte{ 0x52, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x4f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, - 0x42, 0x26, 0x5a, 0x24, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x73, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x6d, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x2f, 0x77, 0x65, 0x62, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x22, 0x45, 0x0a, 0x09, 0x52, 0x61, 0x6e, 0x6b, 0x41, 0x77, 0x61, 0x72, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x45, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x03, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x4e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x03, 0x4e, 0x75, 0x6d, 0x22, 0x8e, 0x03, 0x0a, 0x0f, 0x41, 0x63, 0x74, 0x49, + 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x50, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x42, 0x69, 0x6e, 0x64, 0x53, + 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x42, 0x69, 0x6e, 0x64, + 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, + 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x52, 0x65, + 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x41, 0x0a, 0x08, 0x50, + 0x61, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, + 0x77, 0x65, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x61, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x50, 0x61, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x52, 0x61, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x03, 0x52, 0x05, 0x52, + 0x61, 0x74, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x07, 0x41, 0x77, 0x61, 0x72, 0x64, 0x73, 0x31, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x77, 0x65, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x52, + 0x61, 0x6e, 0x6b, 0x41, 0x77, 0x61, 0x72, 0x64, 0x52, 0x07, 0x41, 0x77, 0x61, 0x72, 0x64, 0x73, + 0x31, 0x12, 0x2b, 0x0a, 0x07, 0x41, 0x77, 0x61, 0x72, 0x64, 0x73, 0x32, 0x18, 0x07, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x77, 0x65, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x61, 0x6e, 0x6b, + 0x41, 0x77, 0x61, 0x72, 0x64, 0x52, 0x07, 0x41, 0x77, 0x61, 0x72, 0x64, 0x73, 0x32, 0x12, 0x2b, + 0x0a, 0x07, 0x41, 0x77, 0x61, 0x72, 0x64, 0x73, 0x33, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x77, 0x65, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x61, 0x6e, 0x6b, 0x41, 0x77, 0x61, + 0x72, 0x64, 0x52, 0x07, 0x41, 0x77, 0x61, 0x72, 0x64, 0x73, 0x33, 0x1a, 0x3b, 0x0a, 0x0d, 0x50, + 0x61, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x26, 0x5a, 0x24, 0x6d, 0x6f, 0x6e, 0x67, + 0x6f, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x6d, 0x65, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x77, 0x65, 0x62, 0x61, 0x70, 0x69, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -6925,7 +7122,7 @@ func file_common_proto_rawDescGZIP() []byte { return file_common_proto_rawDescData } -var file_common_proto_msgTypes = make([]protoimpl.MessageInfo, 63) +var file_common_proto_msgTypes = make([]protoimpl.MessageInfo, 66) var file_common_proto_goTypes = []interface{}{ (*MysqlDbSetting)(nil), // 0: webapi.MysqlDbSetting (*MongoDbSetting)(nil), // 1: webapi.MongoDbSetting @@ -6985,32 +7182,35 @@ var file_common_proto_goTypes = []interface{}{ (*WelfarePhoneLotteryStatus)(nil), // 55: webapi.WelfarePhoneLotteryStatus (*WelfareCollectConfig)(nil), // 56: webapi.WelfareCollectConfig (*ChannelSwitchConfig)(nil), // 57: webapi.ChannelSwitchConfig - nil, // 58: webapi.Platform.BindTelRewardEntry - nil, // 59: webapi.PlayerData.RankScoreEntry - nil, // 60: webapi.ItemShop.AwardEntry - nil, // 61: webapi.VIPcfg.AwardEntry - nil, // 62: webapi.VIPcfg.Privilege7Entry - (*server.DB_GameFree)(nil), // 63: server.DB_GameFree + (*RankAward)(nil), // 58: webapi.RankAward + (*ActInviteConfig)(nil), // 59: webapi.ActInviteConfig + nil, // 60: webapi.Platform.BindTelRewardEntry + nil, // 61: webapi.PlayerData.RankScoreEntry + nil, // 62: webapi.ItemShop.AwardEntry + nil, // 63: webapi.VIPcfg.AwardEntry + nil, // 64: webapi.VIPcfg.Privilege7Entry + nil, // 65: webapi.ActInviteConfig.PayScoreEntry + (*server.DB_GameFree)(nil), // 66: server.DB_GameFree } var file_common_proto_depIdxs = []int32{ 2, // 0: webapi.Platform.Leaderboard:type_name -> webapi.RankSwitch 3, // 1: webapi.Platform.ClubConfig:type_name -> webapi.ClubConfig 4, // 2: webapi.Platform.ThirdGameMerchant:type_name -> webapi.ThirdGame - 58, // 3: webapi.Platform.BindTelReward:type_name -> webapi.Platform.BindTelRewardEntry + 60, // 3: webapi.Platform.BindTelReward:type_name -> webapi.Platform.BindTelRewardEntry 6, // 4: webapi.GameConfigGlobal.GameStatus:type_name -> webapi.GameStatus - 63, // 5: webapi.GameFree.DbGameFree:type_name -> server.DB_GameFree + 66, // 5: webapi.GameFree.DbGameFree:type_name -> server.DB_GameFree 8, // 6: webapi.PlatformGameConfig.DbGameFrees:type_name -> webapi.GameFree 0, // 7: webapi.PlatformDbConfig.Mysql:type_name -> webapi.MysqlDbSetting 1, // 8: webapi.PlatformDbConfig.MongoDb:type_name -> webapi.MongoDbSetting 1, // 9: webapi.PlatformDbConfig.MongoDbLog:type_name -> webapi.MongoDbSetting - 63, // 10: webapi.GameConfigGroup.DbGameFree:type_name -> server.DB_GameFree - 59, // 11: webapi.PlayerData.RankScore:type_name -> webapi.PlayerData.RankScoreEntry + 66, // 10: webapi.GameConfigGroup.DbGameFree:type_name -> server.DB_GameFree + 61, // 11: webapi.PlayerData.RankScore:type_name -> webapi.PlayerData.RankScoreEntry 29, // 12: webapi.PlayerData.Items:type_name -> webapi.ItemInfo 20, // 13: webapi.OnlineReport.GameCount:type_name -> webapi.OnlineGameCnt 22, // 14: webapi.CommonNoticeList.List:type_name -> webapi.CommonNotice 25, // 15: webapi.ExchangeShop.ExType:type_name -> webapi.ExchangeType 24, // 16: webapi.ExchangeShopList.List:type_name -> webapi.ExchangeShop - 60, // 17: webapi.ItemShop.Award:type_name -> webapi.ItemShop.AwardEntry + 62, // 17: webapi.ItemShop.Award:type_name -> webapi.ItemShop.AwardEntry 27, // 18: webapi.ItemShopList.List:type_name -> webapi.ItemShop 29, // 19: webapi.MatchInfoAward.ItemId:type_name -> webapi.ItemInfo 30, // 20: webapi.GameMatchDate.Award:type_name -> webapi.MatchInfoAward @@ -7028,16 +7228,20 @@ var file_common_proto_depIdxs = []int32{ 35, // 32: webapi.WelfareSpree.Item:type_name -> webapi.WelfareDate 44, // 33: webapi.WelfareFirstPayDataList.List:type_name -> webapi.WelfareSpree 44, // 34: webapi.WelfareContinuousPayDataList.List:type_name -> webapi.WelfareSpree - 61, // 35: webapi.VIPcfg.Award:type_name -> webapi.VIPcfg.AwardEntry - 62, // 36: webapi.VIPcfg.Privilege7:type_name -> webapi.VIPcfg.Privilege7Entry + 63, // 35: webapi.VIPcfg.Award:type_name -> webapi.VIPcfg.AwardEntry + 64, // 36: webapi.VIPcfg.Privilege7:type_name -> webapi.VIPcfg.Privilege7Entry 47, // 37: webapi.VIPcfgDataList.List:type_name -> webapi.VIPcfg 35, // 38: webapi.ChessRankConfig.Item:type_name -> webapi.WelfareDate 51, // 39: webapi.ChessRankcfgData.Datas:type_name -> webapi.ChessRankConfig - 40, // [40:40] is the sub-list for method output_type - 40, // [40:40] is the sub-list for method input_type - 40, // [40:40] is the sub-list for extension type_name - 40, // [40:40] is the sub-list for extension extendee - 0, // [0:40] is the sub-list for field type_name + 65, // 40: webapi.ActInviteConfig.PayScore:type_name -> webapi.ActInviteConfig.PayScoreEntry + 58, // 41: webapi.ActInviteConfig.Awards1:type_name -> webapi.RankAward + 58, // 42: webapi.ActInviteConfig.Awards2:type_name -> webapi.RankAward + 58, // 43: webapi.ActInviteConfig.Awards3:type_name -> webapi.RankAward + 44, // [44:44] is the sub-list for method output_type + 44, // [44:44] is the sub-list for method input_type + 44, // [44:44] is the sub-list for extension type_name + 44, // [44:44] is the sub-list for extension extendee + 0, // [0:44] is the sub-list for field type_name } func init() { file_common_proto_init() } @@ -7742,6 +7946,30 @@ func file_common_proto_init() { return nil } } + file_common_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RankAward); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_common_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ActInviteConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -7749,7 +7977,7 @@ func file_common_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_common_proto_rawDesc, NumEnums: 0, - NumMessages: 63, + NumMessages: 66, NumExtensions: 0, NumServices: 0, }, diff --git a/protocol/webapi/common.proto b/protocol/webapi/common.proto index 3a131bd..23bad89 100644 --- a/protocol/webapi/common.proto +++ b/protocol/webapi/common.proto @@ -658,4 +658,22 @@ message ChannelSwitchConfig{ int32 Tp = 1; // 开关类型 1.兑换 2.道具掉落 string Platform = 2; // 平台id repeated string OnChannelName = 3; // 开启渠道 +} + +message RankAward{ + int64 Start = 1; // 开始积分 + int64 End = 2; // 结束积分 + int64 Num = 3; // 奖励 +} + +// etcd /game/act_invite +message ActInviteConfig { + string Platform = 1; + int64 BindScore = 2; // 绑定积分 + int64 RechargeScore = 3; // 充值积分,一个玩家最多给上级贡献一次 + map PayScore = 4; // 充值积分;充值金额:获得积分 + repeated int64 Rates = 5; // 返佣比例;多级按顺序给 + repeated RankAward Awards1 = 6; // 周榜奖励列表 + repeated RankAward Awards2 = 7; // 周榜奖励列表 + repeated RankAward Awards3 = 8; // 周榜奖励列表 } \ No newline at end of file diff --git a/protocol/welfare/welfare.pb.go b/protocol/welfare/welfare.pb.go index 2bef3c9..4d7dbdb 100644 --- a/protocol/welfare/welfare.pb.go +++ b/protocol/welfare/welfare.pb.go @@ -1964,23 +1964,93 @@ func (*CSInviteInfo) Descriptor() ([]byte, []int) { return file_welfare_proto_rawDescGZIP(), []int{28} } +type RankAward struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Start int64 `protobuf:"varint,1,opt,name=Start,proto3" json:"Start,omitempty"` // 开始积分 + End int64 `protobuf:"varint,2,opt,name=End,proto3" json:"End,omitempty"` // 结束积分 + Num int64 `protobuf:"varint,3,opt,name=Num,proto3" json:"Num,omitempty"` // 奖励 +} + +func (x *RankAward) Reset() { + *x = RankAward{} + if protoimpl.UnsafeEnabled { + mi := &file_welfare_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RankAward) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RankAward) ProtoMessage() {} + +func (x *RankAward) ProtoReflect() protoreflect.Message { + mi := &file_welfare_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RankAward.ProtoReflect.Descriptor instead. +func (*RankAward) Descriptor() ([]byte, []int) { + return file_welfare_proto_rawDescGZIP(), []int{29} +} + +func (x *RankAward) GetStart() int64 { + if x != nil { + return x.Start + } + return 0 +} + +func (x *RankAward) GetEnd() int64 { + if x != nil { + return x.End + } + return 0 +} + +func (x *RankAward) GetNum() int64 { + if x != nil { + return x.Num + } + return 0 +} + // PACKET_SCInviteInfo type SCInviteInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Num int32 `protobuf:"varint,1,opt,name=Num,proto3" json:"Num,omitempty"` // 邀请人数 - Code string `protobuf:"bytes,2,opt,name=Code,proto3" json:"Code,omitempty"` // 邀请码 - InviteUrl string `protobuf:"bytes,3,opt,name=InviteUrl,proto3" json:"InviteUrl,omitempty"` // 邀请链接 - Score int64 `protobuf:"varint,4,opt,name=Score,proto3" json:"Score,omitempty"` // 邀请积分 - OtherCode string `protobuf:"bytes,5,opt,name=OtherCode,proto3" json:"OtherCode,omitempty"` // 已绑定的邀请码 + Num int32 `protobuf:"varint,1,opt,name=Num,proto3" json:"Num,omitempty"` // 邀请人数 + Code string `protobuf:"bytes,2,opt,name=Code,proto3" json:"Code,omitempty"` // 邀请码 + InviteUrl string `protobuf:"bytes,3,opt,name=InviteUrl,proto3" json:"InviteUrl,omitempty"` // 邀请链接 + Score int64 `protobuf:"varint,4,opt,name=Score,proto3" json:"Score,omitempty"` // 邀请积分 + OtherCode string `protobuf:"bytes,5,opt,name=OtherCode,proto3" json:"OtherCode,omitempty"` // 已绑定的邀请码 + BindScore int64 `protobuf:"varint,6,opt,name=BindScore,proto3" json:"BindScore,omitempty"` // 绑定积分 + RechargeScore int64 `protobuf:"varint,7,opt,name=RechargeScore,proto3" json:"RechargeScore,omitempty"` // 充值积分,一个玩家最多给上级贡献一次 + PayScore map[int64]int64 `protobuf:"bytes,8,rep,name=PayScore,proto3" json:"PayScore,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` // 充值积分;充值金额:获得积分 + Rates []int64 `protobuf:"varint,9,rep,packed,name=Rates,proto3" json:"Rates,omitempty"` // 返佣比例;多级按顺序给 + Awards1 []*RankAward `protobuf:"bytes,10,rep,name=Awards1,proto3" json:"Awards1,omitempty"` // 周榜奖励列表 + Awards2 []*RankAward `protobuf:"bytes,11,rep,name=Awards2,proto3" json:"Awards2,omitempty"` // 周榜奖励列表 + Awards3 []*RankAward `protobuf:"bytes,12,rep,name=Awards3,proto3" json:"Awards3,omitempty"` // 周榜奖励列表 } func (x *SCInviteInfo) Reset() { *x = SCInviteInfo{} if protoimpl.UnsafeEnabled { - mi := &file_welfare_proto_msgTypes[29] + mi := &file_welfare_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1993,7 +2063,7 @@ func (x *SCInviteInfo) String() string { func (*SCInviteInfo) ProtoMessage() {} func (x *SCInviteInfo) ProtoReflect() protoreflect.Message { - mi := &file_welfare_proto_msgTypes[29] + mi := &file_welfare_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2006,7 +2076,7 @@ func (x *SCInviteInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use SCInviteInfo.ProtoReflect.Descriptor instead. func (*SCInviteInfo) Descriptor() ([]byte, []int) { - return file_welfare_proto_rawDescGZIP(), []int{29} + return file_welfare_proto_rawDescGZIP(), []int{30} } func (x *SCInviteInfo) GetNum() int32 { @@ -2044,6 +2114,55 @@ func (x *SCInviteInfo) GetOtherCode() string { return "" } +func (x *SCInviteInfo) GetBindScore() int64 { + if x != nil { + return x.BindScore + } + return 0 +} + +func (x *SCInviteInfo) GetRechargeScore() int64 { + if x != nil { + return x.RechargeScore + } + return 0 +} + +func (x *SCInviteInfo) GetPayScore() map[int64]int64 { + if x != nil { + return x.PayScore + } + return nil +} + +func (x *SCInviteInfo) GetRates() []int64 { + if x != nil { + return x.Rates + } + return nil +} + +func (x *SCInviteInfo) GetAwards1() []*RankAward { + if x != nil { + return x.Awards1 + } + return nil +} + +func (x *SCInviteInfo) GetAwards2() []*RankAward { + if x != nil { + return x.Awards2 + } + return nil +} + +func (x *SCInviteInfo) GetAwards3() []*RankAward { + if x != nil { + return x.Awards3 + } + return nil +} + // 绑定邀请人 // PACKET_CSBindInvite type CSBindInvite struct { @@ -2057,7 +2176,7 @@ type CSBindInvite struct { func (x *CSBindInvite) Reset() { *x = CSBindInvite{} if protoimpl.UnsafeEnabled { - mi := &file_welfare_proto_msgTypes[30] + mi := &file_welfare_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2070,7 +2189,7 @@ func (x *CSBindInvite) String() string { func (*CSBindInvite) ProtoMessage() {} func (x *CSBindInvite) ProtoReflect() protoreflect.Message { - mi := &file_welfare_proto_msgTypes[30] + mi := &file_welfare_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2083,7 +2202,7 @@ func (x *CSBindInvite) ProtoReflect() protoreflect.Message { // Deprecated: Use CSBindInvite.ProtoReflect.Descriptor instead. func (*CSBindInvite) Descriptor() ([]byte, []int) { - return file_welfare_proto_rawDescGZIP(), []int{30} + return file_welfare_proto_rawDescGZIP(), []int{31} } func (x *CSBindInvite) GetCode() string { @@ -2105,7 +2224,7 @@ type SCBindInvite struct { func (x *SCBindInvite) Reset() { *x = SCBindInvite{} if protoimpl.UnsafeEnabled { - mi := &file_welfare_proto_msgTypes[31] + mi := &file_welfare_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2118,7 +2237,7 @@ func (x *SCBindInvite) String() string { func (*SCBindInvite) ProtoMessage() {} func (x *SCBindInvite) ProtoReflect() protoreflect.Message { - mi := &file_welfare_proto_msgTypes[31] + mi := &file_welfare_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2131,7 +2250,7 @@ func (x *SCBindInvite) ProtoReflect() protoreflect.Message { // Deprecated: Use SCBindInvite.ProtoReflect.Descriptor instead. func (*SCBindInvite) Descriptor() ([]byte, []int) { - return file_welfare_proto_rawDescGZIP(), []int{31} + return file_welfare_proto_rawDescGZIP(), []int{32} } func (x *SCBindInvite) GetOpRetCode() OpResultCode { @@ -2152,7 +2271,7 @@ type CSPigbankGetInfo struct { func (x *CSPigbankGetInfo) Reset() { *x = CSPigbankGetInfo{} if protoimpl.UnsafeEnabled { - mi := &file_welfare_proto_msgTypes[32] + mi := &file_welfare_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2165,7 +2284,7 @@ func (x *CSPigbankGetInfo) String() string { func (*CSPigbankGetInfo) ProtoMessage() {} func (x *CSPigbankGetInfo) ProtoReflect() protoreflect.Message { - mi := &file_welfare_proto_msgTypes[32] + mi := &file_welfare_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2178,7 +2297,7 @@ func (x *CSPigbankGetInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use CSPigbankGetInfo.ProtoReflect.Descriptor instead. func (*CSPigbankGetInfo) Descriptor() ([]byte, []int) { - return file_welfare_proto_rawDescGZIP(), []int{32} + return file_welfare_proto_rawDescGZIP(), []int{33} } // 存钱罐信息 @@ -2199,7 +2318,7 @@ type SCPigbankGetInfo struct { func (x *SCPigbankGetInfo) Reset() { *x = SCPigbankGetInfo{} if protoimpl.UnsafeEnabled { - mi := &file_welfare_proto_msgTypes[33] + mi := &file_welfare_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2212,7 +2331,7 @@ func (x *SCPigbankGetInfo) String() string { func (*SCPigbankGetInfo) ProtoMessage() {} func (x *SCPigbankGetInfo) ProtoReflect() protoreflect.Message { - mi := &file_welfare_proto_msgTypes[33] + mi := &file_welfare_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2225,7 +2344,7 @@ func (x *SCPigbankGetInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use SCPigbankGetInfo.ProtoReflect.Descriptor instead. func (*SCPigbankGetInfo) Descriptor() ([]byte, []int) { - return file_welfare_proto_rawDescGZIP(), []int{33} + return file_welfare_proto_rawDescGZIP(), []int{34} } func (x *SCPigbankGetInfo) GetOpRetCode() OpResultCode { @@ -2281,7 +2400,7 @@ type CSPigbankTakeCoin struct { func (x *CSPigbankTakeCoin) Reset() { *x = CSPigbankTakeCoin{} if protoimpl.UnsafeEnabled { - mi := &file_welfare_proto_msgTypes[34] + mi := &file_welfare_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2294,7 +2413,7 @@ func (x *CSPigbankTakeCoin) String() string { func (*CSPigbankTakeCoin) ProtoMessage() {} func (x *CSPigbankTakeCoin) ProtoReflect() protoreflect.Message { - mi := &file_welfare_proto_msgTypes[34] + mi := &file_welfare_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2307,7 +2426,7 @@ func (x *CSPigbankTakeCoin) ProtoReflect() protoreflect.Message { // Deprecated: Use CSPigbankTakeCoin.ProtoReflect.Descriptor instead. func (*CSPigbankTakeCoin) Descriptor() ([]byte, []int) { - return file_welfare_proto_rawDescGZIP(), []int{34} + return file_welfare_proto_rawDescGZIP(), []int{35} } // 存钱罐领取金币 @@ -2328,7 +2447,7 @@ type SCPigbankTakeCoin struct { func (x *SCPigbankTakeCoin) Reset() { *x = SCPigbankTakeCoin{} if protoimpl.UnsafeEnabled { - mi := &file_welfare_proto_msgTypes[35] + mi := &file_welfare_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2341,7 +2460,7 @@ func (x *SCPigbankTakeCoin) String() string { func (*SCPigbankTakeCoin) ProtoMessage() {} func (x *SCPigbankTakeCoin) ProtoReflect() protoreflect.Message { - mi := &file_welfare_proto_msgTypes[35] + mi := &file_welfare_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2354,7 +2473,7 @@ func (x *SCPigbankTakeCoin) ProtoReflect() protoreflect.Message { // Deprecated: Use SCPigbankTakeCoin.ProtoReflect.Descriptor instead. func (*SCPigbankTakeCoin) Descriptor() ([]byte, []int) { - return file_welfare_proto_rawDescGZIP(), []int{35} + return file_welfare_proto_rawDescGZIP(), []int{36} } func (x *SCPigbankTakeCoin) GetOpRetCode() OpResultCode { @@ -2580,135 +2699,161 @@ var file_welfare_proto_rawDesc = []byte{ 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x47, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x22, 0x0e, 0x0a, 0x0c, 0x43, 0x53, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, - 0x22, 0x86, 0x01, 0x0a, 0x0c, 0x53, 0x43, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x4e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, - 0x4e, 0x75, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x49, 0x6e, 0x76, 0x69, 0x74, - 0x65, 0x55, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x49, 0x6e, 0x76, 0x69, - 0x74, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x4f, - 0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x4f, 0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x22, 0x0a, 0x0c, 0x43, 0x53, 0x42, - 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f, 0x64, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x43, 0x0a, - 0x0c, 0x53, 0x43, 0x42, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x12, 0x33, 0x0a, - 0x09, 0x4f, 0x70, 0x52, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x15, 0x2e, 0x77, 0x65, 0x6c, 0x66, 0x61, 0x72, 0x65, 0x2e, 0x4f, 0x70, 0x52, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x09, 0x4f, 0x70, 0x52, 0x65, 0x74, 0x43, 0x6f, - 0x64, 0x65, 0x22, 0x12, 0x0a, 0x10, 0x43, 0x53, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x47, - 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xe9, 0x01, 0x0a, 0x10, 0x53, 0x43, 0x50, 0x69, 0x67, - 0x62, 0x61, 0x6e, 0x6b, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x0a, 0x09, 0x4f, - 0x70, 0x52, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, - 0x2e, 0x77, 0x65, 0x6c, 0x66, 0x61, 0x72, 0x65, 0x2e, 0x4f, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x09, 0x4f, 0x70, 0x52, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, - 0x12, 0x1a, 0x0a, 0x08, 0x42, 0x61, 0x6e, 0x6b, 0x43, 0x6f, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x08, 0x42, 0x61, 0x6e, 0x6b, 0x43, 0x6f, 0x69, 0x6e, 0x12, 0x1c, 0x0a, 0x09, - 0x54, 0x61, 0x6b, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x09, 0x54, 0x61, 0x6b, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, - 0x73, 0x74, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0b, 0x43, 0x6f, 0x73, 0x74, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x12, 0x20, 0x0a, 0x0b, - 0x42, 0x61, 0x6e, 0x6b, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0b, 0x42, 0x61, 0x6e, 0x6b, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x69, 0x6e, 0x12, 0x22, - 0x0a, 0x0c, 0x44, 0x61, 0x79, 0x42, 0x75, 0x79, 0x4d, 0x61, 0x78, 0x43, 0x6e, 0x74, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x44, 0x61, 0x79, 0x42, 0x75, 0x79, 0x4d, 0x61, 0x78, 0x43, - 0x6e, 0x74, 0x22, 0x13, 0x0a, 0x11, 0x43, 0x53, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x54, - 0x61, 0x6b, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x22, 0xf0, 0x01, 0x0a, 0x11, 0x53, 0x43, 0x50, 0x69, - 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x54, 0x61, 0x6b, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x12, 0x33, 0x0a, - 0x09, 0x4f, 0x70, 0x52, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x15, 0x2e, 0x77, 0x65, 0x6c, 0x66, 0x61, 0x72, 0x65, 0x2e, 0x4f, 0x70, 0x52, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x09, 0x4f, 0x70, 0x52, 0x65, 0x74, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x54, 0x61, 0x6b, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x4e, 0x75, - 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x54, 0x61, 0x6b, 0x65, 0x43, 0x6f, 0x69, - 0x6e, 0x4e, 0x75, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x61, 0x6b, 0x65, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x54, 0x61, 0x6b, 0x65, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x73, 0x74, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x43, 0x6f, 0x73, 0x74, 0x44, 0x69, 0x61, - 0x6d, 0x6f, 0x6e, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x42, 0x61, 0x6e, 0x6b, 0x4d, 0x61, 0x78, 0x43, - 0x6f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x42, 0x61, 0x6e, 0x6b, 0x4d, - 0x61, 0x78, 0x43, 0x6f, 0x69, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x44, 0x61, 0x79, 0x42, 0x75, 0x79, - 0x4d, 0x61, 0x78, 0x43, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x44, 0x61, - 0x79, 0x42, 0x75, 0x79, 0x4d, 0x61, 0x78, 0x43, 0x6e, 0x74, 0x2a, 0x86, 0x02, 0x0a, 0x0c, 0x4f, - 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x4f, - 0x50, 0x52, 0x43, 0x5f, 0x53, 0x75, 0x63, 0x65, 0x73, 0x73, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, - 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, - 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x4e, 0x6f, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x10, 0x02, 0x12, 0x14, - 0x0a, 0x10, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x43, 0x6f, 0x69, 0x6e, 0x54, 0x6f, 0x6f, 0x4d, 0x6f, - 0x72, 0x65, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x45, 0x72, 0x72, - 0x43, 0x6f, 0x69, 0x6e, 0x10, 0x04, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x41, - 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x42, 0x69, 0x6e, 0x64, 0x10, 0x05, 0x12, 0x11, 0x0a, 0x0d, - 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x42, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x6c, 0x66, 0x10, 0x06, 0x12, - 0x11, 0x0a, 0x0d, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x4d, 0x79, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x4e, 0x6f, 0x74, 0x45, 0x78, - 0x69, 0x73, 0x74, 0x10, 0x08, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x44, 0x69, - 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x4c, 0x65, 0x73, 0x73, 0x10, 0x09, 0x12, 0x17, 0x0a, 0x13, 0x4f, - 0x50, 0x52, 0x43, 0x5f, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x4e, 0x6f, 0x74, 0x46, 0x75, - 0x6c, 0x6c, 0x10, 0x0a, 0x12, 0x1d, 0x0a, 0x19, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x50, 0x69, 0x67, - 0x62, 0x61, 0x6e, 0x6b, 0x4f, 0x76, 0x65, 0x72, 0x54, 0x61, 0x6b, 0x65, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x10, 0x0b, 0x2a, 0xcd, 0x07, 0x0a, 0x09, 0x53, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x49, - 0x44, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x48, 0x4f, 0x50, - 0x5f, 0x5a, 0x45, 0x52, 0x4f, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1c, 0x50, 0x41, 0x43, 0x4b, 0x45, - 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, 0x52, 0x45, 0x4c, - 0x49, 0x45, 0x46, 0x46, 0x55, 0x4e, 0x44, 0x10, 0x94, 0x14, 0x12, 0x21, 0x0a, 0x1c, 0x50, 0x41, - 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, - 0x52, 0x45, 0x4c, 0x49, 0x45, 0x46, 0x46, 0x55, 0x4e, 0x44, 0x10, 0x95, 0x14, 0x12, 0x20, 0x0a, - 0x1b, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, - 0x47, 0x45, 0x54, 0x54, 0x55, 0x52, 0x4e, 0x50, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x96, 0x14, 0x12, - 0x20, 0x0a, 0x1b, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, - 0x46, 0x5f, 0x47, 0x45, 0x54, 0x54, 0x55, 0x52, 0x4e, 0x50, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x97, - 0x14, 0x12, 0x20, 0x0a, 0x1b, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, - 0x45, 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, 0x41, 0x44, 0x44, 0x55, 0x50, 0x53, 0x49, 0x47, 0x4e, - 0x10, 0x98, 0x14, 0x12, 0x20, 0x0a, 0x1b, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, - 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, 0x41, 0x44, 0x44, 0x55, 0x50, 0x53, 0x49, - 0x47, 0x4e, 0x10, 0x99, 0x14, 0x12, 0x1f, 0x0a, 0x1a, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, - 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x41, 0x52, 0x45, 0x49, - 0x4e, 0x46, 0x4f, 0x10, 0x9a, 0x14, 0x12, 0x1f, 0x0a, 0x1a, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, - 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x41, 0x52, 0x45, - 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x9b, 0x14, 0x12, 0x1f, 0x0a, 0x1a, 0x50, 0x41, 0x43, 0x4b, 0x45, - 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x42, 0x4f, - 0x58, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x9c, 0x14, 0x12, 0x1f, 0x0a, 0x1a, 0x50, 0x41, 0x43, 0x4b, - 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x42, - 0x4f, 0x58, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x9d, 0x14, 0x12, 0x1e, 0x0a, 0x19, 0x50, 0x41, 0x43, - 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, 0x42, - 0x4c, 0x49, 0x4e, 0x42, 0x4f, 0x58, 0x10, 0x9e, 0x14, 0x12, 0x1e, 0x0a, 0x19, 0x50, 0x41, 0x43, - 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, 0x42, - 0x4c, 0x49, 0x4e, 0x42, 0x4f, 0x58, 0x10, 0x9f, 0x14, 0x12, 0x20, 0x0a, 0x1b, 0x50, 0x41, 0x43, - 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x46, 0x49, 0x52, 0x53, - 0x54, 0x50, 0x41, 0x59, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0xa0, 0x14, 0x12, 0x20, 0x0a, 0x1b, 0x50, - 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x46, 0x49, - 0x52, 0x53, 0x54, 0x50, 0x41, 0x59, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0xa1, 0x14, 0x12, 0x1c, 0x0a, - 0x17, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, - 0x46, 0x49, 0x52, 0x53, 0x54, 0x50, 0x41, 0x59, 0x10, 0xa2, 0x14, 0x12, 0x1c, 0x0a, 0x17, 0x50, - 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x46, 0x49, - 0x52, 0x53, 0x54, 0x50, 0x41, 0x59, 0x10, 0xa3, 0x14, 0x12, 0x21, 0x0a, 0x1c, 0x50, 0x41, 0x43, - 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x43, 0x4f, 0x4e, 0x54, - 0x49, 0x4e, 0x50, 0x41, 0x59, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0xa4, 0x14, 0x12, 0x21, 0x0a, 0x1c, - 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x43, - 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x50, 0x41, 0x59, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0xa5, 0x14, 0x12, - 0x1d, 0x0a, 0x18, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, - 0x46, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x50, 0x41, 0x59, 0x10, 0xa6, 0x14, 0x12, 0x1d, - 0x0a, 0x18, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, - 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x50, 0x41, 0x59, 0x10, 0xa7, 0x14, 0x12, 0x18, 0x0a, - 0x13, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x57, 0x65, 0x6c, 0x66, 0x52, 0x65, - 0x6c, 0x69, 0x65, 0x66, 0x10, 0xd4, 0x16, 0x12, 0x18, 0x0a, 0x13, 0x50, 0x41, 0x43, 0x4b, 0x45, - 0x54, 0x5f, 0x53, 0x43, 0x57, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x6c, 0x69, 0x65, 0x66, 0x10, 0xd5, - 0x16, 0x12, 0x18, 0x0a, 0x13, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x49, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x10, 0xd6, 0x16, 0x12, 0x18, 0x0a, 0x13, 0x50, - 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x49, 0x6e, - 0x66, 0x6f, 0x10, 0xd7, 0x16, 0x12, 0x18, 0x0a, 0x13, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, - 0x43, 0x53, 0x42, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x10, 0xd8, 0x16, 0x12, - 0x18, 0x0a, 0x13, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x42, 0x69, 0x6e, 0x64, - 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x10, 0xd9, 0x16, 0x12, 0x1c, 0x0a, 0x17, 0x50, 0x41, 0x43, - 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x47, 0x65, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x10, 0xde, 0x16, 0x12, 0x1c, 0x0a, 0x17, 0x50, 0x41, 0x43, 0x4b, 0x45, - 0x54, 0x5f, 0x53, 0x43, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x47, 0x65, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x10, 0xdf, 0x16, 0x12, 0x1d, 0x0a, 0x18, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, - 0x43, 0x53, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x54, 0x61, 0x6b, 0x65, 0x43, 0x6f, 0x69, - 0x6e, 0x10, 0xe0, 0x16, 0x12, 0x1d, 0x0a, 0x18, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, - 0x43, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x54, 0x61, 0x6b, 0x65, 0x43, 0x6f, 0x69, 0x6e, - 0x10, 0xe1, 0x16, 0x42, 0x27, 0x5a, 0x25, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x2e, 0x67, 0x61, 0x6d, - 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x6d, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x77, 0x65, 0x6c, 0x66, 0x61, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x22, 0x45, 0x0a, 0x09, 0x52, 0x61, 0x6e, 0x6b, 0x41, 0x77, 0x61, 0x72, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x45, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x03, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x4e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x03, 0x4e, 0x75, 0x6d, 0x22, 0xe8, 0x03, 0x0a, 0x0c, 0x53, 0x43, 0x49, 0x6e, + 0x76, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x4e, 0x75, 0x6d, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x4e, 0x75, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x55, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, + 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x53, 0x63, 0x6f, + 0x72, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x1c, 0x0a, 0x09, 0x42, 0x69, 0x6e, 0x64, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x09, 0x42, 0x69, 0x6e, 0x64, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x24, + 0x0a, 0x0d, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x53, + 0x63, 0x6f, 0x72, 0x65, 0x12, 0x3f, 0x0a, 0x08, 0x50, 0x61, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, + 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x65, 0x6c, 0x66, 0x61, 0x72, 0x65, + 0x2e, 0x53, 0x43, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x50, 0x61, + 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x50, 0x61, 0x79, + 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x52, 0x61, 0x74, 0x65, 0x73, 0x18, 0x09, + 0x20, 0x03, 0x28, 0x03, 0x52, 0x05, 0x52, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x07, 0x41, + 0x77, 0x61, 0x72, 0x64, 0x73, 0x31, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x77, + 0x65, 0x6c, 0x66, 0x61, 0x72, 0x65, 0x2e, 0x52, 0x61, 0x6e, 0x6b, 0x41, 0x77, 0x61, 0x72, 0x64, + 0x52, 0x07, 0x41, 0x77, 0x61, 0x72, 0x64, 0x73, 0x31, 0x12, 0x2c, 0x0a, 0x07, 0x41, 0x77, 0x61, + 0x72, 0x64, 0x73, 0x32, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x77, 0x65, 0x6c, + 0x66, 0x61, 0x72, 0x65, 0x2e, 0x52, 0x61, 0x6e, 0x6b, 0x41, 0x77, 0x61, 0x72, 0x64, 0x52, 0x07, + 0x41, 0x77, 0x61, 0x72, 0x64, 0x73, 0x32, 0x12, 0x2c, 0x0a, 0x07, 0x41, 0x77, 0x61, 0x72, 0x64, + 0x73, 0x33, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x77, 0x65, 0x6c, 0x66, 0x61, + 0x72, 0x65, 0x2e, 0x52, 0x61, 0x6e, 0x6b, 0x41, 0x77, 0x61, 0x72, 0x64, 0x52, 0x07, 0x41, 0x77, + 0x61, 0x72, 0x64, 0x73, 0x33, 0x1a, 0x3b, 0x0a, 0x0d, 0x50, 0x61, 0x79, 0x53, 0x63, 0x6f, 0x72, + 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x22, 0x22, 0x0a, 0x0c, 0x43, 0x53, 0x42, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x76, 0x69, + 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x43, 0x0a, 0x0c, 0x53, 0x43, 0x42, 0x69, 0x6e, 0x64, + 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x4f, 0x70, 0x52, 0x65, 0x74, 0x43, + 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x65, 0x6c, 0x66, + 0x61, 0x72, 0x65, 0x2e, 0x4f, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, + 0x52, 0x09, 0x4f, 0x70, 0x52, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x12, 0x0a, 0x10, 0x43, + 0x53, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, + 0xe9, 0x01, 0x0a, 0x10, 0x53, 0x43, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x47, 0x65, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x0a, 0x09, 0x4f, 0x70, 0x52, 0x65, 0x74, 0x43, 0x6f, 0x64, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x65, 0x6c, 0x66, 0x61, 0x72, + 0x65, 0x2e, 0x4f, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x09, + 0x4f, 0x70, 0x52, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x42, 0x61, 0x6e, + 0x6b, 0x43, 0x6f, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x42, 0x61, 0x6e, + 0x6b, 0x43, 0x6f, 0x69, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x61, 0x6b, 0x65, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x54, 0x61, 0x6b, 0x65, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x73, 0x74, 0x44, 0x69, 0x61, 0x6d, 0x6f, + 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x43, 0x6f, 0x73, 0x74, 0x44, 0x69, + 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x42, 0x61, 0x6e, 0x6b, 0x4d, 0x61, 0x78, + 0x43, 0x6f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x42, 0x61, 0x6e, 0x6b, + 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x69, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x44, 0x61, 0x79, 0x42, 0x75, + 0x79, 0x4d, 0x61, 0x78, 0x43, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x44, + 0x61, 0x79, 0x42, 0x75, 0x79, 0x4d, 0x61, 0x78, 0x43, 0x6e, 0x74, 0x22, 0x13, 0x0a, 0x11, 0x43, + 0x53, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x54, 0x61, 0x6b, 0x65, 0x43, 0x6f, 0x69, 0x6e, + 0x22, 0xf0, 0x01, 0x0a, 0x11, 0x53, 0x43, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x54, 0x61, + 0x6b, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x12, 0x33, 0x0a, 0x09, 0x4f, 0x70, 0x52, 0x65, 0x74, 0x43, + 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x77, 0x65, 0x6c, 0x66, + 0x61, 0x72, 0x65, 0x2e, 0x4f, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, + 0x52, 0x09, 0x4f, 0x70, 0x52, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x54, + 0x61, 0x6b, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x4e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x54, 0x61, 0x6b, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x4e, 0x75, 0x6d, 0x12, 0x1c, 0x0a, + 0x09, 0x54, 0x61, 0x6b, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x09, 0x54, 0x61, 0x6b, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x43, + 0x6f, 0x73, 0x74, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x43, 0x6f, 0x73, 0x74, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x12, 0x20, 0x0a, + 0x0b, 0x42, 0x61, 0x6e, 0x6b, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0b, 0x42, 0x61, 0x6e, 0x6b, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x69, 0x6e, 0x12, + 0x22, 0x0a, 0x0c, 0x44, 0x61, 0x79, 0x42, 0x75, 0x79, 0x4d, 0x61, 0x78, 0x43, 0x6e, 0x74, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x44, 0x61, 0x79, 0x42, 0x75, 0x79, 0x4d, 0x61, 0x78, + 0x43, 0x6e, 0x74, 0x2a, 0x86, 0x02, 0x0a, 0x0c, 0x4f, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x43, 0x6f, 0x64, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x53, 0x75, 0x63, + 0x65, 0x73, 0x73, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x4e, 0x6f, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x52, 0x43, 0x5f, + 0x43, 0x6f, 0x69, 0x6e, 0x54, 0x6f, 0x6f, 0x4d, 0x6f, 0x72, 0x65, 0x10, 0x03, 0x12, 0x10, 0x0a, + 0x0c, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x45, 0x72, 0x72, 0x43, 0x6f, 0x69, 0x6e, 0x10, 0x04, 0x12, + 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x42, + 0x69, 0x6e, 0x64, 0x10, 0x05, 0x12, 0x11, 0x0a, 0x0d, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x42, 0x69, + 0x6e, 0x64, 0x53, 0x65, 0x6c, 0x66, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x4f, 0x50, 0x52, 0x43, + 0x5f, 0x4d, 0x79, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x4f, + 0x50, 0x52, 0x43, 0x5f, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x69, 0x73, 0x74, 0x10, 0x08, 0x12, 0x14, + 0x0a, 0x10, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x4c, 0x65, + 0x73, 0x73, 0x10, 0x09, 0x12, 0x17, 0x0a, 0x13, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x50, 0x69, 0x67, + 0x62, 0x61, 0x6e, 0x6b, 0x4e, 0x6f, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x0a, 0x12, 0x1d, 0x0a, + 0x19, 0x4f, 0x50, 0x52, 0x43, 0x5f, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x4f, 0x76, 0x65, + 0x72, 0x54, 0x61, 0x6b, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x10, 0x0b, 0x2a, 0xcd, 0x07, 0x0a, + 0x09, 0x53, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x41, + 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x48, 0x4f, 0x50, 0x5f, 0x5a, 0x45, 0x52, 0x4f, 0x10, 0x00, + 0x12, 0x21, 0x0a, 0x1c, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, + 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, 0x52, 0x45, 0x4c, 0x49, 0x45, 0x46, 0x46, 0x55, 0x4e, 0x44, + 0x10, 0x94, 0x14, 0x12, 0x21, 0x0a, 0x1c, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, + 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, 0x52, 0x45, 0x4c, 0x49, 0x45, 0x46, 0x46, + 0x55, 0x4e, 0x44, 0x10, 0x95, 0x14, 0x12, 0x20, 0x0a, 0x1b, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, + 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, 0x54, 0x55, 0x52, 0x4e, + 0x50, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x96, 0x14, 0x12, 0x20, 0x0a, 0x1b, 0x50, 0x41, 0x43, 0x4b, + 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, 0x54, 0x55, + 0x52, 0x4e, 0x50, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x97, 0x14, 0x12, 0x20, 0x0a, 0x1b, 0x50, 0x41, + 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, + 0x41, 0x44, 0x44, 0x55, 0x50, 0x53, 0x49, 0x47, 0x4e, 0x10, 0x98, 0x14, 0x12, 0x20, 0x0a, 0x1b, + 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x47, + 0x45, 0x54, 0x41, 0x44, 0x44, 0x55, 0x50, 0x53, 0x49, 0x47, 0x4e, 0x10, 0x99, 0x14, 0x12, 0x1f, + 0x0a, 0x1a, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, + 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x41, 0x52, 0x45, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x9a, 0x14, 0x12, + 0x1f, 0x0a, 0x1a, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, + 0x46, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x41, 0x52, 0x45, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x9b, 0x14, + 0x12, 0x1f, 0x0a, 0x1a, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, + 0x4c, 0x46, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x42, 0x4f, 0x58, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x9c, + 0x14, 0x12, 0x1f, 0x0a, 0x1a, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, + 0x45, 0x4c, 0x46, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x42, 0x4f, 0x58, 0x49, 0x4e, 0x46, 0x4f, 0x10, + 0x9d, 0x14, 0x12, 0x1e, 0x0a, 0x19, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, + 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, 0x42, 0x4c, 0x49, 0x4e, 0x42, 0x4f, 0x58, 0x10, + 0x9e, 0x14, 0x12, 0x1e, 0x0a, 0x19, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x5f, + 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x47, 0x45, 0x54, 0x42, 0x4c, 0x49, 0x4e, 0x42, 0x4f, 0x58, 0x10, + 0x9f, 0x14, 0x12, 0x20, 0x0a, 0x1b, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, + 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x50, 0x41, 0x59, 0x49, 0x4e, 0x46, + 0x4f, 0x10, 0xa0, 0x14, 0x12, 0x20, 0x0a, 0x1b, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, + 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x50, 0x41, 0x59, 0x49, + 0x4e, 0x46, 0x4f, 0x10, 0xa1, 0x14, 0x12, 0x1c, 0x0a, 0x17, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, + 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x50, 0x41, + 0x59, 0x10, 0xa2, 0x14, 0x12, 0x1c, 0x0a, 0x17, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, + 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x50, 0x41, 0x59, 0x10, + 0xa3, 0x14, 0x12, 0x21, 0x0a, 0x1c, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, + 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x50, 0x41, 0x59, 0x49, 0x4e, + 0x46, 0x4f, 0x10, 0xa4, 0x14, 0x12, 0x21, 0x0a, 0x1c, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, + 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, 0x50, 0x41, + 0x59, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0xa5, 0x14, 0x12, 0x1d, 0x0a, 0x18, 0x50, 0x41, 0x43, 0x4b, + 0x45, 0x54, 0x5f, 0x43, 0x53, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x49, + 0x4e, 0x50, 0x41, 0x59, 0x10, 0xa6, 0x14, 0x12, 0x1d, 0x0a, 0x18, 0x50, 0x41, 0x43, 0x4b, 0x45, + 0x54, 0x5f, 0x53, 0x43, 0x5f, 0x57, 0x45, 0x4c, 0x46, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x49, 0x4e, + 0x50, 0x41, 0x59, 0x10, 0xa7, 0x14, 0x12, 0x18, 0x0a, 0x13, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, + 0x5f, 0x43, 0x53, 0x57, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x6c, 0x69, 0x65, 0x66, 0x10, 0xd4, 0x16, + 0x12, 0x18, 0x0a, 0x13, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x57, 0x65, 0x6c, + 0x66, 0x52, 0x65, 0x6c, 0x69, 0x65, 0x66, 0x10, 0xd5, 0x16, 0x12, 0x18, 0x0a, 0x13, 0x50, 0x41, + 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x10, 0xd6, 0x16, 0x12, 0x18, 0x0a, 0x13, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, + 0x43, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x10, 0xd7, 0x16, 0x12, 0x18, + 0x0a, 0x13, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x42, 0x69, 0x6e, 0x64, 0x49, + 0x6e, 0x76, 0x69, 0x74, 0x65, 0x10, 0xd8, 0x16, 0x12, 0x18, 0x0a, 0x13, 0x50, 0x41, 0x43, 0x4b, + 0x45, 0x54, 0x5f, 0x53, 0x43, 0x42, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x10, + 0xd9, 0x16, 0x12, 0x1c, 0x0a, 0x17, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x50, + 0x69, 0x67, 0x62, 0x61, 0x6e, 0x6b, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x10, 0xde, 0x16, + 0x12, 0x1c, 0x0a, 0x17, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x50, 0x69, 0x67, + 0x62, 0x61, 0x6e, 0x6b, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x10, 0xdf, 0x16, 0x12, 0x1d, + 0x0a, 0x18, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x43, 0x53, 0x50, 0x69, 0x67, 0x62, 0x61, + 0x6e, 0x6b, 0x54, 0x61, 0x6b, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x10, 0xe0, 0x16, 0x12, 0x1d, 0x0a, + 0x18, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x53, 0x43, 0x50, 0x69, 0x67, 0x62, 0x61, 0x6e, + 0x6b, 0x54, 0x61, 0x6b, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x10, 0xe1, 0x16, 0x42, 0x27, 0x5a, 0x25, + 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x67, 0x61, 0x6d, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x77, 0x65, + 0x6c, 0x66, 0x61, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2724,7 +2869,7 @@ func file_welfare_proto_rawDescGZIP() []byte { } var file_welfare_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_welfare_proto_msgTypes = make([]protoimpl.MessageInfo, 36) +var file_welfare_proto_msgTypes = make([]protoimpl.MessageInfo, 38) var file_welfare_proto_goTypes = []interface{}{ (OpResultCode)(0), // 0: welfare.OpResultCode (SPacketID)(0), // 1: welfare.SPacketID @@ -2757,13 +2902,15 @@ var file_welfare_proto_goTypes = []interface{}{ (*CSWelfareRelief)(nil), // 28: welfare.CSWelfareRelief (*SCWelfareRelief)(nil), // 29: welfare.SCWelfareRelief (*CSInviteInfo)(nil), // 30: welfare.CSInviteInfo - (*SCInviteInfo)(nil), // 31: welfare.SCInviteInfo - (*CSBindInvite)(nil), // 32: welfare.CSBindInvite - (*SCBindInvite)(nil), // 33: welfare.SCBindInvite - (*CSPigbankGetInfo)(nil), // 34: welfare.CSPigbankGetInfo - (*SCPigbankGetInfo)(nil), // 35: welfare.SCPigbankGetInfo - (*CSPigbankTakeCoin)(nil), // 36: welfare.CSPigbankTakeCoin - (*SCPigbankTakeCoin)(nil), // 37: welfare.SCPigbankTakeCoin + (*RankAward)(nil), // 31: welfare.RankAward + (*SCInviteInfo)(nil), // 32: welfare.SCInviteInfo + (*CSBindInvite)(nil), // 33: welfare.CSBindInvite + (*SCBindInvite)(nil), // 34: welfare.SCBindInvite + (*CSPigbankGetInfo)(nil), // 35: welfare.CSPigbankGetInfo + (*SCPigbankGetInfo)(nil), // 36: welfare.SCPigbankGetInfo + (*CSPigbankTakeCoin)(nil), // 37: welfare.CSPigbankTakeCoin + (*SCPigbankTakeCoin)(nil), // 38: welfare.SCPigbankTakeCoin + nil, // 39: welfare.SCInviteInfo.PayScoreEntry } var file_welfare_proto_depIdxs = []int32{ 0, // 0: welfare.SCGetReliefFund.OpRetCode:type_name -> welfare.OpResultCode @@ -2787,14 +2934,18 @@ var file_welfare_proto_depIdxs = []int32{ 0, // 18: welfare.SCWelfareContinuousPayData.OpRetCode:type_name -> welfare.OpResultCode 19, // 19: welfare.SCWelfareContinuousPayData.List:type_name -> welfare.WelfareSpree 0, // 20: welfare.SCWelfareContinuousPay.OpRetCode:type_name -> welfare.OpResultCode - 0, // 21: welfare.SCBindInvite.OpRetCode:type_name -> welfare.OpResultCode - 0, // 22: welfare.SCPigbankGetInfo.OpRetCode:type_name -> welfare.OpResultCode - 0, // 23: welfare.SCPigbankTakeCoin.OpRetCode:type_name -> welfare.OpResultCode - 24, // [24:24] is the sub-list for method output_type - 24, // [24:24] is the sub-list for method input_type - 24, // [24:24] is the sub-list for extension type_name - 24, // [24:24] is the sub-list for extension extendee - 0, // [0:24] is the sub-list for field type_name + 39, // 21: welfare.SCInviteInfo.PayScore:type_name -> welfare.SCInviteInfo.PayScoreEntry + 31, // 22: welfare.SCInviteInfo.Awards1:type_name -> welfare.RankAward + 31, // 23: welfare.SCInviteInfo.Awards2:type_name -> welfare.RankAward + 31, // 24: welfare.SCInviteInfo.Awards3:type_name -> welfare.RankAward + 0, // 25: welfare.SCBindInvite.OpRetCode:type_name -> welfare.OpResultCode + 0, // 26: welfare.SCPigbankGetInfo.OpRetCode:type_name -> welfare.OpResultCode + 0, // 27: welfare.SCPigbankTakeCoin.OpRetCode:type_name -> welfare.OpResultCode + 28, // [28:28] is the sub-list for method output_type + 28, // [28:28] is the sub-list for method input_type + 28, // [28:28] is the sub-list for extension type_name + 28, // [28:28] is the sub-list for extension extendee + 0, // [0:28] is the sub-list for field type_name } func init() { file_welfare_proto_init() } @@ -3152,7 +3303,7 @@ func file_welfare_proto_init() { } } file_welfare_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SCInviteInfo); i { + switch v := v.(*RankAward); i { case 0: return &v.state case 1: @@ -3164,7 +3315,7 @@ func file_welfare_proto_init() { } } file_welfare_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CSBindInvite); i { + switch v := v.(*SCInviteInfo); i { case 0: return &v.state case 1: @@ -3176,7 +3327,7 @@ func file_welfare_proto_init() { } } file_welfare_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SCBindInvite); i { + switch v := v.(*CSBindInvite); i { case 0: return &v.state case 1: @@ -3188,7 +3339,7 @@ func file_welfare_proto_init() { } } file_welfare_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CSPigbankGetInfo); i { + switch v := v.(*SCBindInvite); i { case 0: return &v.state case 1: @@ -3200,7 +3351,7 @@ func file_welfare_proto_init() { } } file_welfare_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SCPigbankGetInfo); i { + switch v := v.(*CSPigbankGetInfo); i { case 0: return &v.state case 1: @@ -3212,7 +3363,7 @@ func file_welfare_proto_init() { } } file_welfare_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CSPigbankTakeCoin); i { + switch v := v.(*SCPigbankGetInfo); i { case 0: return &v.state case 1: @@ -3224,6 +3375,18 @@ func file_welfare_proto_init() { } } file_welfare_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CSPigbankTakeCoin); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_welfare_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SCPigbankTakeCoin); i { case 0: return &v.state @@ -3242,7 +3405,7 @@ func file_welfare_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_welfare_proto_rawDesc, NumEnums: 2, - NumMessages: 36, + NumMessages: 38, NumExtensions: 0, NumServices: 0, }, diff --git a/protocol/welfare/welfare.proto b/protocol/welfare/welfare.proto index 0ac6416..23c6b1d 100644 --- a/protocol/welfare/welfare.proto +++ b/protocol/welfare/welfare.proto @@ -246,6 +246,13 @@ message SCWelfareRelief{ // 邀请信息 // PACKET_CSInviteInfo message CSInviteInfo{} + +message RankAward{ + int64 Start = 1; // 开始积分 + int64 End = 2; // 结束积分 + int64 Num = 3; // 奖励 +} + // PACKET_SCInviteInfo message SCInviteInfo{ int32 Num = 1; // 邀请人数 @@ -253,6 +260,13 @@ message SCInviteInfo{ string InviteUrl = 3; // 邀请链接 int64 Score = 4; // 邀请积分 string OtherCode = 5; // 已绑定的邀请码 + int64 BindScore = 6; // 绑定积分 + int64 RechargeScore = 7; // 充值积分,一个玩家最多给上级贡献一次 + map PayScore = 8; // 充值积分;充值金额:获得积分 + repeated int64 Rates = 9; // 返佣比例;多级按顺序给 + repeated RankAward Awards1 = 10; // 周榜奖励列表 + repeated RankAward Awards2 = 11; // 周榜奖励列表 + repeated RankAward Awards3 = 12; // 周榜奖励列表 } // 绑定邀请人 diff --git a/public b/public index 363a220..63d1713 160000 --- a/public +++ b/public @@ -1 +1 @@ -Subproject commit 363a22034898c87b42588d088a7838134d84dcb6 +Subproject commit 63d1713eb8595d4ad6334f88febbd0ca46bb67a1 diff --git a/worldsrv/action_player.go b/worldsrv/action_player.go index a8aaf0a..1c97def 100644 --- a/worldsrv/action_player.go +++ b/worldsrv/action_player.go @@ -2094,15 +2094,16 @@ func CSPlayerData(s *netlib.Session, packetid int, data interface{}, sid int64) } proto.SetDefaults(scPlayerData) common.SendToGate(sid, int(player_proto.PlayerPacketID_PACKET_SC_PLAYERDATA), scPlayerData, s) + logger.Logger.Tracef("SC_PLAYERDATA %v", scPlayerData) } + sid := PlayerMgrSington.EndPlayerLoading(cspl.GetAccId()) + if pd == nil { send(player_proto.OpResultCode_OPRC_Login_CreateFailed) return } - sid := PlayerMgrSington.EndPlayerLoading(cspl.GetAccId()) - var promoterID string var promoterCfg *PromoterConfig f := func() { diff --git a/worldsrv/action_welfare.go b/worldsrv/action_welfare.go index b01042a..f1b85a8 100644 --- a/worldsrv/action_welfare.go +++ b/worldsrv/action_welfare.go @@ -1,8 +1,9 @@ package main import ( - "encoding/base64" + "errors" "fmt" + "time" "mongo.games.com/goserver/core/basic" "mongo.games.com/goserver/core/logger" @@ -307,7 +308,7 @@ func CSInviteInfo(s *netlib.Session, packetid int, data interface{}, sid int64) } link := model.GameParamData.InviteUrl f := func() string { - return fmt.Sprintf("%s?user=%s", link, base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s|%d", p.Platform, p.SnId)))) + return fmt.Sprintf("%s?user=%s", link, p.ICode) } var res []byte @@ -330,12 +331,42 @@ func CSInviteInfo(s *netlib.Session, packetid int, data interface{}, sid int64) } ret := &welfare.SCInviteInfo{ - Num: p.InviteNum, - Code: p.InviteCode, + Num: int32(p.INum), + Code: p.ICode, InviteUrl: f(), - Score: p.InviteScore, - OtherCode: p.OtherCode, + Score: p.IScore, + OtherCode: p.PCode, } + + cfg := PlatformMgrSingleton.GetConfig(p.Platform).ActInviteConfig + if cfg != nil { + ret.BindScore = cfg.GetBindScore() + ret.RechargeScore = cfg.GetRechargeScore() + ret.PayScore = cfg.GetPayScore() + for _, v := range cfg.GetAwards1() { + ret.Awards1 = append(ret.Awards1, &welfare.RankAward{ + Start: v.GetStart(), + End: v.GetEnd(), + Num: v.GetNum(), + }) + } + for _, v := range cfg.GetAwards2() { + ret.Awards2 = append(ret.Awards2, &welfare.RankAward{ + Start: v.GetStart(), + End: v.GetEnd(), + Num: v.GetNum(), + }) + } + for _, v := range cfg.GetAwards3() { + ret.Awards3 = append(ret.Awards3, &welfare.RankAward{ + Start: v.GetStart(), + End: v.GetEnd(), + Num: v.GetNum(), + }) + } + ret.Rates = cfg.GetRates() + } + p.SendToClient(int(welfare.SPacketID_PACKET_SCInviteInfo), ret) logger.Logger.Tracef("SCInviteInfo %v", ret) })).Start() @@ -358,25 +389,20 @@ func CSBindInvite(s *netlib.Session, packetid int, data interface{}, sid int64) var inviteSnId int32 var err error + now := time.Now() + cfg := PlatformMgrSingleton.GetConfig(p.Platform).ActInviteConfig send := func() { p.SendToClient(int(welfare.SPacketID_PACKET_SCBindInvite), ret) logger.Logger.Tracef("SCBindInvite %v", ret) if ret.OpRetCode == welfare.OpResultCode_OPRC_Sucess { - // 更新绑定关系 - LogChannelSingleton.WriteLog(&model.BindInvite{ - Platform: p.Platform, - SnId: p.SnId, - InviteSnId: inviteSnId, - }) - + // 玩家自己的绑定任务 TaskSubjectSingleton.Touch(common.TaskTypeBindInviter, &TaskData{SnId: p.SnId, Num: 1}) - p.InviteTask(common.InviteScoreTypeLogin, 0, 1) } } - if p.InviteSnId != 0 { + if p.PSnId != 0 { ret.OpRetCode = welfare.OpResultCode_OPRC_AlreadyBind send() return nil @@ -393,43 +419,43 @@ func CSBindInvite(s *netlib.Session, packetid int, data interface{}, sid int64) return } - if inviteSnId == p.SnId { - ret.OpRetCode = welfare.OpResultCode_OPRC_BindSelf - send() - return - } - - pp := PlayerMgrSington.GetPlayerBySnId(inviteSnId) - if pp != nil { - if pp.InviteSnId == p.SnId { - ret.OpRetCode = welfare.OpResultCode_OPRC_MyInvite - send() - return - } - p.InviteSnId = pp.SnId - p.OtherCode = pp.InviteCode - ret.OpRetCode = welfare.OpResultCode_OPRC_Sucess - send() - return - } - - inviteSnId2 := int32(0) + // 3级父级不能是自己 var err error + tmpSnId := inviteSnId task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { - inviteSnId2, err = model.GetPlayerInviteSnid(p.Platform, inviteSnId) + // todo 优化查找顶级代理 + for i := 0; i < 10000; i++ { + if tmpSnId == p.SnId { + ret.OpRetCode = welfare.OpResultCode_OPRC_BindSelf + err = errors.New("bind error") + return nil + } + tmpSnId, err = model.GetPlayerInviteSnid(p.Platform, tmpSnId) + if err != nil { + ret.OpRetCode = welfare.OpResultCode_OPRC_Error + return nil + } + if tmpSnId == 0 { + break + } + } + SaveInviteScore(&model.InviteScore{ + Platform: p.Platform, + SnId: p.SnId, + InviteSnId: inviteSnId, + Tp: common.InviteScoreTypeBind, + Score: cfg.GetBindScore(), + Ts: now.Unix(), + Money: 0, + }) return nil }), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) { if err != nil { send() return } - if inviteSnId2 == p.SnId { - ret.OpRetCode = welfare.OpResultCode_OPRC_MyInvite - send() - return - } - p.InviteSnId = inviteSnId - p.OtherCode = msg.GetCode() + p.PSnId = inviteSnId + p.PCode = msg.GetCode() ret.OpRetCode = welfare.OpResultCode_OPRC_Sucess send() })).Start() diff --git a/worldsrv/bagmgr.go b/worldsrv/bagmgr.go index 394277a..f56e1e7 100644 --- a/worldsrv/bagmgr.go +++ b/worldsrv/bagmgr.go @@ -522,11 +522,11 @@ func (this *BagMgr) Shutdown() { //========================implement IPlayerLoad ============================== func (this *BagMgr) Load(platform string, snid int32, player any) *internal.PlayerLoadReplay { - data := model.GetBagInfo(snid, platform) + data, err := model.GetBagInfo(snid, platform) return &internal.PlayerLoadReplay{ Platform: platform, Snid: snid, - Err: nil, + Err: err, Data: data, } } diff --git a/worldsrv/etcd.go b/worldsrv/etcd.go index 53a4037..51faf23 100644 --- a/worldsrv/etcd.go +++ b/worldsrv/etcd.go @@ -66,6 +66,8 @@ func init() { etcd.Register(etcd.ETCDKEY_CHESSRANK_CFG, webapi.ChessRankcfgData{}, platformConfigEvent) // 手机积分 etcd.Register(etcd.ETCDKEY_ACT_PHONELOTTERY, webapi.WelfarePhoneLotteryStatus{}, platformConfigEvent) + // 邀请活动 + etcd.Register(etcd.ETCDKEY_ACT_Invite, webapi.ActInviteConfig{}, platformConfigEvent) } func platformConfigEvent(ctx context.Context, completeKey string, isInit bool, event *clientv3.Event, data interface{}) { @@ -195,7 +197,8 @@ func platformConfigEvent(ctx context.Context, completeKey string, isInit bool, e ChessRankMgrSington.UpdateChessRankConfig(config) case *webapi.WelfarePhoneLotteryStatus: WelfareMgrSington.UpdatePhoneLotteryStatus(config) - + case *webapi.ActInviteConfig: + PlatformMgrSingleton.GetConfig(config.Platform).ActInviteConfig = config default: logger.Logger.Errorf("etcd completeKey:%s, Not processed", completeKey) } diff --git a/worldsrv/invitecode.go b/worldsrv/invitecode.go index 74eb10f..971460c 100644 --- a/worldsrv/invitecode.go +++ b/worldsrv/invitecode.go @@ -1,124 +1,34 @@ package main import ( - "fmt" - - "mongo.games.com/goserver/core/basic" - "mongo.games.com/goserver/core/logger" - "mongo.games.com/goserver/core/task" + "time" "mongo.games.com/game/common" "mongo.games.com/game/model" - "mongo.games.com/game/worldsrv/internal" ) +// SaveInviteScore 保存玩家操作 +// 绑定,充值成功,充值;及产生的积分,充值金额 func SaveInviteScore(data *model.InviteScore) { if data == nil { return } - var err error - task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { - err = model.SaveInviteScore(data) - if err != nil { - logger.Logger.Errorf("SaveInviteScore error:%v", err) - return err - } - // 后台统计积分记录 - data.Ts /= 1000000000 // 后台需要秒 - LogChannelSingleton.WriteLog(data) - logger.Logger.Tracef("==> php InviteScore %+v", *data) - return nil - }), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) { - p := PlayerMgrSington.GetPlayerBySnId(data.InviteSnId) - if err == nil && p != nil { - if data.Score != 0 { - if data.Score < 0 { - if -data.Score > p.InviteScore { - data.Score = -p.InviteScore - } - } - p.InviteScore += data.Score - p.dirty = true - - // 更新邀请任务进度 - if data.Score > 0 { - TaskSubjectSingleton.Touch(common.TaskTypeInviteScore, &TaskData{ - SnId: p.SnId, - Num: data.Score, - }) - } - } - - if data.Money > 0 { - TaskSubjectSingleton.Touch(common.TaskTypeInviteRecharge, &TaskData{ - SnId: p.SnId, - Num: data.Money, - }) - } - } - })).StartByFixExecutor(fmt.Sprintf("invite_score_%v", data.InviteSnId)) + cfg := PlatformMgrSingleton.GetConfig(data.Platform).ActInviteConfig + data.Rate = cfg.GetRates() + LogChannelSingleton.WriteLog(&model.EvtInviteMsg{ + InviteScore: *data, + RechargeScore: cfg.GetRechargeScore(), + }) } -func GetInviteScore(platform string, snid int32) { - var n, z, money int64 - var err error - task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { - n, z, money, err = model.GetInviteScore(platform, snid) - if err != nil { - logger.Logger.Errorf("GetInviteScore error:%v", err) - return err - } - return nil - }), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) { - p := PlayerMgrSington.GetPlayerBySnId(snid) - if err == nil && p != nil { - p.InviteScore = n - p.dirty = true - - // 更新邀请任务进度 - p.ResetTaskN(common.TaskTypeInviteScore) - TaskSubjectSingleton.Touch(common.TaskTypeInviteScore, &TaskData{ - SnId: p.SnId, - Num: z, - }) - - p.ResetTaskN(common.TaskTypeInviteRecharge) - TaskSubjectSingleton.Touch(common.TaskTypeInviteRecharge, &TaskData{ - SnId: p.SnId, - Num: money, - }) - } - })).StartByFixExecutor(fmt.Sprintf("invite_score_%v", snid)) -} - -type InviteCode struct { - internal.BasePlayerLoader -} - -func (i *InviteCode) LoadAfter(platform string, snid int32) *internal.PlayerLoadReplay { - n, err := model.GetInviteNum(platform, snid) - return &internal.PlayerLoadReplay{ - Platform: platform, - Snid: snid, - Err: err, - Data: n, - } -} - -func (i *InviteCode) CallbackAfter(ret *internal.PlayerLoadReplay) { - if ret == nil { - return - } - p := PlayerMgrSington.GetPlayerBySnId(ret.Snid) - if p == nil { - return - } - p.InviteNum = ret.Data.(int32) - p.ResetTaskN(common.TaskTypeInviteNum) - TaskSubjectSingleton.Touch(common.TaskTypeInviteNum, &TaskData{SnId: p.SnId, Num: int64(p.InviteNum)}) - GetInviteScore(ret.Platform, ret.Snid) -} - -func init() { - internal.RegisterPlayerLoad(new(InviteCode)) +// CheckNewWeek 每周重置积分 +func CheckNewWeek(platform string, snid int32) { + LogChannelSingleton.WriteLog(&model.EvtInviteMsg{ + InviteScore: model.InviteScore{ + Platform: platform, + SnId: snid, + Tp: common.InviteScoreCheckWeek, + Ts: time.Now().Unix(), + }, + }) } diff --git a/worldsrv/logchannel.go b/worldsrv/logchannel.go index d1853b2..ceecdef 100644 --- a/worldsrv/logchannel.go +++ b/worldsrv/logchannel.go @@ -58,7 +58,6 @@ func init() { LogChannelSingleton.RegisterLogCName(model.MQRankPlayerCoin, &model.RankPlayerCoin{}) LogChannelSingleton.RegisterLogCName(mq.BackBankrupt, &model.BankruptLog{}) LogChannelSingleton.RegisterLogCName(mq.BackReliefund, &model.ReliefFundLog{}) - LogChannelSingleton.RegisterLogCName(model.EvtBindInvite, &model.BindInvite{}) - LogChannelSingleton.RegisterLogCName(mq.BackInviteScore, &model.InviteScore{}) + LogChannelSingleton.RegisterLogCName(model.EvtInvite, &model.EvtInviteMsg{}) LogChannelSingleton.RegisterLogCName(model.MQRankPlayerLevel, &model.PlayerLevelInfo{}) } diff --git a/worldsrv/mq_coinlog.go b/worldsrv/mq_coinlog.go index e78259f..01b9ec0 100644 --- a/worldsrv/mq_coinlog.go +++ b/worldsrv/mq_coinlog.go @@ -7,6 +7,7 @@ import ( "mongo.games.com/goserver/core/basic" "mongo.games.com/goserver/core/broker" "mongo.games.com/goserver/core/broker/rabbitmq" + "mongo.games.com/goserver/core/logger" "mongo.games.com/game/common" "mongo.games.com/game/model" @@ -41,31 +42,49 @@ func init() { return nil }, broker.Queue(model.TopicProbeCoinLogAck), rabbitmq.DurableQueue()) - // 绑定数量同步 - mq.RegisterSubscriber(model.AckBindNum, func(e broker.Event) error { + // 邀请数据同步 + mq.RegisterSubscriber(model.EvtInviteAck, func(e broker.Event) error { msg := e.Message() if msg != nil { defer func() { e.Ack() }() - var log model.BindNum + var log model.EvtInviteAckMsg err := json.Unmarshal(msg.Body, &log) if err != nil { return err } + logger.Logger.Tracef("EvtInviteAckMsg: %+v", log) + //通知主线程执行后续操作 core.CoreObject().SendCommand(basic.CommandWrapper(func(o *basic.Object) error { - player := PlayerMgrSington.GetPlayerBySnId(log.SnId) + player := PlayerMgrSington.GetPlayerBySnId(log.Snid) if player != nil { - player.InviteNum = log.Num + // 邀请数量 + player.INum = log.Num player.ResetTaskN(common.TaskTypeInviteNum) - TaskSubjectSingleton.Touch(common.TaskTypeInviteNum, &TaskData{SnId: player.SnId, Num: int64(player.InviteNum)}) + TaskSubjectSingleton.Touch(common.TaskTypeInviteNum, &TaskData{SnId: player.SnId, Num: player.INum}) + + // 邀请积分 + player.IScore = log.Score + player.ResetTaskN(common.TaskTypeInviteScore) + TaskSubjectSingleton.Touch(common.TaskTypeInviteScore, &TaskData{ + SnId: player.SnId, + Num: log.Score, + }) + // 充值金额 + player.IMoney = log.Money + player.ResetTaskN(common.TaskTypeInviteRecharge) + TaskSubjectSingleton.Touch(common.TaskTypeInviteRecharge, &TaskData{ + SnId: player.SnId, + Num: log.Money, + }) } return nil }), true) } return nil - }, broker.Queue(model.AckBindNum), rabbitmq.DurableQueue()) + }, broker.Queue(model.EvtInviteAck), rabbitmq.DurableQueue()) } diff --git a/worldsrv/player.go b/worldsrv/player.go index 315069d..ad3a894 100644 --- a/worldsrv/player.go +++ b/worldsrv/player.go @@ -146,7 +146,6 @@ type Player struct { // 最后玩的游戏id LastGameId int GameID []int32 // 最近三天玩的游戏 - InviteNum int32 // 邀请人数 ApplyList []int32 //玩家申请好友记录 } @@ -2222,8 +2221,6 @@ func (this *Player) OnDayTimer(login, continuous bool, t int) { for _, v := range srvdata.TaskMgr.GetActivityType(common.TaskActivityTypeEveryDay) { this.WelfData.Task[v.GetId()] = &model.TaskData{} } - this.WelfData.Task[common.TaskIDInvitePlayGame] = &model.TaskData{} - this.WelfData.Task[common.TaskIDInviteFirstLogin] = &model.TaskData{} } } //周卡数据更新 @@ -2312,6 +2309,8 @@ func (this *Player) OnWeekTimer() { } } // 重置周任务 + // 重置邀请积分 + CheckNewWeek(this.Platform, this.SnId) } func (this *Player) GetName() string { @@ -2452,10 +2451,10 @@ func (this *Player) SendDiffData() { pack.UpdateField += UpdateField_PhoneScore } // 邀请积分 - if this.diffData.InviteScore != this.InviteScore { + if this.diffData.InviteScore != this.IScore { dirty = true - pack.InviteScore = this.InviteScore - this.diffData.InviteScore = this.InviteScore + pack.InviteScore = this.IScore + this.diffData.InviteScore = this.IScore pack.UpdateField += UpdateField_InviteScore } //总充值金额 @@ -4372,97 +4371,38 @@ func (this *Player) PhoneLotteryTask(taskId int32, num int64) { } func (this *Player) InviteTask(scoreType int32, gameId int32, n int64) { - if this.InviteSnId == 0 { + if this.PSnId == 0 { return } - if this.WelfData == nil { - this.WelfData = model.NewWelfareData() - } - if this.WelfData.Task == nil { - this.WelfData.Task = make(map[int32]*model.TaskData) - } + cfg := PlatformMgrSingleton.GetConfig(this.Platform).ActInviteConfig switch scoreType { case common.InviteScoreTypeBind: - SaveInviteScore(&model.InviteScore{ - Platform: this.Platform, - SnId: this.SnId, - InviteSnId: this.InviteSnId, - Tp: scoreType, - Score: 5000, - Ts: time.Now().UnixNano(), - }) - case common.InviteScoreTypeLogin: - if this.WelfData.Task[common.TaskIDInviteFirstLogin] == nil { - this.WelfData.Task[common.TaskIDInviteFirstLogin] = &model.TaskData{} // 初始化任务数据 - } - if this.WelfData.Task[common.TaskIDInviteFirstLogin].Ts == 0 { - this.WelfData.Task[common.TaskIDInviteFirstLogin].Ts = time.Now().Unix() + case common.InviteScoreTypePay: + score, ok := cfg.GetPayScore()[n] + if ok { SaveInviteScore(&model.InviteScore{ Platform: this.Platform, SnId: this.SnId, - InviteSnId: this.InviteSnId, + InviteSnId: this.PSnId, Tp: scoreType, - Score: 1000, - Ts: time.Now().UnixNano(), + Score: score, + Ts: time.Now().Unix(), + Money: n, }) - } - - case common.InviteScoreTypePlayTimes: - if this.WelfData.Task[common.TaskIDInvitePlayGame] == nil { - this.WelfData.Task[common.TaskIDInvitePlayGame] = &model.TaskData{} // 初始化任务数据 - } - if this.WelfData.Task[common.TaskIDInvitePlayGame].Ts == 0 { - this.WelfData.Task[common.TaskIDInvitePlayGame].Ts = time.Now().Unix() + } else { SaveInviteScore(&model.InviteScore{ Platform: this.Platform, SnId: this.SnId, - InviteSnId: this.InviteSnId, - Tp: scoreType, - Score: 5000, - Ts: time.Now().UnixNano(), + InviteSnId: this.PSnId, + Tp: common.InviteScoreTypeRecharge, + Score: cfg.GetRechargeScore(), + Ts: time.Now().Unix(), + Money: n, }) } - - case common.InviteScoreTypeRecharge: - if this.WelfData.Task[common.TaskIDInviteRecharge] == nil { - this.WelfData.Task[common.TaskIDInviteRecharge] = &model.TaskData{} // 初始化任务数据 - } - this.WelfData.Task[common.TaskIDInviteRecharge].N += n - a := this.WelfData.Task[common.TaskIDInviteRecharge].N / 100 - this.WelfData.Task[common.TaskIDInviteRecharge].N %= 100 - SaveInviteScore(&model.InviteScore{ - Platform: this.Platform, - SnId: this.SnId, - InviteSnId: this.InviteSnId, - Tp: scoreType, - Score: a * common.InviteScoreRecharge, - Ts: time.Now().UnixNano(), - Money: n, - }) - - case common.InviteScoreTypeGameTimes: - score := 0 - switch { - case srvdata.GameFreeMgr.IsGameDif(gameId, common.GameDifTienlen): - score = 500 - case srvdata.GameFreeMgr.IsGameDif(gameId, common.GameDifThirteen): - score = 300 - case srvdata.GameFreeMgr.IsGameDif(gameId, common.GameDifRocket): - score = 30 - case srvdata.GameFreeMgr.IsGameDif(gameId, common.GameDifChess): - score = 100 - } - SaveInviteScore(&model.InviteScore{ - Platform: this.Platform, - SnId: this.SnId, - InviteSnId: this.InviteSnId, - Tp: scoreType, - Score: int64(score), - Ts: time.Now().UnixNano(), - }) } } diff --git a/worldsrv/taskmgr.go b/worldsrv/taskmgr.go index cc7ad77..13cd8ca 100644 --- a/worldsrv/taskmgr.go +++ b/worldsrv/taskmgr.go @@ -96,21 +96,18 @@ func (t *TaskHandle) TaskUpdate(id int, data any) { case common.TaskTypeWinTimes: // 赢游戏次数 case common.TaskTypePlayTimes: // 玩游戏次数 - p.InviteTask(common.InviteScoreTypePlayTimes, int32(info.GameID), num) - p.InviteTask(common.InviteScoreTypeGameTimes, int32(info.GameID), num) case common.TaskTypeRankMatchTimes: // 排位赛次数 case common.TaskTypePay: // 玩家充值 p.PhoneLotteryTask(common.TaskTypePay, num) - p.InviteTask(common.InviteScoreTypeRecharge, int32(info.GameID), num) + p.InviteTask(common.InviteScoreTypePay, int32(info.GameID), num) case common.TaskTypeWinOrLose: // 游戏输赢金币数量 p.PhoneLotteryTask(common.TaskTypeWinOrLose, num) case common.TaskTypeTienlenCount: //tienlen游戏场次 p.PhoneLotteryTask(common.TaskTypeTienlenCount, 1) case common.TaskTypeBindInviter: // 绑定邀请人数量 - p.InviteTask(common.InviteScoreTypeBind, 0, num) case common.TaskTypeWinCoin: // 赢取金币数量 @@ -123,7 +120,6 @@ func (t *TaskHandle) TaskUpdate(id int, data any) { case common.TaskTypeFirstLogin: //抽奖次数增加 p.PhoneLotteryTask(common.TaskTypeFirstLogin, 0) - p.InviteTask(common.InviteScoreTypeLogin, int32(info.GameID), num) p.CollectTask(common.TaskTypeFirstLogin, num) case common.TaskTypeInviteNum: diff --git a/worldsrv/trascate_webapi.go b/worldsrv/trascate_webapi.go index 96d40ec..8577669 100644 --- a/worldsrv/trascate_webapi.go +++ b/worldsrv/trascate_webapi.go @@ -2468,7 +2468,7 @@ func init() { if len(ret.List) > 0 { playerRankScore = ret.List[0] } - playerBagInfo = model.GetBagInfo(id, platform) + playerBagInfo, _ = model.GetBagInfo(id, platform) return data }), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) { playerData, ok := data.(*model.PlayerData) @@ -2559,7 +2559,7 @@ func init() { for _, v := range ret.List { playerRankScore[v.SnId] = v //todo 优化 - items := model.GetBagInfo(v.SnId, msg.GetPlatform()) + items, _ := model.GetBagInfo(v.SnId, msg.GetPlatform()) playerItems[v.SnId] = items } diff --git a/xlsx/DB_GameItem.xlsx b/xlsx/DB_GameItem.xlsx index fcc533a4a70e4c60021873435c620efdabb5ded3..928c317196bf6f99edc2ceea2a1c6fe118300ab5 100644 GIT binary patch delta 14320 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 SX2?MVpdKwuczBJc6Z}8!Y0Mn} delta 13752 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 YWCa6Q*-`MZ!f|j};W)dO+#jL;0bEdGZ2$lO diff --git a/xlsx/DB_Task.xlsx b/xlsx/DB_Task.xlsx index 0008809d6bf38f585077ab4ffb8652707e8ee01b..466a32be8781572f748f0b8df58110eb931ab901 100644 GIT binary patch delta 8395 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 pQv(1NNdN%lpBs_a|1L-Q7