package minislot import ( "encoding/json" "fmt" "math/rand" "os" "time" "bet24.com/log" coreservice "bet24.com/servers/coreservice/client" "bet24.com/servers/games/slotcommon" task "bet24.com/servers/micros/task/proto" "bet24.com/servers/transaction" ) type Prize struct { PrizeId int Desc string Multiple float64 } type PrizeEx struct { Prize Chance int // 范围值 } type GameLogic struct { BetOptions []int Prizes []PrizeEx pools []int slotSink slotcommon.SlotSink configString string lastConfigString string } const config_key = "minislot_config" const refresh_config_sec = 600 func newGameLogic(slotSink slotcommon.SlotSink) *GameLogic { ret := new(GameLogic) ret.slotSink = slotSink log.Color(LogColor, "minislot GameLogic.run") rand.Seed(time.Now().UnixNano()) ret.refreshData() time.AfterFunc(time.Second, ret.test) return ret } func (this *GameLogic) refreshData() { go this.initData() time.AfterFunc(time.Duration(refresh_config_sec)*time.Second, this.refreshData) } func (this *GameLogic) initData() { configString := coreservice.GetPlatformConfig(config_key) if configString == "" { data, err := os.ReadFile("fishconf/minislot.json") if err != nil { log.Release("read minislot.json failed") return } configString = string(data) coreservice.SetPlatformConfig(config_key, configString) } if this.lastConfigString == configString { return } this.lastConfigString = configString err := json.Unmarshal([]byte(configString), &this) if err != nil { log.Release("Unmarshal minislot.json failed err:%v", err) return } var config struct { BetOptions []int Prizes []Prize } config.BetOptions = this.BetOptions for i := 0; i < len(this.Prizes); i++ { config.Prizes = append(config.Prizes, this.Prizes[i].Prize) } d, _ := json.Marshal(config) this.configString = string(d) // 生成pool this.makePrizePool() } func (this *GameLogic) makePrizePool() { this.pools = []int{} for _, v := range this.Prizes { for i := 0; i < v.Chance; i++ { this.pools = append(this.pools, v.PrizeId) } } } func (this *GameLogic) onMessage(userId int, msg, data string) { switch msg { case "minislot_config": this.sendConfig(userId) case "minislot_bet": this.doBet(userId, msg, data) } } func (this *GameLogic) sendConfig(userId int) { this.slotSink.SendGameCmd(userId, "minislot_config", this.configString) } func (this *GameLogic) isValidBet(betAmount int) bool { if betAmount <= 0 { return false } if len(this.BetOptions) == 0 { return true } for _, v := range this.BetOptions { if v == betAmount { return true } } return false } func (this *GameLogic) doBet(userId int, msg, data string) { var ret CmdBetReturn var bet CmdBet err := json.Unmarshal([]byte(data), &bet) if err != nil { log.Release("Unmarshal minislot.json failed err:%v", err) ret.ErrMsg = "Unmarshal failed" this.sendBetReturn(userId, ret, msg) return } if !this.isValidBet(bet.Amount) { log.Release("Invalid bet[%d] of %v", bet.Amount, this.BetOptions) ret.ErrMsg = "Invalid bet" this.sendBetReturn(userId, ret, msg) return } ret.Amount = bet.Amount scoreType := GAMEID*100 + 1 status := 1 isSuceeded := this.slotSink.WriteMoney(userId, GAMEID, -bet.Amount, 0, status, scoreType, GAME_NAME) if !isSuceeded { log.Release("minislot.dobet WriteMoney failed,UserId[%d],amount[%d]", userId, bet.Amount) // 扣金币失败 ret.ErrMsg = "not enough money" this.sendBetReturn(userId, ret, msg) return } result := this.getResult() ret.WinAmount = int(float64(bet.Amount) * result.Multiple) ret.PrizeId = result.PrizeId this.slotSink.WriteMoney(userId, GAMEID, ret.WinAmount, 0, 2, 2+GAMEID*100, GAME_NAME) transaction.WriteBetRecordAction(userId, GAMEID, "", bet.Amount, ret.WinAmount, 0, result.Multiple, fmt.Sprintf("bet:%d", bet.Amount), fmt.Sprintf("PrizeId:%d,WinAmount:%d", ret.PrizeId, ret.WinAmount), 0, "", GAME_NAME) task.DoTaskAction(userId, task.TaskAction_playgame, 1, task.TaskScope{GameName: GAME_NAME}) task.DoTaskAction(userId, task.TaskAction_fire, bet.Amount, task.TaskScope{GameName: GAME_NAME}) ret.ErrMsg = "OK" this.sendBetReturn(userId, ret, msg) } func (this *GameLogic) sendBetReturn(userId int, ret CmdBetReturn, msg string) { d, _ := json.Marshal(ret) this.slotSink.SendGameCmd(userId, msg, string(d)) } func (this *GameLogic) getResult() Prize { prizeId := this.pools[rand.Intn(len(this.pools))] return this.getResultByPrizeId(prizeId) } func (this *GameLogic) getResultByPrizeId(prizeId int) Prize { for _, v := range this.Prizes { if v.PrizeId == prizeId { return v.Prize } } log.Release("GameLogic.getResultByPrizeId failed %d,%v", prizeId, this.Prizes) return Prize{} } func (this *GameLogic) test() { if len(os.Args) < 2 { return } if os.Args[1] != "minislot" { return } testCount := 10000000 winAmount := 0 betAmount := this.BetOptions[0] for i := 0; i < testCount; i++ { ret := this.getResult() winAmount += int(float64(betAmount) * ret.Multiple) } log.Release("minislot.test end winAmount = %d,betAmount = %d", winAmount, testCount*betAmount) }