prizewheelmgr.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. package prizewheel
  2. import (
  3. "encoding/json"
  4. "math/rand"
  5. "sync"
  6. "time"
  7. "bet24.com/log"
  8. "bet24.com/servers/common"
  9. "bet24.com/servers/coreservice/jackpot"
  10. "bet24.com/servers/coreservice/serviceconfig"
  11. inventory "bet24.com/servers/micros/item_inventory/proto"
  12. item "bet24.com/servers/micros/item_inventory/proto"
  13. )
  14. type prizewheelmgr struct {
  15. prizes []*Prize
  16. totalChance int
  17. lock *sync.RWMutex
  18. UserList map[int]*userPrize
  19. RecordList []*userPrizeRecord
  20. }
  21. type userPrize struct {
  22. UserId int //用户ID
  23. Times int //次数
  24. Crdate int //时间戳
  25. }
  26. type userPrizeRecord struct {
  27. UserId int //用户ID
  28. NickName string //昵称
  29. WheelId int //转盘ID
  30. Items []item.ItemPack //奖励
  31. Crdate int //时间戳
  32. }
  33. func newPrizeWheelManager() *prizewheelmgr {
  34. pm := new(prizewheelmgr)
  35. pm.UserList = make(map[int]*userPrize)
  36. pm.lock = &sync.RWMutex{}
  37. pm.loadPrizes()
  38. pm.loadRecord()
  39. pm.checkDayRefresh()
  40. log.Debug("prizewheelmgr manager running")
  41. return pm
  42. }
  43. func (pm *prizewheelmgr) loadPrizes() {
  44. // 从数据库加载配置信息
  45. pm.prizes = getList()
  46. //TODO:从数据库获取奖池金额
  47. pm.totalChance = 0
  48. for _, v := range pm.prizes {
  49. pm.totalChance += v.Chance
  50. }
  51. }
  52. func (pm *prizewheelmgr) loadRecord() {
  53. records := getRecord()
  54. pm.lock.Lock()
  55. defer pm.lock.Unlock()
  56. pm.RecordList = append(pm.RecordList, records...)
  57. }
  58. func (pm *prizewheelmgr) checkDayRefresh() {
  59. ticker := time.NewTicker(10 * time.Minute)
  60. go func(t *time.Ticker) {
  61. lastCheck := common.GetTimeStamp()
  62. for { //循环
  63. select {
  64. case <-t.C:
  65. now := common.GetTimeStamp()
  66. if !common.IsSameDay(lastCheck, now) {
  67. pm.refreshUserList()
  68. }
  69. lastCheck = now
  70. }
  71. }
  72. }(ticker)
  73. }
  74. // 0点过后去数据库刷新在线玩家数据
  75. func (pm *prizewheelmgr) refreshUserList() {
  76. dayIndex := common.GetDayIndex(common.GetTimeStamp())
  77. pm.lock.Lock()
  78. defer pm.lock.Unlock()
  79. for _, v := range pm.UserList {
  80. //过期了
  81. if common.GetDayIndex(v.Crdate) < dayIndex {
  82. v.Times = 0
  83. }
  84. }
  85. }
  86. func (pm *prizewheelmgr) onUserEnter(userId int) {
  87. //TODO: 去数据库获取今日剩余抽奖次数 count
  88. u := new(userPrize)
  89. u.UserId = userId
  90. u.Times, u.Crdate = getInfo(userId)
  91. //判断是否过期,过期清零
  92. if common.GetDayIndex(u.Crdate) < common.GetDayIndex(common.GetTimeStamp()) {
  93. u.Times = 0
  94. }
  95. pm.lock.Lock()
  96. pm.UserList[userId] = u
  97. pm.lock.Unlock()
  98. }
  99. func (pm *prizewheelmgr) onUserExit(userId int) {
  100. pm.lock.Lock()
  101. defer pm.lock.Unlock()
  102. delete(pm.UserList, userId)
  103. }
  104. func (pm *prizewheelmgr) getPrizes() []*Prize {
  105. pm.lock.RLock()
  106. defer pm.lock.RUnlock()
  107. return pm.prizes
  108. }
  109. func (pm *prizewheelmgr) getWheelTimes(userId int) (int, int, int) {
  110. pm.lock.RLock()
  111. u, ok := pm.UserList[userId]
  112. pm.lock.RUnlock()
  113. if !ok {
  114. u = new(userPrize)
  115. u.UserId = userId
  116. u.Times, u.Crdate = getInfo(userId)
  117. //判断是否过期,过期清零
  118. if common.GetDayIndex(u.Crdate) < common.GetDayIndex(common.GetTimeStamp()) {
  119. u.Times = 0
  120. }
  121. pm.lock.Lock()
  122. pm.UserList[userId] = u
  123. pm.lock.Unlock()
  124. }
  125. return u.Times, serviceconfig.SpecialCfg.PrizeTimes, serviceconfig.SpecialCfg.PrizeCost
  126. }
  127. // 摇奖,返回中奖结果
  128. func (pm *prizewheelmgr) wheel(userId, count int, nickName, ipAddress string) ([]*Prize, string) {
  129. var ret []*Prize
  130. if count <= 0 {
  131. log.Debug("prizewheelmgr.wheel count <= 0")
  132. return ret, "转盘不可用"
  133. }
  134. pm.lock.RLock()
  135. u, ok := pm.UserList[userId]
  136. pm.lock.RUnlock()
  137. if !ok {
  138. log.Debug("prizewheelmgr.wheel userId(%d) is not exist, count=%d", userId, count)
  139. return ret, "无效数据"
  140. }
  141. //是否还有抽奖次数
  142. if count > serviceconfig.SpecialCfg.PrizeTimes-u.Times {
  143. log.Debug("prizewheelmgr.wheel count <= %d", u.Times)
  144. return ret, "没有抽奖次数"
  145. }
  146. //lotteryCount, consumeAmount, amount := count, count, 0
  147. //
  148. //// 先判断抽奖券是否足够
  149. //if item := inventory.GetUserLottery(userId); item != nil {
  150. // // 抽奖券不够,有多少扣多少
  151. // if item.Count < count {
  152. // lotteryCount = item.Count
  153. // }
  154. //
  155. // consumeAmount = count - lotteryCount
  156. //}
  157. //
  158. //// 再判断金币是否足够
  159. //if consumeAmount > 0 {
  160. // // 去数据库扣钱
  161. // amount = consumeAmount * serviceconfig.SpecialCfg.PrizeCost
  162. //
  163. // if _, gold, _ := cash.GetMoney(userId); gold < amount {
  164. // return ret, "金币不足"
  165. // }
  166. //}
  167. //
  168. ////扣减抽奖券
  169. //if lotteryCount > 0 {
  170. // if success, _ := inventory.ConsumeLottery(userId, lotteryCount); !success {
  171. // amount = count * serviceconfig.SpecialCfg.PrizeCost
  172. // }
  173. //}
  174. //
  175. ////扣减金币
  176. //if amount > 0 {
  177. // reduceGoldFailed := cash.ReduceMoney(userId, amount, common.LOGTYPE_PRIZEWHEEL_CONSUME,
  178. // "幸运抽奖", "幸运抽奖", ipAddress)
  179. // if reduceGoldFailed != 1 {
  180. // return ret, "金币不足"
  181. // }
  182. //}
  183. //加上抽奖次数
  184. u.Times += count
  185. //TODO: 通知数据库扣减抽奖次数
  186. go updateInfo(userId, u.Times)
  187. for i := 0; i < count; i++ {
  188. p := pm.getRandomPrize()
  189. if p == nil {
  190. continue
  191. }
  192. ret = append(ret, p)
  193. }
  194. go pm.sendAwards(userId, nickName, ret)
  195. return ret, "OK"
  196. }
  197. func (pm *prizewheelmgr) getRandomPrize() *Prize {
  198. if pm.totalChance == 0 {
  199. log.Debug("prizewheelmgr.getRandomPrize() totalChance == 0")
  200. return nil
  201. }
  202. result := rand.Intn(pm.totalChance)
  203. current := 0
  204. for _, v := range pm.prizes {
  205. if result < current+v.Chance {
  206. return v
  207. }
  208. current += v.Chance
  209. }
  210. log.Debug("prizewheelmgr.getRandomPrize() no result error current = %d,result = %d,totalChance = %d", current, result, pm.totalChance)
  211. return nil
  212. }
  213. func (pm *prizewheelmgr) dump(param1, param2 string) {
  214. log.Debug("-------------------------------")
  215. log.Debug("prizewheelmgr.dump %s %s", param1, param2)
  216. defer func() {
  217. log.Debug("+++++++++++++++++++++++++++++++")
  218. log.Debug("")
  219. }()
  220. for _, v := range pm.prizes {
  221. log.Debug(" %d:%d:%v", v.Id, v.Chance, v.Items)
  222. }
  223. }
  224. func (pm *prizewheelmgr) sendAwards(userId int, nickName string, prizes []*Prize) {
  225. if len(prizes) == 0 {
  226. log.Debug("prizewheelmgr.sendAwards[%d] no prizes", userId)
  227. return
  228. }
  229. var items []item.ItemPack
  230. for _, v := range prizes {
  231. for _, i := range v.Items {
  232. if i.ItemId == item.Item_Gold {
  233. go jackpot.ModifyJackpot(0, -i.Count, userId, "中奖", false)
  234. go pm.addRecord(userId, v.Id, nickName, v.Items)
  235. }
  236. }
  237. items = append(items, v.Items...)
  238. }
  239. inventory.AddItems(userId, items, "彩票刮奖", common.LOGTYPE_PRIZEWHEEL_GIFT)
  240. }
  241. func (pm *prizewheelmgr) addRecord(userId, wheelId int, nickName string, items []item.ItemPack) {
  242. pm.lock.Lock()
  243. //只保留最近50条
  244. if len(pm.RecordList) >= 50 {
  245. pm.RecordList = append(pm.RecordList[:0], pm.RecordList[1:]...)
  246. }
  247. pm.RecordList = append(pm.RecordList, &userPrizeRecord{
  248. UserId: userId,
  249. NickName: nickName,
  250. WheelId: wheelId,
  251. Items: items,
  252. Crdate: common.GetTimeStamp(),
  253. })
  254. pm.lock.Unlock()
  255. buff, err := json.Marshal(items)
  256. if err != nil {
  257. log.Error("prizeWheelMgr.SendAwards userId[%d] wheelId[%d] items=%v", userId, wheelId, items)
  258. return
  259. }
  260. //添加记录
  261. addRecord(userId, wheelId, string(buff))
  262. }
  263. func (pm *prizewheelmgr) getRecord() []*userPrizeRecord {
  264. pm.lock.RLock()
  265. defer pm.lock.RUnlock()
  266. return pm.RecordList
  267. }