package room import ( "encoding/json" "fmt" "game/common/proto/pb" "github.com/fox/fox/ipb" "github.com/fox/fox/log" "math" "sort" "time" ) // 发送场景消息 func (rm *ColorRoom) SendSceneMsg(u *model.User) { rm.MutexUserList.RLock() defer rm.MutexUserList.RUnlock() msg := new(pb.SceneMessage) msg.RoomID = int32(rm.Table.GetId()) // 游戏状态信息 msg.GameStatus = new(pb.ColorPinoyLiveStatusMessage) msg.GameStatus.Status = int32(rm.GetGameStatus()) msg.GameStatus.StatusTime = int32(rm.StatusTime / 1000) // 转成秒 msg.GameStatus.StatusRemainTime = int32(math.Floor(float64(rm.TimerJob.GetTimeDifference() / 1000))) // 转成秒 msg.GameStatus.Jackpot = rm.jackpotMgr.GetJackpot() msg.Jackpot = msg.GameStatus.Jackpot // 玩家信息 和下注信息 var betAreaInfo []*pb.ColorPinoyLiveGameBetAreaInfo for _, betArea := range rm.betEndBetAreasOdds { areaInfo := new(pb.ColorPinoyLiveGameBetAreaInfo) areaInfo.BetType = betArea.BetType areaInfo.Odd = betArea.Odd areaInfo.IsBigOdd = betArea.IsBigOdd areaInfo.IsJackpot = betArea.IsJackpot areaInfo.BigSingleColorOddPos = betArea.BigSingleColorOddPos areaInfo.BetChipsInfo = []*pb.ColorPinoyLiveGameBetAreaUserInfo{} betAreaInfo = append(betAreaInfo, areaInfo) } rm.Traverse(func(u *model.User) bool { if u.TotalBet > 0 { // 下注玩家下注区域信息 for _, info := range betAreaInfo { for betType, betChips := range u.TotalBets { if pb.ColorPinoyLiveBetTypeJP(betType) == info.BetType && betChips != 0 { var betAearUser = new(pb.ColorPinoyLiveGameBetAreaUserInfo) betAearUser.UserID = u.UserID betAearUser.BetChips = betChips info.BetChipsInfo = append(info.BetChipsInfo, betAearUser) } } } } return true }) msg.BetAreaInfo = betAreaInfo msg.MulRangeConfig = rm.MulRangeConfig() if u != nil { // 后台配置的下注档位信息 roomBetRule := new(pb.ColorPinoyLiveRoomBetRuleMsg) for _, v := range rm.RoomCfg.ColorPinoyLiveConfig.BetList { betArr := new(pb.ColorPinoyLiveBetArr) betArr.BetArr = v roomBetRule.BetLevels = append(roomBetRule.BetLevels, betArr) } roomBetRule.BetMinLimit = rm.RoomCfg.BaseBet roomBetRule.Level = rm.RoomCfg.ColorPinoyLiveConfig.BetLevel msg.BetRule = roomBetRule // 上局下注数据 if u.TempLastTimeBet != nil { msg.LastTimeBet = make([]*pb.ColorPinoyLiveBetReqs, 0) for _, reqs := range u.TempLastTimeBet { betreq := &pb.ColorPinoyLiveBetReqs{} for _, req := range reqs { betreq.Info = append(betreq.Info, req) } msg.LastTimeBet = append(msg.LastTimeBet, betreq) } } } if rm.Status == pb.ColorPinoyLiveGameStatus_ColorPinoyLiveOpenThreeDice || rm.Status == pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus { // 3个骰子 // log.Debug("同步房间信息发送场景信息 rm.NormalDices:", rm.NormalDices) msg.LuckyDice = pb.ColorPinoyLiveDiceColorType(model.GetColor(rm.LuckyDice)) msg.ThreeDice = []pb.ColorPinoyLiveDiceColorType{} for _, dice := range rm.NormalDices { msg.ThreeDice = append(msg.ThreeDice, pb.ColorPinoyLiveDiceColorType(model.GetColor(dice))) // log.Debug("同步房间信息发送场景信息 i:", i, "dice:", dice, "color:", pb.DiceColorType(model.GetColor(dice)), "msg.ThreeDice:", msg.ThreeDice) } msg.AniThreeDiceRouteIndex = rm._aniThreeDiceRouteIndex } // 走势图 msg.TrendList = rm.GameTrend if msg.TrendList != nil { msg.TrendList.LuckStarRate = rm.GetGameTrend() } // 在线人数 msg.OnlineNums = int32(len(rm.OnlineUserList)) if rm.LiveMgr.RankList != nil { msg.RankList = rm.LiveMgr.RankList.PlayerData } // msg.Bonus = int32(rm.RoomCfg.ColorPinoyLiveConfig.Bonus) liveAuthDuration := time.Hour * 24 //goland:noinspection GoDfaNilDereference msg.ArtcUrl, _ = artc.GetAuthedUrl( gconfig.LiveRtcConfig.Uri, gconfig.LiveRtcConfig.Key, u.UserInetr.GetId(), liveAuthDuration, ) roomArgs, _ := trtc.GetRoomArgs( gconfig.LiveTrtcConfig.AppId, gconfig.LiveTrtcConfig.SecretKey, int64(gconfig.LiveTrtcConfig.GameId), u.UserInetr.GetId(), liveAuthDuration, gconfig.GConfig.GDataConfig.VersionMode, ) msg.TrtcRoomArgs = &pb.TRTCRoomArgs{ AppId: roomArgs.AppId, StrRoomId: roomArgs.StrRoomId, UserId: roomArgs.UserId, UserSig: roomArgs.UserSig, } msg.Balance = u.Balance msg.BigWinner = rm.BigWinner if rm.GetGameStatus() < pb.ColorPinoyLiveGameStatus_ColorPinoyLiveEndBetMovie { msg.BigWinner = nil } msg.DealerName = rm.dealerName // log.Debug("同步房间信息发送场景信息 msg:", msg) // log.Debug(msg) u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameSync), msg) } func (rm *ColorRoom) SendUserBet(u *model.User) { msg := new(pb.ColorPinoyLiveSceneBetInfo) msg.UserBets = u.TotalBets[:] msg.TotalBets = rm.TotalBets[:] msg.UserBetTotal = u.TotalBet // msg.MasterBetType = rm.LastMasterBetType msg.UserInfo = new(pb.ColorPinoyLiveUserInfo) msg.UserInfo.UserID = u.UserID msg.UserInfo.UserGlod = u.Balance msg.UserInfo.NikeName = u.UserInetr.GetNike() msg.UserInfo.Head = u.UserInetr.GetHead() _ = u.UserInetr.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameUserBet), msg) } func (rm *ColorRoom) SendRuleInfo() { // 后台配置的下注档位信息 msg := new(pb.ColorPinoyLiveRoomBetRuleMsg) for _, v := range rm.RoomCfg.ColorPinoyLiveConfig.BetList { betArr := new(pb.ColorPinoyLiveBetArr) betArr.BetArr = v msg.BetLevels = append(msg.BetLevels, betArr) } msg.BetMinLimit = rm.RoomCfg.BaseBet msg.Level = rm.RoomCfg.ColorPinoyLiveConfig.BetLevel msg.MulRangeConfig = rm.MulRangeConfig() // log.Debug("发送规则 2222 BroadcastRuleInfo:", msg) rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeRoomBetRuleMsg), msg) } func (rm *ColorRoom) SendScene(user inter.UserInetr) bool { _ = user return true } func (rm *ColorRoom) copyBetAreaOdds() []*pb.ColorPinoyLiveBetAreaOdd { var betAreaMul []*pb.ColorPinoyLiveBetAreaOdd // 游戏下注区域倍率 for _, areaOdds := range rm.afterBetAreaOdds { area := &pb.ColorPinoyLiveBetAreaOdd{ BetArea: areaOdds.BetArea, Odd: areaOdds.Odd, ViewOdd: areaOdds.ViewOdd, IsBigOdd: areaOdds.IsBigOdd, BigSingleColorOddPos: areaOdds.BigSingleColorOddPos, IsWin: areaOdds.IsWin, IsJackpot: areaOdds.IsJackpot, } betAreaMul = append(betAreaMul, area) } return betAreaMul } func (rm *ColorRoom) GameSync(user inter.UserInetr) { // 玩家加入 牌桌 u := rm.getUser(user) rm.SendSceneMsg(u) rm.Table.AddTimer(100, func() { if rm.LiveMgr.MaintenanceStatus == 1 { rm.sendUserMainte(u, int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameMainte)) } }) } // 向客户端发送结算消息 func (rm *ColorRoom) sendSettleMsg2Client() { MaxWinGold := int64(0) MaxWinUserID := int64(0) var RealSystemWins [config.BET_TYPE_NUM]int64 var RealSystemWin int64 var SystemTax int64 var PlayerData []*pb.ColorPinoyLivePlayerData betTypePlayerCount := [config.BET_TYPE_NUM]int64{} wins := rm.PokerMsg.WinBetArea // 玩家各个下注区域的输赢情况 var betAreaInfo []*pb.ColorPinoyLiveGameBetAreaInfo for i := 0; i < config.BET_TYPE_NUM; i++ { areaInfo := new(pb.ColorPinoyLiveGameBetAreaInfo) areaInfo.BetType = pb.ColorPinoyLiveBetTypeJP(i) for _, win := range wins { if win.BetArea == areaInfo.BetType { areaInfo.IsWin = 1 } } areaInfo.BetChipsInfo = []*pb.ColorPinoyLiveGameBetAreaUserInfo{} betAreaInfo = append(betAreaInfo, areaInfo) } // 获取有座玩家下注情况 暂时没有有座玩家下注 var betUserInfo []*pb.ColorPinoyLiveSceneUserInfo noChairTotalWin := int64(0) rm.Traverse(func(u *model.User) bool { if u.TotalBet > 0 && u.SettleMsg != nil { user := new(pb.ColorPinoyLiveSceneUserInfo) user.UserID = u.UserID user.TotalWin = u.SettleMsg.TotalWin user.UserScore = u.SettleMsg.UserScore for _, info := range betAreaInfo { for betType, betChips := range u.SettleMsg.UserBets { if pb.ColorPinoyLiveBetTypeJP(betType) == info.BetType && betChips != 0 { var betAearUser = new(pb.ColorPinoyLiveGameBetAreaUserInfo) betAearUser.UserID = u.UserID betAearUser.BetChips = betChips info.BetChipsInfo = append(info.BetChipsInfo, betAearUser) } } } betUserInfo = append(betUserInfo, user) noChairTotalWin += u.SettleMsg.TotalWin } return true }) // 单播每个玩家的结算信息 copyBetAreaMul := rm.copyBetAreaOdds() betCount := int64(0) GameTotalBets := [config.BET_TYPE_NUM]int64{} rm.Traverse(func(u *model.User) bool { SceneUserInfo := new(pb.ColorPinoyLiveSceneSettleMsg) // 下注区域投注信息 SceneUserInfo.BetAreaInfo = betAreaInfo // 本局走势图数据 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))) } SceneUserInfo.TrendGroup = trendGroup // 有座玩家下注信息 暂时没有有座玩家 // SceneUserInfo.UserList = betUserInfo // 幸运骰子 SceneUserInfo.LuckyDice = pb.ColorPinoyLiveDiceColorType(model.GetColor(rm.LuckyDice)) // 3个骰子 SceneUserInfo.ThreeDice = []pb.ColorPinoyLiveDiceColorType{} for _, dice := range rm.NormalDices { SceneUserInfo.ThreeDice = append(SceneUserInfo.ThreeDice, pb.ColorPinoyLiveDiceColorType(model.GetColor(dice))) } // 自己的投注信息 if u.SettleMsg != nil { SceneUserInfo.SelfWinInfo = new(pb.ColorPinoyLiveSceneUserInfo) SceneUserInfo.SelfWinInfo.UserID = int64(u.UserInetr.GetId()) SceneUserInfo.SelfWinInfo.SceneSeatID = int32(u.SceneChairId) SceneUserInfo.SelfWinInfo.TotalWin = u.SettleMsg.TotalWin // 净利 + 投注本金 SceneUserInfo.SelfWinInfo.UserScore = u.SettleMsg.UserScore SceneUserInfo.SelfWinInfo.JackpotWin = u.SettleMsg.JackpotWin SceneUserInfo.SelfWinInfo.NormalWin = u.SettleMsg.TotalWin - u.SettleMsg.JackpotWin } // 上局投注信息 SceneUserInfo.LastTimeBet = make([]*pb.ColorPinoyLiveBetReqs, 0) for _, reqs := range u.LastTimeBet { betreq := &pb.ColorPinoyLiveBetReqs{} for _, req := range reqs { betreq.Info = append(betreq.Info, req) } SceneUserInfo.LastTimeBet = append(SceneUserInfo.LastTimeBet, betreq) } SceneUserInfo.TrendGroupEx = &pb.ColorPinoyLiveTrend{} SceneUserInfo.TrendGroupEx.ListTrendGroup = rm.GameTrend.ListTrendGroup SceneUserInfo.TrendGroupEx.LuckStarRate = rm.GetGameTrend() SceneUserInfo.BigWinner = rm.BigWinner SceneUserInfo.Jackpot = rm.jackpotMgr.GetJackpot() SceneUserInfo.JackpotUserName = u.SettleMsg.JackpotUserName // 单播玩家结算信息 // log.Debug("发送结算信息 SceneUserInfo BetAreaInfo:", SceneUserInfo.BetAreaInfo) // log.Debug("发送结算信息 SceneUserInfo UserList:", SceneUserInfo.UserList) // log.Debug("发送结算信息 SceneUserInfo SelfWinInfo:", SceneUserInfo.SelfWinInfo) u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameUserSettle), SceneUserInfo) if !u.IsRobot && u.SettleMsg != nil { RealSystemWin += u.TotalBet RealSystemWin -= u.SettleMsg.TotalWin betCount += u.TotalBet SystemTax += u.SettleMsg.Tax if MaxWinGold < u.SettleMsg.TotalWin-u.TotalBet { MaxWinGold = u.SettleMsg.TotalWin - u.TotalBet MaxWinUserID = u.UserInetr.GetId() } for i, bet := range u.TotalBets { if bet > 0 { RealSystemWins[i] += bet betTypePlayerCount[i] += 1 RealSystemWins[i] -= u.SettleMsg.UserRealWins[i] GameTotalBets[i] += bet } } // 写入数据库统计信息 if u.TotalBet > 0 { // 玩家下注区域统计 u.SettleMsg.UserBetsCount = make([]int64, config.BET_TYPE_NUM) for i, count := range u.TotalBetsCount { u.SettleMsg.UserBetsCount[i] = count } 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, Nickname: u.UserInetr.GetNike(), Avatar: u.UserInetr.GetHead(), }) } // log.Debug("开奖倍率:", u.SettleMsg.OddsWins) } // u.ResetUserData() return true }) // rm.Table.GameBetInfo(gameBetInfos) cou := model.Usercount{} cou = rm.OnlineUserList sort.Sort(cou) for key, v := range pb.ColorPinoyLiveBetTypeJP_value { if rm.TotalBets[v] > 0 || betTypePlayerCount[v] > 0 || RealSystemWins[v] > 0 { log.Debug(rm.Log("%v 区域:总:%v 真:%v 真人数量:%v 真输赢:%v", key, score.GetScoreStr(rm.TotalBets[v]), score.GetScoreStr(GameTotalBets[v]), betTypePlayerCount[v], score.GetScoreStr(rm.TotalBets[v]-RealSystemWins[v]))) } } str := fmt.Sprintf("开局结果 幸运骰子:%v :普通骰子:%v ,%v ,%v ,", model.GetColorString(rm.LuckyDice), model.GetColorString(rm.NormalDices[0]), model.GetColorString(rm.NormalDices[1]), model.GetColorString(rm.NormalDices[2])) str += fmt.Sprintf("总押注:%v ", score.GetScoreStr(rm.TotalBet)) str += fmt.Sprintf("真人 总押注:%v , 系统输赢额度:%v ", score.GetScoreStr(betCount), score.GetScoreStr(RealSystemWin), ) str += fmt.Sprintf("最高获利用户ID:%v 获得:%v", MaxWinUserID, score.GetScoreStr(MaxWinGold)) log.Debug(rm.Log(str)) log.Debug(rm.Log("各区域投注:%v", rm.TotalBets)) log.Debug(rm.Log("真人各区域投注:%v", GameTotalBets)) log.Debug(rm.Log("真人各区域中奖:%v", RealSystemWins)) log.Debug(rm.Log("中奖区域:%v", wins)) // SceneSettleMsg.NoChairTotalWin = noChairTotalWin // rm.Table.Broadcast(int32(pb.SendToClientMessageType_NoticeGameSettle), SceneSettleMsg) rm.LiveMgr.RankList = &pb.ColorPinoyLiveRankList{ PlayerData: nil, GameNo: rm.Table.GetGameRoundId(), StartTime: rm.startAt, EndTime: rm.endAt, } // 发布事件 if PlayerData == nil || len(PlayerData) == 0 { return } // 开奖结果 var threeDice []pb.ColorPinoyLiveDiceColorType for _, dice := range rm.NormalDices { threeDice = append(threeDice, pb.ColorPinoyLiveDiceColorType(model.GetColor(dice))) } var startDice []pb.ColorPinoyLiveDiceColorType for _, dice := range rm.StartDices { startDice = append(startDice, pb.ColorPinoyLiveDiceColorType(model.GetColor(dice))) } gameDetail := &pb.ColorPinoyLiveDetail{ // LuckyDice: pb.ColorPinoyLiveDiceColorType(model.GetColor(rm.LuckyDice)), ThreeDice: threeDice, // Bonus: rm.RoomCfg.ColorPinoyLiveConfig.Bonus, StartDice: startDice, ResultImg: rm.ResultImgs, DealerName: rm.dealerName, BetAreaMul: copyBetAreaMul, JackpotFunding: rm.jackpotFunding, JackpotX: rm.jackpotX, JackpotY: rm.jackpotY, } gameRecordData := &pb.ColorPinoyLiveEnd{ GameNo: rm.Table.GetGameRoundId(), 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[:], RealSystemWin: RealSystemWin, RealSystemWins: RealSystemWins[:], Tax: SystemTax, Wins: nil, OpToken: gconfig.GConfig.GServConfig.ChannelId, Detail: gameDetail, } for _, winArea := range rm.PokerMsg.WinBetArea { gameRecordData.Wins = append(gameRecordData.Wins, winArea.BetArea) } sort.Slice(PlayerData, func(i, j int) bool { return PlayerData[i].Profit > PlayerData[j].Profit }) for i := 0; i < 6 && i < len(PlayerData); i++ { if PlayerData[i].TransWin == 0 { continue } rm.LiveMgr.RankList.PlayerData = append(rm.LiveMgr.RankList.PlayerData, PlayerData[i]) } log.Debug(rm.Log("玩家数量:%v 赢家数量:%v", len(PlayerData), len(rm.LiveMgr.RankList.PlayerData))) go func() { // log.Debug("color game 游戏记录:", gameDetail) // log.Debug("color game 游戏记录 Tax:", gameRecordData.Tax) // log.Debug("color game 游戏记录 Wins:", gameRecordData.Wins) // log.Debug("color game 游戏记录 PlayerData:", gameRecordData.PlayerData) s, _ := json.Marshal(gameRecordData) log.Debug(rm.Log("记录区域数据:%v", string(s))) 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) SendOnlinePlayerNum() { msg := new(pb.ColorPinoyLiveS2COnlinePlayerNum) msg.Num = int64(len(rm.OnlineUserList)) rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeOnlinePlayerNum), msg) } func (rm *ColorRoom) SendRoomInfo() { // if rm.GetGameStatus() == 0 { // return // } // msg := new(pb.UpdateRoomInfoMsg) // msg.OnlineNum = int64(len(rm.OnlineUserList)) // rm.Table.Broadcast(int32(pb.SendToClientMessageType_NoticeUpdateRoomInfo), msg) } // 广播主播名字 func (rm *ColorRoom) NotifyDealerName() { msg := new(pb.ColorPinoyLiveDealerName) msg.DealerName = rm.dealerName rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeDealerName), msg) log.Debug(rm.Log("NotifyDealerName:%v", msg)) } type MulRangeW struct { *config.MulRate MinW int // 权重转换成数值区间 MaxW int // 权重转换成数值区间 ColorPos pb.ColorPinoyLiveBigBetAreaPos // 0:单色区域基础倍率 1:单色区域双色倍率 2:单色区域开三色倍率 3:双色区域 4:三色区域 } // 带有权重信息的五行倍率数组(单色单,单色双,单色三,双色,三色倍率数组) func (rm *ColorRoom) initMulRangeW() (mulRangeW [][]*MulRangeW) { mulRangeW = make([][]*MulRangeW, 0, 5) for pos, mulWs := range rm.Cfg.WinSingleColorMul { var single []*MulRangeW for _, mul := range mulWs { single = append(single, &MulRangeW{MulRate: mul, ColorPos: pb.ColorPinoyLiveBigBetAreaPos(pos)}) } mulRangeW = append(mulRangeW, single) } var double []*MulRangeW for _, mul := range rm.Cfg.WinDoubleColorMul { double = append(double, &MulRangeW{MulRate: mul, ColorPos: pb.ColorPinoyLiveBigBetAreaPos_BBA_Double}) } mulRangeW = append(mulRangeW, double) var three []*MulRangeW for _, mul := range rm.Cfg.WinThreeColorMul { three = append(three, &MulRangeW{MulRate: mul, ColorPos: pb.ColorPinoyLiveBigBetAreaPos_BBA_Three}) } mulRangeW = append(mulRangeW, three) for _, mulRws := range mulRangeW { begin := 0 for _, v := range mulRws { v.MinW = begin v.MaxW = begin + v.Rate begin += v.Rate } } return mulRangeW } // 返回单色投注区爆奖的权重数组及是爆在双色还是三色位置 func (rm *ColorRoom) randSingle(cfg *config.ColorPinoyLiveConfig) (singleMul []*MulRangeW, singlePos int) { maxWeight := 0 for _, w := range cfg.WinSingleColorWeight { maxWeight += w } weight := rand.RandInt(0, maxWeight) log.Debug(rm.Log("单色投注区获取爆奖在双色还是三色,随机值为:%v 最大值:%v", weight, maxWeight)) for pos, w := range cfg.WinSingleColorWeight { if weight > w { weight -= w continue } log.Debug(rm.Log("单色投注区获取爆奖根据权重随机出来的爆奖位置为:%v", pos)) // 爆奖只会提高开出双色或三色的赔率,基础赔率区不会爆奖 if pos == 0 { log.Debug(rm.Log("单色投注区的基础赔率区不会爆奖")) return nil, pos } for _, mul := range cfg.WinSingleColorMul[pos] { singleMul = append(singleMul, &MulRangeW{MulRate: mul, ColorPos: pb.ColorPinoyLiveBigBetAreaPos(pos)}) } begin := 0 for _, v := range singleMul { v.MinW = begin v.MaxW = begin + v.Rate begin += v.Rate } return singleMul, pos } return nil, 0 } // 更新 func (rm *ColorRoom) updateBetEndBetAreasOdds(mulRangeWs [][]*MulRangeW) { for pos, betArea := range rm.betEndBetAreasOdds { log.Debug(rm.Log("区域:%v 随机前 爆奖状态:%v", pb.ColorPinoyLiveBetTypeJP(pos), betArea.IsBigOdd)) betArea.IsBigOdd = false // 区域位置 0-2分别为单色、双色、三色投注区域, index := pos / 6 singlePos := 0 var mulRangeW []*MulRangeW if index == 0 { mulRangeW, singlePos = rm.randSingle(rm.Cfg) } else { mulRangeW = mulRangeWs[index+2] } if mulRangeW == nil { log.Error(rm.Log("投注区域:%v 获取爆奖权重数组为nil", pos)) continue } rdv := rand.RandInt(mulRangeW[0].MinW, mulRangeW[len(mulRangeW)-1].MaxW) for mulPos, mul := range mulRangeW { if rdv < mul.MinW || rdv >= mul.MaxW { continue } if index == 0 { betArea.Odd[singlePos] = mul.Mul if singlePos != 0 && mulPos != 0 { log.Debug(rm.Log("区域:%v 爆奖位置:%v", pb.ColorPinoyLiveBetTypeJP(pos), mul.ColorPos)) betArea.IsBigOdd = true } } else { betArea.Odd[0] = mul.Mul if mulPos != 0 { log.Debug(rm.Log("区域:%v 爆奖位置:%v", pb.ColorPinoyLiveBetTypeJP(pos), mul.ColorPos)) betArea.IsBigOdd = true } } betArea.BigSingleColorOddPos = mul.ColorPos break } log.Debug(rm.Log("区域:%v 爆奖权重区间:[%v,%v],随机数:%v betArea:%+v", pb.ColorPinoyLiveBetTypeJP(pos), mulRangeW[0].MinW, mulRangeW[len(mulRangeW)-1].MaxW, rdv, betArea)) } // 更新jackpot标记 _ = rm.randJackpotArea() return } func (rm *ColorRoom) randJackpotArea() []pb.ColorPinoyLiveBetTypeJP { betAreaInfo := make(map[int]*pb.ColorPinoyLiveGameBetAreaInfo) for pos, betArea := range rm.betEndBetAreasOdds { betAreaInfo[pos] = betArea } // 利用map的随机特性 for pos, betArea := range betAreaInfo { // 区域位置 0-2分别为单色、双色、三色投注区域, index := pos / 6 if index > 0 { continue } _, singlePos := rm.randSingle(rm.Cfg) // 在单色区域 命中三同色爆奖之后 再随jackpot概率 // 只会有一个区域有jackpot标签 if singlePos == 2 { if rand.RandInt(0, 10000) < rm.Cfg.JackpotRate { betArea.IsJackpot = true return []pb.ColorPinoyLiveBetTypeJP{betArea.BetType} } } } return nil } // 区域爆奖 func (rm *ColorRoom) NotifyBigBetAreaMul() { mulRangeW := rm.initMulRangeW() rm.updateBetEndBetAreasOdds(mulRangeW) for _, betArea := range rm.betEndBetAreasOdds { log.Debug(rm.Log("投注区域:%v 倍率:%v 是否爆奖:%v 是否jackpot:%v 倍率位置:%v", betArea.BetType, betArea.Odd, betArea.IsBigOdd, betArea.IsJackpot, betArea.BigSingleColorOddPos)) } msg := new(pb.ColorPinoyLiveNtfBigOddBetArea) msg.BetAreas = rm.betEndBetAreasOdds rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeBigOddBetArea), msg) log.Debug(rm.Log("ColorPinoyLiveNtfBigOddBetArea:%v", msg)) } func (rm *ColorRoom) formatScore(score int64) string { s := float64(score / 100.0) numStr := fmt.Sprintf("%.2f", s) // result := "" // for i := len(numStr) - 1; i >= 0; i-- { // result = string(numStr[i]) + result // if (len(numStr)-i)%3 == 0 && i != 0 { // result = "," + result // } // } return numStr // return result } func (rm *ColorRoom) BroadHitJackpot(user *model.User, jpScore int64) { go func() { req := &fmsg.ChatReq{ Uid: user.UserID, GameId: rm.RoomCfg.GameId, Content: fmt.Sprintf("%v WIN ₱ %v FROM JACKPOT", user.UserInetr.GetNike(), rm.formatScore(jpScore)), Type: 0, } bReq, err := proto.Marshal(req) if err != nil { log.Error(rm.Log(err.Error())) return } lobbyMsg := &events.SingleMsgToLobbyEvent{ Module: events.SingleMsgToLobbyEvent_mtl_chat, Data: bReq, } err = gconfig.Produce(context.Background(), define.TopicSingleMsgToLobby, lobbyMsg) if err != nil { log.Error(rm.Log("fail to Produce SingleMsgToLobbyEvent_mtl_chat, err: %v", err)) } }() }