package entity import ( "github.com/tomas-qstarrs/boost/mathx" "mongo.games.com/game/gamesrv/slotspkg/internal/generic/errors" "mongo.games.com/game/gamesrv/slotspkg/internal/generic/key" "mongo.games.com/game/gamesrv/slotspkg/internal/module/player" "mongo.games.com/game/gamesrv/slotspkg/internal/module/shared" ) // ActBet calcs bet of act value func (e *Entity) ActBet() int64 { lineBet := e.GetLineBetByType(key.BaseSpin) lineCount := e.GetLineCountByType(key.BaseSpin) ratioType := e.NodeTree.Act.RatioType ratio := e.NodeTree.Act.Ratio if ratio == 0 { ratio = 1 } switch ratioType { case key.MachineRatioTypeNil: return lineBet * lineCount case key.MachineRatioMoreCoinMoreBet: return int64(float64(lineBet*lineCount) * ratio) case key.MachineRatioMoreCoinSameBet: return lineBet * lineCount case key.MachineRatioSameCoinMoreBet: return int64(float64(lineBet*lineCount) * ratio) default: panic(errors.Errorf("unknown ratio type: %v", ratioType)) } } func (e *Entity) MinBet() int64 { return e.GetMinLineBet(key.BaseSpin) * e.GetLineCountByType(key.BaseSpin) } // ConsumeCoins consume coins when cursor node is base spin func (e *Entity) ConsumeCoins() { if e.CursorNode().GetType() != key.BaseSpin { if !e.CursorNode().NoBase { return } if e.CursorNode().GetType() == key.FreeSpin && e.CursorNode().GetProgressValue() != 0 { return } } cc := player.CoinCenter.Get(e.Session) lineBet := e.GetLineBetByType(key.BaseSpin) lineCount := e.GetLineCountByType(key.BaseSpin) ratioType := e.NodeTree.Act.RatioType ratio := e.NodeTree.Act.Ratio if ratio == 0 { ratio = 1 } var coin int64 switch ratioType { case key.MachineRatioTypeNil: coin = lineBet * lineCount case key.MachineRatioMoreCoinMoreBet: coin = int64(float64(lineBet*lineCount) * ratio) case key.MachineRatioMoreCoinSameBet: coin = int64(float64(lineBet*lineCount) * ratio) case key.MachineRatioSameCoinMoreBet: coin = lineBet * lineCount default: panic(errors.Errorf("unknown ratio type: %v", ratioType)) } betCoin := player.NewDecCoin(cc, coin) e.SetBetCoin(betCoin) winCoin := betCoin.Rate(e.IsFree, 0) e.SetWinCoin(winCoin) // Recorder 模式 if e.NodeTree.Mode != key.MachineModeRecorder { var roomType string if e.IsFree { roomType = key.RoomTypeFree } else { roomType = key.RoomTypePaid } game := &shared.Game{ Contest: "Slots", ContestType: e.Theme, RoomID: int64(e.Session.UID()), RoomType: roomType, RoundID: e.NextNode().GetID(), } player.CoinCenter.Dec(e.Session, game, key.ReasonSlotsBet, betCoin) player.BetWin(e.Session, betCoin, player.IncCoin{}) e.Player.Agg.SlotsSpinTimes.Set(e.Player.Agg.SlotsSpinTimes.Get() + 1) e.Player.Agg.SlotsBetCoin.Set(e.Player.Agg.SlotsBetCoin.Get() + betCoin.GetCoin()) e.Player.Agg.SlotsDailySpins.Set(e.Player.Agg.SlotsDailySpins.Get() + 1) e.Player.Agg.SlotsDailyBet.Set(e.Player.Agg.SlotsDailyBet.Get() + betCoin.GetCoin()) } } // ObtainCoins obtains coins after next node is chosen func (e *Entity) ObtainCoins() { var closingBaseSpin = false for _, closingNode := range e.ClosingNodes() { if closingNode.Type == key.BaseSpin { closingBaseSpin = true break } } if e.NextNode().GetType() != key.BaseSpin && !closingBaseSpin { e.NodeTree.LastNodeSettled = false } else { rate := float64(e.TotalWin()) / float64(e.TotalBet()) winCoin := e.GetBetCoin().Rate(e.IsFree, rate) e.SetWinCoin(winCoin) // 非Recorder 模式 if e.NodeTree.Mode != key.MachineModeRecorder { var roomType string if e.IsFree { roomType = key.RoomTypeFree } else { roomType = key.RoomTypePaid } game := &shared.Game{ Contest: "Slots", ContestType: e.Theme, RoomID: int64(e.Session.UID()), RoomType: roomType, RoundID: e.CursorNode().GetID(), } player.CoinCenter.Inc(e.Session, game, key.ReasonSlotsWin, winCoin) player.BetWin(e.Session, player.DecCoin{}, winCoin) e.Player.Agg.SlotsWinCoin.Set(e.Player.Agg.SlotsWinCoin.Get() + winCoin.GetCoin()) e.Player.Agg.SlotsDailyWin.Set(e.Player.Agg.SlotsDailyWin.Get() + winCoin.GetCoin()) if winCoin.GetCoin() == 0 { e.Player.Agg.SlotsContinuousZeroSpins.Set(e.Player.Agg.SlotsContinuousZeroSpins.Get() + 1) } else { e.Player.Agg.SlotsContinuousZeroSpins.Set(0) } } e.NodeTree.LastNodeSettled = true } } // ResetWin resets win fields before each spin func (e *Entity) ResetWin() { for _, node := range e.NodeTree.Nodes { for _, formation := range node.Formations { formation.Win = 0 } for _, feature := range node.Features { feature.Win = 0 } node.Win = 0 node.ChildrenWin = 0 } if e.NodeTree.LastNodeSettled { e.RootNode().ChildrenTotalWin = 0 e.RootNode().TotalWin = 0 } } // UpdateWin updates all win info // Win is win amount for this spin win // EffectiveWin is win amount for lastest effective spin win // TotalWin is the sum of current node win // ChildrenWin is the sum of children node wins func (e *Entity) UpdateWin() { e.WalkTree(WalkRootLast, func(node *shared.Node) bool { e.updateFormationWin(node) e.updateFeatureWin(node) e.updateNodeWin(node) e.updateChildrenWin(node) return false }) } func (e *Entity) updateFormationWin(node *shared.Node) { for _, formation := range node.Formations { if formation.Win > 0 { formation.EffectiveWin = formation.Win } formation.TotalWin += formation.Win } } func (e *Entity) updateFeatureWin(node *shared.Node) { for _, feature := range node.Features { if feature.Win > 0 { feature.EffectiveWin = feature.Win } feature.TotalWin += feature.Win } } func (e *Entity) updateNodeWin(node *shared.Node) { for _, formation := range node.Formations { node.Win += formation.Win } for _, feature := range node.Features { node.Win += feature.Win } if node.Win > 0 { node.EffectiveWin = node.Win } node.TotalWin += node.Win } func (e *Entity) updateChildrenWin(node *shared.Node) { for _, child := range node.Children { childNode := e.GetNode(child) node.ChildrenWin += (childNode.Win + childNode.ChildrenWin) node.ChildrenTotalWin += (childNode.Win + childNode.ChildrenWin) } } func (e *Entity) Win() int64 { return e.RootNode().Win + e.RootNode().ChildrenWin } func (e *Entity) NodeTotalWin() int64 { return e.CursorNode().TotalWin } // TotalWin returns total win of this spin func (e *Entity) TotalWin() int64 { return e.RootNode().ChildrenTotalWin + e.RootNode().TotalWin } func (e *Entity) ActualWin() int64 { if e.NextNode().Type != key.BaseSpin { return 0 } return e.TotalWin() } func (e *Entity) ActualWinType() int64 { if e.NextNode().Type != key.BaseSpin { return key.WinTypeNil } actualWin := e.TotalWin() multi := mathx.SafeDiv(actualWin, e.CursorNode().Bet) return e.CalcWinType(multi) } func (e *Entity) CalcWinType(multi float64) int64 { prizeModels := e.MachineDesc.GetPrizeModel() for winType, prizeModel := range prizeModels { if (prizeModel.MinMultiple < 0 || multi >= float64(prizeModel.MinMultiple)) && (prizeModel.MaxMultiple < 0 || multi < float64(prizeModel.MaxMultiple)) { switch winType { case 1: return key.WinTypeBig case 2: return key.WinTypeMega case 3: return key.WinTypeEpic } } } if multi > 0 { return key.WinTypeNormal } return key.WinTypeNil } func (e *Entity) GetLineBetByType(nodeType string) int64 { return e.MachineDesc.GetLineBet(e.NodeTree.Act.BetSizeIndex, e.NodeTree.Act.BetLevelIndex, e.NodeTree.Act.BetLineIndex) } func (e *Entity) GetMinLineBet(nodeType string) int64 { return e.MachineDesc.GetLineBet(1, 1, 1) } func (e *Entity) SetBetCoin(betCoin player.DecCoin) { e.NodeTree.BetCoin.Coin = betCoin.Coin } func (e *Entity) GetBetCoin() player.DecCoin { return player.DecCoin{ Coin: e.NodeTree.BetCoin.Coin, } } func (e *Entity) SetWinCoin(winCoin player.IncCoin) { e.NodeTree.WinCoin.Coin = winCoin.Coin } func (e *Entity) GetWinCoin() player.IncCoin { return player.IncCoin{ Coin: e.NodeTree.WinCoin.Coin, } } func (e *Entity) TotalBet() int64 { betCoin := e.NodeTree.BetCoin return betCoin.Coin } func (e *Entity) ActualBet() int64 { if e.CursorNode().GetType() != key.BaseSpin { if !e.CursorNode().NoBase { return 0 } if e.CursorNode().GetType() == key.FreeSpin && e.CursorNode().GetProgressValue() != 1 { return 0 } } return e.TotalBet() }