蛋蛋星球-客户端
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.
 
 
 
 
 
 

438 lines
14 KiB

  1. package hdl
  2. import (
  3. "applet/app/db"
  4. "applet/app/e"
  5. "applet/app/md"
  6. "applet/app/svc"
  7. "applet/app/utils"
  8. "applet/app/utils/cache"
  9. "code.fnuoos.com/EggPlanet/egg_models.git/src/implement"
  10. "code.fnuoos.com/EggPlanet/egg_models.git/src/model"
  11. md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md"
  12. "encoding/json"
  13. "github.com/gin-gonic/gin"
  14. "github.com/shopspring/decimal"
  15. "math"
  16. "time"
  17. )
  18. // HomePage
  19. // @Summary 蛋蛋星球-主页-基础信息(获取)
  20. // @Tags 主页
  21. // @Description 基础信息(获取)
  22. // @Accept json
  23. // @Produce json
  24. // @param Authorization header string true "验证参数Bearer和token空格拼接"
  25. // @Success 200 {object} md.HomePageResp "具体数据"
  26. // @Failure 400 {object} md.Response "具体错误"
  27. // @Router /api/v1/homePage/index [get]
  28. func HomePage(c *gin.Context) {
  29. now := time.Now()
  30. val, exists := c.Get("user")
  31. if !exists {
  32. e.OutErr(c, e.ERR_USER_CHECK_ERR, nil)
  33. return
  34. }
  35. user, ok := val.(*model.User)
  36. if !ok {
  37. e.OutErr(c, e.ERR_USER_CHECK_ERR, nil)
  38. return
  39. }
  40. //1、查找 `egg_energy_basic_setting` 基础设置
  41. eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(db.Db)
  42. eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{
  43. "key": "is_open",
  44. "value": 1,
  45. })
  46. if err != nil {
  47. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  48. return
  49. }
  50. //2、计算今日涨幅
  51. err, rises, isRise, nowPrice, initialPrice := svc.CalcTodayEggEnergyPriceRises(db.Db, now)
  52. if err != nil {
  53. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  54. return
  55. }
  56. //3、获取当前用户 蛋蛋能量(可用+结算+今日签到预估蛋蛋能量)
  57. var isSign bool
  58. var signCountdown string
  59. var signEggEnergy = "0.00"
  60. var totalEggEnergy float64
  61. var teamRewardSetting *md2.TeamRewardSettingStruct
  62. // 3.1 获取团队收益设置 一轮持续时间
  63. err = json.Unmarshal([]byte(eggEnergyBasicSetting.DirectPushReward), &teamRewardSetting)
  64. if err != nil {
  65. e.OutErr(c, e.ERR, err.Error())
  66. return
  67. }
  68. //3.2 计算用户是否在团队收益时间段内签到
  69. var oneRoundDuration = utils.StrToInt(teamRewardSetting.OneRoundDuration)
  70. startTime := now.Add(-time.Hour * time.Duration(oneRoundDuration)).Format("2006-01-02 15:04:05")
  71. signInDb := implement.NewEggSignInDb(db.Db)
  72. has, signIn, err := signInDb.EggSignInGetOne(startTime, now.Format("2006-01-02 15:04:05"), user.Id)
  73. if err != nil {
  74. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  75. return
  76. }
  77. if has && utils.TimeParseStd(signIn.EndTime).After(now) {
  78. //3.2.1 获取预估每秒获得蛋蛋能量数
  79. estimatePerSecondEggEnergyValue, err1 := decimal.NewFromString(signIn.EstimatePerSecondEggEnergyValue)
  80. if err1 != nil {
  81. e.OutErr(c, e.ERR, err1.Error())
  82. return
  83. }
  84. signEggEnergy = estimatePerSecondEggEnergyValue.String()
  85. isSign = true
  86. signCountdown = signIn.EndTime
  87. }
  88. // 3.3 查询个人及团队蛋蛋能量
  89. amountDb := implement.NewUserVirtualAmountDb(db.Db)
  90. personEggEnergy, err := amountDb.GetUserVirtualWalletBySession(user.Id, eggEnergyBasicSetting.PersonEggEnergyCoinId)
  91. if err != nil {
  92. return
  93. }
  94. teamEggEnergy, err := amountDb.GetUserVirtualWalletBySession(user.Id, eggEnergyBasicSetting.TeamEggEnergyCoinId)
  95. if err != nil {
  96. return
  97. }
  98. signEggEnergyValue, _ := decimal.NewFromString(signEggEnergy)
  99. personEggEnergyValue, _ := decimal.NewFromString(personEggEnergy.Amount)
  100. teamEggEnergyValue, _ := decimal.NewFromString(teamEggEnergy.Amount)
  101. totalEggEnergy, _ = signEggEnergyValue.Add(personEggEnergyValue).Add(teamEggEnergyValue).Float64()
  102. //4、活跃积分(个人+团队)
  103. var totalActivePoints float64
  104. personActivePoints, err := amountDb.GetUserVirtualWalletBySession(user.Id, eggEnergyBasicSetting.PersonEggPointsCoinId)
  105. if err != nil {
  106. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  107. return
  108. }
  109. teamActivePoints, err := amountDb.GetUserVirtualWalletBySession(user.Id, eggEnergyBasicSetting.TeamEggPointsCoinId)
  110. if err != nil {
  111. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  112. return
  113. }
  114. totalActivePoints = utils.StrToFloat64(personActivePoints.Amount) + utils.StrToFloat64(teamActivePoints.Amount)
  115. //5、计算当前基础速率、团队速率
  116. nowBasalRate := utils.StrToFloat64(signEggEnergy) * 60 * 60 //每小时基础速率
  117. var estimateLevel int
  118. nowBasalRateValue := decimal.NewFromFloat(nowBasalRate)
  119. for {
  120. estimateLevel++
  121. rewardDecrementValue := utils.StrToFloat64(teamRewardSetting.RewardDecrementValue) / 100
  122. tmpRewardBase := decimal.NewFromFloat(math.Pow(rewardDecrementValue, float64(estimateLevel)))
  123. tmpReward := nowBasalRateValue.Mul(tmpRewardBase)
  124. rewardEndValue, _ := decimal.NewFromString(teamRewardSetting.RewardEndValue)
  125. if !tmpReward.GreaterThanOrEqual(rewardEndValue) {
  126. estimateLevel--
  127. break
  128. }
  129. if estimateLevel == 99 {
  130. e.OutErr(c, e.ERR, "奖励结束值设置有误")
  131. return
  132. }
  133. }
  134. relateDb := implement.NewUserRelateDb(db.Db)
  135. userRelates, err := relateDb.FindUserRelateByParentUid(user.Id, estimateLevel)
  136. if err != nil {
  137. e.OutErr(c, e.ERR, err.Error())
  138. return
  139. }
  140. var userRelatesUids []string
  141. var userRelatesMap = map[int64]model.UserRelate{}
  142. if userRelates != nil {
  143. for _, userRelate := range *userRelates {
  144. userRelatesUids = append(userRelatesUids, utils.Int64ToStr(userRelate.Uid))
  145. userRelatesMap[userRelate.Uid] = userRelate
  146. }
  147. }
  148. var eggSignIns []*model.EggSignIn
  149. if len(userRelatesUids) > 0 {
  150. eggSignIns, err = signInDb.EggSignInFindByParams(map[string]interface{}{
  151. "key": "uid",
  152. "value": userRelatesUids,
  153. })
  154. if err != nil {
  155. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  156. return
  157. }
  158. }
  159. var nowTeamRate float64 //每小时基础速率
  160. for _, vv := range eggSignIns {
  161. rewardDecrementValue := utils.StrToFloat64(teamRewardSetting.RewardDecrementValue) / 100
  162. tmpRewardBase := decimal.NewFromFloat(math.Pow(rewardDecrementValue, float64(userRelatesMap[vv.Uid].Level)))
  163. tmpReward := nowBasalRateValue.Mul(tmpRewardBase)
  164. rewardEndValue, _ := decimal.NewFromString(teamRewardSetting.RewardEndValue)
  165. if tmpReward.GreaterThanOrEqual(rewardEndValue) {
  166. tmpRewardValue, _ := tmpReward.Float64()
  167. nowTeamRate += tmpRewardValue
  168. }
  169. }
  170. decimalRate := decimal.NewFromInt(100) //百分比
  171. risesValue, _ := decimal.NewFromFloat(rises).Mul(decimalRate).Float64()
  172. var residueTimes = utils.TimeParseStd(signCountdown).Unix() - time.Now().Unix()
  173. userDb := implement.NewUserDb(db.Db)
  174. userCount, err := userDb.UserCount()
  175. if err != nil {
  176. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  177. return
  178. }
  179. utils.FilePutContents("HomePage", utils.SerializeStr(map[string]interface{}{
  180. "user_phone": user.Phone,
  181. "user_uid": user.Id,
  182. "data": map[string]interface{}{
  183. "is_sign": isSign,
  184. "sign_end_date": signCountdown,
  185. "sign_end_timestamp": utils.TimeParseStd(signCountdown).Unix(),
  186. "residue_times": residueTimes,
  187. "total_egg_energy": totalEggEnergy,
  188. "sign_reward_egg_energy": utils.StrToFloat64(signIn.EstimatePerSecondEggEnergyValue),
  189. "total_active_points": totalActivePoints,
  190. "egg_energy_now_price": nowPrice,
  191. "initial_price": initialPrice,
  192. "is_rises": isRise,
  193. "rises": risesValue,
  194. "now_basal_rate": nowBasalRate,
  195. "now_team_rate": nowTeamRate,
  196. "user_count": userCount,
  197. "nickname": user.Nickname,
  198. },
  199. }))
  200. resp := md.HomePageResp{
  201. IsSign: isSign,
  202. SignEndTime: signCountdown,
  203. TotalEggEnergy: utils.Float64ToStr(totalEggEnergy),
  204. SignRewardEggEnergy: signIn.EstimatePerSecondEggEnergyValue,
  205. TotalActivePoints: utils.Float64ToStr(totalActivePoints),
  206. EggEnergyNowPrice: nowPrice,
  207. InitialPrice: initialPrice,
  208. IsRises: isRise,
  209. Rises: utils.Float64ToStr(risesValue),
  210. NowBasalRate: utils.Float64ToStr(nowBasalRate),
  211. NowTeamRate: utils.Float64ToStr(nowTeamRate),
  212. UserCount: userCount,
  213. NickName: user.Nickname,
  214. }
  215. e.OutSuc(c, resp, nil)
  216. return
  217. }
  218. // HomePageWatchAdRule
  219. // @Summary 蛋蛋星球-主页-视频奖励规则(获取)
  220. // @Tags 主页
  221. // @Description 视频奖励规则(获取)
  222. // @Accept json
  223. // @Produce json
  224. // @param Authorization header string true "验证参数Bearer和token空格拼接"
  225. // @Success 200 {object} md.HomePageWatchAdRuleResp "具体数据"
  226. // @Failure 400 {object} md.Response "具体错误"
  227. // @Router /api/v1/homePage/adRule [get]
  228. func HomePageWatchAdRule(c *gin.Context) {
  229. energyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(db.Db)
  230. basicSetting, err := energyBasicSettingDb.EggEnergyBasicSettingGetOne()
  231. if err != nil {
  232. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  233. return
  234. }
  235. var videoRewardSystem md2.VideoRewardSystemStruct
  236. utils.Unserialize([]byte(basicSetting.VideoRewardSystem), &videoRewardSystem)
  237. resp := md.HomePageWatchAdRuleResp{
  238. RewardValue: videoRewardSystem.RewardValue,
  239. RewardTotalNum: videoRewardSystem.RewardTotalNum,
  240. IntervalMinutes: videoRewardSystem.IntervalMinutes,
  241. EachRoundHour: videoRewardSystem.EachRoundHour,
  242. }
  243. e.OutSuc(c, resp, nil)
  244. }
  245. const HomePageRealTimeRedisKey = "Home_Page_Real_Time_Cache_Key"
  246. // RealTimePrice
  247. // @Summary 蛋蛋星球-主页-实时数据(获取)
  248. // @Tags 主页
  249. // @Description 实时数据(获取)
  250. // @Accept json
  251. // @Produce json
  252. // @param Authorization header string true "验证参数Bearer和token空格拼接"
  253. // @Success 200 {object} md.RealTimePriceResp "具体数据"
  254. // @Failure 400 {object} md.Response "具体错误"
  255. // @Router /api/v1/homePage/realTimePrice [get]
  256. func RealTimePrice(c *gin.Context) {
  257. var isRises, userCount, risesValue, nowPrice interface{}
  258. var rises float64
  259. redisKey := HomePageRealTimeRedisKey
  260. redisValue, err := cache.GetString(redisKey)
  261. if err != nil {
  262. if err.Error() == "redigo: nil returned" {
  263. now := time.Now()
  264. err, rises, isRises, nowPrice, _ = svc.CalcTodayEggEnergyPriceRises(db.Db, now)
  265. if err != nil {
  266. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  267. return
  268. }
  269. userDb := implement.NewUserDb(db.Db)
  270. userCount, err = userDb.UserCount()
  271. if err != nil {
  272. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  273. return
  274. }
  275. decimalRate := decimal.NewFromInt(100) //百分比
  276. risesValue, _ = decimal.NewFromFloat(rises).Mul(decimalRate).Float64()
  277. // 缓存 5 s
  278. cache.SetEx(redisKey, utils.SerializeStr(map[string]interface{}{
  279. "user_count": userCount,
  280. "is_rises": isRises,
  281. "rises": risesValue,
  282. "egg_energy_now_price": nowPrice,
  283. }), 5)
  284. } else {
  285. e.OutErr(c, e.ERR, err.Error())
  286. return
  287. }
  288. } else {
  289. var result map[string]interface{}
  290. err1 := json.Unmarshal([]byte(redisValue), &result)
  291. if err1 != nil {
  292. e.OutErr(c, e.ERR, err1.Error())
  293. return
  294. }
  295. userCount = result["user_count"]
  296. isRises = result["is_rises"]
  297. risesValue = result["rises"]
  298. nowPrice = result["green_energy_now_price"]
  299. }
  300. isRisesResp, ok := isRises.(bool)
  301. if !ok {
  302. e.OutErr(c, e.ERR, "断言失败")
  303. }
  304. resp := md.RealTimePriceResp{
  305. UserCount: utils.AnyToString(userCount),
  306. NowPrice: utils.AnyToString(nowPrice),
  307. IsRises: isRisesResp,
  308. Rises: utils.AnyToString(risesValue),
  309. }
  310. e.OutSuc(c, resp, nil)
  311. }
  312. // IsCanSignIn
  313. // @Summary 蛋蛋星球-主页-是否能签到(获取)
  314. // @Tags 主页
  315. // @Description 是否可以签到(获取)
  316. // @Accept json
  317. // @Produce json
  318. // @param Authorization header string true "验证参数Bearer和token空格拼接"
  319. // @Success 200 {object} md.IsCanSignInResp "具体数据"
  320. // @Failure 400 {object} md.Response "具体错误"
  321. // @Router /api/v1/homePage/isCanSignIn [get]
  322. func IsCanSignIn(c *gin.Context) {
  323. val, exists := c.Get("user")
  324. if !exists {
  325. e.OutErr(c, e.ERR_USER_CHECK_ERR, nil)
  326. return
  327. }
  328. user, ok := val.(*model.User)
  329. if !ok {
  330. e.OutErr(c, e.ERR_USER_CHECK_ERR, nil)
  331. return
  332. }
  333. //1、查找 `OneCirclesPublicPlatoonBasicSetting` 基础设置
  334. energyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(db.Db)
  335. eggEnergyBasicSetting, err := energyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{
  336. "key": "is_open",
  337. "value": 1,
  338. })
  339. if err != nil {
  340. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  341. return
  342. }
  343. var videoRewardSystem *md2.VideoRewardSystemStruct
  344. err = json.Unmarshal([]byte(eggEnergyBasicSetting.VideoRewardSystem), &videoRewardSystem)
  345. if err != nil {
  346. e.OutErr(c, e.ERR, err.Error())
  347. return
  348. }
  349. rewardTotalNum := utils.StrToInt(videoRewardSystem.RewardTotalNum)
  350. //2、查询当前用户观看视屏记录
  351. watchRecordsDb := implement.NewEggEnergyUserWatchRecordsDb(db.Db)
  352. userWatchRecords, err := watchRecordsDb.EggEnergyUserWatchRecordsGetOneByParams(map[string]interface{}{
  353. "key": "uid",
  354. "value": user.Id,
  355. })
  356. if err != nil {
  357. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  358. return
  359. }
  360. var isCan bool
  361. now := time.Now()
  362. if userWatchRecords != nil && userWatchRecords.ResidueWatchAdNum == rewardTotalNum && userWatchRecords.NextWatchAdDate.After(now) {
  363. isCan = true
  364. }
  365. utils.FilePutContents("HomePageIsCanSignIn", utils.SerializeStr(map[string]interface{}{
  366. "user_phone": user.Phone,
  367. "user_uid": user.Id,
  368. "is_can": isCan,
  369. "time": now.Format("2006-01-02 15:04:05"),
  370. }))
  371. resp := md.IsCanSignInResp{
  372. IsCan: isCan,
  373. }
  374. e.OutSuc(c, resp, nil)
  375. return
  376. }
  377. // IsCanGetRedPackage
  378. // @Summary 蛋蛋星球-主页-是否领取红包(获取)
  379. // @Tags 主页
  380. // @Description 是否可以领取红包(获取)
  381. // @Accept json
  382. // @Produce json
  383. // @param Authorization header string true "验证参数Bearer和token空格拼接"
  384. // @Success 200 {object} md.IsCanGetRedPackageResp "具体数据"
  385. // @Failure 400 {object} md.Response "具体错误"
  386. // @Router /api/v1/homePage/isCanGetRedPackage [get]
  387. func IsCanGetRedPackage(c *gin.Context) {
  388. redPackageDb := implement.NewNewUserRedPackageDb(db.Db)
  389. redPackage, err := redPackageDb.NewUserRedPackageGetOne()
  390. if err != nil {
  391. e.OutErr(c, e.ERR, err.Error())
  392. return
  393. }
  394. isCan := false
  395. if redPackage != nil {
  396. if redPackage.IsOpen == 1 {
  397. isCan = true
  398. }
  399. }
  400. resp := md.IsCanGetRedPackageResp{
  401. IsCan: isCan,
  402. }
  403. e.OutSuc(c, resp, nil)
  404. }