package room import ( "game/common/config/game" "game/common/proto/pb" "game/server/colorgame/config" "github.com/fox/fox/ksync" "github.com/fox/fox/log" "github.com/fox/fox/xrand" "github.com/fox/fox/xtime" "sync" ) func (rm *ColorRoom) setStatus(status pb.ColorGameStatus) { rm.status = status rm.statusTime = xtime.Now().TimestampMilli() } // 状态结束时间点,毫秒 func (rm *ColorRoom) endTimeStatus() int64 { duration := int64(0) switch rm.status { case pb.ColorGameStatus_CGS_Start: duration = rm.timingCfg.Start case pb.ColorGameStatus_CGS_Betting: duration = rm.timingCfg.Betting case pb.ColorGameStatus_CGS_BetEnd: duration = rm.timingCfg.EndBetting case pb.ColorGameStatus_CGS_OpenThreeDice: duration = rm.timingCfg.OpenThreeDice case pb.ColorGameStatus_CGS_Settle: duration = rm.timingCfg.Settle } return rm.statusTime + duration } // 游戏开始前更新配置 func (rm *ColorRoom) updateConfig() { colorConfig := config.GetColorConfig() rm.timingCfg = colorConfig.GameTiming for _, cfg := range colorConfig.Rooms { if rm.RoomType() == cfg.RoomType { rm.roomCfg = cfg break } } } // 游戏开始时展示每个区域的默认赔率 func (rm *ColorRoom) initEndBetAreaMul() { rm.endBetAreaMul = rm.endBetAreaMul[0:0] for pos := 0; pos < len(pb.ColorBetArea_name); pos++ { prizeArea := pb.ColorPrizeArea_CPA_Single_0 var mul = rm.roomCfg.WinSingleColorMul[0] switch pos / 6 { case 1: prizeArea = pb.ColorPrizeArea_CPA_Double mul = rm.roomCfg.WinDoubleColorMul case 2: prizeArea = pb.ColorPrizeArea_CPA_Three mul = rm.roomCfg.WinThreeColorMul } rm.endBetAreaMul = append(rm.endBetAreaMul, &pb.ColorBetAreaMul{ Area: pb.ColorBetArea(pos), PrizeArea: prizeArea, PrizeType: pb.ColorPrizeType_CPT_Normal, Mul: mul[0].Mul / config.Hundred, }) } } // 随机出某个奖励档位下的赔率数组,档位,赔率数组概率之和 func (rm *ColorRoom) randArrMul(area pb.ColorBetArea) (arrMul []*game.ColorMulRate, prizeArea pb.ColorPrizeArea, sumRate int) { switch area / 6 { case 0: maxWeight := 0 for _, w := range rm.roomCfg.WinSingleColorWeight { maxWeight += w } weight := xrand.RandRange[int](0, maxWeight) for pos, w := range rm.roomCfg.WinSingleColorWeight { if weight < w { prizeArea = pb.ColorPrizeArea(pos) arrMul = rm.roomCfg.WinSingleColorMul[pos] break } weight -= w } case 1: prizeArea = pb.ColorPrizeArea_CPA_Double arrMul = rm.roomCfg.WinDoubleColorMul case 2: prizeArea = pb.ColorPrizeArea_CPA_Three arrMul = rm.roomCfg.WinThreeColorMul default: log.Error("area:%v is not exist") return } for _, mr := range arrMul { sumRate += mr.Rate } return } // 下注结束后,更新每个区域的实际赔率 func (rm *ColorRoom) updateEndBetAreaMul() { jackpotExist := false for pos := range pb.ColorBetArea_name { bam := rm.endBetAreaMul[pos] arrMul, prizeArea, sumRate := rm.randArrMul(pb.ColorBetArea(pos)) bam.PrizeArea = prizeArea bam.PrizeType = pb.ColorPrizeType_CPT_Normal if prizeArea == pb.ColorPrizeArea_CPA_Single_2 { // 在单色区域 命中三同色爆奖之后 再随jackpot概率 // 只会有一个区域有jackpot标签 if !jackpotExist && xrand.RandRange(0, config.RateBase) < rm.roomCfg.JackpotRate { bam.Mul = 0 bam.PrizeType = pb.ColorPrizeType_CPT_Jackpot jackpotExist = true continue } } mulPos := 0 rd := xrand.RandRange[int](0, sumRate) for i, mr := range arrMul { if rd < mr.Rate { mulPos = i } rd -= mr.Rate } // 赔率数组里第一个是基础赔率,后面的都是爆奖赔率 if mulPos > 0 { bam.PrizeType = pb.ColorPrizeType_CPT_Big } bam.Mul = arrMul[mulPos].Mul / config.Hundred log.Debug(rm.Log("区域:%v 显示赔率:%v 奖励类型:%v 奖励档位:%v", bam.Area, bam.Mul, bam.PrizeType, bam.PrizeArea)) } } // 获取三个骰子指定颜色中了几个 func (rm *ColorRoom) getDiceColorCount(color []pb.ColorType, c pb.ColorType) (count int) { for _, colorType := range color { if colorType == c { count++ } } return } // 获取投注区域的颜色 func (rm *ColorRoom) getAreaColor(area pb.ColorBetArea) (color pb.ColorType) { switch area { case pb.ColorBetArea_CBA_Yellow, pb.ColorBetArea_CBA_Yellow2, pb.ColorBetArea_CBA_Yellow3: return pb.ColorType_CT_Yellow case pb.ColorBetArea_CBA_White, pb.ColorBetArea_CBA_White2, pb.ColorBetArea_CBA_White3: return pb.ColorType_CT_White case pb.ColorBetArea_CBA_Pink, pb.ColorBetArea_CBA_Pink2, pb.ColorBetArea_CBA_Pink3: return pb.ColorType_CT_Pink case pb.ColorBetArea_CBA_Blue, pb.ColorBetArea_CBA_Blue2, pb.ColorBetArea_CBA_Blue3: return pb.ColorType_CT_Blue case pb.ColorBetArea_CBA_Red, pb.ColorBetArea_CBA_Red2, pb.ColorBetArea_CBA_Red3: return pb.ColorType_CT_Red case pb.ColorBetArea_CBA_Green, pb.ColorBetArea_CBA_Green2, pb.ColorBetArea_CBA_Green3: return pb.ColorType_CT_Green } return } // 获取某个区域的实际中奖赔率 func (rm *ColorRoom) getAreaMul(area pb.ColorBetArea, prizeArea pb.ColorPrizeArea) (mul int64, prizeType pb.ColorPrizeType) { bam := rm.endBetAreaMul[area] // 奖励档位一样,比如单黄投注区域,显示双色爆奖,赔率为9。此时开出双黄色,则该投注区域赔率为9。 // 如果开出三黄色,则赔率为CPA_Single_2的赔率组里的第1个赔率(基础赔率) // 如果开出单黄色,则赔率为CPA_Single_0的赔率组里的第1个赔率(基础赔率) if bam.PrizeArea == prizeArea { mul = bam.Mul prizeType = bam.PrizeType } else { arr2Mul := make([][]*game.ColorMulRate, 0) arr2Mul = append(arr2Mul, rm.roomCfg.WinSingleColorMul...) arr2Mul = append(arr2Mul, rm.roomCfg.WinDoubleColorMul) arr2Mul = append(arr2Mul, rm.roomCfg.WinThreeColorMul) mul = arr2Mul[prizeArea][0].Mul prizeType = pb.ColorPrizeType_CPT_Normal } return } // 检查投掷结果是否匹配某个下注区域 func (rm *ColorRoom) isWinInArea(color []pb.ColorType, area pb.ColorBetArea) (win bool, prizeArea pb.ColorPrizeArea) { colorCount := rm.getDiceColorCount(color, rm.getAreaColor(area)) if colorCount == 0 { return false, 0 } // 单色投注区,查看开出几个该颜色 if area < pb.ColorBetArea_CBA_Yellow2 { if colorCount == 1 { return true, pb.ColorPrizeArea_CPA_Single_0 } else if colorCount == 2 { return true, pb.ColorPrizeArea_CPA_Single_1 } else { return true, pb.ColorPrizeArea_CPA_Single_2 } } else if area < pb.ColorBetArea_CBA_Yellow3 { if colorCount > 1 { return true, pb.ColorPrizeArea_CPA_Double } } else { if colorCount > 2 { return true, pb.ColorPrizeArea_CPA_Three } } return false, 0 } // 开3个骰子,并计算出赢钱区域及实际赔率 func (rm *ColorRoom) openDices() { for i := 0; i < 3; i++ { c := xrand.RandRange(int(pb.ColorType_CT_Yellow), int(pb.ColorType_CT_Green)) rm.ntfOpenThreeDice.Color = append(rm.ntfOpenThreeDice.Color, pb.ColorType(c)) } rm.ntfOpenThreeDice.AniRouteIndex = 0 for _, area := range rm.endBetAreaMul { isWin, prizeArea := rm.isWinInArea(rm.ntfOpenThreeDice.Color, area.Area) mul, prizeType := rm.getAreaMul(area.Area, prizeArea) if !isWin { continue } rm.winBetAreaMul = append(rm.winBetAreaMul, &pb.ColorBetAreaMul{ Area: area.Area, PrizeArea: prizeArea, PrizeType: prizeType, Mul: mul, }) rm.ntfOpenThreeDice.WinArea = append(rm.ntfOpenThreeDice.WinArea, area.Area) } } // 计算 下注区域中奖得分,返回是否有jp奖,jp奖位置,中奖人数 func (rm *ColorRoom) CalculateJackpotScore() (pb.ColorBetArea, map[int64]int64) { jackpotArea := pb.ColorBetArea(-1) for _, winArea := range rm.winBetAreaMul { if winArea.PrizeType != pb.ColorPrizeType_CPT_Jackpot { continue } for _, user := range rm.users { if user.totalBets[winArea.Area] < 1 { continue } rm.jackpotMgr.AddJpUser(user.ID, user.totalBets[winArea.Area]) } } rm.jackpotUser, rm.jackpotValue = rm.jackpotMgr.WinJackpot() log.Debug(rm.Log("本局是否中jackpot奖:%v, 玩家一起分走jackpot:%v, 当前jackpot值:%v", rm.jackpotValue > 0, rm.jackpotValue, rm.jackpotMgr.GetJackpot())) return jackpotArea, rm.jackpotUser } // 计算 所有玩家的下注区域中奖得分 func (rm *ColorRoom) CalculateAllUserScore() { // 赢钱会清空jackpot池 jpArea, userJackPot := rm.CalculateJackpotScore() var jackpotUserName []string for _, user := range rm.users { if user.totalBet > 0 { // 算分 jpScore := userJackPot[user.ID] rm.CalculateUserScore(user, jpArea, jpScore) if jpScore > 0 { jackpotUserName = append(jackpotUserName, user.Nickname) //rm.BroadHitJackpot(user, jpScore) } } } } // 计算 下注区域中奖得分 func (rm *ColorRoom) CalculateUserScore(user *ColorPlayer, jpArea pb.ColorBetArea, jpScore int64) { msg := user.settleMsg for _, winArea := range rm.winBetAreaMul { win2 := int64(0) // 税前 gold := int64(0) // 税后 if user.totalBets[winArea.Area] <= 0 { continue } if jpArea != winArea.Area { odds := winArea.Mul // 奖金计算公式 Payouts =( Odds * Bet ) * ( 1 + Bonus) + Bet odds 是倍率 Bonus是猜中幸运骰子 的加成 // 本区域赢未扣税 倍率是百分值所以计算时要除以100 win2 = (odds * user.totalBets[winArea.Area]) / 100 // 本区域赢扣税 gold = win2 * (100 - rm.roomCfg.Rate) / 100 // 算税() msg.Tax += win2 - gold // 加回投注本金 gold += user.totalBets[winArea.Area] msg.TotalWin += gold // 统计赢区的下注总额 msg.TotalWinBaseBet += user.totalBets[winArea.Area] log.Debug(rm.UserLog(user.ID, "算分 odds:%v 投注区:%v 税前:%v 税后+本金:%v", odds, winArea.Area, win2, gold)) } else { win2 = jpScore // 本区域赢扣税 gold = jpScore * (100 - rm.roomCfg.Rate) / 100 // 算税() msg.Tax += win2 - gold // 加回投注本金 gold += user.totalBets[winArea.Area] msg.TotalWin += gold // 统计赢区的下注总额 msg.TotalWinBaseBet += user.totalBets[winArea.Area] log.Debug(rm.UserLog(user.ID, "算分 jackpotValue 投注区:%v win2:%v Gold:%v", winArea.Area, win2, gold)) } msg.UserAreaWin = append(msg.UserAreaWin, &pb.NtfColorSettle_UserBetAreaMul{ AreaMul: &pb.ColorBetAreaMul{ Area: winArea.Area, PrizeType: winArea.PrizeType, PrizeArea: winArea.PrizeArea, Mul: winArea.Mul, }, Bet: user.totalBets[winArea.Area], Win: win2, RealWin: gold, }) } } // 和平台做结算 func (rm *ColorRoom) settle() { //var allWinner []*pb.ColorPinoyLiveBigWinner rm.CalculateAllUserScore() wg := new(sync.WaitGroup) for _, user := range rm.users { wg.Add(1) ksync.GoSafe(func() { defer wg.Done() if user.totalBet > 0 { // 和平台做赢钱结算 //_, err := rm.TransInoutGameEnd(u, 0, u.SettleMsg.TotalWin, u.SettleMsg.Tax) //if err != nil { // log.Error(rm.Log(err.Error())) //} } }, nil) } wg.Wait() //// 异步加钱完成后再执行后续的结算操作 //rm.Traverse(func(u *model.User) bool { // msg := u.SettleMsg // if msg == nil || msg.TotalWin < 1 { // return true // } // winner := &pb.ColorPinoyLiveBigWinner{ // NickName: u.UserInetr.GetNike(), // Avatar: u.UserInetr.GetHead(), // WinChips: msg.TotalWin, // AreaId: msg.UserRealWins, // } // allWinner = append(allWinner, winner) // log.Debug(rm.LogEx(u, "赢钱:%v", winner.WinChips)) // return true //}) //// 更新大客户 //rm.updateBigWinner(allWinner) //// 更新路途 //rm.SetGameTrend() } // // import ( // "encoding/json" // "fmt" // "game/common/proto/pb" // "github.com/fox/fox/ipb" // "github.com/fox/fox/log" // "sort" // "sync" // "time" // ) // // func (rm *ColorRoom) SceneUserSitDown(user *model.User) { // _ = user // rm.SendOnlinePlayerNum() // } // // // CheckAndBet 检查并下注 // func (rm *ColorRoom) CheckAndBet(user *model.User, bets []*pb.ColorPinoyLiveBetReq) { // if len(bets) == 0 { // log.Error(rm.Log("玩家(%d) bets data err :%v ", bets)) // model.SendBetFailMessage(model.DataErr, user) // return // } // // betInfos := [config.BET_TYPE_NUM]int64{} // betCountInfos := [config.BET_TYPE_NUM]int64{} // totalBetAmount := int64(0) // oneBetMessage := &pb.ColorPinoyLiveS2CRepetBet{} // oneBetMessage.Uid = user.UserID // oneBetMessage.BetInfo = []*pb.ColorPinoyLiveBetSuccessMessage{} // // if rm.GetGameStatus() != pb.ColorPinoyLiveGameStatus_ColorPinoyLiveBetStatus { // log.Error(rm.Log("玩家(%d) UndoBet data err GetGameStatus:%v,LastTimeBet:%v ", user.UserID, rm.GetGameStatus(), user.LastTimeBet)) // model.SendBetFailMessage(model.StatusError, user) // return // } // // for _, bet := range bets { // // 判断下注下标和下注区域下标是否超出列表 // if _, ok := pb.ColorPinoyLiveBetTypeJP_name[int32(bet.BetType)]; !ok || // bet.BetLevel < 0 || bet.BetLevel >= int32(len(rm.RoomCfg.ColorPinoyLiveConfig.BetList)) || // bet.BetIndex < 0 || bet.BetIndex >= int32(len(rm.RoomCfg.ColorPinoyLiveConfig.BetList[bet.BetLevel])) { // log.Error(rm.Log("玩家(%d) bets data err BetLevel:%d BetIndex:%d ", bet.BetLevel, bet.BetIndex)) // model.SendBetFailMessage(model.DataErr, user) // return // } // // 下注总金额 // betAmountCount := rm.RoomCfg.ColorPinoyLiveConfig.BetList[bet.BetLevel][bet.BetIndex] // bet.BetAmount = betAmountCount // // if betAmountCount > user.Balance-totalBetAmount { // log.Debug(rm.Log("用户余额为:%v 总押注%d 押注%d", user.Balance, totalBetAmount, betAmountCount)) // model.SendBetFailMessage(model.ScoreLess, user) // return // } else { // totalBetAmount += betAmountCount // betInfos[bet.BetType%config.BET_TYPE_NUM] += betAmountCount // betCountInfos[bet.BetType%config.BET_TYPE_NUM] += 1 // } // } // // if totalBetAmount <= 0 || totalBetAmount+user.totalBet > rm.RoomCfg.ColorPinoyLiveConfig.TotalBetLimit { // log.Error(rm.Log("DataErr totalBetAmount:%d err ", totalBetAmount)) // model.SendBetFailMessage(model.PlayerEarTopScore, user) // return // } // log.Debug(rm.LogEx(user, "下注区域最大金额:%v", rm.Cfg.AreaBetLimit)) // for i, num := range betInfos { // // 投注大于下注区域限制 // if (user.totalBets[i] + num) > rm.Cfg.AreaBetLimit { // // log.Debug("PlayerEarTopScore totalBetAmount:%d err ", totalBetAmount) // model.SendBetFailMessage(model.PlayerEarTopScore, user) // return // } // } // // user.AddBalance(-totalBetAmount) // // if user.LastTimeBet == nil { // user.LastTimeBet = make([][]*pb.ColorPinoyLiveBetReq, 0) // } // user.LastTimeBet = append(user.LastTimeBet, bets) // user.totalBet += totalBetAmount // // log.Debug("上次下注:", user.LastTimeBet) // rm.MutexData.Lock() // for i, num := range betInfos { // if num > 0 { // user.totalBets[i] += num // rm.totalBets[i] += num // // SendSuccessMessage := new(pb.ColorPinoyLiveBetSuccessMessage) // SendSuccessMessage.BetType = pb.ColorPinoyLiveBetTypeJP(i) // SendSuccessMessage.UserBet = num // SendSuccessMessage.UserBets = user.totalBets[i] + num // SendSuccessMessage.totalBets = rm.totalBets[i] + num // oneBetMessage.BetInfo = append(oneBetMessage.BetInfo, SendSuccessMessage) // } // } // // 统计个区域投注次数 // // user.TotalBetsCount = make([]int64, config.BET_TYPE_NUM) // for i, count := range betCountInfos { // if count > 0 { // user.TotalBetsCount[i] += count // } // } // user.AllBet += totalBetAmount // user.NoBetCount = 0 // oneBetMessage.UserScore = user.Balance // // oneBetMessage.UserBets = user.totalBets[:] // // rm.totalBet += totalBetAmount // rm.MutexData.Unlock() // // rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameSeatUserBet), oneBetMessage) // live.PushColorBet(&lws.CPLBet{ // Uid: user.UserID, // Nickname: user.UserInetr.GetNike(), // Bet: totalBetAmount, // Avatar: user.UserInetr.GetHead(), // }) // } // // func (rm *ColorRoom) UndoBet(user *model.User, undoType pb.ColorPinoyLiveUndoType) { // // betInfos := [config.BET_TYPE_NUM]int64{} // betCountInfos := [config.BET_TYPE_NUM]int64{} // totalBetAmount := int64(0) // undoBetMessage := &pb.S2CUndoBet{} // undoBetMessage.Uid = user.UserID // undoBetMessage.BetInfo = []*pb.ColorPinoyLiveBetSuccessMessage{} // undoBetMessage.UndoType = undoType // // if rm.GetGameStatus() != pb.ColorPinoyLiveGameStatus_ColorPinoyLiveBetStatus { // log.Error(rm.Log("玩家(%d) UndoBet data err GetGameStatus:%v,LastTimeBet:%v ", user.UserID, rm.GetGameStatus(), user.LastTimeBet)) // model.SendBetFailMessage(model.StatusError, user) // return // } // if len(user.LastTimeBet) == 0 { // log.Error(rm.Log("玩家(%d) LastTimeBet null err:%v ", user.UserID, user.LastTimeBet)) // model.SendBetFailMessage(model.LastBetNull, user) // return // } // var bets []*pb.ColorPinoyLiveBetReq // if undoType == pb.ColorPinoyLiveUndoType_ColorPinoyLiveUndoOne { // bets = user.LastTimeBet[len(user.LastTimeBet)-1] // } else if undoType == pb.ColorPinoyLiveUndoType_ColorPinoyLiveUndoAll { // for _, bet := range user.LastTimeBet { // bets = append(bets, bet...) // } // } else { // log.Error(rm.Log("玩家(%d) undoType err %v,", user.UserID, undoType)) // model.SendBetFailMessage(model.DataErr, user) // return // } // if len(bets) == 0 { // log.Error(rm.Log("玩家(%d) bets err %v,", user.UserID, bets)) // model.SendBetFailMessage(model.LastBetNull, user) // return // } // for _, bet := range bets { // // 判断下注下标和下注区域下标是否超出列表 // if _, ok := pb.ColorPinoyLiveBetTypeJP_name[int32(bet.BetType)]; !ok { // log.Error(rm.Log("玩家(%d) bet err %v,", bet)) // model.SendBetFailMessage(model.DataErr, user) // return // } // totalBetAmount += bet.BetAmount // betInfos[bet.BetType%config.BET_TYPE_NUM] += bet.BetAmount // betCountInfos[bet.BetType%config.BET_TYPE_NUM] += 1 // } // // if totalBetAmount > 0 { // user.AddBalance(totalBetAmount) // } // // if user.LastTimeBet != nil && len(user.LastTimeBet) > 0 { // if undoType == pb.ColorPinoyLiveUndoType_ColorPinoyLiveUndoOne { // user.LastTimeBet = user.LastTimeBet[:len(user.LastTimeBet)-1] // } else { // user.LastTimeBet = nil // } // } // // rm.MutexData.Lock() // for i, num := range betInfos { // user.totalBets[i] -= num // rm.totalBets[i] -= num // } // // 统计个区域投注次数 // for i, count := range betCountInfos { // if count > 0 { // user.TotalBetsCount[i] -= count // } // if user.TotalBetsCount[i] < 0 { // user.TotalBetsCount[i] = 0 // } // } // rm.totalBet -= totalBetAmount // // user.totalBet -= totalBetAmount // user.AllBet -= totalBetAmount // user.NoBetCount = 0 // // for i, num := range betInfos { // // SendSuccessMessage := new(pb.ColorPinoyLiveBetSuccessMessage) // SendSuccessMessage.SeatId = int32(user.SceneChairId) // SendSuccessMessage.BetType = pb.ColorPinoyLiveBetTypeJP(i) // SendSuccessMessage.UserBet = num // SendSuccessMessage.UserBets = user.totalBets[i] // SendSuccessMessage.totalBets = rm.totalBets[i] // // undoBetMessage.BetInfo = append(undoBetMessage.BetInfo, SendSuccessMessage) // } // rm.MutexData.Unlock() // // 玩家当前分数 // undoBetMessage.UserScore = user.Balance // // // log.Debug("undoBetMessage %v", undoBetMessage) // rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeUndoBet), undoBetMessage) // // } // func (rm *ColorRoom) KickOutUser(u *model.User) { // // delete(rm.AllUserList, k) // rm.DeletePlayer(u.UserID) // if u.SceneChairId != 0 { // rm.OnUserStanUp(u) // } // role := "机器人" // // rm.DeleteExitUserFromOnlineUserListSlice(u) // if !u.IsRobot { // rm.Table.KickOut(u.UserInetr) // role = "玩家" // } // log.Debug(rm.Log("删除(%s)(%d) 金额:%d 输赢:%d", role, u.UserID, u.Balance, u.Balance-u.UserInetr.GetScore())) // rm.SendOnlinePlayerNum() // } // func (rm *ColorRoom) TransInoutGameBet(user *model.User, bet int64) error { // if config.CHIPS_DEBUG { // user.Balance -= bet // return nil // } // user.Mn.Lock() // defer user.Mn.Unlock() // transferInOutResp, err := rm.Table.TransInoutGameCarryAdd(user.UserInetr, rm.Table.GetLevel(), bet, "") // if err != nil { // return err // } // user.Balance = transferInOutResp.Balance // user.Carry = transferInOutResp.Carry // user.UserInetr.SetPreserve(transferInOutResp.Preserve) // // time.Sleep(10 * time.Second) // return nil // } // func (rm *ColorRoom) TransInoutGameEnd(user *model.User, bet int64, amountWin int64, tax int64) (int64, error) { // if config.CHIPS_DEBUG || user.IsRobot { // user.Balance += amountWin // return amountWin, nil // } // transferInOutResp, err := rm.Table.TransInoutGameEnd(user.UserInetr, rm.Table.GetLevel(), bet+tax, amountWin+tax, "") // if err != nil { // return 0, err // } // user.Balance = transferInOutResp.GetBalance() // if transferInOutResp.GetRealTransfer() == 0 { // return 0, errors.New("error") // } // user.TransBet += bet // user.TransWin += amountWin // // time.Sleep(10 * time.Second) // return transferInOutResp.RealTransfer, nil // } // // func (rm *ColorRoom) ResetUserBet(user *model.User) { // rm.MutexData.Lock() // for i, bet := range user.totalBets { // rm.totalBets[i] -= bet // // rm.BetNumber[i] -= user.BetNumber[i] // } // rm.totalBet -= user.totalBet // rm.MutexData.Unlock() // user.totalBet = 0 // user.totalBets = [config.BET_TYPE_NUM]int64{} // // user.BetNumber = [config.BET_TYPE_NUM]int64{} // // } // // func (rm *ColorRoom) StartTransInoutBet() { // wg := new(sync.WaitGroup) // var failUser []*model.User // failMutx := &sync.Mutex{} // rm.Traverse(func(u *model.User) bool { // wg.Add(1) // go func(user *model.User) { // defer wg.Done() // user.Mn.Lock() // defer user.Mn.Unlock() // if user.totalBet > 0 { // _, err := rm.TransInoutGameEnd(user, user.totalBet, 0, 0) // if err != nil { // func() { // failMutx.Lock() // defer failMutx.Unlock() // failUser = append(failUser, user) // }() // } // } // }(u) // return true // }) // wg.Wait() // // 异步扣款完成后,处理部分扣款失败回滚操作 // if len(failUser) > 0 { // pbMsg := &pb.ColorPinoyLiveS2CBetEndFailResult{ // Code: 1, // } // for _, user := range failUser { // rm.ResetUserBet(user) // player := &pb.ColorPinoyLiveS2CRepetBet{} // player.UserScore = user.Balance // player.Uid = user.UserID // // var bets []*pb.ColorPinoyLiveBetReq // for _, bet := range user.LastTimeBet { // bets = append(bets, bet...) // } // for _, bet := range bets { // // 判断下注下标和下注区域下标是否超出列表 // if _, ok := pb.ColorPinoyLiveBetTypeJP_name[int32(bet.BetType)]; !ok { // log.Error(rm.Log("玩家(%d) bet err %v,", bet)) // model.SendBetFailMessage(model.DataErr, user) // return // } // SendSuccessMessage := new(pb.ColorPinoyLiveBetSuccessMessage) // SendSuccessMessage.BetIndex = bet.BetIndex // SendSuccessMessage.BetLevel = bet.BetLevel // SendSuccessMessage.BetType = bet.BetType // SendSuccessMessage.SeatId = int32(user.SceneChairId) // SendSuccessMessage.UserBet = bet.BetAmount // SendSuccessMessage.totalBets = rm.totalBets[bet.BetType] // // player.BetInfo = append(player.BetInfo, SendSuccessMessage) // } // pbMsg.Players = append(pbMsg.Players, player) // } // // log.Debug("玩家停止下注后 扣钱失败: %v", pbMsg) // rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticePlayerBetEndResultFailed), pbMsg) // } // // 大客投注 // var allWinner []*pb.ColorPinoyLiveBigWinner // rm.Traverse(func(user *model.User) bool { // if user.totalBet > 0 { // allWinner = append(allWinner, &pb.ColorPinoyLiveBigWinner{NickName: user.UserInetr.GetNike(), Avatar: user.UserInetr.GetHead(), WinChips: user.totalBet, AreaId: user.totalBets[:]}) // } // return true // }) // rm.updateBigWinner(allWinner) // bigMsg := &pb.ColorPinoyLivePlayerBigWinner{BigBet: allWinner, Jackpot: rm.jackpotMgr.GetJackpot()} // rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameBigWinner), bigMsg) // // rm.TimerJob, _ = rm.Table.AddTimer(time.Duration(rm.RoomCfg.TimeConf.Endmove), func() { // rm.NotifyBigBetAreaMul() // }) // allUserTotalBet := int64(0) // 所有玩家投注未中奖的总金额,用于计算jackpot池 // rm.Traverse(func(user *model.User) bool { // if user.totalBet < 1 { // return true // } // allUserTotalBet += user.totalBet // return true // }) // log.Debug(rm.Log("本局总投注金额为:%v 赎回比例:%v 追加比例:%v 满额追加比例:%v", allUserTotalBet, rm.Cfg.JpXRate, rm.Cfg.JpYRate, rm.Cfg.JpXYRate)) // rm.jackpotX, rm.jackpotY = rm.jackpotMgr.AddJp(allUserTotalBet, int64(rm.Cfg.JpXRate), int64(rm.Cfg.JpYRate), int64(rm.Cfg.JpXYRate)) // if rm.jackpotX > 0 || rm.jackpotY > 0 { // rm.kafkaJackpotUserRepaid(rm.jackpotX, rm.jackpotY) // } // } // // // 计算 下注区域中奖得分,返回是否有jp奖,jp奖位置,中奖人数 // func (rm *ColorRoom) CalculateJackpotScore() (pb.ColorPinoyLiveBetTypeJP, map[int64]int64) { // jackpotArea := pb.ColorPinoyLiveBetTypeJP(-1) // for _, winArea := range rm.PokerMsg.WinBetArea { // if !winArea.IsJackpot || !winArea.IsWin { // continue // } // color := getColorByBetArea(winArea.BetArea) // colorCount := getColorCount(rm.NormalDices, color) // if colorCount != 3 { // continue // } // jackpotArea = winArea.BetArea // rm.Traverse(func(user *model.User) bool { // if user.totalBets[winArea.BetArea] <= 0 { // return true // } // rm.jackpotMgr.AddJpUser(user.UserID, user.totalBets[winArea.BetArea]) // return true // }) // } // rm.jackpotUser, rm.costJackpot = rm.jackpotMgr.WinJackpot() // if rm.costJackpot > 0 { // rm.kafkaHitJackpot(rm.costJackpot, rm.jackpotUser) // } // log.Debug(rm.Log("本局是否中jackpot奖:%v, 玩家一起分走jackpot:%v, 当前jackpot值:%v", rm.costJackpot > 0, rm.costJackpot, rm.jackpotMgr.GetJackpot())) // return jackpotArea, rm.jackpotUser // } // // // 计算 所有玩家的下注区域中奖得分 // func (rm *ColorRoom) CalculateAllUserScore() { // // 赢钱会清空jackpot池 // jpArea, userJackPot := rm.CalculateJackpotScore() // var jackpotUserName []string // rm.Traverse(func(user *model.User) bool { // msg := new(pb.ColorPinoyLiveUserSettleMsg) // msg.WinAreaOdd = rm.PokerMsg.WinBetArea // msg.UserBets = rm.CopyArr(user.totalBets) // msg.UserRealWins = make([]int64, config.BET_TYPE_NUM) // msg.UserWins = make([]int64, config.BET_TYPE_NUM) // // if user.totalBet > 0 { // // 算分 // jpScore := userJackPot[user.UserID] // rm.CalculateUserScore(user, jpArea, jpScore, msg) // if jpScore > 0 { // jackpotUserName = append(jackpotUserName, user.UserInetr.GetNike()) // rm.BroadHitJackpot(user, jpScore) // } // } // // 统计玩家信息 // if msg.TotalWin > user.totalBet { // user.UserCount(true, msg.TotalWin) // } else { // user.UserCount(false, 0) // } // user.Balance += msg.TotalWin // msg.UserScore = user.Balance // user.SettleMsg = msg // return true // }) // rm.Traverse(func(user *model.User) bool { // user.SettleMsg.JackpotUserName = jackpotUserName // return true // }) // } // // // 计算 下注区域中奖得分 // func (rm *ColorRoom) CalculateUserScore(user *model.User, jpArea pb.ColorPinoyLiveBetTypeJP, jpScore int64, msg *pb.ColorPinoyLiveUserSettleMsg) { // for _, winArea := range msg.WinAreaOdd { // if msg.UserBets[winArea.BetArea] <= 0 { // continue // } // if jpArea != winArea.BetArea { // odds := winArea.Odd // // 奖金计算公式 Payouts =( Odds * Bet ) * ( 1 + Bonus) + Bet odds 是倍率 Bonus是猜中幸运骰子 的加成 // // 本区域赢未扣税 倍率是百分值所以计算时要除以100 // win2 := (odds * msg.UserBets[winArea.BetArea]) / 100 // // 本区域赢扣税 // Gold := win2 * (100 - rm.RoomCfg.Rate) / 100 // // 算税() // msg.Tax += win2 - Gold // // 加回投注本金 // Gold += msg.UserBets[winArea.BetArea] // msg.TotalWin += Gold // // 统计赢区的下注总额 // msg.TotalWinBaseBet += msg.UserBets[winArea.BetArea] // // msg.UserWins[winArea.BetArea] += win2 // msg.UserRealWins[winArea.BetArea] += Gold // log.Debug(rm.LogEx(user, "算分 odds:%v 投注区:%v win2:%v Gold:%v", odds, winArea.BetArea, win2, Gold)) // } else { // win2 := jpScore // // 本区域赢扣税 // Gold := jpScore * (100 - rm.RoomCfg.Rate) / 100 // // 算税() // msg.Tax += win2 - Gold // // 加回投注本金 // Gold += msg.UserBets[winArea.BetArea] // msg.TotalWin += Gold // // 统计赢区的下注总额 // msg.TotalWinBaseBet += msg.UserBets[winArea.BetArea] // // msg.UserWins[winArea.BetArea] += win2 // msg.UserRealWins[winArea.BetArea] += Gold // msg.JackpotWin = Gold // log.Debug(rm.LogEx(user, "算分 jackpotValue 投注区:%v win2:%v Gold:%v", winArea.BetArea, win2, Gold)) // } // } // // } // // type areaWin struct { // areaId int64 // win int64 // } // // // 更新大赢家 // func (rm *ColorRoom) updateBigWinner(allWinner []*pb.ColorPinoyLiveBigWinner) { // // log.Debug(fmt.Sprintf("allWinner:%+v", allWinner)) // rm.BigWinner = rm.BigWinner[:0] // sort.Slice(allWinner, func(i, j int) bool { // return allWinner[i].WinChips > allWinner[j].WinChips // }) // if len(allWinner) > BigWinnerCount { // allWinner = allWinner[:BigWinnerCount] // } // for _, winner := range allWinner { // var areaWins []*areaWin // for areaId, win := range winner.AreaId { // if win > 0 { // areaWins = append(areaWins, &areaWin{areaId: int64(areaId), win: win}) // } // } // sort.Slice(areaWins, func(i, j int) bool { // return areaWins[i].win > areaWins[j].win // }) // if len(areaWins) > BigWinnerCount { // areaWins = areaWins[:BigWinnerCount] // } // winner.AreaId = make([]int64, 0, BigWinnerCount) // for _, area := range areaWins { // winner.AreaId = append(winner.AreaId, area.areaId) // } // } // rm.BigWinner = allWinner // } // // // 和平台做结算 // func (rm *ColorRoom) SetUserSettleMsg() { // var allWinner []*pb.ColorPinoyLiveBigWinner // rm.CalculateAllUserScore() // wg := new(sync.WaitGroup) // rm.Traverse(func(uu *model.User) bool { // wg.Add(1) // go func(u *model.User) { // defer wg.Done() // if u.totalBet > 0 { // // 和平台做赢钱结算 // // if msg.TotalWin > 0 { // _, err := rm.TransInoutGameEnd(u, 0, u.SettleMsg.TotalWin, u.SettleMsg.Tax) // if err != nil { // log.Error(rm.Log(err.Error())) // // model.SendBetFailMessage(model.BalanceError, u) // } // // } // } // }(uu) // return true // }) // wg.Wait() // // 异步加钱完成后再执行后续的结算操作 // rm.Traverse(func(u *model.User) bool { // msg := u.SettleMsg // if msg == nil || msg.TotalWin < 1 { // return true // } // winner := &pb.ColorPinoyLiveBigWinner{ // NickName: u.UserInetr.GetNike(), // Avatar: u.UserInetr.GetHead(), // WinChips: msg.TotalWin, // AreaId: msg.UserRealWins, // } // allWinner = append(allWinner, winner) // log.Debug(rm.LogEx(u, "赢钱:%v", winner.WinChips)) // return true // }) // rm.updateBigWinner(allWinner) // // rm.SetGameTrend() // rm.sendSettleMsg2Client() // // log.Debug(time.Now().Unix() - rm.endAt) // rm.Table.EndGame() // rm.NotifyLiveDelayUpdate() // 通知延迟更新服务器配置,切换维护状态 // rm.TimerJob, _ = rm.Table.AddTimer(time.Duration(rm.RoomCfg.TimeConf.Endpay), func() { // rm.Rank() // }) // } // // func (rm *ColorRoom) CountUser(u *model.User) { // u.Icon = 0 // // rm.OnlineUserList = append(rm.OnlineUserList, u) // } // func (rm *ColorRoom) ResetData(all bool) { // rm.totalBets = [config.BET_TYPE_NUM]int64{} // rm.totalBet = 0 // rm.LuckyDice = 0 // rm.NormalDices = make([]byte, 3) // rm.StartDices = make([]byte, 3) // rm.ResultImgs = make([]string, 0) // rm.InitBigOddsBetAreas() // // if all { // rm.LiveMgr.Reset() // rm.Traverse(func(u *model.User) bool { // u.ResetUserData() // u.RetrunGold = 0 // return true // }) // } // } // func (rm *ColorRoom) GetPairDice(count int, startIndex int, endIndex int) []byte { // if gconfig.GConfig.IsProd() { // return nil // } // // PokerCard 表示一张扑克牌 // type Dice struct { // Color int // 花色 // Point int // 点数 // } // type PairDice struct { // Cards []Dice // } // key := fmt.Sprintf("preset-cards:0:color:%d", rm.Table.GetId()) // log.Debug(rm.Log("获取配牌配置 key:", key)) // str := redisf.RSC.GetPairCard(key) // if str == "" { // return nil // } // pairCard := new(PairDice) // err := json.Unmarshal([]byte(str), pairCard) // if err != nil { // log.Debug(rm.Log("getPairCard:%v", err)) // return nil // } // if len(pairCard.Cards) < 2 { // log.Error(rm.Log("getPairCard ", pairCard)) // return nil // } // log.Debug(rm.Log("getPairCard pairCard:%v", pairCard)) // var res []byte // for index, card := range pairCard.Cards { // if index >= startIndex && index < endIndex { // res = append(res, byte(card.Point)) // if (len(res)) == count { // break // } // } // } // return res // } // // func (rm *ColorRoom) GetGameTrend() (luckyRates []int32) { // // var mapLuckyRate = map[pb.ColorPinoyLiveDiceColorType]int32{} // // for _, trend := range rm.GameTrend.ListTrendGroup { // // mapLuckyRate[trend.LuckyDice]++ // // } // // for i := pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_YELLOW; i <= pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_GREEN; i++ { // // luckyRates = append(luckyRates, 0) // // } // // if len(mapLuckyRate) > 0 { // // for k, v := range mapLuckyRate { // // // log.Debug(fmt.Sprintf("颜色:%v 数量:%v 总数量:%v 配置:%v", k, v, len(rm.GameTrend.ListTrendGroup), config.WinTrendNum)) // // if int(k-1) < len(luckyRates) { // // luckyRates[k-1] = v * 10000 / int32(len(rm.GameTrend.ListTrendGroup)) // // } // // } // // } // // return luckyRates // // } // // func (rm *ColorRoom) SetGameTrend() { // // trendGroup := new(pb.ColorPinoyLiveTrendGroup) // trendGroup.LuckyDice = pb.ColorPinoyLiveDiceColorType(model.GetColor(rm.LuckyDice)) // for _, dice := range rm.NormalDices { // trendGroup.ThreeDice = append(trendGroup.ThreeDice, pb.ColorPinoyLiveDiceColorType(model.GetColor(dice))) // } // // rm.GameTrend.ListTrendGroup = append(rm.GameTrend.ListTrendGroup, trendGroup) // // // log.Debug("走势图 rm.GameTrend.ListTrendGroup: ", rm.GameTrend.ListTrendGroup) // winlen := len(rm.GameTrend.ListTrendGroup) // if winlen > config.WinTrendNum { // rm.GameTrend.ListTrendGroup = rm.GameTrend.ListTrendGroup[(winlen - config.WinTrendNum):] // } // // if rm.ServerStatus == define.GameStatusNoraml { // str, err := json.Marshal(rm.GameTrend.ListTrendGroup) // if err != nil { // return // } // redisf.RSC.SetColorGameTrend(rm.TrendRedisKey, str) // // log.Debug("SetGameTrend 保存走势图到redis :", str) // // } // } // // // 获取投注区域的颜色 // func getColorByBetArea(area pb.ColorPinoyLiveBetTypeJP) pb.ColorPinoyLiveDiceColorType { // switch area { // case pb.ColorPinoyLiveBetTypeJP_CLJ_Yellow, pb.ColorPinoyLiveBetTypeJP_CLJ_Double_Yellow, pb.ColorPinoyLiveBetTypeJP_CLJ_Three_Yellow: // return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_YELLOW // case pb.ColorPinoyLiveBetTypeJP_CLJ_White, pb.ColorPinoyLiveBetTypeJP_CLJ_Double_White, pb.ColorPinoyLiveBetTypeJP_CLJ_Three_White: // return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_WHITE // case pb.ColorPinoyLiveBetTypeJP_CLJ_Pink, pb.ColorPinoyLiveBetTypeJP_CLJ_Double_Pink, pb.ColorPinoyLiveBetTypeJP_CLJ_Three_Pink: // return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_PINK // case pb.ColorPinoyLiveBetTypeJP_CLJ_Blue, pb.ColorPinoyLiveBetTypeJP_CLJ_Double_Blue, pb.ColorPinoyLiveBetTypeJP_CLJ_Three_Blue: // return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_BLUE // case pb.ColorPinoyLiveBetTypeJP_CLJ_Red, pb.ColorPinoyLiveBetTypeJP_CLJ_Double_Red, pb.ColorPinoyLiveBetTypeJP_CLJ_Three_Red: // return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_RED // case pb.ColorPinoyLiveBetTypeJP_CLJ_Green, pb.ColorPinoyLiveBetTypeJP_CLJ_Double_Green, pb.ColorPinoyLiveBetTypeJP_CLJ_Three_Green: // return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_GREEN // } // return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_Void // } // // func getColorCount(result []byte, color pb.ColorPinoyLiveDiceColorType) int { // count := 0 // for _, c := range result { // if model.GetColor(c) == int32(color) { // count++ // } // } // return count // } // // func stringDices(result []byte) string { // s := "" // for _, c := range result { // s += fmt.Sprintf("%v", pb.ColorPinoyLiveDiceColorType(model.GetColor(c))) // } // return s // } // // // 检查投掷结果是否匹配某个下注区域 // func isWinningArea(result []byte, area pb.ColorPinoyLiveBetTypeJP) (win bool, bigPos pb.ColorPinoyLiveBigBetAreaPos, colorCount int) { // color := getColorByBetArea(area) // colorCount = getColorCount(result, color) // if colorCount == 0 { // return false, 0, colorCount // } // // 单色投注区,查看开出几个该颜色 // if area < pb.ColorPinoyLiveBetTypeJP_CLJ_Double_Yellow { // if colorCount == 1 { // return true, pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_0, colorCount // } else if colorCount == 2 { // return true, pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_1, colorCount // } else { // return true, pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_2, colorCount // } // } else if area < pb.ColorPinoyLiveBetTypeJP_CLJ_Three_Yellow { // if colorCount > 1 { // return true, pb.ColorPinoyLiveBigBetAreaPos_BBA_Double, colorCount // } // } else { // if colorCount > 2 { // return true, pb.ColorPinoyLiveBigBetAreaPos_BBA_Three, colorCount // } // } // return false, 0, colorCount // } // // // 计算开奖结果 // func (rm *ColorRoom) CompareDiceResult() { // var wins []*pb.ColorPinoyLiveBetAreaOdd // // // 存储中奖区域 // result := rm.NormalDices // log.Debug(rm.Log("开奖结果:%v", stringDices(result))) // rm.afterBetAreaOdds = rm.afterBetAreaOdds[0:0] // // 检查所有下注区域是否中奖 // for pos, area := range rm.betEndBetAreasOdds { // betAreaOdd := &pb.ColorPinoyLiveBetAreaOdd{ // BetArea: area.BetType, // Odd: area.Odd[0], // ViewOdd: 0, // IsBigOdd: area.IsBigOdd, // BigSingleColorOddPos: area.BigSingleColorOddPos, // IsWin: false, // IsJackpot: area.IsJackpot, // } // if pos/6 == 0 { // // 第一行投注区域,赔率是多个赔率中的一个 // betAreaOdd.Odd = area.Odd[area.BigSingleColorOddPos] // } else { // betAreaOdd.Odd = area.Odd[0] // } // betAreaOdd.ViewOdd = betAreaOdd.Odd // // 更新实际赔率 // isWin, winOddPos, colorCount := isWinningArea(result, area.BetType) // betAreaOdd.IsWin = isWin // if betAreaOdd.IsWin { // if betAreaOdd.IsJackpot && colorCount == 3 { // betAreaOdd.Odd = 0 // } else { // if winOddPos == pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_0 { // betAreaOdd.Odd = area.Odd[0] // } else if winOddPos == pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_1 { // betAreaOdd.Odd = area.Odd[1] // } else if winOddPos == pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_2 { // betAreaOdd.Odd = area.Odd[2] // } // // 爆奖需要修正 // if betAreaOdd.IsBigOdd && winOddPos > betAreaOdd.BigSingleColorOddPos { // betAreaOdd.Odd = area.Odd[area.BigSingleColorOddPos] // } // } // wins = append(wins, betAreaOdd) // } // // // 修正牌局记录倍率 // tmpAreaOdd := &pb.ColorPinoyLiveBetAreaOdd{ // BetArea: betAreaOdd.BetArea, // Odd: betAreaOdd.Odd, // ViewOdd: betAreaOdd.ViewOdd, // IsBigOdd: betAreaOdd.IsBigOdd, // BigSingleColorOddPos: betAreaOdd.BigSingleColorOddPos, // IsWin: betAreaOdd.IsWin, // IsJackpot: betAreaOdd.IsJackpot, // } // if !tmpAreaOdd.IsWin && pos/6 == 0 && // (betAreaOdd.BigSingleColorOddPos == pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_1 || // betAreaOdd.BigSingleColorOddPos == pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_2) { // tmpAreaOdd.Odd = area.Odd[0] // if !tmpAreaOdd.IsBigOdd { // tmpAreaOdd.ViewOdd = tmpAreaOdd.Odd // } // } // if !tmpAreaOdd.IsWin && pos/6 == 1 && tmpAreaOdd.IsBigOdd { // tmpAreaOdd.Odd = rm.RoomCfg.ColorPinoyLiveConfig.WinDoubleColorMul[0].Mul // } // if !tmpAreaOdd.IsWin && pos/6 == 2 && tmpAreaOdd.IsBigOdd { // tmpAreaOdd.Odd = rm.RoomCfg.ColorPinoyLiveConfig.WinThreeColorMul[0].Mul // } // // rm.afterBetAreaOdds = append(rm.afterBetAreaOdds, tmpAreaOdd) // log.Debug(rm.Log("开奖,区域:%v 是否中奖:%v 实际赔率:%v 显示赔率:%v 是否爆奖:%v 爆奖位置:%v", betAreaOdd.BetArea, betAreaOdd.IsWin, betAreaOdd.Odd, // betAreaOdd.ViewOdd, betAreaOdd.IsBigOdd, betAreaOdd.BigSingleColorOddPos)) // } // rm.PokerMsg.WinBetArea = wins // } // // // 检查用户是否被踢掉 // func (rm *ColorRoom) checkUserBet() { // kickMsg, isKick := redisf.RSC.IsGameMaintenance(gconfig.GConfig.GRoomConfig.ChannelId, gconfig.GConfig.GServConfig.GameId) // rm.Traverse(func(u *model.User) bool { // u.NoBetCount++ // if isKick { // msg := new(pb.ColorPinoyLiveKickOutUserMsg) // // msg.KickOutReason = fmt.Sprintf("you did not bet %d games", rm.RoomCfg.LongHuConfig.NoBetCountMax) // msg.Reason = int32(pb.ColorPinoyLiveLeaveReason_ColorPinoyLiveLeaveReason_Maintaince) // msg.KickOutReason = kickMsg // u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeKickOutUser), msg) // u.NoBetCount = 0 // rm.KickOutUser(u) // return true // } // if rm.ServerStatus != define.GameStatusNoraml || u.UserInetr.NeedKickout() { // msg := new(pb.ColorPinoyLiveKickOutUserMsg) // // msg.KickOutReason = fmt.Sprintf("game server maintenance ") // msg.Reason = int32(pb.ColorPinoyLiveLeaveReason_ColorPinoyLiveLeaveReason_PLAYER_QUIT_ROOM) // u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeKickOutUser), msg) // rm.KickOutUser(u) // return true // } // if redisf.RSC.IsUserLiveBan(u.UserInetr.GetOpToken(), int64(gconfig.GConfig.GRoomConfig.GameId), u.UserID) { // msg := new(pb.ColorPinoyLiveKickOutUserMsg) // msg.Reason = int32(pb.ColorPinoyLiveLeaveReason_ColorPinoyLiveLeaveReason_Ban) // u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeKickOutUser), msg) // rm.KickOutUser(u) // return true // } // // if u.NoBetCount >= (rm.RoomCfg.ColorPinoyLiveConfig.NoBetCountMax + 1) { // // msg := new(pb.ColorPinoyLiveKickOutUserMsg) // // // msg.KickOutReason = fmt.Sprintf("you did not bet %d games", rm.RoomCfg.LongHuConfig.NoBetCountMax) // // msg.Reason = 1 // // u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeKickOutUser), msg) // // // 踢掉用户 // // u.NoBetCount = 0 // // rm.KickOutUser(u) // // return true // // } // // return true // }) // } // // // 初始走势图 // func (rm *ColorRoom) InitWinTrend() { // rm.TrendRedisKey = fmt.Sprintf("pb.:%d:%d:trend", gconfig.GConfig.GDataConfig.VersionMode, rm.RoomCfg.Level) // if rm.ServerStatus == define.GameStatusNoraml { // winTrend := redisf.RSC.GetColorGameTrend(rm.TrendRedisKey) // if winTrend != "" { // rm.GameTrend = new(pb.ColorPinoyLiveTrend) // rm.GameTrend.ListTrendGroup = []*pb.ColorPinoyLiveTrendGroup{} // err := json.Unmarshal([]byte(winTrend), &rm.GameTrend.ListTrendGroup) // winlen := len(rm.GameTrend.ListTrendGroup) // // log.Debug("初始化走势图1:", len(rm.GameTrend.ListTrendGroup)) // if winlen > config.WinTrendNum { // rm.GameTrend.ListTrendGroup = rm.GameTrend.ListTrendGroup[(winlen - config.WinTrendNum):] // // log.Debug("初始化走势图2:", len(rm.GameTrend.ListTrendGroup)) // } // // log.Debug("初始化走势图:", rm.GameTrend.ListTrendGroup) // if err != nil { // log.Error(rm.Log("初始化走势图:%v", err)) // } // } // // } // // } // // func (rm *ColorRoom) DeleteExitUserFromOnlineUserListSlice(user *model.User) { // rm.MutexUserList.Lock() // defer rm.MutexUserList.Unlock() // for k, v := range rm.OnlineUserList { // if user == v { // rm.OnlineUserList = append(rm.OnlineUserList[:k], rm.OnlineUserList[k+1:]...) // break // } // } // } // // func (rm *ColorRoom) SelectUserListBalanceTopSitDownChair() { // rm.MutexUserList.Lock() // rm.SceneInfo.ClearSceneChairId() // rm.SceneInfo.Init() // index := len(rm.OnlineUserList) // if index >= config.SEAT_NUM { // index = config.SEAT_NUM // } // cou := model.Usercount{} // cou = rm.OnlineUserList // sort.Sort(cou) // for i := 0; i < index; i++ { // u := rm.OnlineUserList[i] // ChairId := i + 1 // if rm.SceneInfo.SitScene(u, ChairId) { // u.SceneChairId = ChairId // } // } // rm.MutexUserList.Unlock() // // } // // func (rm *ColorRoom) CopyArr(arr [config.BET_TYPE_NUM]int64) []int64 { // slice := make([]int64, len(arr)) // copy(slice, arr[:]) // return slice // } // // func (rm *ColorRoom) GameDiscard() { // rm.TimerJob.Cancel() // rm.GameUserDiscard() // // rm.TimerJob, _ = rm.Table.AddTimer(1000, func() { // // rm.LiveCnt(rm.Ready, false, true, []bool{true}...) // // }) // rm.ResetData(false) // rm.Traverse(func(user *model.User) bool { // if rm.LiveMgr.MaintenanceStatus == 1 { // rm.sendUserMainte(user, int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameMainte)) // } // if rm.LiveMgr.DiscardStatus == 1 { // rm.sendUserMainte(user, int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeDiscard)) // } // return true // }) // rm.Ready() // } // // func (rm *ColorRoom) sendUserMainte(user *model.User, cmd int32) { // userinfo := new(pb.ColorPinoyLiveUserInfo) // userinfo.NikeName = user.UserInetr.GetNike() // userinfo.UserGlod = user.Balance // userinfo.Head = user.UserInetr.GetHead() // userinfo.UserID = user.UserID // _ = user.UserInetr.SendMsg(cmd, &pb.ColorPinoyLiveMainteNtf{ // UserInfo: userinfo, // MaintMsg: rm.LiveMgr.MainteMsg, // ReturnGold: user.RetrunGold, // }) // } // // func (rm *ColorRoom) GameUserDiscard() { // rm.MutexStatus.RLock() // defer rm.MutexStatus.RUnlock() // log.Debug(rm.Log("流局,状态:%v,分出去的jackpot:%v", rm.GetGameStatus(), rm.costJackpot)) // // 回退 // if rm.GetGameStatus() >= pb.ColorPinoyLiveGameStatus_ColorPinoyLiveEndBetMovie && rm.GetGameStatus() < pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus { // rm.jackpotMgr.RollBackJpXAndJpY(0, 0, rm.jackpotX, rm.jackpotY) // rm.kafkaBackJackpot(0, rm.jackpotX, rm.jackpotY, rm.jackpotUser) // } else if rm.GetGameStatus() >= pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus { // rm.jackpotMgr.RollBackJpXAndJpY(rm.costJackpot, rm.jackpotFunding, rm.jackpotX, rm.jackpotY) // rm.kafkaBackJackpot(rm.costJackpot, rm.jackpotX, rm.jackpotY, rm.jackpotUser) // } // // var betCount int64 // GameTotalBets := make([]int64, config.BET_TYPE_NUM) // var PlayerData []*pb.ColorPinoyLivePlayerData // copyBetAreaMul := rm.copyBetAreaOdds() // wg := new(sync.WaitGroup) // playerDataMu := new(sync.Mutex) // rm.Traverse(func(v *model.User) bool { // wg.Add(1) // monitor.GoSafe(func(u *model.User) { // defer wg.Done() // u.RetrunGold = u.totalBet // msg := new(pb.ColorPinoyLiveUserSettleMsg) // msg.UserBets = rm.CopyArr(u.totalBets) // msg.UserRealWins = make([]int64, config.BET_TYPE_NUM) // msg.UserWins = make([]int64, config.BET_TYPE_NUM) // msg.WinAreaOdd = rm.PokerMsg.WinBetArea // msg.UserScore = u.Balance // u.SettleMsg = msg // // 写入数据库统计信息 // if u.totalBet > 0 { // for i, bet := range u.totalBets { // betCount += bet // GameTotalBets[i] += bet // } // // 玩家下注区域统计 // u.SettleMsg.UserBetsCount = make([]int64, config.BET_TYPE_NUM) // for i, count := range u.TotalBetsCount { // u.SettleMsg.UserBetsCount[i] = count // } // if rm.GetGameStatus() < pb.ColorPinoyLiveGameStatus_ColorPinoyLiveEndBetMovie { // u.AddBalance(u.totalBet) // } else if rm.GetGameStatus() < pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus { // _, err := rm.TransInoutGameEnd(u, u.TransWin, u.TransBet, 0) // if err != nil { // log.Error(rm.Log("discard error:%v, game_no:%s, uid:%d, TransWin:%d, TransBet:%d", err, rm.Table.GetGameRoundId(), u.UserID, u.TransWin, u.TransBet)) // } // } else { // if rm.LiveMgr.DiscardStatus == 1 { // _, err := rm.TransInoutGameEnd(u, u.TransWin, u.TransBet, 0) // if err != nil { // log.Error(rm.Log("discard error:%v, game_no:%s, uid:%d, TransWin:%d, TransBet:%d", err, rm.Table.GetGameRoundId(), u.UserID, u.TransWin, u.TransBet)) // } // } else { // return // } // } // func() { // playerDataMu.Lock() // defer playerDataMu.Unlock() // PlayerData = append(PlayerData, &pb.ColorPinoyLivePlayerData{ // Uid: u.UserID, // totalBets: u.SettleMsg.UserBets, // 玩家各个区域的总下注额 // totalBet: u.totalBet, // Profit: u.SettleMsg.TotalWin, // Tax: u.SettleMsg.Tax, // Balance: u.Balance, // PreBalance: u.PreBalance, // UserWins: u.SettleMsg.UserWins, // 玩家赢取的下注区域总下注额 // UserRealWins: u.SettleMsg.UserRealWins, // 玩家赢取的下注区域总下注额 扣税后 // AreaOdds: copyBetAreaMul, // 投注区域倍率 // StartTime: u.StartAt, // TransBet: u.TransBet, // TransWin: u.TransWin, // DevMode: u.UserInetr.GetDevMode(), // UserBetsCount: u.SettleMsg.UserBetsCount, // IsDiscard: 1, // }) // }() // } // u.ResetUserData() // }, v) // return true // }) // wg.Wait() // // 发布事件 // if PlayerData == nil || len(PlayerData) == 0 { // return // } // // 开奖结果 // gameDetail := &pb.ColorPinoyLiveDetail{DealerName: rm.dealerName, ResultImg: rm.ResultImgs} // gameDetail.BetAreaMul = copyBetAreaMul // gameRecordData := &pb.ColorPinoyLiveEnd{ // GameNo: fmt.Sprintf("%d|%d|%d", gconfig.GConfig.GRoomConfig.GameId, rm.Table.GetId(), time.Now().UnixMilli()), // StartTime: rm.startAt, // EndTime: rm.endAt, // Level: gconfig.GConfig.GRoomConfig.Level, // BaseBet: rm.RoomCfg.BaseBet, // PlayerData: PlayerData, // TaxRate: rm.RoomCfg.Rate, // totalBet: betCount, // totalBets: GameTotalBets[:], // OpToken: gconfig.GConfig.GServConfig.ChannelId, // Detail: gameDetail, // IsDiscard: 1, // } // log.Debug("GameUserDiscard") // go func() { // err := gconfig.Produce(context.Background(), define.TopicColoLiveGameGameEnd, gameRecordData) // if err != nil { // log.Error(rm.Log("[%s] fail to Produce TongitsGameEndEvent(%+v), err: %v", gameRecordData.GameNo, gameRecordData, err)) // } // }() // } // // func (rm *ColorRoom) LoadDealerNames() { // ssv := redisf.RSC.DealerNameGet(gconfig.GConfig.GDataConfig.VersionMode, gconfig.GConfig.GRoomConfig.GameId, GameName) // var dealerNames []string // _ = json.Unmarshal([]byte(ssv), &dealerNames) // rm.dealerName = dealerNames // log.Debug(rm.Log("dealerNames:%v", rm.dealerName)) // } // // // 发送垫资kafka // func (rm *ColorRoom) kafkaJackpotFunding(funding int64) { // msg := &events.JackpotEvent{ // EventType: events.JackpotEvent_et_funding, // GameId: rm.RoomCfg.GameId, // Time: time.Now().UnixMilli(), // Funding: &events.JackpotEvent_Funding{Funding: funding}, // GameNo: rm.Table.GetGameRoundId(), // } // go func() { // err := gconfig.Produce(context.Background(), define.TopicJackpot, msg) // if err != nil { // log.Error(rm.Log("kafka JackpotEvent_et_funding err: %v", err)) // } // }() // log.Debug(rm.Log("kafka 垫资:%v", funding)) // } // // // 发送赎回及追加kafka // func (rm *ColorRoom) kafkaJackpotUserRepaid(jpx, jpy int64) { // msg := &events.JackpotEvent{ // EventType: events.JackpotEvent_et_user_repaid, // GameId: rm.RoomCfg.GameId, // Time: time.Now().UnixMilli(), // UserRepaid: &events.JackpotEvent_UserRepaid{JackpotX: jpx, JackpotY: jpy}, // GameNo: rm.Table.GetGameRoundId(), // } // go func() { // err := gconfig.Produce(context.Background(), define.TopicJackpot, msg) // if err != nil { // log.Error(rm.Log("kafka JackpotEvent_et_user_repaid err: %v", err)) // } // }() // log.Debug(rm.Log("kafka 赎回jpx:%v 追加jpy:%v", jpx, jpy)) // } // // // 中jackpot分奖 // func (rm *ColorRoom) kafkaHitJackpot(jackpotValue int64, userJp map[int64]int64) { // msg := &events.JackpotEvent{ // EventType: events.JackpotEvent_et_hit_jackpot, // GameId: rm.RoomCfg.GameId, // Time: time.Now().UnixMilli(), // HitJackpot: &events.JackpotEvent_HitJackpot{SumJackpot: jackpotValue, UserJackpot: userJp}, // GameNo: rm.Table.GetGameRoundId(), // } // go func() { // err := gconfig.Produce(context.Background(), define.TopicJackpot, msg) // if err != nil { // log.Error(rm.Log("kafka JackpotEvent_HitJackpot err: %v", err)) // } // }() // log.Debug(rm.Log("kafka 中jackpot:%v", jackpotValue)) // } // // func (rm *ColorRoom) kafkaBackJackpot(jackpotValue, jpx, jpy int64, userJp map[int64]int64) { // userJp2 := make(map[int64]int64) // for k, v := range userJp { // userJp2[k] = -v // } // msg := &events.JackpotEvent{ // EventType: events.JackpotEvent_et_game_discard, // GameId: rm.RoomCfg.GameId, // Time: time.Now().UnixMilli(), // GameDiscard: &events.JackpotEvent_GameDiscard{ // Jackpot: -jackpotValue, // JackpotX: -jpx, // JackpotY: -jpy, // UserJackpot: userJp2, // }, // GameNo: rm.Table.GetGameRoundId(), // } // go func() { // err := gconfig.Produce(context.Background(), define.TopicJackpot, msg) // if err != nil { // log.Error(rm.Log("kafka JackpotEvent_HitJackpot err: %v", err)) // } // }() // log.Debug(rm.Log("kafka 回退jackpot:%v jpx:%v jpy:%v", -jackpotValue, -jpx, -jpy)) // }