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