package statistics import ( "fmt" "server/call" "server/common" "server/db" "server/modules/backend/app" "server/modules/backend/bdb" "server/modules/backend/models" utils "server/modules/backend/util" "server/modules/backend/values" "server/util" "sort" "sync" "time" "github.com/gin-gonic/gin" ) // 数据总览 func ReviewData(c *gin.Context) { a := app.NewApp(c) defer func() { a.Response() }() req := new(values.ReviewDataReq) if !a.S(req) { return } resp := values.ReviewDataResp{} // if values.CompaireData != nil { // resp.CompaireData = values.CompaireData // } else { // compairCIDs := a.User.SChannels cids := []*int{} if req.ChannelID != nil { cids = []*int{req.ChannelID} // compairCIDs = []int{*req.ChannelID} } else if len(a.User.SChannels) > 0 { for i := range a.User.SChannels { cids = append(cids, &a.User.SChannels[i]) } } // resp.CompaireData = GetCompaireData(compairCIDs) // } total := &values.ReviewData{} var oneDay int64 = 24 * 60 * 60 su, eu := utils.GetQueryUnix(req.Start, req.End) if eu-su > 60*oneDay { a.Code = values.CodeParam return } zeroTime := util.GetZeroTime(time.Now()).Unix() resp.Count = (eu - su) / (24 * 60 * 60) list := []*values.ReviewData{} cid := -1 if len(cids) == 0 { cid = 0 } else if len(cids) == 1 { cid = *cids[0] } if cid >= 0 { bdb.BackDB.QueryAll(fmt.Sprintf("Time >= %d and Time <= %d and PlatformID = %d", su, eu, cid), "", &values.ReviewData{}, &list) } // var newRigist, newPlayTime, oldPlayTime, activePlayTime, arppu, withdrawSuccess float64 var newRigist float64 // 协程并发查询 resp.PlatformData = make([]*values.ReviewData, resp.Count) step := 0 group := new(sync.WaitGroup) group.Add(int(resp.Count)) for i := su; i < eu; i += oneDay { tmp := step t := i util.Go(func() { var one *values.ReviewData if cid < 0 { one = GetReviewPlatformData(t, t+oneDay, cids...) } else { for _, v := range list { if v.Time == t { one = v break } } tag := one == nil var channelFee, adFee int64 var profit, roi, remark string if !tag { channelFee = one.ChannelFee profit = one.Profit roi = one.ROI remark = one.Remark adFee = one.ADFee } if tag || !one.Check { one = GetReviewPlatformData(t, t+oneDay, &cid) one.Check = true // 当天数据不缓存 if t >= zeroTime { one.Check = false } if tag { bdb.BackDB.Create(one) } else { bdb.BackDB.UpdateW(&values.ReviewData{}, one, fmt.Sprintf("Time = %d and PlatformID = %d", t, cid)) one.ChannelFee = channelFee one.Profit = profit one.ROI = roi one.Remark = remark one.ADFee = adFee } } } resp.PlatformData[tmp] = one group.Done() }) step++ } group.Wait() for _, one := range resp.PlatformData { total.NewCount += one.NewCount total.DownloadCount += one.DownloadCount // total.NewPlayCount += one.NewPlayCount total.NewPayCount += one.NewPayCount total.NewPayRepeatCount += one.NewPayRepeatCount total.NewPayAmount += one.NewPayAmount // total.OldCount += one.OldCount // total.OldPayCount += one.OldPayCount // total.OldPayAmount += one.OldPayAmount // total.OldPlayCount += one.OldPlayCount total.ActiveCount += one.ActiveCount // total.ActivePlayCount += one.ActivePlayCount total.ActivePayCount += one.ActivePayCount total.RechargeTotal += one.RechargeTotal total.WithdrawTotal += one.WithdrawTotal // total.WithdrawCount += one.WithdrawCount total.WithdrawPlayerNum += one.WithdrawPlayerNum newRigist = utils.AddPerFloat(newRigist, one.NewRegisterPer) // np, _ := strconv.ParseFloat(one.NewPlayTime, 64) // newPlayTime += np // op, _ := strconv.ParseFloat(one.OldPlayTime, 64) // oldPlayTime += op // ap, _ := strconv.ParseFloat(one.ActivePlayTime, 64) // activePlayTime += ap // ar, _ := strconv.ParseFloat(one.ARPPU, 64) // arppu += ar // withdrawSuccess = utils.AddPerFloat(withdrawSuccess, one.EmailWithdrawSuccess) } sort.Slice(resp.PlatformData, func(i, j int) bool { return resp.PlatformData[i].Time > resp.PlatformData[j].Time }) // var newFlag = true // var oldFlag = false // total.NewPlayTime = utils.GetPoint(models.GetPlayTime(&su, &eu, nil, nil, req.ChannelID, &newFlag), total.NewPlayCount) // total.OldPlayTime = utils.GetPoint(models.GetPlayTime(&su, &eu, nil, nil, req.ChannelID, &oldFlag), total.OldPlayCount) // total.ActivePlayTime = utils.GetPoint(models.GetPlayTime(&su, &eu, nil, nil, req.ChannelID, nil), total.ActivePlayCount) // total.ARPPU = utils.GetPoint(models.GetAmountTotalBySQL(su, eu, req.ChannelID), total.NewPayCount+total.OldPayCount) total.NewRegisterPer = utils.GetPer(int64(newRigist*100), resp.Count*10000) // total.NewPlayTime = util.FormatFloat(newPlayTime/float64(resp.Count), 2) // total.OldPlayTime = util.FormatFloat(oldPlayTime/float64(resp.Count), 2) // total.ActivePlayTime = util.FormatFloat(activePlayTime/float64(resp.Count), 2) // total.ARPPU = util.FormatFloat(arppu/float64(resp.Count), 2) // total.EmailWithdrawSuccess = utils.GetPer(int64(withdrawSuccess*100), resp.Count*10000) total.NewPayPer = utils.GetPer(total.NewPayCount, total.NewCount) // total.NewPlayPer = utils.GetPer(total.NewPlayCount, total.NewCount) // total.NewARPU = utils.GetPoint(total.NewPayAmount, total.NewCount) // total.OldPayPer = utils.GetPer(total.OldPayCount, total.OldCount) // total.OldPlayPer = utils.GetPer(total.OldPlayCount, total.OldCount) // total.ActivePayPer = utils.GetPer(total.ActivePayCount, total.ActiveCount) // total.ActivePlayPer = utils.GetPer(total.ActivePlayCount, total.ActiveCount) // total.ActiveARPU = utils.GetPoint(total.RechargeTotal, total.ActiveCount) total.WithdrawPer = utils.GetPer(total.WithdrawTotal, total.RechargeTotal) resp.Total = total left := (req.Page - 1) * req.Num right := req.Page * req.Num if right > len(resp.PlatformData) { right = len(resp.PlatformData) } resp.PlatformData = resp.PlatformData[left:right] a.Data = resp } func GetReviewChannelData(start, end int64, channel *int) []*values.ReviewData { var ret []*values.ReviewData var oneDay int64 = 24 * 60 * 60 // s := util.GetZeroTime(time.Unix(int64(start), 0)).Unix() // e := util.GetZeroTime(time.Unix(int64(end), 0)).AddDate(0, 0, 1).Unix() now := time.Now() for i := end; i > start; i -= oneDay { j := i - oneDay if j > now.Unix() { continue } t := time.Unix(j, 0).Format("20060102") // key := common.GetBackendReviewKey(t, channel) // one := new(values.ReviewPlatformData) one := GetReviewPlatformData(j, i, channel) one.Date = t ret = append(ret, one) } return ret } func GetReviewPlatformData(start, end int64, platform ...*int) *values.ReviewData { ret := &values.ReviewData{} if len(platform) == 1 { ret.PlatformID = *platform[0] if ret.PlatformID == 0 { platform = []*int{} } } ret.Time = start ret.Date = time.Unix(start, 0).Format("20060102") // var newFlag = true // var oldFlag = false // s := time.Unix(start, 0).Format("2006-01-02") // e := time.Unix(end, 0).Format("2006-01-02") // 完成注册数 ret.NewCount = models.GetNewPlayerCountBySqls(start, end, platform...) // 新增安装数 ret.DownloadCount = models.GetDownloadCounts(&start, &end, platform...) // 新增玩牌人数 // ret.NewPlayCount = models.GetPlayGameUserCounts(&start, &end, &newFlag, platform...) // 新增注册率 = 新增注册用户/新增安装用户 // 计算去重注册人数 sqlNew := fmt.Sprintf("SELECT count(DISTINCT(deviceid)) FROM users WHERE birth >= %v and birth < %v %v", start, end, models.PackChannels(platform...)) var disNewCount int64 db.Mysql().C().Raw(sqlNew).Scan(&disNewCount) // ret.NewRegisterPer = utils.GetPer(disNewCount2-disNewCount, ret.DownloadCount) ret.NewRegisterPer = utils.GetPer(disNewCount, ret.DownloadCount) // ret.NewPlayPer = utils.GetPer(ret.NewPlayCount, ret.NewCount) // 首先聚合求出新老用户玩牌总时长 // newPlayTime, oldPlayTime := models.GetPlayTimesGroupByIsNew(&start, &end, platform...) // 新增用户平均玩牌时长 // ret.NewPlayTime = utils.GetPoint(newPlayTime, ret.NewPlayCount) newRechargeBrl := models.GetNewPayAmountBySqls(start, end, common.CurrencyINR, platform...) // newRechargeUsdt := models.GetNewPayAmountBySqls(start, end, common.CurrencyUSDT, platform...) // oldRechargeBrl := models.GetOldPayAmountBySqls(start, end, common.CurrencyINR, platform...) // oldRechargeUsdt := models.GetOldPayAmountBySqls(start, end, common.CurrencyUSDT, platform...) // ret.RechargeBrl = newRechargeBrl + oldRechargeBrl // ret.RechargeUsdt = newRechargeUsdt + oldRechargeUsdt // 新增付费人数 ret.NewPayCount = models.GetNewPayCountBySqls(start, end, platform...) // 新增付费复充人数 ret.NewPayRepeatCount = models.GetNewPayRepeatCountBySqls(start, end, platform...) // 新增付费率 = 新增付费人数/新增注册人数 ret.NewPayPer = utils.GetPer(ret.NewPayCount, ret.NewCount) // 首次付费人数 ret.FirstPayCount = models.GetFirstPayCount(start, end, common.CurrencyINR, platform...) // 首充付费率 ret.FirstPayPer = utils.GetPer(ret.FirstPayCount, ret.NewCount) // 新增付费总额 ret.NewPayAmount = call.RateBRL(common.CurrencyINR, newRechargeBrl) // 新增ARPU = 新增付费总额/新增注册人数 // ret.NewARPU = utils.GetPoint(ret.NewPayAmount/common.DecimalDigits, ret.NewCount) // 老用户活跃人数 // ret.OldCount = models.GetOldPlayerCountBySqls(start, end, platform...) // 老用户付费人数 // ret.OldPayCount = models.GetOldPayCountBySqls(start, end, platform...) // 老用户付费总额(预估成美元) // ret.OldPayAmount = call.RateBRL(common.CurrencyINR, oldRechargeBrl) + oldRechargeUsdt // 老用户玩牌人数 // ret.OldPlayCount = models.GetPlayGameUserCounts(&start, &end, &oldFlag, platform...) // 老用户付费率 = 老用户付费人数/老用户活跃人数 // ret.OldPayPer = utils.GetPer(ret.OldPayCount, ret.OldCount) // 老用户玩牌率 = 当天老用户玩牌人数/老用户数 // ret.OldPlayPer = utils.GetPer(ret.OldPlayCount, ret.OldCount) // 老用户平均玩牌时长 // ret.OldPlayTime = utils.GetPoint(oldPlayTime, ret.OldPlayCount) // 活跃玩牌数 = 新用户玩牌人数 + 老用户玩牌人数 // ret.ActivePlayCount = ret.NewPlayCount + ret.OldPlayCount // 活跃用户 = 新增用户数 + 老用户数 ret.ActiveCount = ret.NewCount + models.GetOldPlayerCountBySqls(start, end, platform...) // 活跃平均玩牌时长 // ret.ActivePlayTime = utils.GetPoint(newPlayTime+oldPlayTime, ret.ActivePlayCount) // 活跃付费人数 = 新增用户付费人数 + 老用户付费人数 ret.ActivePayCount = ret.NewPayCount + models.GetOldPayCountBySqls(start, end, platform...) // 活跃玩牌率 = 当天活跃玩牌人数/活跃用户数 // ret.ActivePlayPer = utils.GetPer(ret.ActivePlayCount, ret.ActiveCount) // 活跃付费率 = 所有付费人数/活跃人数 // ret.ActivePayPer = utils.GetPer(ret.ActivePayCount, ret.ActiveCount) // 付费总额 = 新用户付费 + 老用户付费 ret.RechargeTotal = models.GetAmountTotalBySQLs(start, end, platform...) // 每付费用户收益= 付费总额/付费用户数 // ret.ARPPU = utils.GetPoint(ret.RechargeTotal/common.DecimalDigits, ret.NewPayCount+ret.OldPayCount) // 付费总额/用户数 // ret.ActiveARPU = utils.GetPoint(ret.RechargeTotal/common.DecimalDigits, ret.ActiveCount) sql := fmt.Sprintf("create_time >= %d and create_time < %d ", start, end) sql += models.PackChannels(platform...) // 获取退出订单总数 var withdrawAll, totalWithdrawPlayer int64 db.Mysql().C().Table("withdraw_order").Where(sql).Count(&withdrawAll) // 代付总人数 db.Mysql().C().Table("withdraw_order").Where(sql).Distinct("uid").Count(&totalWithdrawPlayer) sql += fmt.Sprintf(" and status = %v", common.StatusROrderFinish) // 退出总额 当天所有退出成功总额 withdrawBrl := models.GetWithdrawAmountTotalBySQLs(start, end, common.CurrencyINR, platform...) // withdrawUsdt := models.GetWithdrawAmountTotalBySQLs(start, end, common.CurrencyUSDT, platform...) ret.WithdrawTotal = call.RateBRL(common.CurrencyINR, withdrawBrl) // ret.WithdrawBrl = withdrawBrl // ret.WithdrawUsdt = withdrawUsdt // 退出比例 退出总额/充值总额 ret.WithdrawPer = utils.GetPer(ret.WithdrawTotal, ret.RechargeTotal) // 成功笔数 // db.Mysql().C().Table("withdraw_order").Where(sql).Count(&ret.WithdrawCount) // 退出人数 db.Mysql().C().Table("withdraw_order").Where(sql).Distinct("uid").Count(&ret.WithdrawPlayerNum) // 退出成功率 // ret.EmailWithdrawSuccess = utils.GetPer(ret.WithdrawCount, withdrawAll) // 人次成功率 // ret.WithdrawPlayerSuccess = utils.GetPer(ret.WithdrawPlayerNum, totalWithdrawPlayer) // 新用户充值占比 ret.NewPayPerTotal = utils.GetPer(ret.NewPayAmount, ret.RechargeTotal) ret.PayWithdrawDiff = ret.RechargeTotal - ret.WithdrawTotal ret.RTP = utils.GetPer(models.GetGameInOut(start, end, 2, platform...), models.GetGameInOut(start, end, 1, platform...)) return ret } func GetCompaireData(channels []int) *values.Compaire { begin := time.Now() // 查询对比数据 compair := &values.Compaire{ Recharge: make(map[common.CurrencyType][]int64), Withdraw: make(map[common.CurrencyType][]int64), } zero := util.GetZeroTime(begin) yesZero := util.GetZeroTime(begin).AddDate(0, 0, -1) yesNow := begin.AddDate(0, 0, -1) sql := fmt.Sprintf("create_time >= %d and create_time < %d", zero.Unix(), begin.Unix()) sqly := fmt.Sprintf("create_time >= %d and create_time < %d", yesZero.Unix(), yesNow.Unix()) sql2 := fmt.Sprintf("callback_time >= %d and callback_time < %d", zero.Unix(), begin.Unix()) sqly2 := fmt.Sprintf("callback_time >= %d and callback_time < %d", yesZero.Unix(), yesNow.Unix()) sqlRe := fmt.Sprintf(" and event = %d", common.CurrencyEventReCharge) sqlRe2 := sqlRe + fmt.Sprintf(" and status = %d", common.StatusROrderPay) if len(channels) > 0 { sql += " and (" sqly += " and (" sql2 += " and (" sqly2 += " and (" for i, v := range channels { sql += fmt.Sprintf(" channel_id = %v", v) sqly += fmt.Sprintf(" channel_id = %v", v) sql2 += fmt.Sprintf(" channel_id = %v", v) sqly2 += fmt.Sprintf(" channel_id = %v", v) if i != len(channels)-1 { sql += " or" sqly += " or" sql2 += " or" sqly2 += " or" } else { sql += ")" sqly += ")" sql2 += ")" sqly2 += ")" } } } sqlWi := fmt.Sprintf(" and event = %d", common.CurrencyEventWithDraw) sqlWi2 := sqlWi + fmt.Sprintf(" and status = %d", common.StatusROrderFinish) // 充值总额 brl := []int64{} usdt := []int64{} brl = append(brl, db.Mysql().Sum(&common.RechargeOrder{}, sql2+sqlRe2+fmt.Sprintf(" and currency_type = %v", common.CurrencyINR), "amount")) brl = append(brl, db.Mysql().Sum(&common.RechargeOrder{}, sqly2+sqlRe2+fmt.Sprintf(" and currency_type = %v", common.CurrencyINR), "amount")) compair.Recharge[common.CurrencyINR] = brl usdt = append(usdt, db.Mysql().Sum(&common.RechargeOrder{}, sql2+sqlRe2+fmt.Sprintf(" and currency_type = %v", common.CurrencyUSDT), "amount")) usdt = append(usdt, db.Mysql().Sum(&common.RechargeOrder{}, sqly2+sqlRe2+fmt.Sprintf(" and currency_type = %v", common.CurrencyUSDT), "amount")) compair.Recharge[common.CurrencyUSDT] = usdt // 充值成功率 compair.RechargeSuccess = append(compair.RechargeSuccess, utils.GetPer(db.Mysql().Count(&common.RechargeOrder{}, sql2+sqlRe2), db.Mysql().Count(&common.RechargeOrder{}, sql+sqlRe))) compair.RechargeSuccess = append(compair.RechargeSuccess, utils.GetPer(db.Mysql().Count(&common.RechargeOrder{}, sqly2+sqlRe2), db.Mysql().Count(&common.RechargeOrder{}, sqly+sqlRe))) // 充值人次成功率 compair.RechargePlayerSuccess = append(compair.RechargePlayerSuccess, utils.GetPer(db.Mysql().DistinctCount(&common.RechargeOrder{}, sql2+sqlRe2, "uid"), db.Mysql().DistinctCount(&common.RechargeOrder{}, sql+sqlRe, "uid"))) compair.RechargePlayerSuccess = append(compair.RechargePlayerSuccess, utils.GetPer(db.Mysql().DistinctCount(&common.RechargeOrder{}, sqly2+sqlRe2, "uid"), db.Mysql().DistinctCount(&common.RechargeOrder{}, sqly+sqlRe, "uid"))) // 代付总金额 // compair.Withdraw = append(compair.Withdraw, db.Mysql().Sum(&common.WithdrawOrder{}, sql+sqlWi2, "amount")) // compair.Withdraw = append(compair.Withdraw, db.Mysql().Sum(&common.WithdrawOrder{}, sqly+sqlWi2, "amount")) brlWithdraw := []int64{} usdtWithdraw := []int64{} brlWithdraw = append(brlWithdraw, db.Mysql().Sum(&common.WithdrawOrder{}, sql+sqlWi2+fmt.Sprintf(" and currency_type = %v", common.CurrencyINR), "amount")) brlWithdraw = append(brlWithdraw, db.Mysql().Sum(&common.WithdrawOrder{}, sqly+sqlWi2+fmt.Sprintf(" and currency_type = %v", common.CurrencyINR), "amount")) compair.Withdraw[common.CurrencyINR] = brlWithdraw usdtWithdraw = append(usdtWithdraw, db.Mysql().Sum(&common.WithdrawOrder{}, sql+sqlWi2+fmt.Sprintf(" and currency_type = %v", common.CurrencyUSDT), "amount")) usdtWithdraw = append(usdtWithdraw, db.Mysql().Sum(&common.WithdrawOrder{}, sqly+sqlWi2+fmt.Sprintf(" and currency_type = %v", common.CurrencyUSDT), "amount")) compair.Withdraw[common.CurrencyUSDT] = usdtWithdraw // 代付成功率 compair.WithdrawSuccess = append(compair.WithdrawSuccess, utils.GetPer(db.Mysql().Count(&common.WithdrawOrder{}, sql+sqlWi2), db.Mysql().Count(&common.WithdrawOrder{}, sql+sqlWi))) compair.WithdrawSuccess = append(compair.WithdrawSuccess, utils.GetPer(db.Mysql().Count(&common.WithdrawOrder{}, sqly+sqlWi2), db.Mysql().Count(&common.WithdrawOrder{}, sqly+sqlWi))) // 代付人次成功率 compair.WithdrawPlayerSuccess = append(compair.WithdrawPlayerSuccess, utils.GetPer(db.Mysql().DistinctCount(&common.WithdrawOrder{}, sql+sqlWi2, "uid"), db.Mysql().DistinctCount(&common.WithdrawOrder{}, sql+sqlWi, "uid"))) compair.WithdrawPlayerSuccess = append(compair.WithdrawPlayerSuccess, utils.GetPer(db.Mysql().DistinctCount(&common.WithdrawOrder{}, sqly+sqlWi2, "uid"), db.Mysql().DistinctCount(&common.WithdrawOrder{}, sqly+sqlWi, "uid"))) return compair } // 编辑数据概要 func ReviewDataEdit(c *gin.Context) { a := app.NewApp(c) defer func() { a.Response() }() req := new(values.ReviewDataEditReq) if !a.S(req) { return } data := &values.ReviewData{} err := bdb.BackDB.QueryBySql(fmt.Sprintf("select * from ReviewData where Time = %d and PlatformID = %d", req.Time, req.Channel), data) if err != nil { a.Code = values.CodeRetry return } u := map[string]interface{}{} if req.ADFee != nil { u["ADFee"] = *req.ADFee if *req.ADFee > 0 { // 计算毛利、roi profit := call.Rate(common.CurrencyINR, data.RechargeTotal*(1000-data.ChannelFee)/1000-data.WithdrawTotal) u["Profit"] = util.FormatFloat(float64(profit)/common.DecimalDigits, 2) roi := utils.GetPer(profit, *req.ADFee*common.DecimalDigits) u["ROI"] = roi } } if req.Remark != nil { u["Remark"] = *req.Remark } if len(u) == 0 { a.Code = values.CodeParam a.Msg = "无内容修改" return } err = bdb.BackDB.UpdateW(&values.ReviewData{}, u, fmt.Sprintf("Time = %d and PlatformID = %d", req.Time, req.Channel)) if err != nil { a.Code = values.CodeRetry return } }