业务逻辑

This commit is contained in:
liuxiaobo 2025-06-09 23:52:18 +08:00
parent 774604644c
commit 41e4c3f9d3
16 changed files with 713 additions and 214 deletions

View File

@ -1,7 +1,7 @@
package config package config
// Common中只有Special会动态更新Special是各类服务自己需要及时更新的配置信息 // Common中只有Special会动态更新Special是各类服务自己需要及时更新的配置信息
type Common[T any] struct { type Common struct {
ServiceType int `json:"service_type"` ServiceType int `json:"service_type"`
Logger Logger `json:"logger"` Logger Logger `json:"logger"`
Etcd Etcd `json:"etcd"` Etcd Etcd `json:"etcd"`
@ -9,7 +9,7 @@ type Common[T any] struct {
Nats Nats `json:"nats"` Nats Nats `json:"nats"`
Mysql Mysql `json:"mysql"` Mysql Mysql `json:"mysql"`
MysqlLog Mysql `json:"mysql_log"` MysqlLog Mysql `json:"mysql_log"`
Special *T `json:"special"` GameJson string `json:"game_json"`
GitCommit string `json:"git_commit"` // 服务当前的hash值 GitCommit string `json:"git_commit"` // 服务当前的hash值
GitBranch string `json:"git_branch"` // 服务当前的版本分支 GitBranch string `json:"git_branch"` // 服务当前的版本分支
BuildDate string `json:"build_date"` // 服务构建时间用作version BuildDate string `json:"build_date"` // 服务构建时间用作version

View File

@ -30,7 +30,7 @@ const (
mysqlLogDBName = "game_log" mysqlLogDBName = "game_log"
) )
func LoadSpecialConfig[T any](rd *redis.Client, specialKey string, comm *Common[T]) error { func LoadGameConfig(rd *redis.Client, specialKey string, comm *Common) error {
s, err := rd.Get(context.Background(), specialKey).Result() s, err := rd.Get(context.Background(), specialKey).Result()
if err != nil && !errors.Is(err, redis.Nil) { if err != nil && !errors.Is(err, redis.Nil) {
log.ErrorF("init config:%v", err) log.ErrorF("init config:%v", err)
@ -39,24 +39,12 @@ func LoadSpecialConfig[T any](rd *redis.Client, specialKey string, comm *Common[
if s == "" { if s == "" {
return fmt.Errorf("config:%s not found from redis", specialKey) return fmt.Errorf("config:%s not found from redis", specialKey)
} }
var result resultT[T] comm.GameJson = s
if err = json.Unmarshal([]byte(s), &result.Value); err != nil {
log.ErrorF("init special config:%v", err)
return err
}
comm.Special = &result.Value
return nil return nil
} }
type resultT[T any] struct { func LoadCommonConfig(rd *redis.Client, GitCommit, GitBranch, BuildDate string) (*Common, error) {
Value T var comm Common
//Err error
}
func LoadCommonConfig[T any](rd *redis.Client, GitCommit, GitBranch, BuildDate string) (*Common[T], error) {
var ret resultT[T]
var comm Common[T]
comm.Special = &ret.Value
comm.GitCommit = GitCommit comm.GitCommit = GitCommit
comm.GitBranch = GitBranch comm.GitBranch = GitBranch
comm.BuildDate = BuildDate comm.BuildDate = BuildDate

View File

@ -34,7 +34,7 @@ func TestConfig(t *testing.T) {
log.Error(err.Error()) log.Error(err.Error())
return return
} }
if err = LoadSpecialConfig[specialConfig](rdb, specialKey, comm); err != nil { if err = LoadGameConfig[specialConfig](rdb, specialKey, comm); err != nil {
log.Error(err.Error()) log.Error(err.Error())
} else { } else {
log.DebugF("load common config success:%#v", comm) log.DebugF("load common config success:%#v", comm)

116
common/jackpot/jackpot.go Normal file
View File

@ -0,0 +1,116 @@
package jackpot
import (
"fmt"
"game/common/model/jackpot"
"github.com/fox/fox/log"
"github.com/go-redis/redis/v8"
)
type JackPotMgr struct {
gameId int
jackpotUser map[int64]int64 // 中jackpot玩家key:玩家id value:投注额bet
rdb *redis.Client
}
func NewJackpotMgr(gameId int, rdb *redis.Client) *JackPotMgr {
mgr := &JackPotMgr{}
mgr.gameId = gameId
mgr.rdb = rdb
return mgr
}
// true:出现垫资
func (m *JackPotMgr) Load(initJp int64) bool {
if jackpot.JackpotGet(m.rdb, m.gameId) < initJp {
return true
}
return false
}
func (m *JackPotMgr) resetJackpot(initJp int64) int64 {
jackpot.JackpotAdd(m.rdb, m.gameId, initJp)
count := jackpot.JackpotInitCountAdd(m.rdb, m.gameId)
system := jackpot.JackpotSystemAdd(m.rdb, m.gameId, -initJp)
log.Info(fmt.Sprintf("game:%v gameid:%v jackpot已被掏空重置为:%v 重置次数:%v 系统盈亏:%v", m.gameId, m.gameId, initJp, count, system))
return initJp
}
func (m *JackPotMgr) GetJackpot() int64 {
return jackpot.JackpotGet(m.rdb, m.gameId)
}
// jpXRate:赎回比例 jpYRate:追加比例
func (m *JackPotMgr) AddJp(loseBet, jpXRate, jpYRate, jpXYRate int64) (jpX, jpY int64) {
if loseBet == 0 {
return
}
// jackpot池追加资金、玩家赎回资金(让庄家jp池垫的钱回归0)、庄家总垫资
var jpAdd, userRepaid, sysValue int64
if sysValue = jackpot.JackpotSystemGet(m.rdb, m.gameId); sysValue < 1 {
userRepaid = loseBet * jpXRate / 10000
jpAdd = loseBet * jpYRate / 10000
sysValue = jackpot.JackpotSystemAdd(m.rdb, m.gameId, userRepaid)
_ = jackpot.JackpotUserRepaidAdd(m.rdb, m.gameId, userRepaid)
} else {
jpAdd = loseBet * jpXYRate / 10000
}
log.Debug(fmt.Sprintf("%v进入系统池,%v进入jackpot池系统池盈亏:%v", userRepaid, jpAdd, sysValue))
return userRepaid, jpAdd
}
// 回滚。funding:垫资,jpX:赎回 jpY:追加
func (m *JackPotMgr) RollBackJpXAndJpY(lastJackpot, funding, jpX, jpY int64) {
log.Debug(fmt.Sprintf("分出去的jackpot:%v,当前jackpot池:%v 需要回退的垫资:%v 需要回退的赎回jpx:%v 需要回退的追加jpy:%v",
lastJackpot, jackpot.JackpotGet(m.rdb, m.gameId), funding, jpX, jpY))
jpv := jackpot.JackpotAdd(m.rdb, m.gameId, -jpY)
sys := jackpot.JackpotSystemAdd(m.rdb, m.gameId, -jpX)
repaid := jackpot.JackpotUserRepaidAdd(m.rdb, m.gameId, -jpX)
log.Debug(fmt.Sprintf("当前系统池:%v赎回值:%v", sys, repaid))
if lastJackpot == 0 {
return
}
jackpot.JackpotSet(m.rdb, m.gameId, lastJackpot)
jpv = jackpot.JackpotAdd(m.rdb, m.gameId, -jpY)
jpv = jackpot.JackpotGet(m.rdb, m.gameId)
sys = jackpot.JackpotSystemAdd(m.rdb, m.gameId, funding)
log.Debug(fmt.Sprintf("当前系统池:%v赎回值:%v jackpot值:%v", sys, repaid, jpv))
}
// 中jackpot玩家
func (m *JackPotMgr) AddJpUser(userId, bet int64) {
if jpBet, ok := m.jackpotUser[userId]; ok {
m.jackpotUser[userId] = jpBet + bet
} else {
m.jackpotUser[userId] = bet
}
}
// 返回map[中奖玩家]奖金,总jackpot值
func (m *JackPotMgr) WinJackpot() (map[int64]int64, int64) {
if len(m.jackpotUser) == 0 {
return nil, 0
}
jpV := jackpot.JackpotGet(m.rdb, m.gameId)
// totalJpBet := int64(0)
// for _, bet := range m.jackpotUser {
// totalJpBet += bet
// }
// jpRate := jackpot / totalJpBet
// log.Debug("jackpot:", jackpot, " totalJpBet:", totalJpBet, " jpRate:", jpRate)
// winUser := make(map[int64]int64)
// for userId, bet := range m.jackpotUser {
// winUser[userId] = bet * jpRate
// }
userJp := jpV / int64(len(m.jackpotUser))
log.DebugF("jackpot:%v 每个玩家分jp:%v. 清空jackpot池", userJp, userJp)
winUser := make(map[int64]int64)
for userId := range m.jackpotUser {
winUser[userId] = userJp
}
jackpot.JackpotSet(m.rdb, m.gameId, 0)
m.jackpotUser = make(map[int64]int64)
return winUser, jpV
}

View File

@ -0,0 +1,10 @@
package jackpot
import (
"testing"
)
func TestCleanWarn(t *testing.T) {
_ = t
_ = NewJackpotMgr
}

View File

@ -0,0 +1,54 @@
package jackpot
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"strconv"
)
func JackpotSet(rdb *redis.Client, gameId int, chips int64) {
key := fmt.Sprintf("Jackpot:%d", gameId)
_, _ = rdb.Set(context.Background(), key, chips, 0).Result()
}
func JackpotAdd(rdb *redis.Client, gameId int, chips int64) int64 {
key := fmt.Sprintf("Jackpot:%d", gameId)
v, _ := rdb.IncrBy(context.Background(), key, chips).Result()
return v
}
func JackpotGet(rdb *redis.Client, gameId int) int64 {
key := fmt.Sprintf("Jackpot:%d", gameId)
jp := rdb.Get(context.Background(), key).Val()
result, _ := strconv.ParseInt(jp, 10, 64)
return result
}
// jp系统池玩家部分利润进入该池重置jackpot池时从这里扣除。系统池反映系统盈亏
func JackpotSystemAdd(rdb *redis.Client, gameId int, chips int64) int64 {
key := fmt.Sprintf("JackpotSystem:%d", gameId)
value, _ := rdb.IncrBy(context.Background(), key, chips).Result()
return value
}
func JackpotSystemGet(rdb *redis.Client, gameId int) int64 {
key := fmt.Sprintf("JackpotSystem:%d", gameId)
jp := rdb.Get(context.Background(), key).Val()
result, _ := strconv.ParseInt(jp, 10, 64)
return result
}
// 玩家总赎回
func JackpotUserRepaidAdd(rdb *redis.Client, gameId int, chips int64) int64 {
key := fmt.Sprintf("JackpotUserRepaid:%d", gameId)
value, _ := rdb.IncrBy(context.Background(), key, chips).Result()
return value
}
// jp池重置次数
func JackpotInitCountAdd(rdb *redis.Client, gameId int) int64 {
key := fmt.Sprintf("JackpotInitCount:%d", gameId)
count, _ := rdb.IncrBy(context.Background(), key, 1).Result()
return count
}

View File

@ -197,9 +197,9 @@ message NtfColorEndBetting
message NtfColorOpenThreeDice message NtfColorOpenThreeDice
{ {
repeated ColorType color = 1; // 3 repeated ColorType color = 1; // 3
int32 aniRouteIndex = 3; // int32 aniRouteIndex = 3; //
repeated ColorBetAreaMul winBetArea = 5; // repeated ColorBetArea winArea = 4; //
} }
@ -208,15 +208,17 @@ message NtfColorSettle
{ {
message UserBetAreaMul message UserBetAreaMul
{ {
ColorBetAreaMul areaMul = 1; ColorBetAreaMul areaMul = 1;
int64 bet = 2; // int64 bet = 2; //
int64 win = 3; // int64 win = 3; //
int64 realWin = 4; //
} }
repeated UserBetAreaMul userAreaWin = 1; // repeated UserBetAreaMul userAreaWin = 1; //
repeated ColorType threeDice = 2; // repeated ColorType threeDice = 2; //
int64 totalWin = 3; // int64 totalWin = 3; //
int64 totalBet = 4; // int64 totalBet = 4; //
int64 totalWinBaseBet = 6; //
int64 tax = 5; // int64 tax = 5; //
} }

View File

@ -1258,9 +1258,9 @@ func (x *NtfColorEndBetting) GetJackpot() int64 {
type NtfColorOpenThreeDice struct { type NtfColorOpenThreeDice struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
Color []ColorType `protobuf:"varint,1,rep,packed,name=color,proto3,enum=pb.ColorType" json:"color,omitempty"` // 骰子开出颜色 3个 Color []ColorType `protobuf:"varint,1,rep,packed,name=color,proto3,enum=pb.ColorType" json:"color,omitempty"` // 骰子开出颜色 3个
AniRouteIndex int32 `protobuf:"varint,3,opt,name=aniRouteIndex,proto3" json:"aniRouteIndex,omitempty"` // 动画路径 AniRouteIndex int32 `protobuf:"varint,3,opt,name=aniRouteIndex,proto3" json:"aniRouteIndex,omitempty"` // 动画路径
WinBetArea []*ColorBetAreaMul `protobuf:"bytes,5,rep,name=winBetArea,proto3" json:"winBetArea,omitempty"` // 中奖区域高亮 WinArea []ColorBetArea `protobuf:"varint,4,rep,packed,name=winArea,proto3,enum=pb.ColorBetArea" json:"winArea,omitempty"` // 中奖区域高亮
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
} }
@ -1309,23 +1309,24 @@ func (x *NtfColorOpenThreeDice) GetAniRouteIndex() int32 {
return 0 return 0
} }
func (x *NtfColorOpenThreeDice) GetWinBetArea() []*ColorBetAreaMul { func (x *NtfColorOpenThreeDice) GetWinArea() []ColorBetArea {
if x != nil { if x != nil {
return x.WinBetArea return x.WinArea
} }
return nil return nil
} }
// 玩家结算信息 // 玩家结算信息
type NtfColorSettle struct { type NtfColorSettle struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
UserAreaWin []*NtfColorSettle_UserBetAreaMul `protobuf:"bytes,1,rep,name=userAreaWin,proto3" json:"userAreaWin,omitempty"` // 每个投注区域的下注及输赢 UserAreaWin []*NtfColorSettle_UserBetAreaMul `protobuf:"bytes,1,rep,name=userAreaWin,proto3" json:"userAreaWin,omitempty"` // 每个投注区域的下注及输赢
ThreeDice []ColorType `protobuf:"varint,2,rep,packed,name=threeDice,proto3,enum=pb.ColorType" json:"threeDice,omitempty"` // 骰子开出颜色 ThreeDice []ColorType `protobuf:"varint,2,rep,packed,name=threeDice,proto3,enum=pb.ColorType" json:"threeDice,omitempty"` // 骰子开出颜色
TotalWin int64 `protobuf:"varint,3,opt,name=totalWin,proto3" json:"totalWin,omitempty"` // 总输赢 TotalWin int64 `protobuf:"varint,3,opt,name=totalWin,proto3" json:"totalWin,omitempty"` // 总输赢
TotalBet int64 `protobuf:"varint,4,opt,name=totalBet,proto3" json:"totalBet,omitempty"` // 总投注 TotalBet int64 `protobuf:"varint,4,opt,name=totalBet,proto3" json:"totalBet,omitempty"` // 总投注
Tax int64 `protobuf:"varint,5,opt,name=tax,proto3" json:"tax,omitempty"` // 税 TotalWinBaseBet int64 `protobuf:"varint,6,opt,name=totalWinBaseBet,proto3" json:"totalWinBaseBet,omitempty"` // 赢钱区域的总投注
unknownFields protoimpl.UnknownFields Tax int64 `protobuf:"varint,5,opt,name=tax,proto3" json:"tax,omitempty"` // 税
sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
} }
func (x *NtfColorSettle) Reset() { func (x *NtfColorSettle) Reset() {
@ -1386,6 +1387,13 @@ func (x *NtfColorSettle) GetTotalBet() int64 {
return 0 return 0
} }
func (x *NtfColorSettle) GetTotalWinBaseBet() int64 {
if x != nil {
return x.TotalWinBaseBet
}
return 0
}
func (x *NtfColorSettle) GetTax() int64 { func (x *NtfColorSettle) GetTax() int64 {
if x != nil { if x != nil {
return x.Tax return x.Tax
@ -1797,8 +1805,9 @@ func (x *NtfColorBetAreaInfo_BetAreaInfo) GetMyBet() int64 {
type NtfColorSettle_UserBetAreaMul struct { type NtfColorSettle_UserBetAreaMul struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
AreaMul *ColorBetAreaMul `protobuf:"bytes,1,opt,name=areaMul,proto3" json:"areaMul,omitempty"` AreaMul *ColorBetAreaMul `protobuf:"bytes,1,opt,name=areaMul,proto3" json:"areaMul,omitempty"`
Bet int64 `protobuf:"varint,2,opt,name=bet,proto3" json:"bet,omitempty"` // 玩家在该区域投注金额 Bet int64 `protobuf:"varint,2,opt,name=bet,proto3" json:"bet,omitempty"` // 玩家在该区域投注金额
Win int64 `protobuf:"varint,3,opt,name=win,proto3" json:"win,omitempty"` // 该区域赢钱 Win int64 `protobuf:"varint,3,opt,name=win,proto3" json:"win,omitempty"` // 该区域税前赢钱
RealWin int64 `protobuf:"varint,4,opt,name=realWin,proto3" json:"realWin,omitempty"` // 税后赢钱
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
} }
@ -1854,6 +1863,13 @@ func (x *NtfColorSettle_UserBetAreaMul) GetWin() int64 {
return 0 return 0
} }
func (x *NtfColorSettle_UserBetAreaMul) GetRealWin() int64 {
if x != nil {
return x.RealWin
}
return 0
}
type NtfColorTrend_ColorRate struct { type NtfColorTrend_ColorRate struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
Color ColorType `protobuf:"varint,1,opt,name=color,proto3,enum=pb.ColorType" json:"color,omitempty"` Color ColorType `protobuf:"varint,1,opt,name=color,proto3,enum=pb.ColorType" json:"color,omitempty"`
@ -1973,23 +1989,23 @@ const file_colorgame_proto_rawDesc = "" +
"\x12NtfColorEndBetting\x12\x18\n" + "\x12NtfColorEndBetting\x12\x18\n" +
"\aendTime\x18\x01 \x01(\x03R\aendTime\x12-\n" + "\aendTime\x18\x01 \x01(\x03R\aendTime\x12-\n" +
"\aareaMul\x18\x02 \x03(\v2\x13.pb.ColorBetAreaMulR\aareaMul\x12\x18\n" + "\aareaMul\x18\x02 \x03(\v2\x13.pb.ColorBetAreaMulR\aareaMul\x12\x18\n" +
"\ajackpot\x18\x03 \x01(\x03R\ajackpot\"\x97\x01\n" + "\ajackpot\x18\x03 \x01(\x03R\ajackpot\"\x8e\x01\n" +
"\x15NtfColorOpenThreeDice\x12#\n" + "\x15NtfColorOpenThreeDice\x12#\n" +
"\x05color\x18\x01 \x03(\x0e2\r.pb.ColorTypeR\x05color\x12$\n" + "\x05color\x18\x01 \x03(\x0e2\r.pb.ColorTypeR\x05color\x12$\n" +
"\raniRouteIndex\x18\x03 \x01(\x05R\raniRouteIndex\x123\n" + "\raniRouteIndex\x18\x03 \x01(\x05R\raniRouteIndex\x12*\n" +
"\n" + "\awinArea\x18\x04 \x03(\x0e2\x10.pb.ColorBetAreaR\awinArea\"\xf5\x02\n" +
"winBetArea\x18\x05 \x03(\v2\x13.pb.ColorBetAreaMulR\n" +
"winBetArea\"\xb1\x02\n" +
"\x0eNtfColorSettle\x12C\n" + "\x0eNtfColorSettle\x12C\n" +
"\vuserAreaWin\x18\x01 \x03(\v2!.pb.NtfColorSettle.UserBetAreaMulR\vuserAreaWin\x12+\n" + "\vuserAreaWin\x18\x01 \x03(\v2!.pb.NtfColorSettle.UserBetAreaMulR\vuserAreaWin\x12+\n" +
"\tthreeDice\x18\x02 \x03(\x0e2\r.pb.ColorTypeR\tthreeDice\x12\x1a\n" + "\tthreeDice\x18\x02 \x03(\x0e2\r.pb.ColorTypeR\tthreeDice\x12\x1a\n" +
"\btotalWin\x18\x03 \x01(\x03R\btotalWin\x12\x1a\n" + "\btotalWin\x18\x03 \x01(\x03R\btotalWin\x12\x1a\n" +
"\btotalBet\x18\x04 \x01(\x03R\btotalBet\x12\x10\n" + "\btotalBet\x18\x04 \x01(\x03R\btotalBet\x12(\n" +
"\x03tax\x18\x05 \x01(\x03R\x03tax\x1ac\n" + "\x0ftotalWinBaseBet\x18\x06 \x01(\x03R\x0ftotalWinBaseBet\x12\x10\n" +
"\x03tax\x18\x05 \x01(\x03R\x03tax\x1a}\n" +
"\x0eUserBetAreaMul\x12-\n" + "\x0eUserBetAreaMul\x12-\n" +
"\aareaMul\x18\x01 \x01(\v2\x13.pb.ColorBetAreaMulR\aareaMul\x12\x10\n" + "\aareaMul\x18\x01 \x01(\v2\x13.pb.ColorBetAreaMulR\aareaMul\x12\x10\n" +
"\x03bet\x18\x02 \x01(\x03R\x03bet\x12\x10\n" + "\x03bet\x18\x02 \x01(\x03R\x03bet\x12\x10\n" +
"\x03win\x18\x03 \x01(\x03R\x03win\"y\n" + "\x03win\x18\x03 \x01(\x03R\x03win\x12\x18\n" +
"\arealWin\x18\x04 \x01(\x03R\arealWin\"y\n" +
"\tColorUser\x12\x12\n" + "\tColorUser\x12\x12\n" +
"\x04Nick\x18\x01 \x01(\tR\x04Nick\x12\x12\n" + "\x04Nick\x18\x01 \x01(\tR\x04Nick\x12\x12\n" +
"\x04Head\x18\x02 \x01(\tR\x04Head\x12\x14\n" + "\x04Head\x18\x02 \x01(\tR\x04Head\x12\x14\n" +
@ -2147,7 +2163,7 @@ var file_colorgame_proto_depIdxs = []int32{
4, // 26: pb.ColorBetAreaMul.prizeType:type_name -> pb.ColorPrizeType 4, // 26: pb.ColorBetAreaMul.prizeType:type_name -> pb.ColorPrizeType
19, // 27: pb.NtfColorEndBetting.areaMul:type_name -> pb.ColorBetAreaMul 19, // 27: pb.NtfColorEndBetting.areaMul:type_name -> pb.ColorBetAreaMul
1, // 28: pb.NtfColorOpenThreeDice.color:type_name -> pb.ColorType 1, // 28: pb.NtfColorOpenThreeDice.color:type_name -> pb.ColorType
19, // 29: pb.NtfColorOpenThreeDice.winBetArea:type_name -> pb.ColorBetAreaMul 2, // 29: pb.NtfColorOpenThreeDice.winArea:type_name -> pb.ColorBetArea
30, // 30: pb.NtfColorSettle.userAreaWin:type_name -> pb.NtfColorSettle.UserBetAreaMul 30, // 30: pb.NtfColorSettle.userAreaWin:type_name -> pb.NtfColorSettle.UserBetAreaMul
1, // 31: pb.NtfColorSettle.threeDice:type_name -> pb.ColorType 1, // 31: pb.NtfColorSettle.threeDice:type_name -> pb.ColorType
26, // 32: pb.NtfColorBigUser.bigUser:type_name -> pb.ColorBigUser 26, // 32: pb.NtfColorBigUser.bigUser:type_name -> pb.ColorBigUser

View File

@ -1,14 +1,13 @@
package config package config
import ( import (
"context"
"encoding/json" "encoding/json"
"game/common/config" "game/common/config"
"game/common/config/game" "game/common/config/game"
"game/common/constant" "game/common/constant"
"github.com/fox/fox/db" "github.com/fox/fox/db"
"github.com/fox/fox/log" "github.com/fox/fox/log"
"github.com/go-redis/redis/v8" "sync"
) )
const ( const (
@ -16,8 +15,11 @@ const (
RateBase = 10000 // 概率或者权重的底数是1万 RateBase = 10000 // 概率或者权重的底数是1万
) )
var Command *config.Command var (
var Cfg *config.Common[game.ColorConfig] Command *config.Command
Cfg *config.Common
mtx sync.RWMutex
)
func InitLog() { func InitLog() {
log.Open("./log/color.log", log.DebugL) log.Open("./log/color.log", log.DebugL)
@ -35,21 +37,48 @@ func LoadConfig(GitCommit, GitBranch, BuildDate string) {
return return
} }
defer func() { _ = rdb.Close() }() defer func() { _ = rdb.Close() }()
Cfg, err = config.LoadCommonConfig[game.ColorConfig](rdb, GitCommit, GitBranch, BuildDate) Cfg, err = config.LoadCommonConfig(rdb, GitCommit, GitBranch, BuildDate)
if err != nil { if err != nil {
log.Error(err.Error()) log.Error(err.Error())
return return
} }
log.DebugF("load common config success") log.DebugF("load common config success")
LoadColorConfig(rdb) if err := config.LoadGameConfig(rdb, game.ColorKey, Cfg); err == nil {
}
func LoadColorConfig(rdb *redis.Client) {
if err := config.LoadSpecialConfig[game.ColorConfig](rdb, game.ColorKey, Cfg); err == nil {
return return
} }
Cfg.Special = &game.ColorConfig{} }
Cfg.Special.GameTiming = &game.ColorGameTiming{
// 当后台修改配置时,服务收到消息调用该消息。由于同进程内有多服务,所以要加锁,防止数据竞争
func LoadGameConfig() {
mtx.Lock()
defer mtx.Unlock()
rdb, err := db.InitRedis(Command.RedisPassword, Command.RedisHost, Command.RedisPort, constant.Redis0Config)
if err != nil {
log.Error(err.Error())
return
}
defer func() { _ = rdb.Close() }()
if err := config.LoadGameConfig(rdb, game.ColorKey, Cfg); err == nil {
return
}
}
func GetColorConfig() *game.ColorConfig {
empty := true
gameCfg := &game.ColorConfig{}
func() {
mtx.RLock()
defer mtx.RUnlock()
if Cfg.GameJson != "" {
_ = json.Unmarshal([]byte(Cfg.GameJson), gameCfg)
empty = false
}
}()
// json不为空后台有配置不需要默认配置
if !empty {
return gameCfg
}
gameCfg.GameTiming = &game.ColorGameTiming{
// Ready: 100, // 倒计时321 // Ready: 100, // 倒计时321
Start: 2000, Start: 2000,
Betting: 15000, Betting: 15000,
@ -102,9 +131,6 @@ func LoadColorConfig(rdb *redis.Client) {
AreaBetLimit: 500000, AreaBetLimit: 500000,
NoBetCountMax: 10, NoBetCountMax: 10,
} }
Cfg.Special.Rooms = append(Cfg.Special.Rooms, rmConfig) gameCfg.Rooms = append(gameCfg.Rooms, rmConfig)
return gameCfg
if bs, err := json.Marshal(&Cfg.Special); err == nil {
err = rdb.Set(context.Background(), game.ColorKey, string(bs), 0).Err()
}
} }

View File

@ -26,7 +26,7 @@ func (rm *ColorRoom) OnEnterRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *
// return // return
// } // }
// // 有下注时不让玩家离开 // // 有下注时不让玩家离开
// if u.TotalBet != 0 { // if u.totalBet != 0 {
// resp.Code = 1 // resp.Code = 1
// _ = user.SendMsg(int32(pb.ColorPinoyLiveReceiveFromClientMessageType_ColorPinoyLiveApplyLeave), resp) // _ = user.SendMsg(int32(pb.ColorPinoyLiveReceiveFromClientMessageType_ColorPinoyLiveApplyLeave), resp)
// return // return

View File

@ -3,6 +3,7 @@ package room
import ( import (
"game/common/baseroom" "game/common/baseroom"
"game/common/model/user" "game/common/model/user"
"game/common/proto/pb"
) )
type ColorPlayer struct { type ColorPlayer struct {
@ -11,6 +12,10 @@ type ColorPlayer struct {
gateTopicName string gateTopicName string
roomId int roomId int
totalBet int64 // 总下注金额
totalBets []int64 // 各个区域的下注
settleMsg *pb.NtfColorSettle // 本局结算消息
costGold int64 // 本局消耗金币 costGold int64 // 本局消耗金币
} }
@ -38,3 +43,14 @@ func (p *ColorPlayer) GateTopicName() string {
func (p *ColorPlayer) RoomId() int { func (p *ColorPlayer) RoomId() int {
return p.roomId return p.roomId
} }
// 游戏开始前,清理玩家上局数据
func (p *ColorPlayer) resetData() {
p.settleMsg = &pb.NtfColorSettle{}
p.costGold = 0
p.totalBet = 0
p.totalBets = p.totalBets[:0]
for range pb.ColorBetArea_name {
p.totalBets = append(p.totalBets, 0)
}
}

View File

@ -3,7 +3,9 @@ package room
import ( import (
"game/common/baseroom" "game/common/baseroom"
"game/common/config/game" "game/common/config/game"
"game/common/jackpot"
"game/common/proto/pb" "game/common/proto/pb"
"game/server/chat/model"
"github.com/fox/fox/log" "github.com/fox/fox/log"
"github.com/fox/fox/processor" "github.com/fox/fox/processor"
"github.com/fox/fox/service" "github.com/fox/fox/service"
@ -12,12 +14,19 @@ import (
type ColorRoom struct { type ColorRoom struct {
*baseroom.BaseRoom[ColorSeat] *baseroom.BaseRoom[ColorSeat]
roomCfg game.ColorRoomConfig roomCfg *game.ColorRoomConfig
timingCfg game.ColorGameTiming timingCfg *game.ColorGameTiming
status pb.ColorGameStatus status pb.ColorGameStatus
statusTime int64 // 毫秒时间戳 statusTime int64 // 毫秒时间戳
jackpot int64 users map[int64]*ColorPlayer // 所有玩家
endBetAreaMul []*pb.ColorBetAreaMul // 下注结束后,每个区域更新是否爆奖以及实际赔率
endBetAreaMul []*pb.ColorBetAreaMul // 下注结束后,每个区域更新是否爆奖以及实际赔率
ntfOpenThreeDice *pb.NtfColorOpenThreeDice // 开骰子的消息
winBetAreaMul []*pb.ColorBetAreaMul // 中奖区域及实际赔率
jackpotMgr *jackpot.JackPotMgr // jackpotValue
jackpotValue int64 // jackpot值
jackpotUser map[int64]int64 // 本局中jackpot的玩家用于游戏内广播
// --------------------------------- // ---------------------------------
// Status pb.ColorPinoyLiveGameStatus // 房间状态1 表示 // Status pb.ColorPinoyLiveGameStatus // 房间状态1 表示
// StatusTime int64 // 切换状态时的时间戳 // StatusTime int64 // 切换状态时的时间戳
@ -28,8 +37,8 @@ type ColorRoom struct {
// // DefaultLuckyDice byte // 幸运骰子 1个 每局开始 放在拉杆上的骰子 // // DefaultLuckyDice byte // 幸运骰子 1个 每局开始 放在拉杆上的骰子
// // DefaultNormalDices []byte // 普通骰子 3个 每局开始 放在拉杆上的骰子 // // DefaultNormalDices []byte // 普通骰子 3个 每局开始 放在拉杆上的骰子
// //
// TotalBets [BET_TYPE_NUM]int64 // 各区域的下注统计 // totalBets [BET_TYPE_NUM]int64 // 各区域的下注统计
// TotalBet int64 // 下注统计 // totalBet int64 // 下注统计
// //SceneInfo model.SceneInfo // 下注的玩家列表 // //SceneInfo model.SceneInfo // 下注的玩家列表
// //
// GameTrend *pb.ColorPinoyLiveTrend // 走势图 // GameTrend *pb.ColorPinoyLiveTrend // 走势图
@ -54,17 +63,19 @@ type ColorRoom struct {
} }
func newColorRoom(id, roomType int, srv service.IService) (baseroom.IRoom, pb.ErrCode) { func newColorRoom(id, roomType int, srv service.IService) (baseroom.IRoom, pb.ErrCode) {
playType := int(pb.ServiceTypeId_STI_ColorGame)
rm := &ColorRoom{ rm := &ColorRoom{
BaseRoom: nil, BaseRoom: nil,
roomCfg: game.ColorRoomConfig{}, roomCfg: &game.ColorRoomConfig{},
timingCfg: game.ColorGameTiming{}, timingCfg: &game.ColorGameTiming{},
status: 0, status: 0,
statusTime: 0, statusTime: 0,
jackpot: 0, jackpotValue: 0,
endBetAreaMul: make([]*pb.ColorBetAreaMul, 0, len(pb.ColorBetArea_name)), endBetAreaMul: make([]*pb.ColorBetAreaMul, 0, len(pb.ColorBetArea_name)),
winBetAreaMul: nil,
jackpotMgr: jackpot.NewJackpotMgr(playType, model.UserRedis),
} }
playType := 0
code := pb.ErrCode_OK code := pb.ErrCode_OK
rm.BaseRoom, code = baseroom.NewBaseRoom[ColorSeat](id, roomType, playType, srv) rm.BaseRoom, code = baseroom.NewBaseRoom[ColorSeat](id, roomType, playType, srv)
if code != pb.ErrCode_OK { if code != pb.ErrCode_OK {
@ -81,16 +92,24 @@ func (rm *ColorRoom) OnInit() {
}) })
rm.RegisterTimerMessages(processor.RegisterTimerMetas{ rm.RegisterTimerMessages(processor.RegisterTimerMetas{
TtGameStart: rm.gameStart, TtGameStart: rm.gameStart,
TtStartBetting: rm.startBetting, TtStartBetting: rm.gameStartBetting,
TtEndBet: rm.endBetting, TtEndBet: rm.gameEndBetting,
TtOpenThreeDices: rm.openThreeDices, TtOpenThreeDices: rm.gameOpenThreeDices,
TtSettle: rm.settle, TtSettle: rm.gameSettle,
}) })
rm.gameStart() rm.gameStart()
return return
} }
// 游戏开始前重置游戏数据
func (rm *ColorRoom) resetGameData() {
rm.updateConfig()
rm.initEndBetAreaMul()
rm.ntfOpenThreeDice = &pb.NtfColorOpenThreeDice{}
rm.jackpotValue = rm.jackpotMgr.GetJackpot()
}
// 当前拥有金币 // 当前拥有金币
func (rm *ColorRoom) GetGold(user *ColorPlayer) int64 { func (rm *ColorRoom) GetGold(user *ColorPlayer) int64 {
return user.Gold - user.costGold return user.Gold - user.costGold
@ -280,7 +299,7 @@ func (rm *ColorRoom) AddGold(user *ColorPlayer, add int64) (int64, bool) {
// func (rm *ColorRoom) UserExit(user inter.UserInetr) bool { // func (rm *ColorRoom) UserExit(user inter.UserInetr) bool {
// u := rm.getUser(user) // u := rm.getUser(user)
// // 有下注时不让玩家离开 // // 有下注时不让玩家离开
// if u.TotalBet != 0 { // if u.totalBet != 0 {
// return false // return false
// } // }
// rm.KickOutUser(u) // rm.KickOutUser(u)
@ -288,7 +307,7 @@ func (rm *ColorRoom) AddGold(user *ColorPlayer, add int64) (int64, bool) {
// } // }
// func (rm *ColorRoom) LeaveGame(user inter.UserInetr) bool { // func (rm *ColorRoom) LeaveGame(user inter.UserInetr) bool {
// u := rm.getUser(user) // u := rm.getUser(user)
// if u.TotalBet != 0 { // if u.totalBet != 0 {
// // msg := new(pb.KickOutUserMsg) // // msg := new(pb.KickOutUserMsg)
// // msg.KickOutReason = "游戏中不能退出!" // // msg.KickOutReason = "游戏中不能退出!"
// // u.SendMsg(int32(pb.SendToClientMessageType_NoticeExitRet), msg) // // u.SendMsg(int32(pb.SendToClientMessageType_NoticeExitRet), msg)

View File

@ -3,9 +3,12 @@ package room
import ( import (
"game/common/config/game" "game/common/config/game"
"game/common/proto/pb" "game/common/proto/pb"
"game/server/colorgame/config"
"github.com/fox/fox/ksync"
"github.com/fox/fox/log" "github.com/fox/fox/log"
"github.com/fox/fox/xrand" "github.com/fox/fox/xrand"
"github.com/fox/fox/xtime" "github.com/fox/fox/xtime"
"sync"
) )
func (rm *ColorRoom) setStatus(status pb.ColorGameStatus) { func (rm *ColorRoom) setStatus(status pb.ColorGameStatus) {
@ -31,6 +34,18 @@ func (rm *ColorRoom) endTimeStatus() int64 {
return rm.statusTime + duration 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() { func (rm *ColorRoom) initEndBetAreaMul() {
rm.endBetAreaMul = rm.endBetAreaMul[0:0] rm.endBetAreaMul = rm.endBetAreaMul[0:0]
@ -50,13 +65,13 @@ func (rm *ColorRoom) initEndBetAreaMul() {
Area: pb.ColorBetArea(pos), Area: pb.ColorBetArea(pos),
PrizeArea: prizeArea, PrizeArea: prizeArea,
PrizeType: pb.ColorPrizeType_CPT_Normal, PrizeType: pb.ColorPrizeType_CPT_Normal,
Mul: mul[0].Mul, Mul: mul[0].Mul / config.Hundred,
}) })
} }
} }
// 随机出某个奖励档位下的赔率数组,档位,赔率数组概率之和 // 随机出某个奖励档位下的赔率数组,档位,赔率数组概率之和
func (rm *ColorRoom) randArrMul(area pb.ColorBetArea) (singleMul []*game.ColorMulRate, prizeArea pb.ColorPrizeArea, sumRate int) { func (rm *ColorRoom) randArrMul(area pb.ColorBetArea) (arrMul []*game.ColorMulRate, prizeArea pb.ColorPrizeArea, sumRate int) {
switch area / 6 { switch area / 6 {
case 0: case 0:
maxWeight := 0 maxWeight := 0
@ -64,66 +79,297 @@ func (rm *ColorRoom) randArrMul(area pb.ColorBetArea) (singleMul []*game.ColorMu
maxWeight += w maxWeight += w
} }
weight := xrand.RandRange[int](0, maxWeight) 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: case 1:
prizeArea = pb.ColorPrizeArea_CPA_Double
arrMul = rm.roomCfg.WinDoubleColorMul
case 2: case 2:
prizeArea = pb.ColorPrizeArea_CPA_Three
arrMul = rm.roomCfg.WinThreeColorMul
default: default:
log.Error("area:%v is not exist") log.Error("area:%v is not exist")
return return
} }
for _, mr := range arrMul {
// log.Debug(rm.Log("单色投注区获取爆奖在双色还是三色,随机值为:%v 最大值:%v", weight, maxWeight)) sumRate += mr.Rate
}
return nil, 0 return
} }
// 下注结束后,更新每个区域的实际赔率 // 下注结束后,更新每个区域的实际赔率
func (rm *ColorRoom) updateEndBetAreaMul() { func (rm *ColorRoom) updateEndBetAreaMul() {
for pos, _ := range pb.ColorBetArea_name { 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概率
for pos, betArea := range rm.betEndBetAreasOdds { // 只会有一个区域有jackpot标签
log.Debug(rm.Log("区域:%v 随机前 爆奖状态:%v", pb.ColorPinoyLiveBetTypeJP(pos), betArea.IsBigOdd)) if !jackpotExist && xrand.RandRange(0, config.RateBase) < rm.roomCfg.JackpotRate {
betArea.IsBigOdd = false bam.Mul = 0
// 区域位置 0-2分别为单色、双色、三色投注区域 bam.PrizeType = pb.ColorPrizeType_CPT_Jackpot
index := pos / 6 jackpotExist = true
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 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), mulPos := 0
mulRangeW[0].MinW, mulRangeW[len(mulRangeW)-1].MaxW, rdv, betArea)) 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 ( // import (
// "encoding/json" // "encoding/json"
@ -186,7 +432,7 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// } // }
// } // }
// //
// if totalBetAmount <= 0 || totalBetAmount+user.TotalBet > rm.RoomCfg.ColorPinoyLiveConfig.TotalBetLimit { // if totalBetAmount <= 0 || totalBetAmount+user.totalBet > rm.RoomCfg.ColorPinoyLiveConfig.TotalBetLimit {
// log.Error(rm.Log("DataErr totalBetAmount:%d err ", totalBetAmount)) // log.Error(rm.Log("DataErr totalBetAmount:%d err ", totalBetAmount))
// model.SendBetFailMessage(model.PlayerEarTopScore, user) // model.SendBetFailMessage(model.PlayerEarTopScore, user)
// return // return
@ -194,7 +440,7 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// log.Debug(rm.LogEx(user, "下注区域最大金额:%v", rm.Cfg.AreaBetLimit)) // log.Debug(rm.LogEx(user, "下注区域最大金额:%v", rm.Cfg.AreaBetLimit))
// for i, num := range betInfos { // for i, num := range betInfos {
// // 投注大于下注区域限制 // // 投注大于下注区域限制
// if (user.TotalBets[i] + num) > rm.Cfg.AreaBetLimit { // if (user.totalBets[i] + num) > rm.Cfg.AreaBetLimit {
// // log.Debug("PlayerEarTopScore totalBetAmount:%d err ", totalBetAmount) // // log.Debug("PlayerEarTopScore totalBetAmount:%d err ", totalBetAmount)
// model.SendBetFailMessage(model.PlayerEarTopScore, user) // model.SendBetFailMessage(model.PlayerEarTopScore, user)
// return // return
@ -207,19 +453,19 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// user.LastTimeBet = make([][]*pb.ColorPinoyLiveBetReq, 0) // user.LastTimeBet = make([][]*pb.ColorPinoyLiveBetReq, 0)
// } // }
// user.LastTimeBet = append(user.LastTimeBet, bets) // user.LastTimeBet = append(user.LastTimeBet, bets)
// user.TotalBet += totalBetAmount // user.totalBet += totalBetAmount
// // log.Debug("上次下注:", user.LastTimeBet) // // log.Debug("上次下注:", user.LastTimeBet)
// rm.MutexData.Lock() // rm.MutexData.Lock()
// for i, num := range betInfos { // for i, num := range betInfos {
// if num > 0 { // if num > 0 {
// user.TotalBets[i] += num // user.totalBets[i] += num
// rm.TotalBets[i] += num // rm.totalBets[i] += num
// //
// SendSuccessMessage := new(pb.ColorPinoyLiveBetSuccessMessage) // SendSuccessMessage := new(pb.ColorPinoyLiveBetSuccessMessage)
// SendSuccessMessage.BetType = pb.ColorPinoyLiveBetTypeJP(i) // SendSuccessMessage.BetType = pb.ColorPinoyLiveBetTypeJP(i)
// SendSuccessMessage.UserBet = num // SendSuccessMessage.UserBet = num
// SendSuccessMessage.UserBets = user.TotalBets[i] + num // SendSuccessMessage.UserBets = user.totalBets[i] + num
// SendSuccessMessage.TotalBets = rm.TotalBets[i] + num // SendSuccessMessage.totalBets = rm.totalBets[i] + num
// oneBetMessage.BetInfo = append(oneBetMessage.BetInfo, SendSuccessMessage) // oneBetMessage.BetInfo = append(oneBetMessage.BetInfo, SendSuccessMessage)
// } // }
// } // }
@ -233,9 +479,9 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// user.AllBet += totalBetAmount // user.AllBet += totalBetAmount
// user.NoBetCount = 0 // user.NoBetCount = 0
// oneBetMessage.UserScore = user.Balance // oneBetMessage.UserScore = user.Balance
// // oneBetMessage.UserBets = user.TotalBets[:] // // oneBetMessage.UserBets = user.totalBets[:]
// //
// rm.TotalBet += totalBetAmount // rm.totalBet += totalBetAmount
// rm.MutexData.Unlock() // rm.MutexData.Unlock()
// //
// rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameSeatUserBet), oneBetMessage) // rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameSeatUserBet), oneBetMessage)
@ -310,8 +556,8 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// //
// rm.MutexData.Lock() // rm.MutexData.Lock()
// for i, num := range betInfos { // for i, num := range betInfos {
// user.TotalBets[i] -= num // user.totalBets[i] -= num
// rm.TotalBets[i] -= num // rm.totalBets[i] -= num
// } // }
// // 统计个区域投注次数 // // 统计个区域投注次数
// for i, count := range betCountInfos { // for i, count := range betCountInfos {
@ -322,9 +568,9 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// user.TotalBetsCount[i] = 0 // user.TotalBetsCount[i] = 0
// } // }
// } // }
// rm.TotalBet -= totalBetAmount // rm.totalBet -= totalBetAmount
// //
// user.TotalBet -= totalBetAmount // user.totalBet -= totalBetAmount
// user.AllBet -= totalBetAmount // user.AllBet -= totalBetAmount
// user.NoBetCount = 0 // user.NoBetCount = 0
// //
@ -334,8 +580,8 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// SendSuccessMessage.SeatId = int32(user.SceneChairId) // SendSuccessMessage.SeatId = int32(user.SceneChairId)
// SendSuccessMessage.BetType = pb.ColorPinoyLiveBetTypeJP(i) // SendSuccessMessage.BetType = pb.ColorPinoyLiveBetTypeJP(i)
// SendSuccessMessage.UserBet = num // SendSuccessMessage.UserBet = num
// SendSuccessMessage.UserBets = user.TotalBets[i] // SendSuccessMessage.UserBets = user.totalBets[i]
// SendSuccessMessage.TotalBets = rm.TotalBets[i] // SendSuccessMessage.totalBets = rm.totalBets[i]
// //
// undoBetMessage.BetInfo = append(undoBetMessage.BetInfo, SendSuccessMessage) // undoBetMessage.BetInfo = append(undoBetMessage.BetInfo, SendSuccessMessage)
// } // }
@ -400,14 +646,14 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// //
// func (rm *ColorRoom) ResetUserBet(user *model.User) { // func (rm *ColorRoom) ResetUserBet(user *model.User) {
// rm.MutexData.Lock() // rm.MutexData.Lock()
// for i, bet := range user.TotalBets { // for i, bet := range user.totalBets {
// rm.TotalBets[i] -= bet // rm.totalBets[i] -= bet
// // rm.BetNumber[i] -= user.BetNumber[i] // // rm.BetNumber[i] -= user.BetNumber[i]
// } // }
// rm.TotalBet -= user.TotalBet // rm.totalBet -= user.totalBet
// rm.MutexData.Unlock() // rm.MutexData.Unlock()
// user.TotalBet = 0 // user.totalBet = 0
// user.TotalBets = [config.BET_TYPE_NUM]int64{} // user.totalBets = [config.BET_TYPE_NUM]int64{}
// // user.BetNumber = [config.BET_TYPE_NUM]int64{} // // user.BetNumber = [config.BET_TYPE_NUM]int64{}
// //
// } // }
@ -422,8 +668,8 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// defer wg.Done() // defer wg.Done()
// user.Mn.Lock() // user.Mn.Lock()
// defer user.Mn.Unlock() // defer user.Mn.Unlock()
// if user.TotalBet > 0 { // if user.totalBet > 0 {
// _, err := rm.TransInoutGameEnd(user, user.TotalBet, 0, 0) // _, err := rm.TransInoutGameEnd(user, user.totalBet, 0, 0)
// if err != nil { // if err != nil {
// func() { // func() {
// failMutx.Lock() // failMutx.Lock()
@ -464,7 +710,7 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// SendSuccessMessage.BetType = bet.BetType // SendSuccessMessage.BetType = bet.BetType
// SendSuccessMessage.SeatId = int32(user.SceneChairId) // SendSuccessMessage.SeatId = int32(user.SceneChairId)
// SendSuccessMessage.UserBet = bet.BetAmount // SendSuccessMessage.UserBet = bet.BetAmount
// SendSuccessMessage.TotalBets = rm.TotalBets[bet.BetType] // SendSuccessMessage.totalBets = rm.totalBets[bet.BetType]
// //
// player.BetInfo = append(player.BetInfo, SendSuccessMessage) // player.BetInfo = append(player.BetInfo, SendSuccessMessage)
// } // }
@ -476,8 +722,8 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// // 大客投注 // // 大客投注
// var allWinner []*pb.ColorPinoyLiveBigWinner // var allWinner []*pb.ColorPinoyLiveBigWinner
// rm.Traverse(func(user *model.User) bool { // rm.Traverse(func(user *model.User) bool {
// if user.TotalBet > 0 { // if user.totalBet > 0 {
// allWinner = append(allWinner, &pb.ColorPinoyLiveBigWinner{NickName: user.UserInetr.GetNike(), Avatar: user.UserInetr.GetHead(), WinChips: user.TotalBet, AreaId: user.TotalBets[:]}) // allWinner = append(allWinner, &pb.ColorPinoyLiveBigWinner{NickName: user.UserInetr.GetNike(), Avatar: user.UserInetr.GetHead(), WinChips: user.totalBet, AreaId: user.totalBets[:]})
// } // }
// return true // return true
// }) // })
@ -490,10 +736,10 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// }) // })
// allUserTotalBet := int64(0) // 所有玩家投注未中奖的总金额用于计算jackpot池 // allUserTotalBet := int64(0) // 所有玩家投注未中奖的总金额用于计算jackpot池
// rm.Traverse(func(user *model.User) bool { // rm.Traverse(func(user *model.User) bool {
// if user.TotalBet < 1 { // if user.totalBet < 1 {
// return true // return true
// } // }
// allUserTotalBet += user.TotalBet // allUserTotalBet += user.totalBet
// return true // return true
// }) // })
// log.Debug(rm.Log("本局总投注金额为:%v 赎回比例:%v 追加比例:%v 满额追加比例:%v", allUserTotalBet, rm.Cfg.JpXRate, rm.Cfg.JpYRate, rm.Cfg.JpXYRate)) // log.Debug(rm.Log("本局总投注金额为:%v 赎回比例:%v 追加比例:%v 满额追加比例:%v", allUserTotalBet, rm.Cfg.JpXRate, rm.Cfg.JpYRate, rm.Cfg.JpXYRate))
@ -517,10 +763,10 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// } // }
// jackpotArea = winArea.BetArea // jackpotArea = winArea.BetArea
// rm.Traverse(func(user *model.User) bool { // rm.Traverse(func(user *model.User) bool {
// if user.TotalBets[winArea.BetArea] <= 0 { // if user.totalBets[winArea.BetArea] <= 0 {
// return true // return true
// } // }
// rm.jackpotMgr.AddJpUser(user.UserID, user.TotalBets[winArea.BetArea]) // rm.jackpotMgr.AddJpUser(user.UserID, user.totalBets[winArea.BetArea])
// return true // return true
// }) // })
// } // }
@ -540,21 +786,21 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// rm.Traverse(func(user *model.User) bool { // rm.Traverse(func(user *model.User) bool {
// msg := new(pb.ColorPinoyLiveUserSettleMsg) // msg := new(pb.ColorPinoyLiveUserSettleMsg)
// msg.WinAreaOdd = rm.PokerMsg.WinBetArea // msg.WinAreaOdd = rm.PokerMsg.WinBetArea
// msg.UserBets = rm.CopyArr(user.TotalBets) // msg.UserBets = rm.CopyArr(user.totalBets)
// msg.UserRealWins = make([]int64, config.BET_TYPE_NUM) // msg.UserRealWins = make([]int64, config.BET_TYPE_NUM)
// msg.UserWins = make([]int64, config.BET_TYPE_NUM) // msg.UserWins = make([]int64, config.BET_TYPE_NUM)
// //
// if user.TotalBet > 0 { // if user.totalBet > 0 {
// // 算分 // // 算分
// jpScore := userJackPot[user.UserID] // jpScore := userJackPot[user.UserID]
// rm.CalculateScore(user, jpArea, jpScore, msg) // rm.CalculateUserScore(user, jpArea, jpScore, msg)
// if jpScore > 0 { // if jpScore > 0 {
// jackpotUserName = append(jackpotUserName, user.UserInetr.GetNike()) // jackpotUserName = append(jackpotUserName, user.UserInetr.GetNike())
// rm.BroadHitJackpot(user, jpScore) // rm.BroadHitJackpot(user, jpScore)
// } // }
// } // }
// // 统计玩家信息 // // 统计玩家信息
// if msg.TotalWin > user.TotalBet { // if msg.TotalWin > user.totalBet {
// user.UserCount(true, msg.TotalWin) // user.UserCount(true, msg.TotalWin)
// } else { // } else {
// user.UserCount(false, 0) // user.UserCount(false, 0)
@ -571,7 +817,7 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// } // }
// //
// // 计算 下注区域中奖得分 // // 计算 下注区域中奖得分
// func (rm *ColorRoom) CalculateScore(user *model.User, jpArea pb.ColorPinoyLiveBetTypeJP, jpScore int64, msg *pb.ColorPinoyLiveUserSettleMsg) { // func (rm *ColorRoom) CalculateUserScore(user *model.User, jpArea pb.ColorPinoyLiveBetTypeJP, jpScore int64, msg *pb.ColorPinoyLiveUserSettleMsg) {
// for _, winArea := range msg.WinAreaOdd { // for _, winArea := range msg.WinAreaOdd {
// if msg.UserBets[winArea.BetArea] <= 0 { // if msg.UserBets[winArea.BetArea] <= 0 {
// continue // continue
@ -609,7 +855,7 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// msg.UserWins[winArea.BetArea] += win2 // msg.UserWins[winArea.BetArea] += win2
// msg.UserRealWins[winArea.BetArea] += Gold // msg.UserRealWins[winArea.BetArea] += Gold
// msg.JackpotWin = Gold // msg.JackpotWin = Gold
// log.Debug(rm.LogEx(user, "算分 jackpot 投注区:%v win2:%v Gold:%v", winArea.BetArea, win2, Gold)) // log.Debug(rm.LogEx(user, "算分 jackpotValue 投注区:%v win2:%v Gold:%v", winArea.BetArea, win2, Gold))
// } // }
// } // }
// //
@ -660,7 +906,7 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// wg.Add(1) // wg.Add(1)
// go func(u *model.User) { // go func(u *model.User) {
// defer wg.Done() // defer wg.Done()
// if u.TotalBet > 0 { // if u.totalBet > 0 {
// // 和平台做赢钱结算 // // 和平台做赢钱结算
// // if msg.TotalWin > 0 { // // if msg.TotalWin > 0 {
// _, err := rm.TransInoutGameEnd(u, 0, u.SettleMsg.TotalWin, u.SettleMsg.Tax) // _, err := rm.TransInoutGameEnd(u, 0, u.SettleMsg.TotalWin, u.SettleMsg.Tax)
@ -707,8 +953,8 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// // rm.OnlineUserList = append(rm.OnlineUserList, u) // // rm.OnlineUserList = append(rm.OnlineUserList, u)
// } // }
// func (rm *ColorRoom) ResetData(all bool) { // func (rm *ColorRoom) ResetData(all bool) {
// rm.TotalBets = [config.BET_TYPE_NUM]int64{} // rm.totalBets = [config.BET_TYPE_NUM]int64{}
// rm.TotalBet = 0 // rm.totalBet = 0
// rm.LuckyDice = 0 // rm.LuckyDice = 0
// rm.NormalDices = make([]byte, 3) // rm.NormalDices = make([]byte, 3)
// rm.StartDices = make([]byte, 3) // rm.StartDices = make([]byte, 3)
@ -1121,17 +1367,17 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// wg.Add(1) // wg.Add(1)
// monitor.GoSafe(func(u *model.User) { // monitor.GoSafe(func(u *model.User) {
// defer wg.Done() // defer wg.Done()
// u.RetrunGold = u.TotalBet // u.RetrunGold = u.totalBet
// msg := new(pb.ColorPinoyLiveUserSettleMsg) // msg := new(pb.ColorPinoyLiveUserSettleMsg)
// msg.UserBets = rm.CopyArr(u.TotalBets) // msg.UserBets = rm.CopyArr(u.totalBets)
// msg.UserRealWins = make([]int64, config.BET_TYPE_NUM) // msg.UserRealWins = make([]int64, config.BET_TYPE_NUM)
// msg.UserWins = make([]int64, config.BET_TYPE_NUM) // msg.UserWins = make([]int64, config.BET_TYPE_NUM)
// msg.WinAreaOdd = rm.PokerMsg.WinBetArea // msg.WinAreaOdd = rm.PokerMsg.WinBetArea
// msg.UserScore = u.Balance // msg.UserScore = u.Balance
// u.SettleMsg = msg // u.SettleMsg = msg
// // 写入数据库统计信息 // // 写入数据库统计信息
// if u.TotalBet > 0 { // if u.totalBet > 0 {
// for i, bet := range u.TotalBets { // for i, bet := range u.totalBets {
// betCount += bet // betCount += bet
// GameTotalBets[i] += bet // GameTotalBets[i] += bet
// } // }
@ -1141,7 +1387,7 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// u.SettleMsg.UserBetsCount[i] = count // u.SettleMsg.UserBetsCount[i] = count
// } // }
// if rm.GetGameStatus() < pb.ColorPinoyLiveGameStatus_ColorPinoyLiveEndBetMovie { // if rm.GetGameStatus() < pb.ColorPinoyLiveGameStatus_ColorPinoyLiveEndBetMovie {
// u.AddBalance(u.TotalBet) // u.AddBalance(u.totalBet)
// } else if rm.GetGameStatus() < pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus { // } else if rm.GetGameStatus() < pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus {
// _, err := rm.TransInoutGameEnd(u, u.TransWin, u.TransBet, 0) // _, err := rm.TransInoutGameEnd(u, u.TransWin, u.TransBet, 0)
// if err != nil { // if err != nil {
@ -1162,8 +1408,8 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// defer playerDataMu.Unlock() // defer playerDataMu.Unlock()
// PlayerData = append(PlayerData, &pb.ColorPinoyLivePlayerData{ // PlayerData = append(PlayerData, &pb.ColorPinoyLivePlayerData{
// Uid: u.UserID, // Uid: u.UserID,
// TotalBets: u.SettleMsg.UserBets, // 玩家各个区域的总下注额 // totalBets: u.SettleMsg.UserBets, // 玩家各个区域的总下注额
// TotalBet: u.TotalBet, // totalBet: u.totalBet,
// Profit: u.SettleMsg.TotalWin, // Profit: u.SettleMsg.TotalWin,
// Tax: u.SettleMsg.Tax, // Tax: u.SettleMsg.Tax,
// Balance: u.Balance, // Balance: u.Balance,
@ -1200,8 +1446,8 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// BaseBet: rm.RoomCfg.BaseBet, // BaseBet: rm.RoomCfg.BaseBet,
// PlayerData: PlayerData, // PlayerData: PlayerData,
// TaxRate: rm.RoomCfg.Rate, // TaxRate: rm.RoomCfg.Rate,
// TotalBet: betCount, // totalBet: betCount,
// TotalBets: GameTotalBets[:], // totalBets: GameTotalBets[:],
// OpToken: gconfig.GConfig.GServConfig.ChannelId, // OpToken: gconfig.GConfig.GServConfig.ChannelId,
// Detail: gameDetail, // Detail: gameDetail,
// IsDiscard: 1, // IsDiscard: 1,
@ -1260,12 +1506,12 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// } // }
// //
// // 中jackpot分奖 // // 中jackpot分奖
// func (rm *ColorRoom) kafkaHitJackpot(jackpot int64, userJp map[int64]int64) { // func (rm *ColorRoom) kafkaHitJackpot(jackpotValue int64, userJp map[int64]int64) {
// msg := &events.JackpotEvent{ // msg := &events.JackpotEvent{
// EventType: events.JackpotEvent_et_hit_jackpot, // EventType: events.JackpotEvent_et_hit_jackpot,
// GameId: rm.RoomCfg.GameId, // GameId: rm.RoomCfg.GameId,
// Time: time.Now().UnixMilli(), // Time: time.Now().UnixMilli(),
// HitJackpot: &events.JackpotEvent_HitJackpot{SumJackpot: jackpot, UserJackpot: userJp}, // HitJackpot: &events.JackpotEvent_HitJackpot{SumJackpot: jackpotValue, UserJackpot: userJp},
// GameNo: rm.Table.GetGameRoundId(), // GameNo: rm.Table.GetGameRoundId(),
// } // }
// go func() { // go func() {
@ -1274,10 +1520,10 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// log.Error(rm.Log("kafka JackpotEvent_HitJackpot err: %v", err)) // log.Error(rm.Log("kafka JackpotEvent_HitJackpot err: %v", err))
// } // }
// }() // }()
// log.Debug(rm.Log("kafka 中jackpot:%v", jackpot)) // log.Debug(rm.Log("kafka 中jackpot:%v", jackpotValue))
// } // }
// //
// func (rm *ColorRoom) kafkaBackJackpot(jackpot, jpx, jpy int64, userJp map[int64]int64) { // func (rm *ColorRoom) kafkaBackJackpot(jackpotValue, jpx, jpy int64, userJp map[int64]int64) {
// userJp2 := make(map[int64]int64) // userJp2 := make(map[int64]int64)
// for k, v := range userJp { // for k, v := range userJp {
// userJp2[k] = -v // userJp2[k] = -v
@ -1287,7 +1533,7 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// GameId: rm.RoomCfg.GameId, // GameId: rm.RoomCfg.GameId,
// Time: time.Now().UnixMilli(), // Time: time.Now().UnixMilli(),
// GameDiscard: &events.JackpotEvent_GameDiscard{ // GameDiscard: &events.JackpotEvent_GameDiscard{
// Jackpot: -jackpot, // Jackpot: -jackpotValue,
// JackpotX: -jpx, // JackpotX: -jpx,
// JackpotY: -jpy, // JackpotY: -jpy,
// UserJackpot: userJp2, // UserJackpot: userJp2,
@ -1300,5 +1546,5 @@ func (rm *ColorRoom) updateEndBetAreaMul() {
// log.Error(rm.Log("kafka JackpotEvent_HitJackpot err: %v", err)) // log.Error(rm.Log("kafka JackpotEvent_HitJackpot err: %v", err))
// } // }
// }() // }()
// log.Debug(rm.Log("kafka 回退jackpot:%v jpx:%v jpy:%v", -jackpot, -jpx, -jpy)) // log.Debug(rm.Log("kafka 回退jackpot:%v jpx:%v jpy:%v", -jackpotValue, -jpx, -jpy))
// } // }

View File

@ -7,31 +7,34 @@ import (
func (rm *ColorRoom) gameStart() { func (rm *ColorRoom) gameStart() {
rm.setStatus(pb.ColorGameStatus_CGS_Start) rm.setStatus(pb.ColorGameStatus_CGS_Start)
rm.resetGameData()
rm.notifyGameStart() rm.notifyGameStart()
rm.NewTimer(TtStartBetting, time.Duration(rm.timingCfg.Start)*time.Millisecond) rm.NewTimer(TtStartBetting, time.Duration(rm.timingCfg.Start)*time.Millisecond)
} }
func (rm *ColorRoom) startBetting() { func (rm *ColorRoom) gameStartBetting() {
rm.setStatus(pb.ColorGameStatus_CGS_Betting) rm.setStatus(pb.ColorGameStatus_CGS_Betting)
rm.notifyBetting() rm.notifyBetting()
rm.NewTimer(TtEndBet, time.Duration(rm.timingCfg.Betting)*time.Millisecond) rm.NewTimer(TtEndBet, time.Duration(rm.timingCfg.Betting)*time.Millisecond)
} }
func (rm *ColorRoom) endBetting() { func (rm *ColorRoom) gameEndBetting() {
rm.setStatus(pb.ColorGameStatus_CGS_BetEnd) rm.setStatus(pb.ColorGameStatus_CGS_BetEnd)
rm.updateEndBetAreaMul() rm.updateEndBetAreaMul()
rm.notifyEndBetting() rm.notifyEndBetting()
rm.NewTimer(TtOpenThreeDices, time.Duration(rm.timingCfg.EndBetting)*time.Millisecond) rm.NewTimer(TtOpenThreeDices, time.Duration(rm.timingCfg.EndBetting)*time.Millisecond)
} }
func (rm *ColorRoom) openThreeDices() { func (rm *ColorRoom) gameOpenThreeDices() {
rm.setStatus(pb.ColorGameStatus_CGS_OpenThreeDice) rm.setStatus(pb.ColorGameStatus_CGS_OpenThreeDice)
rm.openDices()
rm.notifyOpenThreeDice() rm.notifyOpenThreeDice()
rm.NewTimer(TtSettle, time.Duration(rm.timingCfg.OpenThreeDice)*time.Millisecond) rm.NewTimer(TtSettle, time.Duration(rm.timingCfg.OpenThreeDice)*time.Millisecond)
} }
func (rm *ColorRoom) settle() { func (rm *ColorRoom) gameSettle() {
rm.setStatus(pb.ColorGameStatus_CGS_Settle) rm.setStatus(pb.ColorGameStatus_CGS_Settle)
rm.settle()
rm.notifySettle() rm.notifySettle()
rm.NewTimer(TtGameStart, time.Duration(rm.timingCfg.Settle)*time.Millisecond) rm.NewTimer(TtGameStart, time.Duration(rm.timingCfg.Settle)*time.Millisecond)
} }
@ -129,7 +132,7 @@ func (rm *ColorRoom) settle() {
// // log.Debug("aabb openThreeDice") // // log.Debug("aabb openThreeDice")
// rm.SetGameStatus(pb.ColorPinoyLiveGameStatus_ColorPinoyLiveOpenThreeDice) // rm.SetGameStatus(pb.ColorPinoyLiveGameStatus_ColorPinoyLiveOpenThreeDice)
// rm.Table.AddTimer(time.Duration(rm.RoomCfg.TimeConf.OpenThreeDice), func() { // rm.Table.AddTimer(time.Duration(rm.RoomCfg.TimeConf.OpenThreeDice), func() {
// // log.Debug("aabb settle") // // log.Debug("aabb gameSettle")
// rm.CompareDiceResult() // rm.CompareDiceResult()
// rm.Settle() // rm.Settle()
// }) // })

View File

@ -5,7 +5,7 @@ import "game/common/proto/pb"
func (rm *ColorRoom) notifyGameStart() { func (rm *ColorRoom) notifyGameStart() {
ntf := &pb.NtfColorGameStart{ ntf := &pb.NtfColorGameStart{
EndTime: rm.endTimeStatus(), EndTime: rm.endTimeStatus(),
Jackpot: rm.jackpot, Jackpot: rm.jackpotValue,
} }
rm.Broadcast(pb.MsgId_NtfColorGameStartId, ntf) rm.Broadcast(pb.MsgId_NtfColorGameStartId, ntf)
} }
@ -19,7 +19,7 @@ func (rm *ColorRoom) notifyEndBetting() {
ntf := &pb.NtfColorEndBetting{ ntf := &pb.NtfColorEndBetting{
EndTime: rm.endTimeStatus(), EndTime: rm.endTimeStatus(),
AreaMul: rm.endBetAreaMul, AreaMul: rm.endBetAreaMul,
Jackpot: rm.jackpot, Jackpot: rm.jackpotValue,
} }
rm.Broadcast(pb.MsgId_NtfColorEndBettingId, ntf) rm.Broadcast(pb.MsgId_NtfColorEndBettingId, ntf)
} }
@ -84,10 +84,10 @@ func (rm *ColorRoom) notifySettle() {
// betAreaInfo = append(betAreaInfo, areaInfo) // betAreaInfo = append(betAreaInfo, areaInfo)
// } // }
// rm.Traverse(func(u *model.User) bool { // rm.Traverse(func(u *model.User) bool {
// if u.TotalBet > 0 { // if u.totalBet > 0 {
// // 下注玩家下注区域信息 // // 下注玩家下注区域信息
// for _, info := range betAreaInfo { // for _, info := range betAreaInfo {
// for betType, betChips := range u.TotalBets { // for betType, betChips := range u.totalBets {
// if pb.ColorPinoyLiveBetTypeJP(betType) == info.BetType && betChips != 0 { // if pb.ColorPinoyLiveBetTypeJP(betType) == info.BetType && betChips != 0 {
// var betAearUser = new(pb.ColorPinoyLiveGameBetAreaUserInfo) // var betAearUser = new(pb.ColorPinoyLiveGameBetAreaUserInfo)
// betAearUser.UserID = u.UserID // betAearUser.UserID = u.UserID
@ -185,9 +185,9 @@ func (rm *ColorRoom) notifySettle() {
// //
// func (rm *ColorRoom) SendUserBet(u *model.User) { // func (rm *ColorRoom) SendUserBet(u *model.User) {
// msg := new(pb.ColorPinoyLiveSceneBetInfo) // msg := new(pb.ColorPinoyLiveSceneBetInfo)
// msg.UserBets = u.TotalBets[:] // msg.UserBets = u.totalBets[:]
// msg.TotalBets = rm.TotalBets[:] // msg.totalBets = rm.totalBets[:]
// msg.UserBetTotal = u.TotalBet // msg.UserBetTotal = u.totalBet
// // msg.MasterBetType = rm.LastMasterBetType // // msg.MasterBetType = rm.LastMasterBetType
// msg.UserInfo = new(pb.ColorPinoyLiveUserInfo) // msg.UserInfo = new(pb.ColorPinoyLiveUserInfo)
// msg.UserInfo.UserID = u.UserID // msg.UserInfo.UserID = u.UserID
@ -276,7 +276,7 @@ func (rm *ColorRoom) notifySettle() {
// var betUserInfo []*pb.ColorPinoyLiveSceneUserInfo // var betUserInfo []*pb.ColorPinoyLiveSceneUserInfo
// noChairTotalWin := int64(0) // noChairTotalWin := int64(0)
// rm.Traverse(func(u *model.User) bool { // rm.Traverse(func(u *model.User) bool {
// if u.TotalBet > 0 && u.SettleMsg != nil { // if u.totalBet > 0 && u.SettleMsg != nil {
// user := new(pb.ColorPinoyLiveSceneUserInfo) // user := new(pb.ColorPinoyLiveSceneUserInfo)
// user.UserID = u.UserID // user.UserID = u.UserID
// user.TotalWin = u.SettleMsg.TotalWin // user.TotalWin = u.SettleMsg.TotalWin
@ -356,15 +356,15 @@ func (rm *ColorRoom) notifySettle() {
// u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameUserSettle), SceneUserInfo) // u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameUserSettle), SceneUserInfo)
// //
// if !u.IsRobot && u.SettleMsg != nil { // if !u.IsRobot && u.SettleMsg != nil {
// RealSystemWin += u.TotalBet // RealSystemWin += u.totalBet
// RealSystemWin -= u.SettleMsg.TotalWin // RealSystemWin -= u.SettleMsg.TotalWin
// betCount += u.TotalBet // betCount += u.totalBet
// SystemTax += u.SettleMsg.Tax // SystemTax += u.SettleMsg.Tax
// if MaxWinGold < u.SettleMsg.TotalWin-u.TotalBet { // if MaxWinGold < u.SettleMsg.TotalWin-u.totalBet {
// MaxWinGold = u.SettleMsg.TotalWin - u.TotalBet // MaxWinGold = u.SettleMsg.TotalWin - u.totalBet
// MaxWinUserID = u.UserInetr.GetId() // MaxWinUserID = u.UserInetr.GetId()
// } // }
// for i, bet := range u.TotalBets { // for i, bet := range u.totalBets {
// if bet > 0 { // if bet > 0 {
// RealSystemWins[i] += bet // RealSystemWins[i] += bet
// betTypePlayerCount[i] += 1 // betTypePlayerCount[i] += 1
@ -373,7 +373,7 @@ func (rm *ColorRoom) notifySettle() {
// } // }
// } // }
// // 写入数据库统计信息 // // 写入数据库统计信息
// if u.TotalBet > 0 { // if u.totalBet > 0 {
// // 玩家下注区域统计 // // 玩家下注区域统计
// u.SettleMsg.UserBetsCount = make([]int64, config.BET_TYPE_NUM) // u.SettleMsg.UserBetsCount = make([]int64, config.BET_TYPE_NUM)
// for i, count := range u.TotalBetsCount { // for i, count := range u.TotalBetsCount {
@ -381,8 +381,8 @@ func (rm *ColorRoom) notifySettle() {
// } // }
// PlayerData = append(PlayerData, &pb.ColorPinoyLivePlayerData{ // PlayerData = append(PlayerData, &pb.ColorPinoyLivePlayerData{
// Uid: u.UserID, // Uid: u.UserID,
// TotalBets: u.SettleMsg.UserBets, // 玩家各个区域的总下注额 // totalBets: u.SettleMsg.UserBets, // 玩家各个区域的总下注额
// TotalBet: u.TotalBet, // totalBet: u.totalBet,
// Profit: u.SettleMsg.TotalWin, // Profit: u.SettleMsg.TotalWin,
// Tax: u.SettleMsg.Tax, // Tax: u.SettleMsg.Tax,
// Balance: u.Balance, // Balance: u.Balance,
@ -411,15 +411,15 @@ func (rm *ColorRoom) notifySettle() {
// sort.Sort(cou) // sort.Sort(cou)
// //
// for key, v := range pb.ColorPinoyLiveBetTypeJP_value { // for key, v := range pb.ColorPinoyLiveBetTypeJP_value {
// if rm.TotalBets[v] > 0 || betTypePlayerCount[v] > 0 || RealSystemWins[v] > 0 { // 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]))) // 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 ,", // 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])) // 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 ", score.GetScoreStr(rm.totalBet))
// //
// str += fmt.Sprintf("真人 总押注:%v , 系统输赢额度:%v ", // str += fmt.Sprintf("真人 总押注:%v , 系统输赢额度:%v ",
// score.GetScoreStr(betCount), // score.GetScoreStr(betCount),
@ -430,7 +430,7 @@ func (rm *ColorRoom) notifySettle() {
// MaxWinUserID, score.GetScoreStr(MaxWinGold)) // MaxWinUserID, score.GetScoreStr(MaxWinGold))
// //
// log.Debug(rm.Log(str)) // log.Debug(rm.Log(str))
// log.Debug(rm.Log("各区域投注:%v", rm.TotalBets)) // log.Debug(rm.Log("各区域投注:%v", rm.totalBets))
// log.Debug(rm.Log("真人各区域投注:%v", GameTotalBets)) // log.Debug(rm.Log("真人各区域投注:%v", GameTotalBets))
// log.Debug(rm.Log("真人各区域中奖:%v", RealSystemWins)) // log.Debug(rm.Log("真人各区域中奖:%v", RealSystemWins))
// log.Debug(rm.Log("中奖区域:%v", wins)) // log.Debug(rm.Log("中奖区域:%v", wins))
@ -480,8 +480,8 @@ func (rm *ColorRoom) notifySettle() {
// BaseBet: rm.RoomCfg.BaseBet, // BaseBet: rm.RoomCfg.BaseBet,
// PlayerData: PlayerData, // PlayerData: PlayerData,
// TaxRate: rm.RoomCfg.Rate, // TaxRate: rm.RoomCfg.Rate,
// TotalBet: betCount, // totalBet: betCount,
// TotalBets: GameTotalBets[:], // totalBets: GameTotalBets[:],
// RealSystemWin: RealSystemWin, // RealSystemWin: RealSystemWin,
// RealSystemWins: RealSystemWins[:], // RealSystemWins: RealSystemWins[:],
// Tax: SystemTax, // Tax: SystemTax,

View File

@ -16,7 +16,8 @@ const (
) )
var Command *config.Command var Command *config.Command
var Cfg *config.Common[GateConfig] var Cfg *config.Common
var GateCfg *GateConfig
type GateConfig struct { type GateConfig struct {
Address []string `json:"address"` // 网关地址 Address []string `json:"address"` // 网关地址
@ -43,14 +44,16 @@ func LoadConfig(GitCommit, GitBranch, BuildDate string) {
log.Error(err.Error()) log.Error(err.Error())
return return
} }
if err = config.LoadSpecialConfig[GateConfig](rdb, gateKey, Cfg); err != nil { if err = config.LoadGameConfig[GateConfig](rdb, gateKey, Cfg); err != nil {
log.DebugF("load config:empty etcd key") log.DebugF("load config:empty etcd key")
Cfg.Special = &GateConfig{ GateCfg = &GateConfig{
Address: []string{gateAddress1, gateAddress2}, Address: []string{gateAddress1, gateAddress2},
} }
if bs, err := json.Marshal(&Cfg.Special); err == nil { if bs, err := json.Marshal(GateCfg); err == nil {
err = rdb.Set(context.Background(), gateKey, string(bs), 0).Err() err = rdb.Set(context.Background(), gateKey, string(bs), 0).Err()
} }
} else {
_ = json.Unmarshal([]byte(Cfg.GameJson), GateCfg)
} }
log.DebugF("load common config success") log.DebugF("load common config success")
} }