| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454 |
- package gamelogic
- import (
- "encoding/json"
- "fmt"
- "time"
- "bet24.com/log"
- "bet24.com/servers/games/greedy/common"
- "bet24.com/servers/games/greedy/config"
- userservices "bet24.com/servers/micros/userservices/proto"
- waterpool "bet24.com/servers/micros/waterpool/proto"
- "bet24.com/servers/user"
- "bet24.com/utils"
- )
- func (ts *tablesink) startPeriod() {
- delaySecond := 0
- switch ts.roomInfo.State {
- case common.GameState_Open:
- delaySecond = ts.roomInfo.BetTime
- ts.roomInfo.TotalBet = 0
- ts.roomInfo.State = common.GameState_Bet
- case common.GameState_Bet:
- common.ResetWinningOdds(ts.roomInfo.Odds)
- common.ResetBetProbability(ts.roomInfo.Probability)
- delaySecond = ts.roomInfo.OpenTime
- ts.roomInfo.State = common.GameState_Open
- default:
- log.Release("startPeriod failed state = %d", ts.roomInfo.State)
- return
- }
- ts.LastStateTick = time.Now()
- ts.onStateChanged()
- if ts.closeGame && ts.roomInfo.State == common.GameState_Open {
- //开奖后关闭房间
- log.Debug("tablesink.startPeriod Close the room after the open draw %v:%d,State = %d noPlayerCount= %d ", ts.roomInfo.RoomName, delaySecond, ts.roomInfo.State, ts.noPlayerCount)
- // 关闭游戏
- ts.stopPeriodPoll()
- return
- }
- ts.timer = time.AfterFunc(time.Duration(delaySecond)*time.Second, ts.startPeriod)
- log.Debug("tablesink.startPeriod %v:%d,State = %d", ts.roomInfo.RoomName, delaySecond, ts.roomInfo.State)
- }
- // 停止定时器的
- func (ts *tablesink) stopPeriodPoll() {
- if ts.timer != nil {
- ts.timer.Stop()
- }
- if ts.noPlayerCount >= 6 {
- ts.table.PrivateRoomSetWinners(nil)
- }
- }
- func (ts *tablesink) getStateSecond() int {
- return int(time.Since(ts.LastStateTick).Seconds())
- }
- func (ts *tablesink) onStateChanged() {
- if ts.roomInfo.State == common.GameState_Bet {
- ts.lock.Lock()
- ts.userBetList = make(map[int][]common.Bet)
- ts.roomInfo.SerialNumber++
- //初始化8个区域
- max := int(common.BidTypeMax)
- betCounts := make([]int, max)
- diamondHots := make([]int, max)
- areaPopular := common.AreaPopular{
- MostPopular: -1,
- BetCount: betCounts,
- DiamondHot: diamondHots,
- }
- ts.areaPopular = &areaPopular
- ts.hotDogAmount = 0
- ts.kebabAmount = 0
- ts.chickenLegAmount = 0
- ts.meatSliceAmount = 0
- ts.radishAmount = 0
- ts.cornAmount = 0
- ts.spinachAmount = 0
- ts.tomatoAmount = 0
- ts.lock.Unlock()
- log.Debug("onStateChanged SerialNumber = %d", ts.roomInfo.SerialNumber)
- go ts.arrangeRobotActions()
- }
- // 如果是开奖阶段
- if ts.roomInfo.State == common.GameState_Open {
- ts.enterOpenState(false)
- go ts.stopRobotPoll()
- }
- ts.table.NotifySceneChanged(-1)
- //ts.refreshRoomInfo()
- }
- func (ts *tablesink) getStateData() string {
- var state common.GameState
- state.Sec = ts.getStateSecond()
- ts.lock.RLock()
- state.State = ts.roomInfo.State
- ts.roomInfo.StateSec = state.Sec
- state.SpinResult = ts.spinResult
- state.Historys = ts.roomInfo.Historys
- state.TableUser = *ts.score_users
- state.AreaPopular = *ts.areaPopular
- state.SerialNumber = ts.roomInfo.SerialNumber
- if state.State == common.GameState_Bet {
- for _, v := range ts.userBetList {
- state.BetCmds = append(state.BetCmds, v...)
- }
- }
- state.CloseGame = ts.closeGame
- ts.lock.RUnlock()
- data, _ := json.Marshal(state)
- return string(data)
- }
- func (ts *tablesink) isCanBet(bet common.Bet) (bool, string) {
- amount := bet.Amount
- userId := bet.UserId
- betId := bet.BetId
- if ts.roomInfo.State != common.GameState_Bet {
- return false, "Bet failed,Please wait for next round"
- }
- if amount < ts.roomInfo.MinBet || amount > ts.roomInfo.MaxBet {
- return false, "Bet amount exceeded"
- }
- bidType := common.BetOption(betId)
- if bidType >= common.BidTypeMax || bidType < common.HotDog {
- log.Release("isCanBet invalid betting area %d,%v", bidType, common.HotDog)
- return false, "invalid bet area"
- }
- // 检查个人下注
- myAmount := 0
- ts.lock.RLock()
- betList, ok := ts.userBetList[userId]
- if ok {
- for _, v := range betList {
- myAmount += v.Amount
- }
- }
- ts.lock.RUnlock()
- maxBet := ts.roomInfo.MaxBet
- totalMaxBet := ts.roomInfo.TotalMax
- totalBet := ts.roomInfo.TotalBet
- if myAmount+amount > maxBet {
- return false, "Bet amount user exceeded"
- }
- // 检查全体下注
- if amount+totalBet > totalMaxBet {
- return false, "Bet amount section exceeded"
- }
- return true, ""
- }
- func (ts *tablesink) addBet(bet common.Bet) (bool, string) {
- ok, errMsg := ts.isCanBet(bet)
- if !ok {
- return ok, errMsg
- }
- ts.lock.Lock()
- ts.roomInfo.TotalBet += bet.Amount
- betList, ok := ts.userBetList[bet.UserId]
- // 合并之前下注
- found := false
- if ok {
- for i := 0; i < len(betList); i++ {
- if !betList[i].IsSameBet(&bet) {
- continue
- }
- betList[i].Amount += bet.Amount
- // 合并下注
- found = true
- break
- }
- }
- //log.Debug("tablesink.addBet %v", ts.userBetList)
- if !found {
- ts.userBetList[bet.UserId] = append(ts.userBetList[bet.UserId], bet)
- ts.areaPopular.BetCount[bet.BetId]++
- }
- ts.lock.Unlock()
- betAmount := bet.Amount
- ts.userList.addBet(bet.UserId, betAmount, bet.BetId)
- return true, ""
- }
- func (ts *tablesink) enterOpenState(isReset bool) {
- spinResult := common.Spin()
- // 钻石场 避免 连续大奖 重新摇奖
- if gs.IsChipRoom() && spinResult == common.MeatSlice && ts.drawMeatSliceWinAmount > 0 {
- spinResult = common.Spin()
- }
- ts.drawMeatSliceWinAmount = 0
- // 开奖
- ts.lock.Lock()
- ts.spinResult = spinResult
- ts.lock.Unlock()
- //针对主区域差额确定,特殊区域不考虑
- controlType := 0 //controlType 1表示扣减,2表示放水
- //找到投注额的最大值和最小值
- maxAmount := ts.hotDogAmount
- minAmount := ts.hotDogAmount
- //最大值和最小值对应的下注区域
- var maxBet, minBet common.BetOption
- betsAmount := []int{ts.hotDogAmount, ts.kebabAmount, ts.chickenLegAmount, ts.meatSliceAmount, ts.radishAmount, ts.cornAmount, ts.spinachAmount, ts.tomatoAmount}
- //只重置一次
- if !isReset {
- for i, f := range betsAmount {
- if f > maxAmount {
- maxAmount = f
- //因为默认值是0,所以这里要加1
- maxBet = common.BetOption(i + 1)
- }
- if f < minAmount {
- minAmount = f
- minBet = common.BetOption(i + 1)
- }
- }
- if maxAmount > 0 || minAmount > 0 {
- controlType = waterpool.GetControlType(0, false, common.GAMEID)
- }
- //根据情况判断是否需要重新开奖
- if controlType == 1 {
- if spinResult == maxBet {
- ts.enterOpenState(true)
- return
- }
- } else if controlType == 2 {
- if spinResult != minBet {
- ts.enterOpenState(true)
- return
- }
- }
- }
- ts.addHistory(int(spinResult))
- ts.lock.Lock()
- ts.scores = []common.UserSetScore{}
- if ts.userList == nil {
- // 如果没有玩家,将 noPlayerCount 的值加 1
- ts.noPlayerCount++
- if ts.noPlayerCount >= 6 {
- // 如果连续 6 期没有玩家,开奖后关闭游戏
- ts.closeGame = true
- }
- } else {
- ts.noPlayerCount = 0
- }
- // 纪录每个玩家总输赢
- for userId, betList := range ts.userBetList {
- usr := ts.table.GetUserByUserId(userId)
- var total struct {
- UserId int
- BetAmount int
- WinAmount int
- WinAmountOnly int
- DayWinAmount int
- }
- total.UserId = userId
- betDesc := fmt.Sprintf("%v:", ts.roomInfo.SerialNumber)
- betIdDesc := ""
- betAmountDesc := ""
- resultDesc := ""
- totalTax := 0
- //开奖赔率
- winOdds := common.GetOdds(spinResult)
- for i, v := range betList {
- // 根据每个人计算结果
- var result common.Result
- result.UserId = v.UserId
- result.Bet = v
- result.SpinResult = spinResult
- result.Amount = v.Amount
- betAmount := v.Amount
- total.BetAmount += betAmount
- odds := common.GetResultOdds(result.BetId, spinResult)
- //log.Debug("GetResultOdds odds= %v, BetId = %v", odds, result.BetId)
- // 看下有没有中的
- if odds > 0 {
- result.WinAmount = int(odds * float64(result.Amount))
- //免费的也要扣本金
- realWin := result.WinAmount - result.Amount
- if realWin > 0 {
- result.Tax = realWin * ts.roomInfo.TaxRate / 100
- }
- total.WinAmountOnly += result.WinAmount
- result.WinAmount -= result.Tax
- total.WinAmount += result.WinAmount
- }
- betIdDesc += fmt.Sprintf("%d", result.BetId)
- if i != len(betList)-1 {
- betIdDesc += ","
- }
- betAmountDesc = fmt.Sprintf("%s [%s:%s]", betAmountDesc, ts.getBetDesc(result.Bet), utils.FormatScore(v.Amount))
- resultDesc = ts.getResultDesc(result)
- totalTax += result.Tax
- //ts.handleResult(result, usr)
- }
- betDesc = fmt.Sprintf("%s%s&%s", betDesc, betIdDesc, betAmountDesc)
- if total.WinAmountOnly > 0 {
- ts.winRank.addWinPool(userId, total.WinAmountOnly)
- }
- go ts.handleResult(userId, total.BetAmount, total.WinAmount, totalTax, usr)
- // 纪录输赢
- go ts.table.WriteBetRecordWithPlayTime(userId, total.BetAmount, total.WinAmount, winOdds,
- betDesc, resultDesc, ts.roomInfo.RoomName, ts.roomInfo.BetTime)
- ts.userList.addResult(userId, total.WinAmount-total.BetAmount, total.WinAmountOnly)
- ts.scores = append(ts.scores, common.UserSetScore{UserId: userId, Score: total.WinAmount - total.BetAmount})
- if usr == nil {
- continue
- }
- _, _, winAmount := ts.winRank.getRankList(userId, -1)
- total.DayWinAmount = winAmount
- // 发送我的总输赢
- data, _ := json.Marshal(total)
- ts.table.SendGameData(usr.GetUserIndex(), TotalResult, string(data))
- }
- ts.lock.Unlock()
- ts.winRank.winPoolToRedis()
- //ts.userList.dump()
- // 结算完毕,计算连胜榜
- ts.lock.Lock()
- //因为前端只需要显示前三名的NickName和金币所以这里只取前三名
- ts.score_users.WinGoldRankingUsers = ts.userList.getWinGoldRankingUsers(3)
- ts.score_users.DayWinGoldRankingUsers = ts.GetWinRank(1)
- ts.lock.Unlock()
- ts.userList.clearBetStatus()
- }
- func (ts *tablesink) addHistory(spinResult int) {
- Historys := config.OpenHistory{SpinResult: spinResult, SerialNumber: ts.roomInfo.SerialNumber}
- ts.lock.Lock()
- defer ts.lock.Unlock()
- log.Debug("addHistory %v,%v", Historys, ts.roomInfo)
- ts.roomInfo.Historys = append(ts.roomInfo.Historys, Historys)
- if len(ts.roomInfo.Historys) > ts.roomInfo.HistoryCount {
- ts.roomInfo.Historys = ts.roomInfo.Historys[1:]
- }
- }
- // 处理结算
- func (ts *tablesink) handleResult(userId int, betAmount, winAmount, tax int, usr *user.UserInfo) {
- // data, _ := json.Marshal(result)
- // if usr != nil {
- // go ts.table.SendGameData(usr.GetUserIndex(), Result, string(data))
- // }
- ts.table.WriteUserMoney(userId, winAmount, tax, 2, 2+common.GAMEID*100, ts.roomInfo.RoomName)
- // 写用户纪录
- // var record common.RecordInfo
- // record.SpinResult = result.SpinResult
- // record.SerialNumber = ts.roomInfo.SerialNumber
- // d, _ := json.Marshal(record)
- // go transaction.WriteGameRecord(userId, common.GAMEID, ts.roomInfo.RoomName, string(d))
- }
- func (ts *tablesink) getHistory() string {
- ts.lock.RLock()
- defer ts.lock.RUnlock()
- data, _ := json.Marshal(ts.roomInfo.Historys)
- return string(data)
- }
- func (ts *tablesink) getBetDesc(bet common.Bet) string {
- return common.GetBetDesc(bet.BetId)
- }
- func (ts *tablesink) getResultDesc(result common.Result) string {
- return common.GetResultDesc(result.SpinResult)
- }
- func (ts *tablesink) currentGameNumber() int {
- now := time.Now()
- startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
- difference := now.Sub(startOfDay)
- secondsSinceMidnight := int(difference.Seconds())
- gameDuration := ts.roomInfo.BetTime + ts.roomInfo.OpenTime
- currentGame := secondsSinceMidnight/gameDuration + 1
- return currentGame
- }
- func (ts *tablesink) GetWinRank(count int) []common.ScoreUser {
- //用户id
- var userIds []int
- //获取winRank前10名
- rankList, _, _ := ts.winRank.getRankList(0, count)
- log.Debug("tablesink.GetWinRank rankList:%v", rankList)
- //不为空
- if len(rankList) > 0 {
- scoreUserList := make([]common.ScoreUser, 0, len(rankList))
- //如果rankList昵称为空则补齐
- userIds = make([]int, len(rankList))
- for i, u := range rankList {
- userIds[i] = u.UserId
- }
- users := userservices.GetUserInfoInBulk(userIds)
- for i, v := range rankList {
- info := make([]int, 0, 1)
- info = append(info, v.WinAmount)
- scoreUser := common.ScoreUser{
- UserId: v.UserId,
- NickName: "",
- FaceId: 0,
- FaceUrl: "",
- VipLevel: 0,
- VipExpire: 0,
- Decorations: nil,
- Info: info,
- }
- user := users[i]
- if user.UserId == v.UserId {
- scoreUser.NickName = user.NickName
- scoreUser.FaceId = user.FaceId
- scoreUser.FaceUrl = user.FaceUrl
- scoreUser.VipLevel = user.Vip
- scoreUser.VipExpire = user.VipExpire
- scoreUser.Decorations = user.Decorations
- }
- scoreUserList = append(scoreUserList, scoreUser)
- }
- return scoreUserList
- }
- return []common.ScoreUser{}
- }
|