player.go 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  1. package models
  2. import (
  3. "context"
  4. "fmt"
  5. jsoniter "github.com/json-iterator/go"
  6. mhayaString "github.com/mhaya/extend/string"
  7. mhayaTime "github.com/mhaya/extend/time"
  8. "github.com/mhaya/game/game_cluster/internal/constant"
  9. "github.com/mhaya/game/game_cluster/internal/data"
  10. "github.com/mhaya/game/game_cluster/internal/mdb"
  11. "github.com/mhaya/game/game_cluster/internal/param"
  12. "github.com/mhaya/game/game_cluster/internal/third"
  13. "github.com/mhaya/game/game_cluster/internal/token"
  14. mhayaLogger "github.com/mhaya/logger"
  15. "math/rand"
  16. "slices"
  17. "strconv"
  18. "strings"
  19. "time"
  20. )
  21. type Player struct {
  22. UserName string `json:"userName" bson:"userName"` // 用户名
  23. OpenId string `json:"openId" bson:"openId"` // 对应tgid
  24. UserNameMaybe string `json:"userNameMaybe" bson:"userNameMaybe"` // 昵称
  25. NickName string `json:"nickName" bson:"nickName"` // 昵称
  26. Pid string `json:"pid" bson:"pid"` // 上级ID
  27. XID string `json:"xID" bson:"xID"` // 绑定推特ID
  28. TonWall string `json:"tonWall" bson:"tonWall"` // 绑定钱包地址
  29. Email string `json:"email" bson:"email"` // 邮箱
  30. Mobile string `json:"mobile" bson:"mobile"` // 手机号
  31. Avatar string `json:"avatar" bson:"avatar"` // 头像
  32. Password string `json:"-" bson:"password"` //账户密码
  33. Salt string `json:"-" bson:"salt"` //密码盐
  34. IsSetPwd bool `json:"isSetPwd" bson:"-"` //是否设置密码
  35. PwdErrTimes int `json:"pwdErrTimes" bson:"pwdErrTimes"` //密码错误次数
  36. PwdErrRefreshTime int64 `json:"pwdErrRefreshTime" bson:"pwdErrRefreshTime"` //密码到期时间
  37. IsCashOut int `json:"-" bson:"IsCashOut"` //服务器判断是否有提现的数据 0 否 1是
  38. IsRobot int `json:"isRobot" bson:"isRobot"` // 是否为机器人
  39. IsLeader int `json:"isLeader" bson:"isLeader"` // 是否是社区长
  40. IsVip int `json:"isVip" bson:"isVip"` // 是否为VIP
  41. IsFirstBindingXID int `json:"isFirstBindingXID" bson:"isFirstBindingXID"` // 是否是第一次绑定推特
  42. Level int `json:"level" bson:"level"` // 等级
  43. Exp int `json:"exp" bson:"exp"` // 经验
  44. Gender int `json:"gender" bson:"gender"` // 性别
  45. Birthday string `json:"birthday" bson:"birthday"` // 生日
  46. Successions int `json:"successions" bson:"successions"` // 连续登陆天数
  47. MaxSuccessions int `json:"maxSuccessions" bson:"maxSuccessions"` // 最大连续等级天数
  48. PrevTime int64 `json:"prevTime" bson:"prevTime"` // 上次登陆时间
  49. LoginTime int64 `json:"loginTime" bson:"loginTime"` // 登陆时间
  50. LoginIP string `json:"loginIP" bson:"loginIP"` // 登录IP
  51. LoginFailure int `json:"loginFailure" bson:"loginFailure"` // 登陆失败次数
  52. JoinIP string `json:"joinIP" bson:"joinIP"` // 注册IP
  53. Rank int `json:"rank" bson:"rank"` // 排名
  54. JoinTime int64 `json:"joinTime" bson:"joinTime"` // 注册时间
  55. CreateTime int64 `json:"createTime" bson:"createTime"` // 创建时间
  56. UpdateTime int64 `json:"updateTime" bson:"updateTime"` // 更新时间
  57. DailyRefreshTime int64 `json:"dailyRefreshTime" bson:"dailyRefreshTime"` // 每日刷新时间
  58. HourRefreshTime int64 `json:"hourRefreshTime" bson:"hourRefreshTime"` // 每小时更新
  59. WeeklyRefreshTime int64 `json:"weeklyRefreshTime" bson:"weeklyRefreshTime"` // 每周刷新时间
  60. RollDay int64 `json:"rollDay" bson:"rollDay"` // 抽奖日期
  61. Status int `json:"status" bson:"status"` // 状态
  62. Roll *Roll `json:"roll" bson:"roll"` // 抽奖
  63. Guide int `json:"guide" bson:"guide"` //
  64. Share *Share `json:"share" bson:"share"` // 分享
  65. FirstReward int `json:"firstReward" bson:"firstReward"` // 首次登陆奖励
  66. Index int `json:"-" bson:"index"` // 索引
  67. Item ItemBasePack `json:"item" bson:"item"` // 道具
  68. SinIn SignIn `json:"sinIn" bson:"sinIn"` // 签到
  69. DailyTask DailyTask `json:"dailyTask" bson:"dailyTask"` // 日常任务
  70. AchieveTask AchieveTask `json:"achieveTask" bson:"achieveTask"` // 成就任务
  71. RankReward RankReward `json:"rankReward" bson:"rankReward"` // 排行奖励
  72. Invite Invite `json:"invite" bson:"invite"` // 邀请
  73. PlayerReward map[int]*PlayerRewardBase `json:"-" bson:"-"`
  74. InviteReward *InviteReward `json:"inviteReward" bson:"inviteReward"` // 邀请奖励
  75. InviteNodeReward InviteNodeReward `json:"inviteNodeReward" bson:"inviteNodeReward"` // 邀请节点奖励
  76. ClaimInviteNum int `json:"claimInviteNum" bson:"claimInviteNum"` // 当前周期,已领取的节点邀请奖励基数
  77. FirstClaimReward FirstReward `json:"firstClaimReward" bson:"firstClaimReward"` // 首次奖励
  78. }
  79. func NewPlayer(token *token.Token) *Player {
  80. return &Player{
  81. UserName: token.PlayerID,
  82. OpenId: token.OpenID,
  83. NickName: token.Nickname,
  84. IsRobot: 0,
  85. Successions: 1,
  86. MaxSuccessions: 1,
  87. LoginTime: mhayaTime.Now().Unix(),
  88. CreateTime: mhayaTime.Now().Unix(),
  89. UpdateTime: mhayaTime.Now().Unix(),
  90. RollDay: mhayaTime.Now().Unix(),
  91. Exp: 0,
  92. Status: 1,
  93. Rank: 0,
  94. Item: NewItem(),
  95. Guide: 1,
  96. Level: 1,
  97. Index: 1,
  98. FirstReward: 1,
  99. Roll: &Roll{RollNums: 0, RollDays: 0},
  100. DailyTask: NewDailyTask(),
  101. Share: &Share{IsDrawShare: 0},
  102. SinIn: NewSignIn(),
  103. AchieveTask: NewAchieveTask(),
  104. RankReward: NewRankReward(),
  105. Invite: NewInvite(),
  106. InviteNodeReward: NewInviteNodeReward(),
  107. FirstClaimReward: NewFirstReward(),
  108. }
  109. }
  110. func NewBotPlayer(token *token.Token) *Player {
  111. return &Player{
  112. UserName: token.PlayerID,
  113. OpenId: token.OpenID,
  114. NickName: token.Nickname,
  115. IsRobot: 1,
  116. Successions: 1,
  117. MaxSuccessions: 1,
  118. LoginTime: mhayaTime.Now().Unix(),
  119. CreateTime: mhayaTime.Now().Unix(),
  120. UpdateTime: mhayaTime.Now().Unix(),
  121. RollDay: mhayaTime.Now().Unix(),
  122. Exp: 0,
  123. Status: 1,
  124. Rank: 0,
  125. Item: NewItem(),
  126. Guide: 1,
  127. Level: 1,
  128. Index: 1,
  129. FirstReward: 1,
  130. Roll: &Roll{RollNums: 0, RollDays: 0},
  131. DailyTask: NewDailyTask(),
  132. Share: &Share{IsDrawShare: 0},
  133. SinIn: NewSignIn(),
  134. AchieveTask: NewAchieveTask(),
  135. RankReward: NewRankReward(),
  136. Invite: NewInvite(),
  137. }
  138. }
  139. func (p *Player) Init() {
  140. if p.InviteReward == nil {
  141. p.InviteReward = &InviteReward{IsClaim: 0}
  142. }
  143. }
  144. // InitDaily 每日刷新
  145. func (p *Player) InitDaily() {
  146. if !mhayaTime.CreateFromTimestamp(p.DailyRefreshTime).IsToday() {
  147. //刷新每日任务
  148. p.DailyTask.RefreshDailyTask()
  149. //刷新抽奖每日分享
  150. p.Share.RefreshShare()
  151. //刷新是否有排行榜奖励
  152. p.RankReward.InitRank(p.UserName, 1)
  153. //更新时间到当天
  154. p.DailyRefreshTime = mhayaTime.Now().Unix()
  155. }
  156. }
  157. func (p *Player) InitWeekly() {
  158. if !mhayaTime.CreateFromTimestamp(p.WeeklyRefreshTime).IsThisWeek() {
  159. //p.SinIn.RefreshSignIn()
  160. // 刷新是否有排行榜奖励
  161. p.RankReward.InitRank(p.UserName, 2)
  162. p.WeeklyRefreshTime = mhayaTime.Now().Unix()
  163. }
  164. }
  165. func (p *Player) InitSignIn() {
  166. ret := data.WeeklySignInConfig.GetAll()
  167. signInNode := []int{1009, 1010, 1011, 1012}
  168. // 最近一次签到
  169. //p.SinIn.RefreshSignIn()
  170. last, exists := p.SinIn.Sign[p.SinIn.Num-1]
  171. if !exists {
  172. // 签到数据初始化
  173. p.SinIn.RefreshSignIn()
  174. p.SinIn.RefreshSignNode(signInNode)
  175. return
  176. }
  177. // todo 测试代码
  178. //p.SinIn.RefreshSignIn()
  179. //p.SinIn.RefreshSignNode(signInNode)
  180. // 将时间戳转换为 time.Time 类型
  181. t := time.Unix(last.SignTime, 0)
  182. fmt.Sprintln(t)
  183. // todo 测试代码
  184. // 减去一天
  185. //t = t.Add(-24 * time.Hour)
  186. // 计算第二天的开始时间(即第二天的零点)
  187. // todo 正式代码
  188. //nextDayStart := t.Add(24 * time.Hour).Truncate(24 * time.Hour)
  189. //if p.SinIn.Num >= len(ret)-1 && time.Now().After(nextDayStart) {
  190. // // 签到周期满的第二天
  191. // p.SinIn.RefreshSignIn()
  192. //}
  193. // todo 测试代码
  194. if p.SinIn.Num >= len(ret) {
  195. // 签到周期满的第二天
  196. p.SinIn.RefreshSignIn()
  197. }
  198. maxNodeId := signInNode[len(signInNode)-1]
  199. maxNode, _ := data.DiscreteRuleConfig.Get(maxNodeId)
  200. maxDay, _ := strconv.Atoi(maxNode.Condition)
  201. //if p.SinIn.NodeProgress.Curr >= maxDay && time.Now().After(nextDayStart) {
  202. // // 签到周期满的第二天
  203. // p.SinIn.RefreshSignNode(signInNode)
  204. //}
  205. // todo 测试代码
  206. if p.SinIn.NodeProgress.Curr >= maxDay {
  207. // 签到周期满的第二天
  208. p.SinIn.RefreshSignNode(signInNode)
  209. }
  210. }
  211. func (p *Player) InitAchieveTask() {
  212. p.AchieveTask.RefreshAchieveTask()
  213. }
  214. func (p *Player) LevelUp() bool {
  215. ret, ok := data.LevelConfig.Get(p.Level + 1)
  216. if !ok {
  217. return false
  218. }
  219. curLevel := p.Level
  220. if p.Item[ItemGold].CurNum >= ret.DiceNum && p.Item[ItemInvite].CurNum >= ret.Invite {
  221. p.Level += 1
  222. if p.Level > curLevel {
  223. p.Item[ItemGold].AddMaxNum(ret.DiceLimit)
  224. p.Item[ItemGold].CurNum -= ret.DiceNum
  225. p.Item[ItemInvite].CurNum -= ret.Invite
  226. go p.SetPassiveInviteReward()
  227. //添加日志
  228. mhayaLogger.Infof("player level up, playerName=%v,level=%v", p.UserName, p.Level)
  229. p.SetPlayerRewardLog(SourceLevelUp, p.Level, []data.ItemReward{{ItemID: ItemAllRoll, ItemBaseType: 2, Amount: ret.DiceLimit}}, []data.ItemReward{}, p.Level)
  230. return true
  231. }
  232. }
  233. return false
  234. }
  235. func (p *Player) RefreshRoll() bool {
  236. ret, ok := data.DiscreteRuleConfig.Get(RefreshRollNew)
  237. if !ok {
  238. return false
  239. }
  240. arr := strings.Split(ret.Condition, ",")
  241. //if len(arr) != 2 {
  242. // return false
  243. //}
  244. slice := make([]int, 0)
  245. for _, s := range arr {
  246. hour, _ := mhayaString.ToInt(s)
  247. slice = append(slice, hour)
  248. }
  249. // 小时数,24小时制
  250. curHour := time.Now().Hour()
  251. if curHour == 0 {
  252. curHour = 24
  253. }
  254. rollHour := time.Unix(p.RollDay, 0).Hour()
  255. if rollHour == 0 {
  256. rollHour = 24
  257. }
  258. // 昨天的24点isToday为true,所以24点必须单独处理
  259. isToday := mhayaTime.CreateFromTimestamp(p.RollDay).IsToday()
  260. isTomorrow := mhayaTime.CreateFromTimestamp(p.RollDay).IsTomorrow()
  261. if (rollHour == 24 && isTomorrow) || (rollHour != 24 && isToday) {
  262. slice = slices.DeleteFunc(slice, func(x int) bool {
  263. return x <= rollHour
  264. })
  265. }
  266. if slices.Contains(slice, curHour) {
  267. p.RollDay = mhayaTime.Now().Unix()
  268. num := p.Item[ItemGold].AddSameTwo(8)
  269. if num > 0 {
  270. p.SetPlayerRewardLog(SourceRefreshRoll, 2, []data.ItemReward{{ItemID: ItemGold, ItemBaseType: 1, Amount: num}}, []data.ItemReward{}, 0)
  271. }
  272. mhayaLogger.Infof("RefreshRoll by condition 2 rollDay:%d,num:%v", p.RollDay, num)
  273. return true
  274. }
  275. return false
  276. }
  277. func (p *Player) CheckTaskByType1(openid int64, id int) bool {
  278. ret := data.AchieveTaskConfig.GetAll()
  279. for _, v := range ret {
  280. if v.Type == 2 {
  281. continue
  282. }
  283. if v.ID == id {
  284. if v.ID == 2 {
  285. if third.GetIfChannel(openid) == 1 {
  286. return true
  287. } else {
  288. return false
  289. }
  290. } else {
  291. return true
  292. }
  293. }
  294. }
  295. return false
  296. }
  297. func (p *Player) FinishAchieveTaskByType1(id int) bool {
  298. if a, ok := p.AchieveTask[id]; ok {
  299. if a.Num == 0 && a.Validate == 1 { //待验证
  300. openid, ok1 := mhayaString.ToInt64(p.OpenId)
  301. if !ok1 {
  302. mhayaLogger.Warnf("FinishAchieveTaskByType1 验证失败 username :%v, id : %v", p.UserName, id)
  303. return false
  304. }
  305. if p.CheckTaskByType1(openid, id) {
  306. p.AchieveTask[id].Validate = 2 //验证成功
  307. p.AchieveTask[id].Num = 1
  308. p.AchieveTask[id].Status = 1
  309. p.AchieveTask[id].RewardNum = 1
  310. //处理邀请订阅顺序问题
  311. if id == 2 {
  312. go p.SetPassiveInviteReward()
  313. }
  314. } else {
  315. p.AchieveTask[id].Validate = 0 //验证成功
  316. p.AchieveTask[id].Status = 0
  317. mhayaLogger.Warnf("FinishAchieveTaskByType1 验证失败 username :%v, id : v%", p.UserName, id)
  318. return false
  319. }
  320. } else {
  321. if a.Validate == 0 {
  322. p.AchieveTask[id].Validate = 1
  323. }
  324. }
  325. return true
  326. }
  327. return false
  328. }
  329. // FinishAchieveTaskByType2 完成成就类型2
  330. func (p *Player) FinishAchieveTaskByType2() bool {
  331. //var range data.RangeInt32{}
  332. for _, v := range p.AchieveTask {
  333. if v.Type == 2 {
  334. ret, ok := data.AchieveTaskConfig.Get(v.ID)
  335. if !ok {
  336. continue
  337. }
  338. if p.Item[ItemInvite].Num <= ret.Condition.Max && p.AchieveTask[v.ID].Num != ret.Condition.Max {
  339. p.AchieveTask[v.ID].Num += 1
  340. if p.AchieveTask[v.ID].Num >= ret.Condition.Min && p.AchieveTask[v.ID].Num <= ret.Condition.Max {
  341. p.AchieveTask[v.ID].Status = 1
  342. p.AchieveTask[v.ID].RewardNum += 1
  343. }
  344. }
  345. }
  346. }
  347. return false
  348. }
  349. func (p *Player) FinishDailyTask(tp, num int) bool {
  350. var f bool
  351. for i := 0; i < num; i++ {
  352. for _, v := range p.DailyTask {
  353. if v.Type == tp && v.Status == 0 {
  354. p.DailyTask[v.ID].Num += 1
  355. if p.DailyTask[v.ID].Num == v.Condition {
  356. p.DailyTask[v.ID].Status = 1
  357. f = true
  358. continue
  359. }
  360. }
  361. }
  362. }
  363. return f
  364. }
  365. func (p *Player) RollOnce(num int) *param.RollOnce {
  366. var roll param.RollOnce
  367. levelConfig, ok := data.LevelConfig.Get(p.Level)
  368. if !ok {
  369. return nil
  370. }
  371. if levelConfig == nil {
  372. return nil
  373. }
  374. r1 := rand.Int31n(5) + 1
  375. r2 := rand.Int31n(5) + 1
  376. r3 := rand.Int31n(5) + 1
  377. //rule 4
  378. if (r1 == 1 && r2 == 1 && r3 == 1) || (r1 == 6 && r2 == 6 && r3 == 6) {
  379. roll.Score = levelConfig.Ratio * levelConfig.Rule4
  380. roll.RollType = constant.RollSpecialTripleBet
  381. } else if r1 == r2 && r2 == r3 {
  382. roll.Score = levelConfig.Ratio * levelConfig.Rule3
  383. roll.RollType = constant.RollTripleBet
  384. } else if r1 == r2 || r1 == r3 || r2 == r3 {
  385. roll.Score = levelConfig.Ratio * levelConfig.Rule2
  386. roll.RollType = constant.RollDoubleBet
  387. } else {
  388. roll.Score = levelConfig.Ratio * levelConfig.Rule1
  389. if r1+r2+r3 > 9 {
  390. roll.RollType = constant.RollBigBet
  391. } else {
  392. roll.RollType = constant.RollSmallBet
  393. }
  394. }
  395. roll.Rand = make(map[int]int32)
  396. roll.Rand[1] = r1
  397. roll.Rand[2] = r2
  398. roll.Rand[3] = r3
  399. p.Item[ItemScore].Add(roll.Score * num)
  400. p.Item[ItemGold].Sub(1 * num)
  401. p.SetPlayerRewardLog(SourceRoll, 0, []data.ItemReward{{ItemID: ItemScore, ItemBaseType: 1, Amount: roll.Score * num}}, []data.ItemReward{{ItemID: ItemGold, ItemBaseType: 1, Amount: 1 * num}}, roll)
  402. p.Roll.RollNums += 1 * num
  403. roll.IsDailyTask = p.FinishDailyTask(1, num)
  404. roll.IsLevelUp = p.LevelUp()
  405. return &roll
  406. }
  407. // Draw 最多尝试重复执行50次
  408. func (p *Player) Draw() *param.Draw {
  409. for i := 0; i < 50; i++ {
  410. draw, ok := p.DrawOnce()
  411. if ok {
  412. return draw
  413. }
  414. }
  415. return nil
  416. }
  417. func (p *Player) NewPlayer10Draw() {
  418. if p.Roll.DrawTotal == 0 {
  419. ret, ok := data.DiscreteRuleConfig.Get(NewPlayer10Draw)
  420. if !ok {
  421. return
  422. }
  423. arr := strings.Split(ret.Condition, ",")
  424. if len(arr) != 2 {
  425. return
  426. }
  427. minC := mhayaString.ToIntD(arr[0], 4)
  428. MaxC := mhayaString.ToIntD(arr[1], 6)
  429. p.Roll.NewDraw = make(map[int]int)
  430. wei := []int{1, 2, 4, 5, 11, 12}
  431. wei2 := []int{1, 2, 4, 12}
  432. var m []int
  433. for i := 0; i < minC; i++ {
  434. r := rand.Intn(2)
  435. if r == 0 {
  436. m = append(m, 5)
  437. } else {
  438. m = append(m, 11)
  439. }
  440. }
  441. var num = len(m)
  442. var num2 = 0
  443. for i := 0; i < 10-minC; i++ {
  444. if num2 == 0 {
  445. if num >= MaxC {
  446. k2 := rand.Intn(len(wei2))
  447. cur := wei2[k2]
  448. if cur == 11 || cur == 5 {
  449. num++
  450. }
  451. if cur == 4 || cur == 12 {
  452. num2++
  453. }
  454. m = append(m, cur)
  455. } else {
  456. k := rand.Intn(len(wei))
  457. cur := wei[k]
  458. if cur == 11 || cur == 5 {
  459. num++
  460. }
  461. if cur == 4 || cur == 12 {
  462. num2++
  463. }
  464. m = append(m, cur)
  465. }
  466. } else {
  467. if num >= MaxC-1 {
  468. k2 := rand.Intn(len(wei2))
  469. cur := wei2[k2]
  470. if cur == 11 || cur == 5 {
  471. num++
  472. }
  473. if cur == 4 || cur == 12 {
  474. num2++
  475. }
  476. m = append(m, cur)
  477. } else {
  478. k := rand.Intn(len(wei))
  479. cur := wei[k]
  480. if cur == 11 || cur == 5 {
  481. num++
  482. }
  483. if cur == 4 || cur == 12 {
  484. num2++
  485. }
  486. m = append(m, cur)
  487. }
  488. }
  489. }
  490. m = Shuffle(m)
  491. for key, v := range m {
  492. p.Roll.NewDraw[key+1] = v
  493. }
  494. }
  495. }
  496. func Shuffle(slice []int) []int {
  497. rand.Seed(time.Now().UnixNano())
  498. for i := len(slice) - 1; i > 0; i-- {
  499. j := rand.Intn(i + 1)
  500. slice[i], slice[j] = slice[j], slice[i]
  501. }
  502. return slice
  503. }
  504. func (p *Player) DrawOnce() (*param.Draw, bool) {
  505. var ret map[int]*data.DrawConfigRow
  506. var draw param.Draw
  507. var wg = 0
  508. p.NewPlayer10Draw()
  509. if p.Roll.DrawTotal < 10 {
  510. ret = data.DrawConfig.GetByType(1)
  511. for _, v := range ret {
  512. wg += v.Weight
  513. }
  514. } else {
  515. ret = data.DrawConfig.GetByType(2)
  516. for _, v := range ret {
  517. wg += v.Weight
  518. }
  519. }
  520. if wg == 0 {
  521. return nil, false
  522. }
  523. var cur int
  524. var curID int
  525. //出去新手10连后规则
  526. if p.Roll.DrawTotal >= 10 {
  527. weight := int(rand.Int31n(int32(wg))) + 1
  528. for _, v := range ret {
  529. if v.Weight == 0 {
  530. continue
  531. }
  532. if weight > cur && weight <= cur+v.Weight {
  533. curID = v.ID
  534. break
  535. }
  536. cur += v.Weight
  537. }
  538. } else {
  539. curID = p.Roll.NewDraw[p.Roll.DrawTotal+1]
  540. }
  541. if d, ok := ret[curID]; ok {
  542. if d.HourTotalCondition > 0 {
  543. i, err := GetDrawHour(curID)
  544. if err != nil {
  545. return nil, false
  546. }
  547. if int(i) > d.HourTotalCondition {
  548. return nil, false
  549. }
  550. }
  551. if d.DailyTotalCondition > 0 {
  552. i, err := GetDrawDailyKey(curID)
  553. if err != nil {
  554. return nil, false
  555. }
  556. if int(i) > d.DailyTotalCondition {
  557. return nil, false
  558. }
  559. }
  560. if d.WeeklyTotalCondition > 0 {
  561. i, err := GetDrawWeeklyKey(curID)
  562. if err != nil {
  563. return nil, false
  564. }
  565. if int(i) > d.WeeklyTotalCondition {
  566. return nil, false
  567. }
  568. }
  569. p.Item.AddItem(d.Reward)
  570. p.Item[ItemDrawsNumber].Sub(1)
  571. draw.Reward = d.Reward
  572. draw.ID = d.Order
  573. draw.CurID = curID
  574. if len(p.Roll.Draw) == 0 {
  575. p.Roll.Draw = make(map[int]int)
  576. }
  577. if len(p.Roll.DrawRatio) == 0 {
  578. p.Roll.DrawRatio = make(map[int]float64)
  579. }
  580. p.Roll.Draw[curID] += 1
  581. p.Roll.DrawTotal += 1
  582. p.Roll.DrawRatio[curID] = float64(p.Roll.Draw[curID]) / float64(p.Roll.DrawTotal)
  583. p.SetPlayerRewardLog(SourceDraw, 0, draw.Reward, []data.ItemReward{{1, ItemDrawsNumber, 1}}, draw)
  584. } else {
  585. return nil, false
  586. }
  587. return &draw, true
  588. }
  589. func GetDrawHour(id int) (int64, error) {
  590. s := mhayaTime.CreateFromTime(mhayaTime.Now().Hour(), 0, 0).ToDateTimeFormat()
  591. key := fmt.Sprintf("%v:%v:%v", constant.DrawHourKey, id, s)
  592. return mdb.RDB.IncrBy(context.Background(), key, 1).Result()
  593. }
  594. func GetDrawDailyKey(id int) (int64, error) {
  595. key := fmt.Sprintf("%v:%v:%v", constant.DrawDailyKey, id, mhayaTime.Now().Format(mhayaTime.DateFormat))
  596. return mdb.RDB.IncrBy(context.Background(), key, 1).Result()
  597. }
  598. func GetDrawWeeklyKey(id int) (int64, error) {
  599. key := fmt.Sprintf("%v:%v:%v", constant.DrawWeeklyKey, id, mhayaTime.Now().Week())
  600. return mdb.RDB.IncrBy(context.Background(), key, 1).Result()
  601. }
  602. //func (p *Player) SignIn() *param.ChangeData {
  603. // var sign param.ChangeData
  604. // p.SinIn.SignDailyTime = mhayaTime.Now().Unix()
  605. // p.SinIn.Sign[p.SinIn.Num].IsSign = 1
  606. // p.SinIn.Sign[p.SinIn.Num].SignTime = mhayaTime.Now().Unix()
  607. // var addItem AddItem
  608. // at := addItem.Add(p.SinIn.Sign[p.SinIn.Num].Reward)
  609. // sign.AddItem = at
  610. // p.Item.AddItem(p.SinIn.Sign[p.SinIn.Num].Reward)
  611. // p.SinIn.Num += 1
  612. // p.SetPlayerRewardLog(SourceSignIn, p.SinIn.Num, p.SinIn.Sign[p.SinIn.Num].Reward, []data.ItemReward{}, nil)
  613. //
  614. // // 节点奖励进度
  615. // p.SinIn.NodeProgress.Curr += 1
  616. //
  617. // // 领取节点奖励
  618. //
  619. // sign.IsLevelUp = p.LevelUp()
  620. // return &sign
  621. //}
  622. func (p *Player) SetPlayerRewardLog(tp, tid int, addReward, subReward []data.ItemReward, desc interface{}) {
  623. p.Index += 1
  624. if len(p.PlayerReward) == 0 {
  625. p.PlayerReward = make(map[int]*PlayerRewardBase)
  626. }
  627. p.PlayerReward[p.Index] = &PlayerRewardBase{
  628. UserName: p.UserName,
  629. AddReward: addReward,
  630. SubReward: subReward,
  631. Desc: desc,
  632. Source: tp,
  633. SourceId: tid,
  634. CreateTime: mhayaTime.Now().Unix(),
  635. }
  636. }
  637. func (p *Player) SetPassiveInviteReward() {
  638. ret2, ok := data.DiscreteRuleConfig.Get(InvitePlayer)
  639. c, tok := mhayaString.ToInt(ret2.Condition)
  640. if !ok || !tok || c != p.Level {
  641. return
  642. }
  643. ret3, ok := data.DiscreteRuleConfig.Get(InviteVipPlayer)
  644. c, tok = mhayaString.ToInt(ret3.Condition)
  645. if !ok || !tok || c != p.Level {
  646. return
  647. }
  648. var isCheck bool
  649. if ts, ok := p.AchieveTask[2]; ok {
  650. if ts.Num == 1 {
  651. isCheck = true
  652. }
  653. }
  654. if !isCheck {
  655. // 升级邀请奖励
  656. openid, _ := mhayaString.ToInt64(p.OpenId)
  657. if third.GetIfChannel(openid) == 0 {
  658. mhayaLogger.Infof("player SetPassiveInviteReward,Not following the channel playerName=%v,level=%v,pid=%v", p.UserName, p.Level, p.Pid)
  659. return
  660. }
  661. }
  662. //被邀请人
  663. key := fmt.Sprintf("%v:1:%v", constant.InviteKey, p.UserName)
  664. //获取邀请人
  665. pUid := mdb.RDB.Get(context.Background(), key).Val()
  666. pbase := mdb.RDB.HGet(context.Background(), constant.PlayerBaseKey, pUid).Val()
  667. mdb.RDB.Del(context.Background(), key)
  668. var base param.PlayerBase
  669. err := jsoniter.Unmarshal([]byte(pbase), &base)
  670. if err != nil {
  671. return
  672. }
  673. var addItem []data.ItemReward
  674. if p.IsVip == 0 {
  675. //主动邀请记录, 设置邀请人数量+1
  676. key = fmt.Sprintf("%v:%v:%v", constant.InviteKey, InvitePlayer, pUid)
  677. err = mdb.RDB.IncrBy(context.Background(), key, 1).Err()
  678. if err != nil {
  679. mhayaLogger.Infof("player SetPassiveInviteReward,not vip invite playerName=%v,level=%v,param=%v,err=%v", p.UserName, p.Level, key, err)
  680. }
  681. addItem = append(addItem, ret2.Reward...)
  682. } else {
  683. //主动邀请记录, 设置邀请人数量+1
  684. key = fmt.Sprintf("%v:%v:%v", constant.InviteKey, InviteVipPlayer, pUid)
  685. err = mdb.RDB.IncrBy(context.Background(), key, 1).Err()
  686. if err != nil {
  687. mhayaLogger.Infof("player SetPassiveInviteReward, vip invite playerName=%v,level=%v,param=%v,err=%v", p.UserName, p.Level, key, err)
  688. }
  689. addItem = append(addItem, ret3.Reward...)
  690. }
  691. //社区长额外奖励
  692. if base.IsLeader == 1 {
  693. ret, ok := data.DiscreteRuleConfig.Get(InvitePlayerByLeader)
  694. if !ok {
  695. return
  696. }
  697. addItem = append(addItem, ret.Reward...)
  698. }
  699. if p.InviteReward.IsClaim == 2 {
  700. p.InviteReward.Reward = []data.ItemReward{}
  701. p.InviteReward.IsClaim = 0
  702. p.InviteReward.RewardTime = 0
  703. }
  704. p.InviteReward.Reward = append(p.InviteReward.Reward, addItem...)
  705. p.InviteReward.Merge()
  706. }
  707. func (p *Player) SetInviteReward() {
  708. ret, ok := data.DiscreteRuleConfig.Get(InvitePlayerByLeader)
  709. if !ok {
  710. return
  711. }
  712. ret2, ok := data.DiscreteRuleConfig.Get(InvitePlayer)
  713. if !ok {
  714. return
  715. }
  716. ret3, ok := data.DiscreteRuleConfig.Get(InviteVipPlayer)
  717. if !ok {
  718. return
  719. }
  720. var addItem []data.ItemReward
  721. key1 := fmt.Sprintf("%v:%v:%v", constant.InviteKey, InvitePlayer, p.UserName)
  722. key2 := fmt.Sprintf("%v:%v:%v", constant.InviteKey, InviteVipPlayer, p.UserName)
  723. //自己作为邀请人判断奖励
  724. freeNum, _ := mdb.RDB.Get(context.Background(), key1).Int()
  725. VipNum, _ := mdb.RDB.Get(context.Background(), key2).Int()
  726. for i := 0; i < freeNum; i++ {
  727. addItem = append(addItem, ret2.Reward...)
  728. p.SetPlayerRewardLog(SourceInvite, InvitePlayer, []data.ItemReward{}, []data.ItemReward{}, 2)
  729. if p.IsLeader == 1 {
  730. addItem = append(addItem, ret.Reward...)
  731. p.SetPlayerRewardLog(SourceInvite, InvitePlayerByLeader, []data.ItemReward{}, []data.ItemReward{}, 2)
  732. }
  733. p.Item[ItemInvite].Num += 1
  734. p.Item[ItemInvite].CurNum += 1
  735. p.Invite.Set(InvitePlayer, ret.Reward)
  736. p.FinishAchieveTaskByType2()
  737. mdb.RDB.DecrBy(context.Background(), key1, 1)
  738. }
  739. for i := 0; i < VipNum; i++ {
  740. addItem = append(addItem, ret3.Reward...)
  741. p.SetPlayerRewardLog(SourceInvite, InviteVipPlayer, []data.ItemReward{}, []data.ItemReward{}, 2)
  742. if p.IsLeader == 1 {
  743. addItem = append(addItem, ret.Reward...)
  744. p.SetPlayerRewardLog(SourceInvite, InvitePlayerByLeader, []data.ItemReward{}, []data.ItemReward{}, 2)
  745. }
  746. p.Item[ItemInvite].Num += 1
  747. p.Item[ItemInvite].CurNum += 1
  748. p.Invite.Set(InviteVipPlayer, ret.Reward)
  749. p.FinishAchieveTaskByType2()
  750. mdb.RDB.DecrBy(context.Background(), key2, 1)
  751. }
  752. if (freeNum + VipNum) > 0 {
  753. SetRank(constant.RankSourceInvite, p.IsRobot, p.UserName, freeNum+VipNum)
  754. }
  755. if p.InviteReward.IsClaim == 2 {
  756. p.InviteReward.Reward = []data.ItemReward{}
  757. p.InviteReward.IsClaim = 0
  758. p.InviteReward.RewardTime = 0
  759. }
  760. p.InviteReward.Reward = append(p.InviteReward.Reward, addItem...)
  761. p.InviteReward.Merge()
  762. }
  763. func (p *Player) SetInvite(pid string) bool {
  764. key := fmt.Sprintf("%v:1:%v", constant.InviteKey, p.UserName)
  765. ret, ok := data.DiscreteRuleConfig.Get(InviteMaxExpireTime)
  766. if !ok {
  767. return false
  768. }
  769. t, _ := mhayaString.ToInt64(ret.Condition)
  770. err := mdb.RDB.Set(context.Background(), key, pid, time.Duration(t)*24*time.Hour).Err()
  771. if err != nil {
  772. return false
  773. }
  774. key = fmt.Sprintf("%v:%v:%v", constant.InviteKey, InvitePlayer, p.Pid)
  775. lRange, _ := mdb.RDB.LRange(context.Background(), key, 0, -1).Result()
  776. if slices.Contains(lRange, p.UserName) {
  777. return false
  778. }
  779. mdb.RDB.LPush(context.Background(), key, p.UserName)
  780. return true
  781. }
  782. func (p *Player) ClaimInviteReward(id int) param.ChangeData {
  783. var resp param.ChangeData
  784. if len(p.InviteReward.Reward) > 0 {
  785. var addItem AddItem
  786. resp.AddItem = addItem.Add(p.InviteReward.Reward)
  787. p.Item.AddItem(p.InviteReward.Reward)
  788. p.InviteReward.IsClaim = 2
  789. p.InviteReward.RewardTime = mhayaTime.Now().Unix()
  790. p.InviteReward.Reward = []data.ItemReward{}
  791. p.SetPlayerRewardLog(SourceInvite, id, p.InviteReward.Reward, []data.ItemReward{}, nil)
  792. }
  793. p.LevelUp()
  794. return resp
  795. }
  796. func (p *Player) ClaimAchieveTaskReward(id int) param.ChangeData {
  797. var resp param.ChangeData
  798. if ach, ok := p.AchieveTask[id]; ok {
  799. if ach.Status == 1 && ach.RewardNum > 0 {
  800. var addItem AddItem
  801. resp.AddItem = addItem.Add(ach.Reward)
  802. p.Item.AddItem(ach.Reward)
  803. ach.RewardNum -= 1
  804. p.SetPlayerRewardLog(SourceAchieveTask, id, ach.Reward, []data.ItemReward{}, nil)
  805. }
  806. if ach.RewardNum == 0 {
  807. ret, _ := data.AchieveTaskConfig.Get(ach.ID)
  808. if ret.Condition.Max == ach.Num {
  809. p.AchieveTask[id].Status = 2
  810. } else {
  811. p.AchieveTask[id].Status = 0
  812. }
  813. }
  814. }
  815. p.LevelUp()
  816. return resp
  817. }
  818. func (p *Player) ClaimDailyTaskReward(id int) param.ChangeData {
  819. var resp param.ChangeData
  820. if task, ok := p.DailyTask[id]; ok {
  821. if task.Status == 1 {
  822. var addItem AddItem
  823. resp.AddItem = addItem.Add(task.Reward)
  824. p.Item.AddItem(task.Reward)
  825. task.Status = 2
  826. p.SetPlayerRewardLog(SourceDailyTask, id, task.Reward, []data.ItemReward{}, nil)
  827. }
  828. }
  829. p.LevelUp()
  830. return resp
  831. }
  832. // 初始化邀请节点奖励
  833. func (p *Player) InitInviteNodeReword() {
  834. icfg := data.InviteConfig.GetAll()
  835. var maxCondition int
  836. var isUpdate bool
  837. for _, value := range icfg {
  838. maxCondition += value.Condition
  839. if item, ok := p.InviteNodeReward[value.ID]; ok {
  840. if !slices.Equal(item.Reward, value.Reward) || item.Condition != value.Condition {
  841. isUpdate = true
  842. }
  843. } else {
  844. isUpdate = true
  845. }
  846. }
  847. // todo 测试代码
  848. p.RefreshInviteNodeReward(icfg)
  849. key := fmt.Sprintf("%v:%v", constant.InviteNodeHistoryKey, p.UserName)
  850. mdb.RDB.Del(context.Background(), key)
  851. if (len(p.InviteNodeReward) == 0) || isUpdate {
  852. // 初次邀请和更新奖励配置
  853. p.RefreshInviteNodeReward(icfg)
  854. } else if p.ClaimInviteNum >= maxCondition {
  855. // 奖励周期满,重置奖励
  856. p.RefreshInviteNodeReward(icfg)
  857. // 保留刷新前的奖励历史记录
  858. var beforeNum int64
  859. for _, item := range p.InviteNodeReward {
  860. beforeNum += int64(item.Condition)
  861. }
  862. key := fmt.Sprintf("%v:%v", constant.InviteNodeHistoryKey, p.UserName)
  863. mdb.RDB.IncrBy(context.Background(), key, beforeNum)
  864. }
  865. }
  866. // 刷新邀请节点奖励
  867. func (p *Player) RefreshInviteNodeReward(icfg map[int]*data.InviteConfigRow) {
  868. p.InviteNodeReward = make(map[int]*InviteNodeRewardItem)
  869. for _, row := range icfg {
  870. condition := row.Condition
  871. inviteReward := &InviteNodeRewardItem{
  872. ID: row.ID,
  873. IsClaim: 0,
  874. IsUnlock: 0,
  875. Reward: row.Reward,
  876. Condition: condition,
  877. }
  878. p.InviteNodeReward[row.ID] = inviteReward
  879. p.ClaimInviteNum = 0
  880. }
  881. }
  882. // 初始化首次奖励
  883. func (p *Player) InitFirstReward() {
  884. ids := []int{1001, 1002, 1003, 1004, 1005, 1006}
  885. firstReward := make(map[int]*FirstRewardItem)
  886. for _, id := range ids {
  887. diConfig, _ := data.DiscreteRuleConfig.Get(id)
  888. item := &FirstRewardItem{
  889. IsClaim: 0,
  890. Reward: diConfig.Reward,
  891. RewardTime: 0,
  892. }
  893. firstReward[id] = item
  894. }
  895. p.FirstClaimReward = firstReward
  896. }