Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+212
View File
@@ -0,0 +1,212 @@
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
}