package v1 import ( "designs/app/common/request" "designs/app/common/response" "designs/global" "designs/model" "designs/utils" "fmt" "github.com/gin-gonic/gin" "github.com/pkg/errors" "sort" "strconv" "strings" ) func UserActionList(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" binding:"required"` //Pf []string `form:"pf" binding:""` StartTime string `form:"startTime" binding:"required"` EndTime string `form:"endTime" binding:"required"` }{}) form.EndTime = form.EndTime + " 23:59:59" //查询出所有的事件 var actionList []model.GameAction query := global.App.DB.Table("game_action") err := query. Where("gid", form.Gid). Select("id", "actionId", "actionName"). Order("id desc").Scan(&actionList).Error if err != nil { response.Fail(c, 1003, err.Error()) return } var optionIdList []int for _, v := range actionList { optionIdList = append(optionIdList, v.ID) } //查询出有无选项 var optionIdList1 []int err = global.App.DB.Table("game_action_option"). WhereIn("actionId", optionIdList). Distinct("actionId"). Pluck("actionId", &optionIdList1).Error if err != nil { response.Fail(c, 1003, err.Error()) return } //查出用户登录数据 userLogin, err := GetUserLogin(form.Gid, form.StartTime, form.EndTime) userLoginCount := len(userLogin) //查询出时间段内事件触发数量,以及触发人的ID var userAction []model.UserAction query2 := global.App.DB.Table("user_action") //if len(form.Pf) > 0 { // query2 = query2.WhereIn("pf", form.Pf) //} err = query2. Where("gid", form.Gid). Where("createdAt", ">=", form.StartTime). Where("createdAt", "<=", form.EndTime). Select("id", "actionId", "userId", "createdAt"). Scan(&userAction).Error if err != nil { response.Fail(c, 1002, err.Error()) return } //计算事件的触发总数和触发用户数 actionSumMap := make(map[string]int) actionUserSumMap := make(map[string]map[int]bool) for _, action := range userAction { if actionUserSumMap[action.ActionId] == nil { actionUserSumMap[action.ActionId] = make(map[int]bool) } actionSumMap[action.ActionId]++ actionUserSumMap[action.ActionId][action.UserId] = true } //根据事件触发和活跃用户数量进行比对得出其他数据 activeUser := make(map[int]bool) var activeUserSlice []int for _, users := range userLogin { activeUser[users.UserId] = true } for k := range activeUser { activeUserSlice = append(activeUserSlice, k) } type responses struct { Id int `json:"id"` ActionId string `json:"actionId"` ActionName string `json:"actionName"` ActionCount int `json:"actionCount"` ActionUserCount int `json:"actionUserCount"` ActiveUserRate float64 `json:"activeUserRate"` LoginActiveRate float64 `json:"loginActiveRate"` HaveOption bool `json:"haveOption"` } var res []responses for _, v := range actionList { var ActiveUserRate float64 var LoginActiveRate float64 if userLoginCount > 0 { ActiveUserRate = DivideWithPrecision(actionSumMap[v.ActionId], userLoginCount) LoginActiveRate = DivideWithPrecision(len(actionUserSumMap[v.ActionId]), userLoginCount) } res = append(res, responses{ Id: v.ID, ActionId: v.ActionId, ActionName: v.ActionName, ActionCount: actionSumMap[v.ActionId], ActionUserCount: len(actionUserSumMap[v.ActionId]), ActiveUserRate: ActiveUserRate, LoginActiveRate: LoginActiveRate, HaveOption: utils.InArray(v.ID, optionIdList1), }) } response.Success(c, gin.H{ "data": res, "count": len(res), }) } func GetUserLogin(Gid string, StartTime string, EndTime string) ([]model.UserLogin, error) { //查询出时间段内的活跃用户,登录次数 var userLogin []model.UserLogin query1 := global.App.DB.Table("user_login") //if len(form.Pf) > 0 { // query1 = query1.WhereIn("pf", form.Pf) //} err := query1. Where("gid", Gid). Where("loginTime", ">=", StartTime). Where("loginTime", "<=", EndTime). Select("userId", "loginTime"). Distinct("userId"). Scan(&userLogin).Error if err != nil { return userLogin, err } return userLogin, nil } func UserActionOptionList(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" binding:"required"` ActionId string `form:"actionId" binding:"required"` StartTime string `form:"startTime" binding:"required"` EndTime string `form:"endTime" binding:"required"` }{}) form.EndTime = form.EndTime + " 23:59:59" //查出用户登录数据 userLogin, err := GetUserLogin(form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1003, err.Error()) return } userLoginCount := len(userLogin) //查询出所有的事件选项 var actionOption []struct { model.UserActionOption UserId int `json:"userId" gorm:"not null;column:userId;"` } err = global.App.DB.Table("user_action_option"). LeftJoin("user_action", "user_action.id = user_action_option.UserActionId"). Where("user_action.actionId", form.ActionId). Where("user_action.gid", form.Gid). Where("user_action.createdAt", ">=", form.StartTime). Where("user_action.createdAt", "<=", form.EndTime). Select("user_action_option.*", "user_action.userId"). Scan(&actionOption).Error if err != nil { response.Fail(c, 1004, err.Error()) return } //循环得出选项 optionList := make(map[string]int) for _, v := range actionOption { optionList[v.OptionId+"|"+v.Value]++ } //根据人数进行比对 //计算事件的触发总数和触发用户数 actionSumMap := make(map[string]int) actionUserSumMap := make(map[string]map[int]bool) for _, action := range actionOption { if actionUserSumMap[action.OptionId+"|"+action.Value] == nil { actionUserSumMap[action.OptionId+"|"+action.Value] = make(map[int]bool) } actionSumMap[action.OptionId+"|"+action.Value]++ actionUserSumMap[action.OptionId+"|"+action.Value][action.UserId] = true } //根据事件触发和活跃用户数量进行比对得出其他数据 activeUser := make(map[int]bool) var activeUserSlice []int for _, users := range userLogin { activeUser[users.UserId] = true } for k := range activeUser { activeUserSlice = append(activeUserSlice, k) } type responses struct { Id int `json:"id"` ActionId int `json:"actionId"` ActionName string `json:"actionName"` ActionCount int `json:"actionCount"` ActionUserCount int `json:"actionUserCount"` ActiveUserRate float64 `json:"activeUserRate"` LoginActiveRate float64 `json:"loginActiveRate"` } var res []responses var optionName []model.GameActionOption optionIdToName := make(map[string]string) global.App.DB.Table("game_action_option"). LeftJoin("game_action", "game_action.id = game_action_option.actionId"). Where("gid", form.Gid).Scan(&optionName) for _, v := range optionName { optionIdToName[v.OptionId] = v.OptionName } for k, v := range optionList { var ActiveUserRate float64 var LoginActiveRate float64 if userLoginCount > 0 { ActiveUserRate = DivideWithPrecision(actionSumMap[k], userLoginCount) LoginActiveRate = DivideWithPrecision(len(actionUserSumMap[k]), userLoginCount) } optionId := strings.Split(k, "|")[0] value := strings.Split(k, "|")[1] valueInt, _ := strconv.Atoi(value) res = append(res, responses{ ActionId: valueInt, ActionName: optionIdToName[optionId] + ":" + value, ActionCount: v, ActionUserCount: len(actionUserSumMap[k]), ActiveUserRate: ActiveUserRate, LoginActiveRate: LoginActiveRate, }) } sort.Slice(res, func(i, j int) bool { return res[i].ActionId < res[j].ActionId // 正序规则:i的Age小于j时返回true }) response.Success(c, gin.H{ "data": res, "count": len(res), }) } func DivideWithPrecision(a, b int) float64 { if b == 0 { panic("除数不能为零") // 实际项目中建议返回 error 类型 } // 转换为浮点数再相除 result := float64(a) / float64(b) // 格式化为三位小数并转换回 float64 formatted, _ := strconv.ParseFloat(fmt.Sprintf("%.3f", result), 64) return formatted } func UserActionDetail(c *gin.Context) { form := request.Check(c, &struct { Id int `form:"id" binding:"required"` Pf []string `form:"pf" binding:""` StartTime string `form:"startTime" binding:"required"` EndTime string `form:"endTime" binding:"required"` }{}) //查询启动次数 var action model.GameAction err := global.App.DB.Table("game_action"). Where("id", form.Id).Find(&action).Error if err != nil { response.Fail(c, 1001, err.Error()) return } var userAction []struct { UserId int `json:"userId" gorm:"not null;column:userId;"` CreatedAt string `json:"createdAt" gorm:"not null;column:createdAt;"` } err = global.App.DB.Table("user_action"). Where("gid", action.Gid). Where("actionId", action.ActionId). Select("userId", "DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt"). Scan(&userAction).Error if err != nil { response.Fail(c, 1002, err.Error()) return } //查询出时间段内的活跃用户,登录次数 var userLogin []struct { UserId int `json:"userId" gorm:"not null;column:userId;"` CreatedAt string `json:"createdAt" gorm:"not null;column:createdAt;"` } err = global.App.DB.Table("user_login"). Where("gid", action.Gid). Where("loginTime", ">=", form.StartTime). Where("loginTime", "<=", form.EndTime). Select("userId", "DATE_FORMAT(loginTime, '%Y-%m-%d') as createdAt"). Scan(&userLogin).Error if err != nil { response.Fail(c, 1001, err.Error()) return } //userLoginCount := len(userLogin) activeCount := make(map[string]int) activeCountUser := make(map[string]map[int]bool) //根据日期进行分组 for _, v := range userAction { activeCount[v.CreatedAt]++ if activeCountUser[v.CreatedAt] == nil { activeCountUser[v.CreatedAt] = make(map[int]bool) } activeCountUser[v.CreatedAt][v.UserId] = true } days := utils.GetTimeDayDateFormat(form.StartTime, form.EndTime) type responses struct { Date string `json:"date"` ActiveCount int `json:"activeCount"` ActiveUserCount int `json:"activeUserCount"` ActiveCountRate float64 `json:"activeCountRate"` ActiveCountUser float64 `json:"activeCountUser"` } var res []responses //输出格式 for _, v := range days { res = append(res, responses{ Date: v, ActiveCount: activeCount[v], ActiveUserCount: len(activeCountUser[v]), ActiveCountRate: float64(activeCount[v] / 1), ActiveCountUser: float64(len(activeCountUser[v]) / 1), }) } response.Success(c, gin.H{ "data": res, }) } func UserActionDetailDistribution(c *gin.Context) { form := request.Check(c, &struct { Id int `form:"id" binding:"required"` Pf []string `form:"pf" binding:""` StartTime string `form:"startTime" binding:"required"` EndTime string `form:"endTime" binding:"required"` Type int `form:"type" binding:"required"` }{}) var action model.GameAction err := global.App.DB.Table("game_action"). Where("id", form.Id).Find(&action).Error if err != nil { response.Fail(c, 1001, err.Error()) return } res := make(map[string]interface{}) if form.Type == 1 { var userAction []struct { UserId int `json:"userId" gorm:"not null;column:userId;"` CreatedAt string `json:"createdAt" gorm:"not null;column:createdAt;"` } query := global.App.DB.Table("user_action") if len(form.Pf) > 0 { query = query.WhereIn("pf", form.Pf) } err = query. Where("gid", action.Gid). Where("actionId", action.ActionId). Select("userId", "DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt"). Scan(&userAction).Error if err != nil { response.Fail(c, 1002, err.Error()) return } activeCount := make(map[string]int) for _, v := range userAction { activeCount[v.CreatedAt]++ } days := utils.GetTimeDayDateFormat(form.StartTime, form.EndTime) for _, v := range days { res[v] = activeCount[v] } response.Success(c, gin.H{ "data": map[string]interface{}{ "avg": fmt.Sprintf("%.2f", float64(len(userAction))/float64(len(days))), "list": res, }, }) } else if form.Type == 2 { var userAction []struct { UserId int `json:"userId" gorm:"not null;column:userId;"` CreatedAt string `json:"createdAt" gorm:"not null;column:createdAt;"` } query := global.App.DB.Table("user_action") if len(form.Pf) > 0 { query = query.WhereIn("gid", form.Pf) } err = query. Where("gid", action.Gid). Where("actionId", action.ActionId). Select("userId", "DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt"). Scan(&userAction).Error if err != nil { response.Fail(c, 1002, err.Error()) return } activeCount := make(map[string]map[int]bool) for _, v := range userAction { if activeCount[v.CreatedAt] == nil { activeCount[v.CreatedAt] = make(map[int]bool) } activeCount[v.CreatedAt][v.UserId] = true } days := utils.GetTimeDayDateFormat(form.StartTime, form.EndTime) for _, v := range days { res[v] = len(activeCount[v]) } response.Success(c, gin.H{ "data": map[string]interface{}{ "avg": fmt.Sprintf("%.2f", float64(len(userAction))/float64(len(days))), "list": res, }, }) } else if form.Type == 3 { //活跃设备发生率 var userAction []string query := global.App.DB.Table("user_action") if len(form.Pf) > 0 { query = query.WhereIn("pf", form.Pf) } err = query. Where("gid", action.Gid). Where("actionId", action.ActionId). Pluck("DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt", &userAction).Error if err != nil { response.Fail(c, 1002, err.Error()) return } actionCount := make(map[string]int) for _, v := range userAction { actionCount[v]++ } //var userOnline model.UserOnline //query = global.App.DB.Table("user_online") //if len(form.Pf) > 0 { // query = query.WhereIn("gid", form.Pf) //} //err = query. // Where("gid", action.Gid). // Error //if err != nil { // response.Fail(c, 1002, err.Error()) // return //} //userCount := make(map[string]map[int]bool) //for _, v := range userOnline { // //} } else if form.Type == 4 { //每次启动发生率 var userLogin []string query := global.App.DB.Table("user_login") if len(form.Pf) > 0 { query = query.WhereIn("pf", form.Pf) } err = query. Where("gid", action.Gid). Pluck("DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt", &userLogin).Error if err != nil { response.Fail(c, 1001, err.Error()) return } loginCount := make(map[string]int) for _, v := range userLogin { loginCount[v]++ } var userAction []string query = global.App.DB.Table("user_action") if len(form.Pf) > 0 { query = query.WhereIn("pf", form.Pf) } err = query. Where("gid", action.Gid). Where("actionId", action.ActionId). Pluck("DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt", &userAction).Error if err != nil { response.Fail(c, 1002, err.Error()) return } actionCount := make(map[string]int) for _, v := range userAction { actionCount[v]++ } days := utils.GetTimeDayDateFormat(form.StartTime, form.EndTime) for _, v := range days { if loginCount[v] > 0 { res[v] = float64(actionCount[v]) / float64(loginCount[v]) } else { res[v] = 0 } } } else { response.Fail(c, 1003, errors.New("type 错误")) return } }