package slotcommon import ( "fmt" "sync" "time" _ "bet24.com/log" coreservice "bet24.com/servers/coreservice/client" "bet24.com/servers/games/slotcommon/betlevel" "bet24.com/servers/games/slotcommon/usermanager" notification "bet24.com/servers/micros/notification/proto" task "bet24.com/servers/micros/task/proto" userservices "bet24.com/servers/micros/userservices/proto" waterpool "bet24.com/servers/micros/waterpool/proto" "bet24.com/servers/transaction" "bet24.com/servers/user" ) const DELAY_REMOVE = 300 // 300秒后删除用户 const DELAY_CHECK = 60 // 每分钟检查一次 type userFreeSpin struct { freeSpinTime int // 免费次数 lastBetAmount int fromAd bool } type SlotSink interface { SendGameCmd(userId int, msg, data string) GetUserInfo(userId int) *user.UserInfo WriteMoney(userId int, gameId int, amount int, tax int, status int, scoreType int, srcName string) bool IsChipRoom() bool } type Slot_Message struct { MsgID int Data string } type Slotcommon struct { gameId int gameName string taxRate int slotSink SlotSink gameMessage string userFreeSpins map[int]*userFreeSpin lock *sync.RWMutex lockRemove *sync.RWMutex removingFreespins map[int]int64 levelMgr *betlevel.BetLevelManager userlist map[int]int lockUser *sync.RWMutex } func NewSlotCommon(slotSink SlotSink, gameId int, gameName string, taxRate int, gameMessage string) *Slotcommon { sc := new(Slotcommon) sc.gameId = gameId sc.gameName = gameName sc.gameMessage = gameMessage sc.taxRate = taxRate sc.slotSink = slotSink sc.lock = &sync.RWMutex{} sc.userFreeSpins = make(map[int]*userFreeSpin) sc.removingFreespins = make(map[int]int64) sc.userlist = make(map[int]int) sc.lockRemove = &sync.RWMutex{} sc.lockUser = &sync.RWMutex{} go sc.checkRemoveUser() return sc } func (sm *Slotcommon) checkRemoveUser() { time.AfterFunc(DELAY_CHECK*time.Second, sm.checkRemoveUser) var toRemove []int latestRemoveTime := time.Now().Unix() - DELAY_REMOVE sm.lockRemove.RLock() for k, v := range sm.removingFreespins { if v < latestRemoveTime { toRemove = append(toRemove, k) } } sm.lockRemove.RUnlock() if len(toRemove) == 0 { return } sm.lockRemove.Lock() for _, v := range toRemove { delete(sm.removingFreespins, v) } sm.lockRemove.Unlock() sm.lock.Lock() for _, v := range toRemove { delete(sm.userFreeSpins, v) } sm.lock.Unlock() } func (this *Slotcommon) AddFreeSpin(userId int, freeCount, bet int, fromAd bool) { this.lock.Lock() uf, ok := this.userFreeSpins[userId] count := freeCount if ok { count += uf.freeSpinTime } this.userFreeSpins[userId] = &userFreeSpin{freeSpinTime: count, lastBetAmount: bet, fromAd: fromAd} this.lock.Unlock() } func (this *Slotcommon) UseFreeSpin(userId int) (bool, int, bool) { this.lock.Lock() defer this.lock.Unlock() t, ok := this.userFreeSpins[userId] if !ok || t.freeSpinTime <= 0 { return false, 0, false } t.freeSpinTime-- return true, t.lastBetAmount, t.fromAd } func (this *Slotcommon) GetFreeSpinTime(userId int) int { this.lock.RLock() defer this.lock.RUnlock() t, ok := this.userFreeSpins[userId] if !ok { return 0 } return t.freeSpinTime } func (this *Slotcommon) OnUserEnter(userId int) { //log.Debug("slotcommon.OnUserEnter %d", userId) this.lockUser.Lock() this.userlist[userId] = 1 this.lockUser.Unlock() go transaction.Trans_SetGameStatus(userId, this.gameId, 1, this.gameName, this.slotSink.IsChipRoom()) go coreservice.FriendSetUserStatus(userId, 1, this.gameName) this.lockRemove.Lock() delete(this.removingFreespins, userId) this.lockRemove.Unlock() } func (this *Slotcommon) OnUserExit(userId int) { found := false this.lockUser.Lock() _, found = this.userlist[userId] if found { delete(this.userlist, userId) } this.lockUser.Unlock() if !found { return } //log.Debug("slotcommon.OnUserExit %d", userId) go transaction.Trans_SetGameStatus(userId, this.gameId, 0, this.gameName, this.slotSink.IsChipRoom()) go coreservice.FriendSetUserStatus(userId, 0, this.gameName) go this.slotSink.WriteMoney(userId, this.gameId, 0, 0, 0, this.gameId*100+99, this.gameName) if this.GetFreeSpinTime(userId) > 0 { this.lockRemove.Lock() this.removingFreespins[userId] = time.Now().Unix() this.lockRemove.Unlock() return } this.lock.Lock() defer this.lock.Unlock() delete(this.userFreeSpins, userId) } func (sc *Slotcommon) GetControlType(userId int) int { usr := sc.slotSink.GetUserInfo(userId) if usr == nil { return 0 } return waterpool.GetControlType(usr.GetUserGold(), true, 0) } func (sc *Slotcommon) WriteResult(userId int, betAmount, winAmount int, freeSpin, fromAd bool, resultDesc string, gameId int) { tax := 0 amount := betAmount if freeSpin { amount = 0 } if sc.taxRate > 0 && (winAmount-amount) > 0 { tax = (winAmount - amount) / 100 * sc.taxRate } go func() { usr := sc.slotSink.GetUserInfo(userId) if usr == nil { return } if betAmount > 0 && !freeSpin && !fromAd { waterpool.AddBet(usr.GetUserGold(), betAmount, true, gameId) } if winAmount > 0 { waterpool.ReducePool(usr.GetUserGold(), winAmount, true, gameId) } }() isFree := 0 if freeSpin { isFree = 1 if fromAd { isFree = 2 } } isNewbie := usermanager.IsNewbie(userId, sc.gameId) sc.slotSink.WriteMoney(userId, sc.gameId, winAmount-tax, tax, 2, 2+sc.gameId*100+isFree, sc.gameName) returnLevel := usermanager.GetUserReturnLevel(userId, sc.gameId, amount) usermanager.AddResult(userId, sc.gameId, betAmount, winAmount, isFree > 0) go func() { if winAmount > 0 { task.DoTaskAction(userId, task.TaskAction_betWin, winAmount, task.TaskScope{GameName: sc.gameName}) } if sc.slotSink.IsChipRoom() { transaction.WriteChipBetRecordAction(userId, sc.gameId, "", amount, winAmount, tax, 2.0, sc.getBetDesc(betAmount, freeSpin, fromAd), resultDesc, returnLevel, "", sc.gameName) slotScore := 1 if winAmount > betAmount { slotScore = 2 } coreservice.AddSlotScore(userId, slotScore) } else { transaction.WriteBetRecordAction(userId, sc.gameId, "", amount, winAmount, tax, 2.0, sc.getBetDesc(betAmount, freeSpin, fromAd), resultDesc, returnLevel, "", sc.gameName) notification.AddNotification(userId, notification.Notification_Chip, "") if isFree == 0 { winAmount -= betAmount } userservices.AddGameExp(userId, sc.gameId, winAmount) } coreservice.AddUserWinScore(userId, winAmount) task.DoTaskAction(userId, task.TaskAction_playgame, 1, task.TaskScope{GameName: sc.gameName}) task.DoTaskAction(userId, task.TaskAction_fire, amount, task.TaskScope{GameName: sc.gameName}) // 上面已经减去betAmount realWin := winAmount if realWin > 0 { task.DoTaskAction(userId, task.TaskAction_earn, realWin, task.TaskScope{GameName: sc.gameName}) task.DoTaskAction(userId, task.TaskAction_wingame, 1, task.TaskScope{GameName: sc.gameName}) } }() // 如果之前是新手,现在不是 if isNewbie != usermanager.IsNewbie(userId, sc.gameId) { sc.SendBetLevel(userId) sc.sendUnlockBet(userId) } } func (sc *Slotcommon) getBetDesc(betAmount int, isFree, fromAd bool) string { if isFree { nFromAd := 0 if fromAd { nFromAd = 1 } return fmt.Sprintf("%d|%d", betAmount, nFromAd) } else { return fmt.Sprintf("%d", betAmount) } }