704 lines
24 KiB
Go
Raw Normal View History

2025-06-08 00:52:17 +08:00
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))
}
}()
}