game_sync/gamesrv/slotspkg/slots/entity/win.go

327 lines
8.2 KiB
Go

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