327 lines
8.2 KiB
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()
|
|
}
|