213 lines
7.0 KiB
Go
213 lines
7.0 KiB
Go
package luckydrawser
|
|
|
|
import (
|
|
"91porn-server/models/v/taskrecordmod"
|
|
"errors"
|
|
"fmt"
|
|
"math/rand"
|
|
"time"
|
|
|
|
"91porn-server/app/appg"
|
|
"91porn-server/common/db"
|
|
"91porn-server/common/log"
|
|
"91porn-server/models/v/activitymod"
|
|
"91porn-server/models/v/prizemod"
|
|
"91porn-server/models/v/txnmod"
|
|
"91porn-server/models/v/walletmod"
|
|
|
|
"github.com/shopspring/decimal"
|
|
"github.com/smallnest/weighted"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
)
|
|
|
|
// 免费模式处理
|
|
func freeModelHanlder(in *DrawReq, activityId primitive.ObjectID, prizeList []*prizemod.Prize, prizePool *activitymod.PrizePool) ([]*prizemod.Prize, error) {
|
|
var (
|
|
wg *weighted.RandW = weighted.NewRandW()
|
|
drawPrice int64 // 本次抽奖总支出
|
|
prizes []*prizemod.Prize // 本次抽奖结果
|
|
reservoir int64 // 蓄水池金额
|
|
systemIncome int64 // 系统收益金额
|
|
systemRake int64 // 系统抽成金额
|
|
now time.Time = time.Now()
|
|
)
|
|
// 奖品分类
|
|
prizeListLen := len(prizeList)
|
|
lowPrizes := make([]*prizemod.Prize, 0, prizeListLen) // 低级奖品列表
|
|
middlePrizes := make([]*prizemod.Prize, 0, prizeListLen) // 中级奖品列表
|
|
for _, v := range prizeList {
|
|
if v.Level == prizemod.Low {
|
|
lowPrizes = append(lowPrizes, v)
|
|
}
|
|
if v.Level == prizemod.Middle {
|
|
middlePrizes = append(middlePrizes, v)
|
|
}
|
|
wg.Add(v, int(v.Weights.Mul(decimal.NewFromInt(100)).IntPart()))
|
|
}
|
|
// 获取用户签到信息
|
|
signInfo, err := taskrecordmod.GetByUID(in.UserId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if signInfo == nil {
|
|
if _, err = taskrecordmod.AddTaskRecord(in.UserId); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
// 获取用户免费次数
|
|
userFree, err := activitymod.GetUserFree(activityId, in.UserId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// 使用金币抽奖
|
|
if userFree != nil && userFree.FreeCount < int32(in.Count) {
|
|
drawPrice = prizePool.Price * in.Count
|
|
wal, err := walletmod.GetWallet(in.UserId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// 余额不足
|
|
if wal.Amount < drawPrice {
|
|
return nil, errors.New("余额不足")
|
|
}
|
|
}
|
|
log.Info(fmt.Sprintf("本次抽奖所需金币为[%d]", drawPrice))
|
|
// 本次抽奖总抽成收益
|
|
systemRake += decimal.NewFromInt(drawPrice).Mul(decimal.NewFromFloat(0.1)).IntPart()
|
|
// 本次抽奖蓄水池抽成收益
|
|
reservoir += decimal.NewFromInt(drawPrice).Mul(decimal.NewFromFloat(0.1)).IntPart()
|
|
// 本次抽奖系统收益
|
|
systemIncome += drawPrice - systemRake - reservoir
|
|
drawRecord := make([]activitymod.UserRecord, in.Count) // 抽奖记录
|
|
for i := 0; i < int(in.Count); i++ {
|
|
p, ok := wg.Next().(*prizemod.Prize)
|
|
if !ok || p == nil {
|
|
return nil, errors.New("异常错误")
|
|
}
|
|
log.Info(fmt.Sprintf("金币抽奖-正常获取奖品[%s]", p.Name))
|
|
// 玩家使用免费抽奖
|
|
if drawPrice == 0 {
|
|
// 替换为低级奖品
|
|
if p.Level != prizemod.Low {
|
|
p = lowPrizes[rand.New(rand.NewSource(time.Now().UnixNano())).Intn(len(lowPrizes))]
|
|
}
|
|
}
|
|
// 金币抽奖 杀分判定 固定70%几率杀分 亏损达到预期2倍100%杀分
|
|
if prizePool.SystemIncome < -(prizePool.EstimatedIncome/2) && drawPrice > 0 && p.Level != prizemod.Low {
|
|
if rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(100) > 30 || prizePool.SystemIncome < -(prizePool.EstimatedIncome*2) {
|
|
log.Info(fmt.Sprintf("金币抽奖-杀分判定成功[当前奖品:%s]", p.Name))
|
|
// 替换为低级奖品
|
|
p = lowPrizes[rand.New(rand.NewSource(time.Now().UnixNano())).Intn(len(lowPrizes))]
|
|
log.Info(fmt.Sprintf("金币抽奖-杀分判定成功[替换奖品:%s]", p.Name))
|
|
}
|
|
}
|
|
// 放分判定 固定30%几率放分
|
|
if prizePool.SystemIncome > prizePool.EstimatedIncome && rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(100) < 30 && drawPrice > 0 && p.Level != prizemod.Middle {
|
|
log.Info(fmt.Sprintf("金币抽奖-放分判定成功[当前奖品:%s]", p.Name))
|
|
// 替换为中级奖品
|
|
p = middlePrizes[rand.New(rand.NewSource(time.Now().UnixNano())).Intn(len(middlePrizes))]
|
|
log.Info(fmt.Sprintf("金币抽奖-放分判定成功[替换奖品:%s]", p.Name))
|
|
}
|
|
// 高级奖品放出判定
|
|
if p.Level == prizemod.High {
|
|
if prizePool.Reservoir < p.GetPrice() {
|
|
// 替换为中级奖品
|
|
p = middlePrizes[rand.New(rand.NewSource(time.Now().UnixNano())).Intn(len(middlePrizes))]
|
|
} else {
|
|
// 扣除蓄水池
|
|
prizePool.Reservoir -= p.GetPrice()
|
|
reservoir -= p.GetPrice()
|
|
}
|
|
}
|
|
// 增加系统收益 不包含本次抽奖收益
|
|
prizePool.SystemIncome -= p.GetPrice()
|
|
systemIncome -= p.GetPrice()
|
|
prizes = append(prizes, p)
|
|
// 增加抽奖记录
|
|
drawRecord[i] = activitymod.UserRecord{
|
|
ActivityID: activityId,
|
|
VIPCardID: p.VIPCardID,
|
|
UID: in.UserId,
|
|
Name: p.Name,
|
|
Type: p.Type,
|
|
Price: p.Price,
|
|
Count: p.Count,
|
|
Value: p.Value,
|
|
Level: p.Level,
|
|
DrawPrice: prizePool.Price,
|
|
CreateTime: now,
|
|
}
|
|
}
|
|
hanlders := make([]prizemod.PrizeHanlder, 0, len(prizes))
|
|
var addGoldHanlder prizemod.PrizeHanlder
|
|
var transactionLogs []txnmod.TransactionLog // 资金流水记录
|
|
for _, v := range prizes {
|
|
hanlder, err := prizemod.Run(in.UserId, *v, txnmod.JiuGongGeDraw)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
switch v.Type {
|
|
case prizemod.Gold:
|
|
addGoldHanlder = hanlder
|
|
hanlders = append(hanlders, hanlder)
|
|
default:
|
|
if hanlder != nil {
|
|
hanlders = append(hanlders, hanlder)
|
|
transactionLogs = append(transactionLogs, hanlder.GetTransactionLog()...)
|
|
}
|
|
}
|
|
}
|
|
if err = appg.VideoDB.Trans(func(t *db.MongoTool) error {
|
|
if reservoir != 0 || systemIncome != 0 || systemRake != 0 {
|
|
// 更新奖池
|
|
if err := activitymod.UpdatePrizePoolInc(t, activityId, reservoir, systemIncome, systemRake); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
// 更新用户免费次数
|
|
if drawPrice == 0 {
|
|
if err := activitymod.UpdateOneUserFreeInc(t, activityId, in.UserId, -int32(in.Count)); err != nil {
|
|
return err
|
|
}
|
|
} else if drawPrice > 0 {
|
|
wal, err := walletmod.DebitAmount(t, drawPrice, in.UserId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
transactionLogs = append(transactionLogs, txnmod.TransactionLog{
|
|
TransNo: primitive.NewObjectID(),
|
|
UID: in.UserId,
|
|
Amount: -drawPrice,
|
|
ActualAmount: -float64(drawPrice),
|
|
TranType: txnmod.JiuGongGeDraw.Key(),
|
|
TranTypeInt: int64(txnmod.JiuGongGeDraw),
|
|
Desc: fmt.Sprintf("%s消费-%d个金币", "", drawPrice),
|
|
RealAmount: wal.RealAmount(),
|
|
})
|
|
}
|
|
// 更新抽奖记录
|
|
if len(drawRecord) > 0 {
|
|
if err = activitymod.AddMany(drawRecord); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for _, v := range hanlders {
|
|
if err = v.Run(t); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if addGoldHanlder != nil {
|
|
transactionLogs = append(transactionLogs, addGoldHanlder.GetTransactionLog()...)
|
|
}
|
|
if len(transactionLogs) > 0 {
|
|
if err = txnmod.InsertManyTransactionLog(t, transactionLogs); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
return prizes, nil
|
|
}
|