package slotcommon import ( "fmt" "sync" "time" _ "bet24.com/log" coreservice "bet24.com/servers/coreservice/client" "bet24.com/servers/games/slotcommon/betlevel" 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" ) const DELAY_REMOVE = 300 // 300秒后删除用户 const DELAY_CHECK = 60 // 每分钟检查一次 type userFreeSpin struct { freeSpinTime int // 免费次数 lastBetAmount int isChipRoom bool } type Slotcommon struct { gameId int gameName string taxRate int 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(gameId int, gameName string, taxRate int) *Slotcommon { sc := new(Slotcommon) sc.gameId = gameId sc.gameName = gameName sc.taxRate = taxRate 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 (sc *Slotcommon) AddFreeSpin(userId int, freeCount, bet int, isChipRoom bool) { sc.lock.Lock() uf, ok := sc.userFreeSpins[userId] count := freeCount if ok { count += uf.freeSpinTime } sc.userFreeSpins[userId] = &userFreeSpin{freeSpinTime: count, lastBetAmount: bet, isChipRoom: isChipRoom} sc.lock.Unlock() } func (sc *Slotcommon) UseFreeSpin(userId int) (bool, int, bool) { sc.lock.Lock() defer sc.lock.Unlock() t, ok := sc.userFreeSpins[userId] if !ok || t.freeSpinTime <= 0 { return false, 0, false } t.freeSpinTime-- return true, t.lastBetAmount, t.isChipRoom } func (sc *Slotcommon) GetFreeSpinTime(userId int) int { sc.lock.RLock() defer sc.lock.RUnlock() t, ok := sc.userFreeSpins[userId] if !ok { return 0 } return t.freeSpinTime } func (sc *Slotcommon) OnUserEnter(userId int, isChipRoom bool) { sc.lockUser.RLock() _, ok := sc.userlist[userId] sc.lockUser.RUnlock() if ok { return } sc.lockUser.Lock() sc.userlist[userId] = 1 sc.lockUser.Unlock() go transaction.Trans_SetGameStatus(userId, sc.gameId, 1, sc.gameName, isChipRoom) go coreservice.FriendSetUserStatus(userId, 1, sc.gameName) sc.lockRemove.Lock() delete(sc.removingFreespins, userId) sc.lockRemove.Unlock() } func (sc *Slotcommon) OnUserExit(userId int, isChipRoom bool) { found := false sc.lockUser.Lock() _, found = sc.userlist[userId] if found { delete(sc.userlist, userId) } sc.lockUser.Unlock() if !found { return } go transaction.Trans_SetGameStatus(userId, sc.gameId, 0, sc.gameName, isChipRoom) go coreservice.FriendSetUserStatus(userId, 0, sc.gameName) go sc.WriteMoney(userId, 0, 0, 0, sc.gameId*100+99, false) if sc.GetFreeSpinTime(userId) > 0 { sc.lockRemove.Lock() sc.removingFreespins[userId] = time.Now().Unix() sc.lockRemove.Unlock() return } sc.lock.Lock() defer sc.lock.Unlock() delete(sc.userFreeSpins, userId) } func (sc *Slotcommon) WriteMoney(userId int, amount, tax, status, scoreType int, isChipRoom bool) bool { gameId := sc.gameId srcName := sc.gameName var ret bool if isChipRoom { ret, _, _ = transaction.WriteChipSync(userId, gameId, amount, tax, status, scoreType, srcName, "") if ret { go notification.AddNotification(userId, notification.Notification_Chip, "") } } else { ret, _, _ = transaction.WriteMoneySync(userId, gameId, amount, tax, status, scoreType, srcName, "") if ret { go notification.AddNotification(userId, notification.Notification_Gold, "") } } return true } func (sc *Slotcommon) GetControlType(userId, gameId int) int { usr := userservices.GetUserInfo(userId) if usr == nil { return 0 } return waterpool.GetControlType(usr.GetUserGold(), true, gameId) } func (sc *Slotcommon) WriteResult(userId int, betAmount, winAmount int, freeSpin, isChipRoom 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 := userservices.GetUserInfo(userId) if usr == nil { return } if betAmount > 0 && !freeSpin && !isChipRoom { waterpool.AddBet(usr.GetUserGold(), betAmount, true, gameId) } if winAmount > 0 && !isChipRoom { waterpool.ReducePool(usr.GetUserGold(), winAmount, true, gameId) } }() isFree := 0 if freeSpin { isFree = 1 if isChipRoom { isFree = 2 } } sc.WriteMoney(userId, winAmount-tax, tax, 2, 2+sc.gameId*100+isFree, isChipRoom) returnLevel := 0 go func() { if isChipRoom { transaction.WriteChipBetRecordAction(userId, sc.gameId, "", amount, winAmount, tax, 2.0, sc.getBetDesc(betAmount, freeSpin, isChipRoom), 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, isChipRoom), resultDesc, returnLevel, "", sc.gameName) notification.AddNotification(userId, notification.Notification_Chip, "") if isFree == 0 { winAmount -= betAmount } } 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 winAmount > 0 { task.DoTaskAction(userId, task.TaskAction_betWin, winAmount, task.TaskScope{GameName: sc.gameName}) } }() } func (sc *Slotcommon) getBetDesc(betAmount int, isFree, isChipRoom bool) string { if isFree { nFromAd := 0 if isChipRoom { nFromAd = 1 } return fmt.Sprintf("%d|%d", betAmount, nFromAd) } else { return fmt.Sprintf("%d", betAmount) } }