package rezekislot import ( "encoding/json" "fmt" "math/rand" "os" "sort" "strconv" "sync" "time" "bet24.com/log" "bet24.com/servers/games/slotcommon" "bet24.com/servers/games/slotcommon/betlevel" "bet24.com/servers/games/slotcommon/slotcount" "bet24.com/servers/games/slotcommon/usermanager" "bet24.com/utils" ) type GameLogic struct { MinBet int MaxBet int MinFreeSlotCount int MinJackpot int FreeSlotId int FreeTime int MaxNoneFreeCount int TaxRate int Slots []Slot FanConfig []Fan //SlotCounts [][][]int //FreeSlotCounts [][][]int BetLevels []betlevel.BetLevel AdBets []RezekiSlot_FreeAdBet lock *sync.RWMutex userFreeSpins map[int]*FreeSpinInfo slotSink slotcommon.SlotSink slotCounts *slotcount.MultipleSlotCountManager freeSlotCount *slotcount.MultipleSlotCountManager freeSpin *FreeSpinInfo slotManager *SlotManager jackpotManager *JackpotManager betLevelManager *betlevel.BetLevelManager fanManager *FanManager testWinAmount int slotCommon *slotcommon.Slotcommon } func NewGameLogic(slotSink slotcommon.SlotSink) *GameLogic { obj := new(GameLogic) obj.lock = &sync.RWMutex{} obj.slotSink = slotSink return obj } func (this *GameLogic) run() { log.Color(LogColor, "rezeki GameLogic.run") rand.Seed(time.Now().UnixNano()) this.slotCommon = slotcommon.NewSlotCommon(this.slotSink, GAMEID, GAME_NAME, this.TaxRate, GAME_MESSAGE) this.initData() time.AfterFunc(5*time.Minute, this.refreshData) } func (this *GameLogic) test() { defer utils.TimeCost(fmt.Sprintf("GameLogic.test"))() /* for _, v := range this.betLevelManager.levels { this.testLevel() } */ if os.Args[1] != "fanslot" { return } testIndex, err := strconv.Atoi(os.Args[2]) if err != nil { return } log.Color(LogColor, "rezeki.GameLogic test") levels := this.betLevelManager.Levels() v := levels[len(levels)-1-testIndex] this.testLevel(v.Bet) log.Color(LogColor, "rezeki.GameLogic test end") } func (this *GameLogic) testLevel(bet int) { m, _ := strconv.Atoi(os.Args[3]) tc, _ := strconv.Atoi(os.Args[4]) originAmount := bet * m log.Debug("开始测试 带入金额[%d] 最多测试次数[%d] 测试底注[%d]", originAmount, tc, bet) winAmount := 0 testAmount := bet totalJackpot := 0 testedCount := 0 freeCount := 0 //betLevel, base := this.betLevelManager.getLevelAndBase(testAmount) betAmount := 0 returnAmount := 0 taxAmount := 0 resultSet := make([]RezekiSlot_Result, tc) freeResultSet := make([]RezekiSlot_Result, tc*3) var wg sync.WaitGroup for i := 0; i < tc; i++ { wg.Add(1) go func(idx int) { defer wg.Done() r := this.getResult(0, testAmount, false) resultSet[idx] = r }(i) } for i := 0; i < tc*3; i++ { wg.Add(1) go func(idx int) { defer wg.Done() freeResultSet[idx] = this.getResult(0, testAmount, true) }(i) } wg.Wait() log.Color(LogColor, "测试结果已准备") leftFreeCount := 0 tmpBet := 0 for i := 0; i < tc; { tmpBet = bet if originAmount < bet && leftFreeCount <= 0 { log.Debug("break %d < %d", originAmount, bet) break } betAmount += tmpBet originAmount -= tmpBet testedCount++ //slots := this.slotCountManager.get15Slots(betLevel) //log.Color(LogColor, "test %d +++++++++++++++", i) //dumpSlots(slots) //results := this.slotManager.getResults(slots) this.testWinAmount = winAmount var result RezekiSlot_Result if leftFreeCount > 0 { leftFreeCount-- result = freeResultSet[freeCount] freeCount++ tmpBet = 0 } else { result = resultSet[i] i++ } winAmount += result.WinAmount winAmount += result.JackpotAmount winAmount -= tmpBet if result.WinAmount+result.JackpotAmount-tmpBet > 0 { taxAmount += int((result.WinAmount + result.JackpotAmount - tmpBet) / 100 * this.TaxRate) } returnAmount += result.WinAmount + result.JackpotAmount leftFreeCount += result.FreeSpin originAmount += result.WinAmount originAmount += result.JackpotAmount //log.Color(LogColor, "test %d end ------------------", i) } log.Color(LogColor, "转数[%d] 底注[%d] 奖池[%d],剩余[%d],输赢[%d] 税[%d] 返还率[%.4f] 概率分布%v", testedCount, bet, totalJackpot, originAmount, winAmount, taxAmount, float64(returnAmount-taxAmount)/float64(betAmount), "") } func (this *GameLogic) refreshData() { go this.initData() time.AfterFunc(5*time.Minute, this.refreshData) } func (this *GameLogic) initData() { data, err := os.ReadFile("slotconf/rezekislot.json") if err != nil { log.Error("read rezekislot.json failed") } this.lock.Lock() err = json.Unmarshal(data, &this) if err != nil { log.Error("Unmarshal rezekislot.json failed err:%v", err) this.lock.Unlock() return } this.slotManager = newSlotManager(this.Slots, this.FreeSlotId) this.fanManager = newFanManager(this.FanConfig) this.slotCounts = slotcount.NewMultipleSlotCountManager("rezekislot_normal_mul") this.freeSlotCount = slotcount.NewMultipleSlotCountManager("rezekislot_free_mul") this.betLevelManager = betlevel.NewBetLevelManagerByData(this.BetLevels, Msg_BetLevel) this.slotCommon.SetBetLevelManager(this.betLevelManager) this.jackpotManager = newJackpotManager(this.fanManager.getJackpotFanId(), 1, this.slotSink.IsChipRoom()) this.freeSpin = newFreeSpinInfo(this.FreeSlotId, this.MinFreeSlotCount, this.FreeTime) sort.Slice(this.AdBets, func(i, j int) bool { return this.AdBets[i].AdCount > this.AdBets[j].AdCount }) this.lock.Unlock() if this.MaxNoneFreeCount > 0 { usermanager.SetMaxNoneFreeCount(GAMEID, this.MaxNoneFreeCount) } if len(os.Args) >= 2 { time.AfterFunc(time.Second, this.test) } } func (this *GameLogic) getUserSlotCountNormal(userId int, betAmount int) *slotcount.SlotCountManager { level := usermanager.GetUserReturnLevel(userId, GAMEID, betAmount) return this.slotCounts.GetMgr(level) } func (this *GameLogic) getUserSlotCountFree(userId int, betAmount int) *slotcount.SlotCountManager { level := usermanager.GetUserReturnLevel(userId, GAMEID, betAmount) return this.freeSlotCount.GetMgr(level) } func (this *GameLogic) getResult(userId int, betAmount int, isFree bool) RezekiSlot_Result { var ret RezekiSlot_Result ret.IsFree = isFree //此次下注是否为免费产生的 var sc *slotcount.SlotCountManager if isFree { sc = this.getUserSlotCountFree(userId, betAmount) } else { sc = this.getUserSlotCountNormal(userId, betAmount) } if sc == nil { log.Release("GameLogic.getResult 服务器配置有问题") return ret } ret.Slots = make([]int, RESULT_COUNT) ret.BetAmount = betAmount level, base := this.betLevelManager.GetLevelAndBase(betAmount) // 取16个result ret.Slots = sc.Get16Slots(level, isFree, this.FreeSlotId) ret.Lines = this.slotManager.getResults(ret.Slots) if len(ret.Lines) > 0 { for _, v := range ret.Lines { winAmount := int(float64(base) * v.WinRate) ret.WinAmount += winAmount } } freeSlotCount := 0 ret.FreeSpin, freeSlotCount = this.freeSpin.getFreeTime(ret.Slots) if isFree { //检查是否重连前有次数 ret.RemainFreeTime = this.getFreeSpinTime(userId) } if ret.FreeSpin > 0 { this.addFreeSpin(userId, ret.FreeSpin, betAmount, false) ret.RemainFreeTime = this.getFreeSpinTime(userId) } //检查有没有Scatter 只要出现三个以上就按倍率乘以投注额返还 if freeSlotCount >= 3 { slot := this.slotManager.getSlot(this.FreeSlotId) winMultiple := float64(0) if slot != nil { switch freeSlotCount { case 3: winMultiple = slot.Win3 case 4: winMultiple = slot.Win4 case 5: winMultiple = slot.Win5 default: winMultiple = slot.Win5 } } winAmount := int(float64(betAmount) * winMultiple) ret.WinAmount += winAmount } //每次下注抽取 added := this.jackpotManager.addJackpot(ret.Slots, betAmount, isFree, userId) //顶格ID topSlotId := ret.Slots[RESULT_COUNT-1] fanId := sc.GetFanID(this.slotManager.getMagicSlotId(), topSlotId, level, isFree) //随机获得扇子id baseAmount := this.betLevelManager.GetAmountByLevel(0) //获得基础下注额 ret.Fan = this.fanManager.getResults(fanId, betAmount, baseAmount, ret.WinAmount) if ret.Fan.FanID >= 0 { winAmount := int(ret.Fan.WinAmount) //免费过程中顶格出现扇子的时候,扇子奖励x2 if isFree && topSlotId == this.slotManager.getMagicSlotId() { winAmount = winAmount * 2 } ret.WinAmount += winAmount } // 奖池 ret.JackpotLevel, ret.JackpotAmount = this.jackpotManager.checkJackpot(ret.Fan, betAmount, level, userId) if added || ret.JackpotAmount > 0 { this.sendJackpot(userId) } return ret } func (this *GameLogic) useFreeSpin(userId int) (bool, int, bool) { return this.slotCommon.UseFreeSpin(userId) } func (this *GameLogic) getFreeSpinTime(userId int) int { return this.slotCommon.GetFreeSpinTime(userId) } func (this *GameLogic) userExit(userId int) { this.slotCommon.OnUserExit(userId) } func (this *GameLogic) getResultDesc(result RezekiSlot_Result) string { var total struct { Slots []int Lines []int } total.Slots = result.Slots for _, v := range result.Lines { total.Lines = append(total.Lines, v.WinShape) } data, _ := json.Marshal(total) return string(data) } func (this *GameLogic) addFreeSpin(userId int, freeCount, bet int, fromAd bool) { this.slotCommon.AddFreeSpin(userId, freeCount, bet, fromAd) }