package egg_energy import ( "code.fnuoos.com/EggPlanet/egg_models.git/src/implement" "code.fnuoos.com/EggPlanet/egg_models.git/src/model" "code.fnuoos.com/EggPlanet/egg_system_rules.git/enum" "code.fnuoos.com/EggPlanet/egg_system_rules.git/md" "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule" md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache" "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/es" zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx" es2 "code.fnuoos.com/go_rely_warehouse/zyos_go_es.git/es" "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit" "encoding/json" "errors" "fmt" "github.com/olivere/elastic/v7" "github.com/shopspring/decimal" "strings" "time" "xorm.io/xorm" ) // SettlementGiveActivityCoin 结算观看激励广告得到蛋蛋积分 func SettlementGiveActivityCoin(engine *xorm.Engine, user model.User, ecpm string, ch *rabbit.Channel) (rewardValue float64, err error) { uid := user.Id now := time.Now() //1、查找 `egg_energy_basic_setting` 基础设置 eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine) eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{ "key": "is_open", "value": 1, }) if err != nil { return } if eggEnergyBasicSetting == nil { err = errors.New("蛋蛋能量设置未开启!") return } if eggEnergyBasicSetting.VideoRewardIsOpen == 1 { var videoRewardSystem *md2.VideoRewardSystemStruct err = json.Unmarshal([]byte(eggEnergyBasicSetting.VideoRewardSystem), &videoRewardSystem) if err != nil { return } if videoRewardSystem.RewardTotalNum == "" || videoRewardSystem.IntervalMinutes == "" || videoRewardSystem.EachRoundHour == "" { err = errors.New("视屏奖励机制设置未完全!") return } var rewardSystem []*md2.RewardSystemStruct err = json.Unmarshal([]byte(eggEnergyBasicSetting.RewardSystem), &rewardSystem) if err != nil { return } if len(rewardSystem) == 0 { err = errors.New("未设置奖励机制!") return } go dealEcpm(user, ecpm, ch) //TODO::协程处理ecpm的变化 //TODO::奖励多少个活跃积分(根据ecpm, 新用户机制, 蛋蛋分机制) redisConn := cache.GetPool().Get() defer redisConn.Close() sysCfgDb := implement.NewSysCfgDb(engine, redisConn) videoRewardUnitPrice := sysCfgDb.SysCfgGetWithDb(enum.VideoRewardUnitPrice) if videoRewardUnitPrice != "" { //处理ecpm var coin model.VirtualCoin _, err = engine.Where("id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).Get(&coin) if err != nil { return rewardValue, err } activePointsCoinExchangeRatioValue, _ := decimal.NewFromString(coin.ExchangeRatio) videoRewardUnitPriceValue, _ := decimal.NewFromString(videoRewardUnitPrice) rewardValue, _ = videoRewardUnitPriceValue.Mul(activePointsCoinExchangeRatioValue).Float64() } else { rewardValue = egg_system_rules.StrToFloat64(videoRewardSystem.RewardValue) } var newUserRewardRules *md2.NewUserRewardRules err = json.Unmarshal([]byte(eggEnergyBasicSetting.NewUserIncentiveRules), &newUserRewardRules) if err != nil { return } userCreateAt := egg_system_rules.String2Time(user.CreateAt) if int(now.Sub(userCreateAt).Hours()/24) <= newUserRewardRules.ContinueDays { //处理新用户机制 rewardValue *= newUserRewardRules.RewardCoefficient } score := 60.00 esIndex := es.GetLatestEffectiveIndexFromAlias(now) esIndexName := md.EggEnergyUserEggScoreEsAlias + "_" + esIndex results, err1 := es2.FirstDoc(esIndexName, esIndex+"_"+egg_system_rules.Int64ToStr(user.Id)) if err1 != nil { if !elastic.IsNotFound(err1) { return rewardValue, err1 } } if !elastic.IsNotFound(err1) { var doc md.EggEnergyUserEggScoreEs err = json.Unmarshal(results.Source, &doc) if err != nil { return } score = doc.ScoreValue } eggPointPartitionCoefficientManagementDb := implement.NewEggPointPartitionCoefficientManagementDb(engine) eggPointPartitionCoefficientManagements, err1 := eggPointPartitionCoefficientManagementDb.EggPointPartitionCoefficientManagementGetAll() if err1 != nil { return rewardValue, err1 } for _, v := range *eggPointPartitionCoefficientManagements { //处理蛋蛋分机制 if egg_system_rules.StrToFloat64(v.StartScore) <= score && egg_system_rules.StrToFloat64(v.EndScore) >= score { rewardValue *= egg_system_rules.StrToFloat64(v.Coefficient) } } //处理圈层奖励 var rewardSystemMap = map[int]*md2.RewardSystemStruct{} for _, v := range rewardSystem { rewardSystemMap[v.Level] = v } publicPlatoonUserRelationDb := implement.NewPublicPlatoonUserRelationDb(engine) publicPlatoonUserRelation, err1 := publicPlatoonUserRelationDb.PublicPlatoonUserRelationGetOneByParams(map[string]interface{}{ "key": "uid", "value": uid, }) if err1 != nil { return rewardValue, err1 } var rewardFather []struct { Uid int64 `json:"uid"` //用户id RewardValue float64 `json:"reward_value"` //奖励值 } var fatherUids []string if publicPlatoonUserRelation != nil { fatherUids = strings.Split(publicPlatoonUserRelation.FatherUid, "-") } for k, id := range fatherUids { tmpOneCirclesPublicPlatoonUserRelation, err11 := publicPlatoonUserRelationDb.PublicPlatoonUserRelationGetOneByParams(map[string]interface{}{ "key": "id", "value": id, }) if err11 != nil { return rewardValue, err11 } if tmpOneCirclesPublicPlatoonUserRelation == nil { continue } if tmpOneCirclesPublicPlatoonUserRelation.Uid <= 0 { //待填充位 continue } fatherUid := egg_system_rules.Int64ToStr(tmpOneCirclesPublicPlatoonUserRelation.Uid) fatherReward := rewardSystemMap[k+1] //TODO::判断是否活跃 var m model.EggSignIn has, err33 := engine.Where("uid =?", fatherUid).And("end_time >=?", time.Now().Format("2006-01-02 15:04:05")).Get(&m) if err33 != nil { return rewardValue, err33 } if !has { //不活跃不需要奖励 continue } //判断是否满足奖励条件 userRelateDb := implement.NewUserRelateDb(engine) userCount, _, err2 := userRelateDb.SumUserRelateByParentUid(fatherUid) if err2 != nil { return rewardValue, err2 } if fatherReward != nil && userCount >= egg_system_rules.StrToInt64(fatherReward.RewardCondition) { fatherRewardValue := rewardValue * (egg_system_rules.StrToFloat64(fatherReward.RewardValue) / 100) rewardFather = append(rewardFather, struct { Uid int64 `json:"uid"` //用户id RewardValue float64 `json:"reward_value"` //奖励值 }{ Uid: egg_system_rules.StrToInt64(fatherUid), RewardValue: fatherRewardValue, }) } } //增加 egg_user_watch_records 记录 eggEnergyUserWatchRecordsDb := implement.NewEggEnergyUserWatchRecordsDb(engine) eggEnergyUserWatchRecords, err1 := eggEnergyUserWatchRecordsDb.EggEnergyUserWatchRecordsGetOneByParams(map[string]interface{}{ "key": "uid", "value": uid, }) if err1 != nil { return rewardValue, err1 } now := time.Now() if eggEnergyUserWatchRecords == nil { residueWatchAdNum := egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) - 1 if residueWatchAdNum < 0 { residueWatchAdNum = egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) } eggEnergyUserWatchRecords = &model.EggEnergyUserWatchRecords{ Uid: uid, NextWatchAdDate: now.Add(time.Hour * time.Duration(egg_system_rules.StrToInt(videoRewardSystem.EachRoundHour))), ResidueWatchAdNum: egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) - 1, CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), } _, err2 := eggEnergyUserWatchRecordsDb.EggEnergyUserWatchRecordsInsert(eggEnergyUserWatchRecords) if err2 != nil { return rewardValue, err2 } } else { residueWatchAdNum := eggEnergyUserWatchRecords.ResidueWatchAdNum - 1 nextWatchAdDate := eggEnergyUserWatchRecords.NextWatchAdDate if residueWatchAdNum == 0 { //最后一条广告 residueWatchAdNum = egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) } if residueWatchAdNum == egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum)-1 { //第一条广告 nextWatchAdDate = now.Add(time.Hour * time.Duration(egg_system_rules.StrToInt(videoRewardSystem.EachRoundHour))) } eggEnergyUserWatchRecords.ResidueWatchAdNum = residueWatchAdNum eggEnergyUserWatchRecords.NextWatchAdDate = nextWatchAdDate _, err2 := eggEnergyUserWatchRecordsDb.EggEnergyUserWatchRecordsUpdate(eggEnergyUserWatchRecords.Id, eggEnergyUserWatchRecords, "residue_watch_ad_num", "next_watch_ad_date") if err2 != nil { return rewardValue, err2 } } session := engine.NewSession() defer func() { session.Close() if err := recover(); err != nil { _ = zhios_order_relate_logx.Error(err) } }() session.Begin() //给相应的用户加上"个人"活跃积分 err = rule.DealUserVirtualCoin(session, md.DealUserVirtualCoinReq{ Kind: "add", Title: enum.UserVirtualAmountFlowTransferType.String(enum.EggEnergyWatchAdRewardPersonalActiveCoin), TransferType: int(enum.EggEnergyWatchAdRewardPersonalActiveCoin), CoinId: eggEnergyBasicSetting.PersonEggPointsCoinId, Uid: uid, Amount: rewardValue, }) if err != nil { _ = session.Rollback() fmt.Println("err:::::2222", err) return rewardValue, err } //给相应的用户加上"团队"活跃积分 for _, vv := range rewardFather { //TODO::推入rabbitmq 异步处理 ch.Publish(md2.EggEnergyExchange, md.DealUserVirtualCoinReq{ Kind: "add", Title: enum.UserVirtualAmountFlowTransferType.String(enum.EggEnergyWatchAdRewardTeamActiveCoin), TransferType: int(enum.EggEnergyWatchAdRewardTeamActiveCoin), CoinId: eggEnergyBasicSetting.TeamEggPointsCoinId, Uid: vv.Uid, Amount: vv.RewardValue, }, md2.EggEnergyRoutKeyForSettlementPublicGiveActivityCoin) } err = session.Commit() if err != nil { _ = session.Rollback() return rewardValue, errors.New("事务提交失败") } redisKey := fmt.Sprintf(md2.UserNextWatchAdDate, uid) var watchAdDate string if eggEnergyUserWatchRecords.ResidueWatchAdNum == egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) { if eggEnergyUserWatchRecords.NextWatchAdDate.Before(time.Now()) { watchAdDate = "" } else { watchAdDate = eggEnergyUserWatchRecords.NextWatchAdDate.Format("2006-01-02 15:04:05") } } else { watchAdDate = time.Now().Add(time.Duration(egg_system_rules.StrToInt64(videoRewardSystem.IntervalMinutes)) * time.Second).Format("2006-01-02 15:04:05") } cache.SetEx(redisKey, watchAdDate, 60*60*24) //TODO::默认缓存1小时 } return } func dealEcpm(user model.User, ecpm string, ch *rabbit.Channel) { //查找缓存中的ecpm值和当前的ecpm是否一致 key := fmt.Sprintf(md.UserEcpmCacheKey, user.Id) ecpmCacheValue, _ := cache.GetString(key) if ecpmCacheValue == "" || ecpmCacheValue != ecpm { //更新缓存值 cache.SetEx(key, ecpm, md.UserEcpmCacheTime) //TODO::推入rabbitmq 异步处理 ch.Publish(md2.EggEnergyExchange, md.DealUserEcpmReq{ Uid: user.Id, Ecpm: ecpm, }, md2.EggEnergyRoutKeyForDealUserEcpm) } } func ActivityCoinToAlipayRealName(engine *xorm.Engine, uid int64, amount string) (err error) { amountValue, _ := decimal.NewFromString(amount) //1、查找 `egg_energy_basic_setting` 基础设置 eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine) eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{ "key": "is_open", "value": 1, }) if err != nil { return } if eggEnergyBasicSetting == nil { err = errors.New("蛋蛋能量设置未开启!") return } var coin model.VirtualCoin _, err = engine.Where("id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).Get(&coin) if err != nil { return } personActivePointsCoinExchangeRatioValue, _ := decimal.NewFromString(coin.ExchangeRatio) //2、判断个人蛋蛋积分是否足够 var personUserVirtualAmount model.UserVirtualAmount _, err = engine.Where("coin_id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).And("uid =?", uid).Get(&personUserVirtualAmount) if err != nil { fmt.Println("err:::::1111", err) return } personUserVirtualAmountValue, _ := decimal.NewFromString(personUserVirtualAmount.Amount) needVirtualAmountValue := amountValue.Mul(personActivePointsCoinExchangeRatioValue) needVirtualAmount, _ := amountValue.Mul(personActivePointsCoinExchangeRatioValue).Float64() if personUserVirtualAmountValue.LessThan(needVirtualAmountValue) { err = errors.New("当前蛋蛋积分不足!") return } //3、扣除对应个人蛋蛋积分 session := engine.NewSession() defer func() { session.Close() if err := recover(); err != nil { _ = zhios_order_relate_logx.Error(err) } }() session.Begin() //给相应的用户加上"个人"活跃积分 err = rule.DealUserVirtualCoin(session, md.DealUserVirtualCoinReq{ Kind: "sub", Title: enum.UserVirtualAmountFlowTransferType.String(enum.EggPointCoinToAliPayRealName), TransferType: int(enum.EggPointCoinToAliPayRealName), CoinId: eggEnergyBasicSetting.PersonEggPointsCoinId, Uid: uid, Amount: needVirtualAmount, }) if err != nil { _ = session.Rollback() fmt.Println("err:::::2222", err) return err } err = session.Commit() if err != nil { _ = session.Rollback() return errors.New("事务提交失败") } return } func CheckActivityCoinToAlipayRealName(engine *xorm.Engine, uid int64, amount string) (err error, isCan bool) { amountValue, _ := decimal.NewFromString(amount) //1、查找 `egg_energy_basic_setting` 基础设置 eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine) eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{ "key": "is_open", "value": 1, }) if err != nil { return } if eggEnergyBasicSetting == nil { err = errors.New("蛋蛋能量设置未开启!") return } var coin model.VirtualCoin _, err = engine.Where("id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).Get(&coin) if err != nil { return } personActivePointsCoinExchangeRatioValue, _ := decimal.NewFromString(coin.ExchangeRatio) //2、判断个人蛋蛋积分是否足够 var personUserVirtualAmount model.UserVirtualAmount _, err = engine.Where("coin_id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).And("uid =?", uid).Get(&personUserVirtualAmount) if err != nil { fmt.Println("err:::::1111", err) return } personUserVirtualAmountValue, _ := decimal.NewFromString(personUserVirtualAmount.Amount) needVirtualAmountValue := amountValue.Mul(personActivePointsCoinExchangeRatioValue) if personUserVirtualAmountValue.GreaterThan(needVirtualAmountValue) { isCan = true } return } // CalcUserContinuousDailyActivityDays 计算用户连续活跃天数 func CalcUserContinuousDailyActivityDays(engine *xorm.Engine, uid int, startDate string, endDate string) (err error, days int, isContinuousDailyActivity bool) { startAt, err := time.ParseInLocation("2006-01-02", startDate, time.Local) //起始时间 endAt, err := time.ParseInLocation("2006-01-02", endDate, time.Local) //起始时间 var list []model.EggEnergyUserActivity err = engine.Where("date >= ?", startAt.Format("2006-01-02")). And("date < ?", endAt.Format("2006-01-02")). And("uid =?", uid).Find(&list) if err != nil { fmt.Println("err:::::1111", err) return } days = len(list) diffDays := egg_system_rules.GetDiffDays(endAt, startAt) //相差天数 if days == diffDays { isContinuousDailyActivity = true } return }