2025-06-08 00:52:17 +08:00

704 lines
24 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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))
}
}()
}