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 }