| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- package gamelogic
- import (
- "encoding/json"
- "fmt"
- "time"
- "bet24.com/log"
- "bet24.com/servers/games/luckyfruit_table/common"
- "bet24.com/servers/games/luckyfruit_table/config"
- userservices "bet24.com/servers/micros/userservices/proto"
- waterpool "bet24.com/servers/micros/waterpool/proto"
- "bet24.com/servers/transaction"
- "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.ResetFruitProbability(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()
- 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) getStateSecond() int {
- return int(time.Since(ts.LastStateTick).Seconds())
- }
- func (ts *tablesink) onStateChanged() {
- if ts.roomInfo.State == common.GameState_Bet {
- now := time.Now()
- serialNumber := now.Minute() + now.Hour()*100 + now.Day()*10000 + int(now.Month())*1000000 + (now.Year()%10)*100000000
- serialNumber = serialNumber*100 + now.Second()
- ts.lock.Lock()
- ts.userBetList = make(map[int][]common.Bet)
- ts.roomInfo.SerialNumber = serialNumber
- // ts.spinResult = -1 //便于查看上一局开奖结果
- ts.appleAmount = 0
- ts.watermelonAmount = 0
- ts.bananaAmount = 0
- ts.orangeAmount = 0
- ts.grapeAmount = 0
- ts.lock.Unlock()
- log.Debug("onStateChanged SerialNumber = %d", ts.roomInfo.SerialNumber)
- go ts.arrangeRobotActions()
- }
- // 如果是开奖阶段
- if ts.roomInfo.State == common.GameState_Open {
- go ts.stopRobotPoll()
- controlType := waterpool.GetControlType(0, false, common.GAMEID)
- ts.enterOpenState(controlType, false)
- }
- 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.RichList = ts.richList
- //state.BetList = ts.betList
- state.SerialNumber = ts.roomInfo.SerialNumber
- // if len(ts.scores) > 0 {
- // state.Scores = append(state.Scores, ts.scores...)
- //} else {
- // state.Scores = []common.UserSetScore{}
- // }
- if state.State == common.GameState_Bet {
- for _, v := range ts.userBetList {
- state.BetCmds = append(state.BetCmds, v...)
- }
- }
- 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.Fruit(betId)
- if bidType >= common.BigOrange || bidType < common.Orange {
- log.Release("isCanBet invalid bet %d,%v", bidType, common.BigOrange)
- return false, "invalid bet"
- }
- // 检查个人下注
- 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.lock.Unlock()
- betAmount := bet.Amount
- if !bet.IsFree {
- ts.userList.addBet(bet.UserId, betAmount, bet.BetId)
- }
- return true, ""
- }
- func (ts *tablesink) enterOpenState(controlType int, isReset bool) {
- spinResult := common.Spin()
- winArea := common.GetWinArea(spinResult)
- // 元宝场 避免 连续大苹果 重新摇奖
- // if ts.IsChipRoom() && spinResult == common.BigApple && ts.drawAppleWinAmount > 0 {
- // spinResult = common.Spin()
- // winArea = common.GetWinArea(spinResult)
- // }
- ts.drawAppleWinAmount = 0
- // 开奖
- ts.lock.Lock()
- ts.spinResult = spinResult
- ts.lock.Unlock()
- poolValue := waterpool.GetInventoryValue(common.GAMEID, waterpool.RoomType_Hundred, ts.roomInfo.RoomName)
- //只重置一次
- if !isReset {
- //1表示扣减,2表示放水
- if controlType != 0 {
- simulateBetResults := 0
- ts.lock.RLock()
- //计算所有区域的下注总额
- for _, betList := range ts.userBetList {
- if len(betList) == 0 {
- continue
- }
- for _, v := range betList {
- if v.IsRobot && !ts.roomInfo.Test {
- //机器人跳过
- continue
- }
- odds := common.GetResultOdds(v.BetId, spinResult)
- if odds > 0 {
- //庄家输
- simulateBetResults -= int(odds * float64(v.Amount))
- }
- //庄家无论输赢都需要收回底注
- simulateBetResults += v.Amount
- }
- }
- ts.lock.RUnlock()
- log.Release("tableSink.enterOpenState controlType:%v,simulateBetResults:%v", controlType, simulateBetResults)
- if controlType == 1 && simulateBetResults < 0 {
- ts.enterOpenState(controlType, false)
- return
- } else if controlType == 2 && simulateBetResults > 0 {
- ts.enterOpenState(controlType, false)
- return
- }
- }
- }
- //log.Debug("getCards %v,%v", ts.bankerCards, ts.playerCards)
- //log.Debug("GetResult r= %v,bankerCardType = %v, bankerCardPoint = %v ,playerCardType = %v, playerCardPoint = %v", r, bankerCardType, bankerCardPoint, playerCardType, playerCardPoint)
- ts.addHistory(int(spinResult))
- ts.lock.Lock()
- ts.scores = []common.UserSetScore{}
- // 纪录每个玩家总输赢
- for userId, betList := range ts.userBetList {
- usr := ts.table.GetUserByUserId(userId)
- var total struct {
- UserId int
- BetAmount int
- WinAmount int
- WinAmountOnly int
- }
- total.UserId = userId
- betDesc := fmt.Sprintf("SpinResult: %v WinArea: %v", spinResult, winArea)
- resultDesc := ""
- totalTax := 0
- //开奖赔率
- winOdds := common.GetOdds(spinResult)
- var betAreas []betAreaInfo
- for _, v := range betList {
- // 根据每个人计算结果
- var result common.Result
- result.UserId = v.UserId
- result.Bet = v
- result.SpinResult = spinResult
- result.WinArea = winArea
- result.Amount = v.Amount
- betAmount := v.Amount
- if v.IsFree {
- betAmount = 0
- }
- betAreas = append(betAreas, betAreaInfo{
- betArea: v.BetId,
- 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
- // }
- result.Tax = result.WinAmount * ts.roomInfo.TaxRate / 100
- total.WinAmountOnly += result.WinAmount
- result.WinAmount -= result.Tax
- total.WinAmount += result.WinAmount
- }
- betDesc = fmt.Sprintf("%s [%s:%s]", betDesc, ts.getBetDesc(result.Bet), utils.FormatScore(v.Amount))
- resultDesc = ts.getResultDesc(result)
- totalTax += result.Tax
- ts.handleResult(result, usr)
- }
- if ts.roomInfo.Test {
- ts.stat.lists = append(ts.stat.lists, Statistics{
- betAmount: total.BetAmount,
- winAmount: total.WinAmount,
- betArea: betAreas,
- winArea: spinResult,
- winOdd: winOdds,
- waterpool: poolValue,
- })
- }
- // 纪录输赢
- 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 {
- //检查是否为机器人
- if !userservices.IsRobot(userId) || ts.roomInfo.Test {
- ts.settleStats(userId, total.BetAmount, total.WinAmount, totalTax)
- }
- continue
- } else if !usr.IsRobot() || ts.roomInfo.Test {
- ts.settleStats(userId, total.BetAmount, total.WinAmount, totalTax)
- }
- // 发送我的总输赢
- data, _ := json.Marshal(total)
- ts.table.SendGameData(usr.GetUserIndex(), TotalResult, string(data))
- }
- ts.lock.Unlock()
- ts.betRank.betPoolToRedis()
- //ts.userList.dump()
- // 结算完毕,计算连胜榜
- ts.lock.Lock()
- // ts.score_users.LuckyStarUsers = ts.userList.getLuckyStarUsers(5)
- //因为前端只需要显示前十名的NickName和金币所以这里只取前十名
- ts.score_users.WinGoldRankingUsers = ts.userList.getWinGoldRankingUsers(10)
- // ts.richList = ts.refreshRichList(20)
- ts.score_users.BetGoldRankingUsers = ts.userList.getBetGoldRankingUsers(5)
- ts.lock.Unlock()
- ts.userList.clearBetStatus()
- }
- // 结算统计
- func (ts *tablesink) settleStats(userId, betAmount, winAmount, totalTax int) {
- if betAmount > 0 {
- ts.betRank.addBetPool(userId, betAmount)
- }
- //上报水池
- go waterpool.AddBet(0, betAmount, false, common.GAMEID)
- go waterpool.ReducePool(0, winAmount, false, common.GAMEID)
- }
- // func (ts *tablesink) refreshRichList(count int) []int {
- // userlist := ts.table.GetUserList()
- // sort.Slice(userlist, func(i, j int) bool {
- // return ts.table.GetUserChipOrGoldByUser(userlist[i]) > ts.table.GetUserChipOrGoldByUser(userlist[j])
- // })
- // ret := []int{}
- // for k, v := range userlist {
- // if k >= count {
- // break
- // }
- // gold := ts.table.GetUserChipOrGoldByUser(v)
- // if gold <= 0 {
- // break
- // }
- // ret = append(ret, v.GetUserId())
- // }
- // return ret
- // }
- 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(result common.Result, usr *user.UserInfo) {
- // data, _ := json.Marshal(result)
- // if usr != nil {
- // go ts.table.SendGameData(usr.GetUserIndex(), Result, string(data))
- // }
- ts.table.WriteUserMoney(result.UserId, result.WinAmount, result.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(result.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) onFreeChipsChange() {
- ts.table.SendGameData(-1, FreeChipChange, "")
- }
|