winrank.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. 1.所有人的赢金总额 都记录起来
  3. 2.不扣本金 不算输金
  4. */
  5. package gamelogic
  6. import (
  7. "encoding/json"
  8. "sort"
  9. "sync"
  10. "time"
  11. "bet24.com/log"
  12. "bet24.com/redis"
  13. "bet24.com/servers/games/greedy/common"
  14. "bet24.com/servers/games/greedy/config"
  15. )
  16. const WinPoolKey = "winPool"
  17. const RankCount = 10
  18. type Rank struct {
  19. UserId int
  20. WinAmount int
  21. }
  22. // 赢金榜 每天刷新一次
  23. type winPool struct {
  24. Day int // 奖池日期
  25. WinList map[int]int // 所有玩家的赢金总额 不扣本金 不算输金
  26. lock *sync.RWMutex
  27. }
  28. func newWinPool() *winPool {
  29. ret := new(winPool)
  30. ret.lock = &sync.RWMutex{}
  31. ret.WinList = make(map[int]int)
  32. //如果是私人场则不做Redis存储
  33. if !config.Server.IsPrivateRoom {
  34. // 从redis中获取奖池数据
  35. key := WinPoolKey
  36. data, _ := redis.String_Get(common.GetRedisKey(key))
  37. if data != "" {
  38. // redis中有奖池数据
  39. wp := &winPool{
  40. Day: 0,
  41. WinList: make(map[int]int),
  42. }
  43. err := json.Unmarshal([]byte(data), wp)
  44. if err != nil {
  45. log.Release("winPool json.Unmarshal err:%v", err)
  46. }
  47. if wp.Day != time.Now().Day() {
  48. // 奖池数据不是今天的,重新初始化
  49. ret.Day = time.Now().Day()
  50. log.Debug("====newWinPool.Refresh Day[%d] ====", wp.Day)
  51. ret.winPoolToRedis()
  52. } else {
  53. // 奖池数据是今天的,直接赋值
  54. ret.Day = wp.Day
  55. ret.WinList = wp.WinList
  56. }
  57. //起一个定时器,每天0点发奖并且清空奖池
  58. ret.startTimer()
  59. return ret
  60. }
  61. }
  62. // redis中没有奖池数据
  63. ret.Day = time.Now().Day()
  64. ret.winPoolToRedis()
  65. //起一个定时器,每天0点发奖并且清空奖池
  66. ret.startTimer()
  67. return ret
  68. }
  69. func (wp *winPool) startTimer() {
  70. wp.refreshPool()
  71. go time.AfterFunc(1*time.Minute, wp.startTimer)
  72. }
  73. // 添加用户
  74. func (wp *winPool) addUser(userId int) {
  75. wp.lock.RLock()
  76. _, ok := wp.WinList[userId]
  77. wp.lock.RUnlock()
  78. if !ok {
  79. wp.lock.Lock()
  80. wp.WinList[userId] = 0
  81. wp.lock.Unlock()
  82. }
  83. }
  84. // 移除用户
  85. func (wp *winPool) removeUser(userId int) {
  86. wp.lock.Lock()
  87. delete(wp.WinList, userId)
  88. wp.lock.Unlock()
  89. // log.Release("winPool.removeUser %d not found", userId)
  90. }
  91. // 是否上榜
  92. func (wp *winPool) isRank(userId int) bool {
  93. _, myRank, _ := wp.getRankList(userId, -1)
  94. return myRank <= RankCount
  95. }
  96. // 每次结算时 将赢金数据保存到历史奖池中
  97. func (wp *winPool) addWinPool(userId int, winAmount int) {
  98. wp.lock.RLock()
  99. data, ok := wp.WinList[userId]
  100. wp.lock.RUnlock()
  101. // 检查用户是否已经投注过
  102. if ok {
  103. wp.lock.Lock()
  104. data += winAmount
  105. wp.WinList[userId] = data
  106. wp.lock.Unlock()
  107. } else {
  108. wp.lock.Lock()
  109. wp.WinList[userId] = winAmount
  110. // log.Release("addWinPool failed wp.WinList is nil userId:%v,winAmount:%d", userId, winAmount)
  111. wp.lock.Unlock()
  112. }
  113. }
  114. func (wp *winPool) winPoolToRedis() {
  115. if config.Server.IsPrivateRoom {
  116. return
  117. }
  118. key := WinPoolKey
  119. wp.lock.RLock()
  120. data, err := json.Marshal(wp)
  121. wp.lock.RUnlock()
  122. if err != nil {
  123. log.Debug("winPool json.Marshal err:%v", err)
  124. return
  125. }
  126. redis.String_Set(common.GetRedisKey(key), string(data))
  127. }
  128. // 获取排名列表
  129. func (wp *winPool) getRankList(userId, count int) ([]Rank, int, int) {
  130. var myRank = RankCount
  131. var rankCount = RankCount
  132. if count != 0 {
  133. rankCount = count
  134. }
  135. var myWinAmount = 0
  136. var rankList []Rank
  137. wp.lock.RLock()
  138. for k, v := range wp.WinList {
  139. rankList = append(rankList, Rank{k, v})
  140. }
  141. wp.lock.RUnlock()
  142. if len(rankList) == 0 {
  143. return rankList, myRank, myWinAmount
  144. }
  145. // 将投注金额从大到小排序
  146. sort.Slice(rankList, func(i, j int) bool {
  147. return rankList[i].WinAmount > rankList[j].WinAmount
  148. })
  149. // 查询自己的下注额度和排名
  150. if userId > 0 {
  151. for i, win := range rankList {
  152. if win.UserId == userId {
  153. myRank = i + 1
  154. myWinAmount = win.WinAmount
  155. break
  156. }
  157. }
  158. }
  159. if rankCount == -1 {
  160. return nil, myRank, myWinAmount
  161. }
  162. // 截取排名在前N名的数据
  163. if len(rankList) > rankCount {
  164. rankList = rankList[:rankCount]
  165. }
  166. return rankList, myRank, myWinAmount
  167. }
  168. // 清空奖池
  169. func (wp *winPool) refreshPool() {
  170. if wp.Day == 0 || wp.Day == time.Now().Day() {
  171. return
  172. }
  173. log.Debug("====WinPool.refreshPool Day[%d]====", wp.Day)
  174. // 清空奖池
  175. wp.lock.Lock()
  176. wp.Day = time.Now().Day()
  177. wp.WinList = make(map[int]int)
  178. wp.lock.Unlock()
  179. //清空奖池打印日志
  180. log.Debug("====Refresh WinPool Day[%d]====", wp.Day)
  181. wp.winPoolToRedis()
  182. }