蛋蛋星球-制度模式
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

447 lines
16 KiB

  1. package egg_energy
  2. import (
  3. "code.fnuoos.com/EggPlanet/egg_models.git/src/dao"
  4. "code.fnuoos.com/EggPlanet/egg_models.git/src/implement"
  5. "code.fnuoos.com/EggPlanet/egg_models.git/src/model"
  6. "code.fnuoos.com/EggPlanet/egg_system_rules.git/enum"
  7. "code.fnuoos.com/EggPlanet/egg_system_rules.git/md"
  8. "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule"
  9. md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md"
  10. egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils"
  11. "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache"
  12. "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/es"
  13. zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx"
  14. es2 "code.fnuoos.com/go_rely_warehouse/zyos_go_es.git/es"
  15. "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit"
  16. "encoding/json"
  17. "errors"
  18. "fmt"
  19. "github.com/olivere/elastic/v7"
  20. "github.com/shopspring/decimal"
  21. "strings"
  22. "time"
  23. "xorm.io/xorm"
  24. )
  25. // SettlementGiveActivityCoin 结算观看激励广告得到蛋蛋积分
  26. func SettlementGiveActivityCoin(engine *xorm.Engine, user model.User, ecpm string, ch *rabbit.Channel) (rewardValue float64, err error) {
  27. uid := user.Id
  28. now := time.Now()
  29. //1、查找 `egg_energy_basic_setting` 基础设置
  30. eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine)
  31. eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{
  32. "key": "is_open",
  33. "value": 1,
  34. })
  35. if err != nil {
  36. return
  37. }
  38. if eggEnergyBasicSetting == nil {
  39. err = errors.New("蛋蛋能量设置未开启!")
  40. return
  41. }
  42. if eggEnergyBasicSetting.VideoRewardIsOpen == 1 {
  43. var videoRewardSystem *md2.VideoRewardSystemStruct
  44. err = json.Unmarshal([]byte(eggEnergyBasicSetting.VideoRewardSystem), &videoRewardSystem)
  45. if err != nil {
  46. return
  47. }
  48. if videoRewardSystem.RewardTotalNum == "" || videoRewardSystem.IntervalMinutes == "" || videoRewardSystem.EachRoundHour == "" {
  49. err = errors.New("视屏奖励机制设置未完全!")
  50. return
  51. }
  52. var rewardSystem []*md2.RewardSystemStruct
  53. err = json.Unmarshal([]byte(eggEnergyBasicSetting.RewardSystem), &rewardSystem)
  54. if err != nil {
  55. return
  56. }
  57. if len(rewardSystem) == 0 {
  58. err = errors.New("未设置奖励机制!")
  59. return
  60. }
  61. go dealEcpm(user, ecpm, ch) //TODO::协程处理ecpm的变化
  62. //TODO::奖励多少个活跃积分(根据ecpm, 新用户机制, 蛋蛋分机制)
  63. redisConn := cache.GetPool().Get()
  64. sysCfgDb := implement.NewSysCfgDb(engine, redisConn)
  65. defer func(sysCfgDb dao.SysCfgDao) {
  66. err = sysCfgDb.Close()
  67. if err != nil {
  68. fmt.Println("redis close err:" + err.Error()) // 记录错误信息
  69. }
  70. }(sysCfgDb)
  71. videoRewardUnitPrice := sysCfgDb.SysCfgGetWithDb(enum.VideoRewardUnitPrice)
  72. if videoRewardUnitPrice != "" { //处理ecpm
  73. var coin model.VirtualCoin
  74. _, err = engine.Where("id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).Get(&coin)
  75. if err != nil {
  76. return rewardValue, err
  77. }
  78. activePointsCoinExchangeRatioValue, _ := decimal.NewFromString(coin.ExchangeRatio)
  79. videoRewardUnitPriceValue, _ := decimal.NewFromString(videoRewardUnitPrice)
  80. rewardValue, _ = videoRewardUnitPriceValue.Mul(activePointsCoinExchangeRatioValue).Float64()
  81. } else {
  82. rewardValue = egg_system_rules.StrToFloat64(videoRewardSystem.RewardValue)
  83. }
  84. var newUserRewardRules *md2.NewUserRewardRules
  85. err = json.Unmarshal([]byte(eggEnergyBasicSetting.NewUserIncentiveRules), &newUserRewardRules)
  86. if err != nil {
  87. return
  88. }
  89. userCreateAt := egg_system_rules.String2Time(user.CreateAt)
  90. if int(now.Sub(userCreateAt).Hours()/24) <= newUserRewardRules.ContinueDays { //处理新用户机制
  91. rewardValue *= newUserRewardRules.RewardCoefficient
  92. }
  93. score := 60.00
  94. esIndex := es.GetLatestEffectiveIndexFromAlias(now)
  95. esIndexName := md.EggEnergyUserEggScoreEsAlias + "_" + esIndex
  96. results, err1 := es2.FirstDoc(esIndexName, esIndex+"_"+egg_system_rules.Int64ToStr(user.Id))
  97. if err1 != nil {
  98. if !elastic.IsNotFound(err1) {
  99. return rewardValue, err1
  100. }
  101. }
  102. if !elastic.IsNotFound(err1) {
  103. var doc md.EggEnergyUserEggScoreEs
  104. err = json.Unmarshal(results.Source, &doc)
  105. if err != nil {
  106. return
  107. }
  108. score = doc.ScoreValue
  109. }
  110. eggPointPartitionCoefficientManagementDb := implement.NewEggPointPartitionCoefficientManagementDb(engine)
  111. eggPointPartitionCoefficientManagements, err1 := eggPointPartitionCoefficientManagementDb.EggPointPartitionCoefficientManagementGetAll()
  112. if err1 != nil {
  113. return rewardValue, err1
  114. }
  115. for _, v := range *eggPointPartitionCoefficientManagements { //处理蛋蛋分机制
  116. if egg_system_rules.StrToFloat64(v.StartScore) <= score && egg_system_rules.StrToFloat64(v.EndScore) >= score {
  117. rewardValue *= egg_system_rules.StrToFloat64(v.Coefficient)
  118. }
  119. }
  120. //处理圈层奖励
  121. var rewardSystemMap = map[int]*md2.RewardSystemStruct{}
  122. for _, v := range rewardSystem {
  123. rewardSystemMap[v.Level] = v
  124. }
  125. publicPlatoonUserRelationDb := implement.NewPublicPlatoonUserRelationDb(engine)
  126. publicPlatoonUserRelation, err1 := publicPlatoonUserRelationDb.PublicPlatoonUserRelationGetOneByParams(map[string]interface{}{
  127. "key": "uid",
  128. "value": uid,
  129. })
  130. if err1 != nil {
  131. return rewardValue, err1
  132. }
  133. var rewardFather []struct {
  134. Uid int64 `json:"uid"` //用户id
  135. RewardValue float64 `json:"reward_value"` //奖励值
  136. }
  137. var fatherUids []string
  138. if publicPlatoonUserRelation != nil {
  139. fatherUids = strings.Split(publicPlatoonUserRelation.FatherUid, "-")
  140. }
  141. for k, id := range fatherUids {
  142. tmpOneCirclesPublicPlatoonUserRelation, err11 := publicPlatoonUserRelationDb.PublicPlatoonUserRelationGetOneByParams(map[string]interface{}{
  143. "key": "id",
  144. "value": id,
  145. })
  146. if err11 != nil {
  147. return rewardValue, err11
  148. }
  149. if tmpOneCirclesPublicPlatoonUserRelation == nil {
  150. continue
  151. }
  152. if tmpOneCirclesPublicPlatoonUserRelation.Uid <= 0 {
  153. //待填充位
  154. continue
  155. }
  156. fatherUid := egg_system_rules.Int64ToStr(tmpOneCirclesPublicPlatoonUserRelation.Uid)
  157. fatherReward := rewardSystemMap[k+1]
  158. //TODO::判断是否活跃
  159. var m model.EggSignIn
  160. has, err33 := engine.Where("uid =?", fatherUid).And("end_time >=?", time.Now().Format("2006-01-02 15:04:05")).Get(&m)
  161. if err33 != nil {
  162. return rewardValue, err33
  163. }
  164. if !has {
  165. //不活跃不需要奖励
  166. continue
  167. }
  168. //判断是否满足奖励条件
  169. userRelateDb := implement.NewUserRelateDb(engine)
  170. userCount, _, err2 := userRelateDb.SumUserRelateByParentUid(fatherUid)
  171. if err2 != nil {
  172. return rewardValue, err2
  173. }
  174. if fatherReward != nil && userCount >= egg_system_rules.StrToInt64(fatherReward.RewardCondition) {
  175. fatherRewardValue := rewardValue * (egg_system_rules.StrToFloat64(fatherReward.RewardValue) / 100)
  176. rewardFather = append(rewardFather, struct {
  177. Uid int64 `json:"uid"` //用户id
  178. RewardValue float64 `json:"reward_value"` //奖励值
  179. }{
  180. Uid: egg_system_rules.StrToInt64(fatherUid),
  181. RewardValue: fatherRewardValue,
  182. })
  183. }
  184. }
  185. //增加 egg_user_watch_records 记录
  186. eggEnergyUserWatchRecordsDb := implement.NewEggEnergyUserWatchRecordsDb(engine)
  187. eggEnergyUserWatchRecords, err1 := eggEnergyUserWatchRecordsDb.EggEnergyUserWatchRecordsGetOneByParams(map[string]interface{}{
  188. "key": "uid",
  189. "value": uid,
  190. })
  191. if err1 != nil {
  192. return rewardValue, err1
  193. }
  194. now := time.Now()
  195. if eggEnergyUserWatchRecords == nil {
  196. residueWatchAdNum := egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) - 1
  197. if residueWatchAdNum < 0 {
  198. residueWatchAdNum = egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum)
  199. }
  200. eggEnergyUserWatchRecords = &model.EggEnergyUserWatchRecords{
  201. Uid: uid,
  202. NextWatchAdDate: now.Add(time.Hour * time.Duration(egg_system_rules.StrToInt(videoRewardSystem.EachRoundHour))),
  203. ResidueWatchAdNum: egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) - 1,
  204. CreateAt: now.Format("2006-01-02 15:04:05"),
  205. UpdateAt: now.Format("2006-01-02 15:04:05"),
  206. }
  207. _, err2 := eggEnergyUserWatchRecordsDb.EggEnergyUserWatchRecordsInsert(eggEnergyUserWatchRecords)
  208. if err2 != nil {
  209. return rewardValue, err2
  210. }
  211. } else {
  212. residueWatchAdNum := eggEnergyUserWatchRecords.ResidueWatchAdNum - 1
  213. nextWatchAdDate := eggEnergyUserWatchRecords.NextWatchAdDate
  214. if residueWatchAdNum == 0 { //最后一条广告
  215. residueWatchAdNum = egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum)
  216. }
  217. if residueWatchAdNum == egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum)-1 { //第一条广告
  218. nextWatchAdDate = now.Add(time.Hour * time.Duration(egg_system_rules.StrToInt(videoRewardSystem.EachRoundHour)))
  219. }
  220. eggEnergyUserWatchRecords.ResidueWatchAdNum = residueWatchAdNum
  221. eggEnergyUserWatchRecords.NextWatchAdDate = nextWatchAdDate
  222. _, err2 := eggEnergyUserWatchRecordsDb.EggEnergyUserWatchRecordsUpdate(eggEnergyUserWatchRecords.Id, eggEnergyUserWatchRecords, "residue_watch_ad_num", "next_watch_ad_date")
  223. if err2 != nil {
  224. return rewardValue, err2
  225. }
  226. }
  227. session := engine.NewSession()
  228. defer func() {
  229. session.Close()
  230. if err := recover(); err != nil {
  231. _ = zhios_order_relate_logx.Error(err)
  232. }
  233. }()
  234. session.Begin()
  235. //给相应的用户加上"个人"活跃积分
  236. err = rule.DealUserVirtualCoin(session, md.DealUserVirtualCoinReq{
  237. Kind: "add",
  238. Title: enum.UserVirtualAmountFlowTransferType.String(enum.EggEnergyWatchAdRewardPersonalActiveCoin),
  239. TransferType: int(enum.EggEnergyWatchAdRewardPersonalActiveCoin),
  240. CoinId: eggEnergyBasicSetting.PersonEggPointsCoinId,
  241. Uid: uid,
  242. Amount: rewardValue,
  243. })
  244. if err != nil {
  245. _ = session.Rollback()
  246. fmt.Println("err:::::2222", err)
  247. return rewardValue, err
  248. }
  249. //给相应的用户加上"团队"活跃积分
  250. for _, vv := range rewardFather {
  251. //TODO::推入rabbitmq 异步处理
  252. ch.Publish(md2.EggEnergyExchange, md.DealUserVirtualCoinReq{
  253. Kind: "add",
  254. Title: enum.UserVirtualAmountFlowTransferType.String(enum.EggEnergyWatchAdRewardTeamActiveCoin),
  255. TransferType: int(enum.EggEnergyWatchAdRewardTeamActiveCoin),
  256. CoinId: eggEnergyBasicSetting.TeamEggPointsCoinId,
  257. Uid: vv.Uid,
  258. Amount: vv.RewardValue,
  259. }, md2.EggEnergyRoutKeyForSettlementPublicGiveActivityCoin)
  260. }
  261. err = session.Commit()
  262. if err != nil {
  263. _ = session.Rollback()
  264. return rewardValue, errors.New("事务提交失败")
  265. }
  266. redisKey := fmt.Sprintf(md2.UserNextWatchAdDate, uid)
  267. var watchAdDate string
  268. if eggEnergyUserWatchRecords.ResidueWatchAdNum == egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) {
  269. if eggEnergyUserWatchRecords.NextWatchAdDate.Before(time.Now()) {
  270. watchAdDate = ""
  271. } else {
  272. watchAdDate = eggEnergyUserWatchRecords.NextWatchAdDate.Format("2006-01-02 15:04:05")
  273. }
  274. } else {
  275. watchAdDate = time.Now().Add(time.Duration(egg_system_rules.StrToInt64(videoRewardSystem.IntervalMinutes)) * time.Second).Format("2006-01-02 15:04:05")
  276. }
  277. cache.SetEx(redisKey, watchAdDate, 60*60*24) //TODO::默认缓存1小时
  278. }
  279. return
  280. }
  281. func dealEcpm(user model.User, ecpm string, ch *rabbit.Channel) {
  282. //查找缓存中的ecpm值和当前的ecpm是否一致
  283. key := fmt.Sprintf(md.UserEcpmCacheKey, user.Id)
  284. ecpmCacheValue, _ := cache.GetString(key)
  285. if ecpmCacheValue == "" || ecpmCacheValue != ecpm {
  286. //更新缓存值
  287. cache.SetEx(key, ecpm, md.UserEcpmCacheTime)
  288. //TODO::推入rabbitmq 异步处理
  289. ch.Publish(md2.EggEnergyExchange, md.DealUserEcpmReq{
  290. Uid: user.Id,
  291. Ecpm: ecpm,
  292. }, md2.EggEnergyRoutKeyForDealUserEcpm)
  293. }
  294. }
  295. func ActivityCoinToAlipayRealName(engine *xorm.Engine, uid int64, amount string) (err error) {
  296. amountValue, _ := decimal.NewFromString(amount)
  297. //1、查找 `egg_energy_basic_setting` 基础设置
  298. eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine)
  299. eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{
  300. "key": "is_open",
  301. "value": 1,
  302. })
  303. if err != nil {
  304. return
  305. }
  306. if eggEnergyBasicSetting == nil {
  307. err = errors.New("蛋蛋能量设置未开启!")
  308. return
  309. }
  310. var coin model.VirtualCoin
  311. _, err = engine.Where("id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).Get(&coin)
  312. if err != nil {
  313. return
  314. }
  315. personActivePointsCoinExchangeRatioValue, _ := decimal.NewFromString(coin.ExchangeRatio)
  316. //2、判断个人蛋蛋积分是否足够
  317. var personUserVirtualAmount model.UserVirtualAmount
  318. _, err = engine.Where("coin_id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).And("uid =?", uid).Get(&personUserVirtualAmount)
  319. if err != nil {
  320. fmt.Println("err:::::1111", err)
  321. return
  322. }
  323. personUserVirtualAmountValue, _ := decimal.NewFromString(personUserVirtualAmount.Amount)
  324. needVirtualAmountValue := amountValue.Mul(personActivePointsCoinExchangeRatioValue)
  325. needVirtualAmount, _ := amountValue.Mul(personActivePointsCoinExchangeRatioValue).Float64()
  326. if personUserVirtualAmountValue.LessThan(needVirtualAmountValue) {
  327. err = errors.New("当前蛋蛋积分不足!")
  328. return
  329. }
  330. //3、扣除对应个人蛋蛋积分
  331. session := engine.NewSession()
  332. defer func() {
  333. session.Close()
  334. if err := recover(); err != nil {
  335. _ = zhios_order_relate_logx.Error(err)
  336. }
  337. }()
  338. session.Begin()
  339. //给相应的用户加上"个人"活跃积分
  340. err = rule.DealUserVirtualCoin(session, md.DealUserVirtualCoinReq{
  341. Kind: "sub",
  342. Title: enum.UserVirtualAmountFlowTransferType.String(enum.EggPointCoinToAliPayRealName),
  343. TransferType: int(enum.EggPointCoinToAliPayRealName),
  344. CoinId: eggEnergyBasicSetting.PersonEggPointsCoinId,
  345. Uid: uid,
  346. Amount: needVirtualAmount,
  347. })
  348. if err != nil {
  349. _ = session.Rollback()
  350. fmt.Println("err:::::2222", err)
  351. return err
  352. }
  353. err = session.Commit()
  354. if err != nil {
  355. _ = session.Rollback()
  356. return errors.New("事务提交失败")
  357. }
  358. return
  359. }
  360. func CheckActivityCoinToAlipayRealName(engine *xorm.Engine, uid int64, amount string) (err error, isCan bool) {
  361. amountValue, _ := decimal.NewFromString(amount)
  362. //1、查找 `egg_energy_basic_setting` 基础设置
  363. eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine)
  364. eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{
  365. "key": "is_open",
  366. "value": 1,
  367. })
  368. if err != nil {
  369. return
  370. }
  371. if eggEnergyBasicSetting == nil {
  372. err = errors.New("蛋蛋能量设置未开启!")
  373. return
  374. }
  375. var coin model.VirtualCoin
  376. _, err = engine.Where("id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).Get(&coin)
  377. if err != nil {
  378. return
  379. }
  380. personActivePointsCoinExchangeRatioValue, _ := decimal.NewFromString(coin.ExchangeRatio)
  381. //2、判断个人蛋蛋积分是否足够
  382. var personUserVirtualAmount model.UserVirtualAmount
  383. _, err = engine.Where("coin_id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).And("uid =?", uid).Get(&personUserVirtualAmount)
  384. if err != nil {
  385. fmt.Println("err:::::1111", err)
  386. return
  387. }
  388. personUserVirtualAmountValue, _ := decimal.NewFromString(personUserVirtualAmount.Amount)
  389. needVirtualAmountValue := amountValue.Mul(personActivePointsCoinExchangeRatioValue)
  390. if personUserVirtualAmountValue.GreaterThan(needVirtualAmountValue) {
  391. isCan = true
  392. }
  393. return
  394. }
  395. // CalcUserContinuousDailyActivityDays 计算用户连续活跃天数
  396. func CalcUserContinuousDailyActivityDays(engine *xorm.Engine, uid int, startDate string, endDate string) (err error, days int, isContinuousDailyActivity bool) {
  397. startAt, err := time.ParseInLocation("2006-01-02", startDate, time.Local) //起始时间
  398. endAt, err := time.ParseInLocation("2006-01-02", endDate, time.Local) //起始时间
  399. var list []model.EggEnergyUserActivity
  400. err = engine.Where("date >= ?", startAt.Format("2006-01-02")).
  401. And("date < ?", endAt.Format("2006-01-02")).
  402. And("uid =?", uid).Find(&list)
  403. if err != nil {
  404. fmt.Println("err:::::1111", err)
  405. return
  406. }
  407. days = len(list)
  408. diffDays := egg_system_rules.GetDiffDays(endAt, startAt) //相差天数
  409. if days == diffDays {
  410. isContinuousDailyActivity = true
  411. }
  412. return
  413. }