package prizewheel import ( "encoding/json" "math/rand" "sync" "time" "bet24.com/log" "bet24.com/servers/common" "bet24.com/servers/coreservice/jackpot" "bet24.com/servers/coreservice/serviceconfig" inventory "bet24.com/servers/micros/item_inventory/proto" item "bet24.com/servers/micros/item_inventory/proto" ) type prizewheelmgr struct { prizes []*Prize totalChance int lock *sync.RWMutex UserList map[int]*userPrize RecordList []*userPrizeRecord } type userPrize struct { UserId int //用户ID Times int //次数 Crdate int //时间戳 } type userPrizeRecord struct { UserId int //用户ID NickName string //昵称 WheelId int //转盘ID Items []item.ItemPack //奖励 Crdate int //时间戳 } func newPrizeWheelManager() *prizewheelmgr { pm := new(prizewheelmgr) pm.UserList = make(map[int]*userPrize) pm.lock = &sync.RWMutex{} pm.loadPrizes() pm.loadRecord() pm.checkDayRefresh() log.Debug("prizewheelmgr manager running") return pm } func (pm *prizewheelmgr) loadPrizes() { // 从数据库加载配置信息 pm.prizes = getList() //TODO:从数据库获取奖池金额 pm.totalChance = 0 for _, v := range pm.prizes { pm.totalChance += v.Chance } } func (pm *prizewheelmgr) loadRecord() { records := getRecord() pm.lock.Lock() defer pm.lock.Unlock() pm.RecordList = append(pm.RecordList, records...) } func (pm *prizewheelmgr) checkDayRefresh() { ticker := time.NewTicker(10 * time.Minute) go func(t *time.Ticker) { lastCheck := common.GetTimeStamp() for { //循环 select { case <-t.C: now := common.GetTimeStamp() if !common.IsSameDay(lastCheck, now) { pm.refreshUserList() } lastCheck = now } } }(ticker) } // 0点过后去数据库刷新在线玩家数据 func (pm *prizewheelmgr) refreshUserList() { dayIndex := common.GetDayIndex(common.GetTimeStamp()) pm.lock.Lock() defer pm.lock.Unlock() for _, v := range pm.UserList { //过期了 if common.GetDayIndex(v.Crdate) < dayIndex { v.Times = 0 } } } func (pm *prizewheelmgr) onUserEnter(userId int) { //TODO: 去数据库获取今日剩余抽奖次数 count u := new(userPrize) u.UserId = userId u.Times, u.Crdate = getInfo(userId) //判断是否过期,过期清零 if common.GetDayIndex(u.Crdate) < common.GetDayIndex(common.GetTimeStamp()) { u.Times = 0 } pm.lock.Lock() pm.UserList[userId] = u pm.lock.Unlock() } func (pm *prizewheelmgr) onUserExit(userId int) { pm.lock.Lock() defer pm.lock.Unlock() delete(pm.UserList, userId) } func (pm *prizewheelmgr) getPrizes() []*Prize { pm.lock.RLock() defer pm.lock.RUnlock() return pm.prizes } func (pm *prizewheelmgr) getWheelTimes(userId int) (int, int, int) { pm.lock.RLock() u, ok := pm.UserList[userId] pm.lock.RUnlock() if !ok { u = new(userPrize) u.UserId = userId u.Times, u.Crdate = getInfo(userId) //判断是否过期,过期清零 if common.GetDayIndex(u.Crdate) < common.GetDayIndex(common.GetTimeStamp()) { u.Times = 0 } pm.lock.Lock() pm.UserList[userId] = u pm.lock.Unlock() } return u.Times, serviceconfig.SpecialCfg.PrizeTimes, serviceconfig.SpecialCfg.PrizeCost } // 摇奖,返回中奖结果 func (pm *prizewheelmgr) wheel(userId, count int, nickName, ipAddress string) ([]*Prize, string) { var ret []*Prize if count <= 0 { log.Debug("prizewheelmgr.wheel count <= 0") return ret, "转盘不可用" } pm.lock.RLock() u, ok := pm.UserList[userId] pm.lock.RUnlock() if !ok { log.Debug("prizewheelmgr.wheel userId(%d) is not exist, count=%d", userId, count) return ret, "无效数据" } //是否还有抽奖次数 if count > serviceconfig.SpecialCfg.PrizeTimes-u.Times { log.Debug("prizewheelmgr.wheel count <= %d", u.Times) return ret, "没有抽奖次数" } //lotteryCount, consumeAmount, amount := count, count, 0 // //// 先判断抽奖券是否足够 //if item := inventory.GetUserLottery(userId); item != nil { // // 抽奖券不够,有多少扣多少 // if item.Count < count { // lotteryCount = item.Count // } // // consumeAmount = count - lotteryCount //} // //// 再判断金币是否足够 //if consumeAmount > 0 { // // 去数据库扣钱 // amount = consumeAmount * serviceconfig.SpecialCfg.PrizeCost // // if _, gold, _ := cash.GetMoney(userId); gold < amount { // return ret, "金币不足" // } //} // ////扣减抽奖券 //if lotteryCount > 0 { // if success, _ := inventory.ConsumeLottery(userId, lotteryCount); !success { // amount = count * serviceconfig.SpecialCfg.PrizeCost // } //} // ////扣减金币 //if amount > 0 { // reduceGoldFailed := cash.ReduceMoney(userId, amount, common.LOGTYPE_PRIZEWHEEL_CONSUME, // "幸运抽奖", "幸运抽奖", ipAddress) // if reduceGoldFailed != 1 { // return ret, "金币不足" // } //} //加上抽奖次数 u.Times += count //TODO: 通知数据库扣减抽奖次数 go updateInfo(userId, u.Times) for i := 0; i < count; i++ { p := pm.getRandomPrize() if p == nil { continue } ret = append(ret, p) } go pm.sendAwards(userId, nickName, ret) return ret, "OK" } func (pm *prizewheelmgr) getRandomPrize() *Prize { if pm.totalChance == 0 { log.Debug("prizewheelmgr.getRandomPrize() totalChance == 0") return nil } result := rand.Intn(pm.totalChance) current := 0 for _, v := range pm.prizes { if result < current+v.Chance { return v } current += v.Chance } log.Debug("prizewheelmgr.getRandomPrize() no result error current = %d,result = %d,totalChance = %d", current, result, pm.totalChance) return nil } func (pm *prizewheelmgr) dump(param1, param2 string) { log.Debug("-------------------------------") log.Debug("prizewheelmgr.dump %s %s", param1, param2) defer func() { log.Debug("+++++++++++++++++++++++++++++++") log.Debug("") }() for _, v := range pm.prizes { log.Debug(" %d:%d:%v", v.Id, v.Chance, v.Items) } } func (pm *prizewheelmgr) sendAwards(userId int, nickName string, prizes []*Prize) { if len(prizes) == 0 { log.Debug("prizewheelmgr.sendAwards[%d] no prizes", userId) return } var items []item.ItemPack for _, v := range prizes { for _, i := range v.Items { if i.ItemId == item.Item_Gold { go jackpot.ModifyJackpot(0, -i.Count, userId, "中奖", false) go pm.addRecord(userId, v.Id, nickName, v.Items) } } items = append(items, v.Items...) } inventory.AddItems(userId, items, "彩票刮奖", common.LOGTYPE_PRIZEWHEEL_GIFT) } func (pm *prizewheelmgr) addRecord(userId, wheelId int, nickName string, items []item.ItemPack) { pm.lock.Lock() //只保留最近50条 if len(pm.RecordList) >= 50 { pm.RecordList = append(pm.RecordList[:0], pm.RecordList[1:]...) } pm.RecordList = append(pm.RecordList, &userPrizeRecord{ UserId: userId, NickName: nickName, WheelId: wheelId, Items: items, Crdate: common.GetTimeStamp(), }) pm.lock.Unlock() buff, err := json.Marshal(items) if err != nil { log.Error("prizeWheelMgr.SendAwards userId[%d] wheelId[%d] items=%v", userId, wheelId, items) return } //添加记录 addRecord(userId, wheelId, string(buff)) } func (pm *prizewheelmgr) getRecord() []*userPrizeRecord { pm.lock.RLock() defer pm.lock.RUnlock() return pm.RecordList }