gameAction.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. package v1
  2. import (
  3. "designs/app/common/request"
  4. "designs/app/common/response"
  5. "designs/global"
  6. "designs/model"
  7. "designs/utils"
  8. "fmt"
  9. "github.com/gin-gonic/gin"
  10. "github.com/pkg/errors"
  11. "sort"
  12. "strconv"
  13. "strings"
  14. )
  15. func UserActionList(c *gin.Context) {
  16. form := request.Check(c, &struct {
  17. Gid string `form:"gid" binding:"required"`
  18. //Pf []string `form:"pf" binding:""`
  19. StartTime string `form:"startTime" binding:"required"`
  20. EndTime string `form:"endTime" binding:"required"`
  21. }{})
  22. form.EndTime = form.EndTime + " 23:59:59"
  23. //查询出所有的事件
  24. var actionList []model.GameAction
  25. query := global.App.DB.Table("game_action")
  26. err := query.
  27. Where("gid", form.Gid).
  28. Select("id", "actionId", "actionName").
  29. Order("id desc").Scan(&actionList).Error
  30. if err != nil {
  31. response.Fail(c, 1003, err.Error())
  32. return
  33. }
  34. var optionIdList []int
  35. for _, v := range actionList {
  36. optionIdList = append(optionIdList, v.ID)
  37. }
  38. //查询出有无选项
  39. var optionIdList1 []int
  40. err = global.App.DB.Table("game_action_option").
  41. WhereIn("actionId", optionIdList).
  42. Distinct("actionId").
  43. Pluck("actionId", &optionIdList1).Error
  44. if err != nil {
  45. response.Fail(c, 1003, err.Error())
  46. return
  47. }
  48. //查出用户登录数据
  49. userLogin, err := GetUserLogin(form.Gid, form.StartTime, form.EndTime)
  50. userLoginCount := len(userLogin)
  51. //查询出时间段内事件触发数量,以及触发人的ID
  52. var userAction []model.UserAction
  53. query2 := global.App.DB.Table("user_action")
  54. //if len(form.Pf) > 0 {
  55. // query2 = query2.WhereIn("pf", form.Pf)
  56. //}
  57. err = query2.
  58. Where("gid", form.Gid).
  59. Where("createdAt", ">=", form.StartTime).
  60. Where("createdAt", "<=", form.EndTime).
  61. Select("id", "actionId", "userId", "createdAt").
  62. Scan(&userAction).Error
  63. if err != nil {
  64. response.Fail(c, 1002, err.Error())
  65. return
  66. }
  67. //计算事件的触发总数和触发用户数
  68. actionSumMap := make(map[string]int)
  69. actionUserSumMap := make(map[string]map[int]bool)
  70. for _, action := range userAction {
  71. if actionUserSumMap[action.ActionId] == nil {
  72. actionUserSumMap[action.ActionId] = make(map[int]bool)
  73. }
  74. actionSumMap[action.ActionId]++
  75. actionUserSumMap[action.ActionId][action.UserId] = true
  76. }
  77. //根据事件触发和活跃用户数量进行比对得出其他数据
  78. activeUser := make(map[int]bool)
  79. var activeUserSlice []int
  80. for _, users := range userLogin {
  81. activeUser[users.UserId] = true
  82. }
  83. for k := range activeUser {
  84. activeUserSlice = append(activeUserSlice, k)
  85. }
  86. type responses struct {
  87. Id int `json:"id"`
  88. ActionId string `json:"actionId"`
  89. ActionName string `json:"actionName"`
  90. ActionCount int `json:"actionCount"`
  91. ActionUserCount int `json:"actionUserCount"`
  92. ActiveUserRate float64 `json:"activeUserRate"`
  93. LoginActiveRate float64 `json:"loginActiveRate"`
  94. HaveOption bool `json:"haveOption"`
  95. }
  96. var res []responses
  97. for _, v := range actionList {
  98. var ActiveUserRate float64
  99. var LoginActiveRate float64
  100. if userLoginCount > 0 {
  101. ActiveUserRate = DivideWithPrecision(actionSumMap[v.ActionId], userLoginCount)
  102. LoginActiveRate = DivideWithPrecision(len(actionUserSumMap[v.ActionId]), userLoginCount)
  103. }
  104. res = append(res, responses{
  105. Id: v.ID,
  106. ActionId: v.ActionId,
  107. ActionName: v.ActionName,
  108. ActionCount: actionSumMap[v.ActionId],
  109. ActionUserCount: len(actionUserSumMap[v.ActionId]),
  110. ActiveUserRate: ActiveUserRate,
  111. LoginActiveRate: LoginActiveRate,
  112. HaveOption: utils.InArray(v.ID, optionIdList1),
  113. })
  114. }
  115. response.Success(c, gin.H{
  116. "data": res,
  117. "count": len(res),
  118. })
  119. }
  120. func GetUserLogin(Gid string, StartTime string, EndTime string) ([]model.UserLogin, error) {
  121. //查询出时间段内的活跃用户,登录次数
  122. var userLogin []model.UserLogin
  123. query1 := global.App.DB.Table("user_login")
  124. //if len(form.Pf) > 0 {
  125. // query1 = query1.WhereIn("pf", form.Pf)
  126. //}
  127. err := query1.
  128. Where("gid", Gid).
  129. Where("loginTime", ">=", StartTime).
  130. Where("loginTime", "<=", EndTime).
  131. Select("userId", "loginTime").
  132. Distinct("userId").
  133. Scan(&userLogin).Error
  134. if err != nil {
  135. return userLogin, err
  136. }
  137. return userLogin, nil
  138. }
  139. func UserActionOptionList(c *gin.Context) {
  140. form := request.Check(c, &struct {
  141. Gid string `form:"gid" binding:"required"`
  142. ActionId string `form:"actionId" binding:"required"`
  143. StartTime string `form:"startTime" binding:"required"`
  144. EndTime string `form:"endTime" binding:"required"`
  145. }{})
  146. form.EndTime = form.EndTime + " 23:59:59"
  147. //查出用户登录数据
  148. userLogin, err := GetUserLogin(form.Gid, form.StartTime, form.EndTime)
  149. if err != nil {
  150. response.Fail(c, 1003, err.Error())
  151. return
  152. }
  153. userLoginCount := len(userLogin)
  154. //查询出所有的事件选项
  155. var actionOption []struct {
  156. model.UserActionOption
  157. UserId int `json:"userId" gorm:"not null;column:userId;"`
  158. }
  159. err = global.App.DB.Table("user_action_option").
  160. LeftJoin("user_action", "user_action.id = user_action_option.UserActionId").
  161. Where("user_action.actionId", form.ActionId).
  162. Where("user_action.gid", form.Gid).
  163. Where("user_action.createdAt", ">=", form.StartTime).
  164. Where("user_action.createdAt", "<=", form.EndTime).
  165. Select("user_action_option.*", "user_action.userId").
  166. Scan(&actionOption).Error
  167. if err != nil {
  168. response.Fail(c, 1004, err.Error())
  169. return
  170. }
  171. //循环得出选项
  172. optionList := make(map[string]int)
  173. for _, v := range actionOption {
  174. optionList[v.OptionId+"|"+v.Value]++
  175. }
  176. //根据人数进行比对
  177. //计算事件的触发总数和触发用户数
  178. actionSumMap := make(map[string]int)
  179. actionUserSumMap := make(map[string]map[int]bool)
  180. for _, action := range actionOption {
  181. if actionUserSumMap[action.OptionId+"|"+action.Value] == nil {
  182. actionUserSumMap[action.OptionId+"|"+action.Value] = make(map[int]bool)
  183. }
  184. actionSumMap[action.OptionId+"|"+action.Value]++
  185. actionUserSumMap[action.OptionId+"|"+action.Value][action.UserId] = true
  186. }
  187. //根据事件触发和活跃用户数量进行比对得出其他数据
  188. activeUser := make(map[int]bool)
  189. var activeUserSlice []int
  190. for _, users := range userLogin {
  191. activeUser[users.UserId] = true
  192. }
  193. for k := range activeUser {
  194. activeUserSlice = append(activeUserSlice, k)
  195. }
  196. type responses struct {
  197. Id int `json:"id"`
  198. ActionId int `json:"actionId"`
  199. ActionName string `json:"actionName"`
  200. ActionCount int `json:"actionCount"`
  201. ActionUserCount int `json:"actionUserCount"`
  202. ActiveUserRate float64 `json:"activeUserRate"`
  203. LoginActiveRate float64 `json:"loginActiveRate"`
  204. }
  205. var res []responses
  206. var optionName []model.GameActionOption
  207. optionIdToName := make(map[string]string)
  208. global.App.DB.Table("game_action_option").
  209. LeftJoin("game_action", "game_action.id = game_action_option.actionId").
  210. Where("gid", form.Gid).Scan(&optionName)
  211. for _, v := range optionName {
  212. optionIdToName[v.OptionId] = v.OptionName
  213. }
  214. for k, v := range optionList {
  215. var ActiveUserRate float64
  216. var LoginActiveRate float64
  217. if userLoginCount > 0 {
  218. ActiveUserRate = DivideWithPrecision(actionSumMap[k], userLoginCount)
  219. LoginActiveRate = DivideWithPrecision(len(actionUserSumMap[k]), userLoginCount)
  220. }
  221. optionId := strings.Split(k, "|")[0]
  222. value := strings.Split(k, "|")[1]
  223. valueInt, _ := strconv.Atoi(value)
  224. res = append(res, responses{
  225. ActionId: valueInt,
  226. ActionName: optionIdToName[optionId] + ":" + value,
  227. ActionCount: v,
  228. ActionUserCount: len(actionUserSumMap[k]),
  229. ActiveUserRate: ActiveUserRate,
  230. LoginActiveRate: LoginActiveRate,
  231. })
  232. }
  233. sort.Slice(res, func(i, j int) bool {
  234. return res[i].ActionId < res[j].ActionId // 正序规则:i的Age小于j时返回true
  235. })
  236. response.Success(c, gin.H{
  237. "data": res,
  238. "count": len(res),
  239. })
  240. }
  241. func DivideWithPrecision(a, b int) float64 {
  242. if b == 0 {
  243. panic("除数不能为零") // 实际项目中建议返回 error 类型
  244. }
  245. // 转换为浮点数再相除
  246. result := float64(a) / float64(b)
  247. // 格式化为三位小数并转换回 float64
  248. formatted, _ := strconv.ParseFloat(fmt.Sprintf("%.3f", result), 64)
  249. return formatted
  250. }
  251. func UserActionDetail(c *gin.Context) {
  252. form := request.Check(c, &struct {
  253. Id int `form:"id" binding:"required"`
  254. Pf []string `form:"pf" binding:""`
  255. StartTime string `form:"startTime" binding:"required"`
  256. EndTime string `form:"endTime" binding:"required"`
  257. }{})
  258. //查询启动次数
  259. var action model.GameAction
  260. err := global.App.DB.Table("game_action").
  261. Where("id", form.Id).Find(&action).Error
  262. if err != nil {
  263. response.Fail(c, 1001, err.Error())
  264. return
  265. }
  266. var userAction []struct {
  267. UserId int `json:"userId" gorm:"not null;column:userId;"`
  268. CreatedAt string `json:"createdAt" gorm:"not null;column:createdAt;"`
  269. }
  270. err = global.App.DB.Table("user_action").
  271. Where("gid", action.Gid).
  272. Where("actionId", action.ActionId).
  273. Select("userId", "DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt").
  274. Scan(&userAction).Error
  275. if err != nil {
  276. response.Fail(c, 1002, err.Error())
  277. return
  278. }
  279. //查询出时间段内的活跃用户,登录次数
  280. var userLogin []struct {
  281. UserId int `json:"userId" gorm:"not null;column:userId;"`
  282. CreatedAt string `json:"createdAt" gorm:"not null;column:createdAt;"`
  283. }
  284. err = global.App.DB.Table("user_login").
  285. Where("gid", action.Gid).
  286. Where("loginTime", ">=", form.StartTime).
  287. Where("loginTime", "<=", form.EndTime).
  288. Select("userId", "DATE_FORMAT(loginTime, '%Y-%m-%d') as createdAt").
  289. Scan(&userLogin).Error
  290. if err != nil {
  291. response.Fail(c, 1001, err.Error())
  292. return
  293. }
  294. //userLoginCount := len(userLogin)
  295. activeCount := make(map[string]int)
  296. activeCountUser := make(map[string]map[int]bool)
  297. //根据日期进行分组
  298. for _, v := range userAction {
  299. activeCount[v.CreatedAt]++
  300. if activeCountUser[v.CreatedAt] == nil {
  301. activeCountUser[v.CreatedAt] = make(map[int]bool)
  302. }
  303. activeCountUser[v.CreatedAt][v.UserId] = true
  304. }
  305. days := utils.GetTimeDayDateFormat(form.StartTime, form.EndTime)
  306. type responses struct {
  307. Date string `json:"date"`
  308. ActiveCount int `json:"activeCount"`
  309. ActiveUserCount int `json:"activeUserCount"`
  310. ActiveCountRate float64 `json:"activeCountRate"`
  311. ActiveCountUser float64 `json:"activeCountUser"`
  312. }
  313. var res []responses
  314. //输出格式
  315. for _, v := range days {
  316. res = append(res, responses{
  317. Date: v,
  318. ActiveCount: activeCount[v],
  319. ActiveUserCount: len(activeCountUser[v]),
  320. ActiveCountRate: float64(activeCount[v] / 1),
  321. ActiveCountUser: float64(len(activeCountUser[v]) / 1),
  322. })
  323. }
  324. response.Success(c, gin.H{
  325. "data": res,
  326. })
  327. }
  328. func UserActionDetailDistribution(c *gin.Context) {
  329. form := request.Check(c, &struct {
  330. Id int `form:"id" binding:"required"`
  331. Pf []string `form:"pf" binding:""`
  332. StartTime string `form:"startTime" binding:"required"`
  333. EndTime string `form:"endTime" binding:"required"`
  334. Type int `form:"type" binding:"required"`
  335. }{})
  336. var action model.GameAction
  337. err := global.App.DB.Table("game_action").
  338. Where("id", form.Id).Find(&action).Error
  339. if err != nil {
  340. response.Fail(c, 1001, err.Error())
  341. return
  342. }
  343. res := make(map[string]interface{})
  344. if form.Type == 1 {
  345. var userAction []struct {
  346. UserId int `json:"userId" gorm:"not null;column:userId;"`
  347. CreatedAt string `json:"createdAt" gorm:"not null;column:createdAt;"`
  348. }
  349. query := global.App.DB.Table("user_action")
  350. if len(form.Pf) > 0 {
  351. query = query.WhereIn("pf", form.Pf)
  352. }
  353. err = query.
  354. Where("gid", action.Gid).
  355. Where("actionId", action.ActionId).
  356. Select("userId", "DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt").
  357. Scan(&userAction).Error
  358. if err != nil {
  359. response.Fail(c, 1002, err.Error())
  360. return
  361. }
  362. activeCount := make(map[string]int)
  363. for _, v := range userAction {
  364. activeCount[v.CreatedAt]++
  365. }
  366. days := utils.GetTimeDayDateFormat(form.StartTime, form.EndTime)
  367. for _, v := range days {
  368. res[v] = activeCount[v]
  369. }
  370. response.Success(c, gin.H{
  371. "data": map[string]interface{}{
  372. "avg": fmt.Sprintf("%.2f", float64(len(userAction))/float64(len(days))),
  373. "list": res,
  374. },
  375. })
  376. } else if form.Type == 2 {
  377. var userAction []struct {
  378. UserId int `json:"userId" gorm:"not null;column:userId;"`
  379. CreatedAt string `json:"createdAt" gorm:"not null;column:createdAt;"`
  380. }
  381. query := global.App.DB.Table("user_action")
  382. if len(form.Pf) > 0 {
  383. query = query.WhereIn("gid", form.Pf)
  384. }
  385. err = query.
  386. Where("gid", action.Gid).
  387. Where("actionId", action.ActionId).
  388. Select("userId", "DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt").
  389. Scan(&userAction).Error
  390. if err != nil {
  391. response.Fail(c, 1002, err.Error())
  392. return
  393. }
  394. activeCount := make(map[string]map[int]bool)
  395. for _, v := range userAction {
  396. if activeCount[v.CreatedAt] == nil {
  397. activeCount[v.CreatedAt] = make(map[int]bool)
  398. }
  399. activeCount[v.CreatedAt][v.UserId] = true
  400. }
  401. days := utils.GetTimeDayDateFormat(form.StartTime, form.EndTime)
  402. for _, v := range days {
  403. res[v] = len(activeCount[v])
  404. }
  405. response.Success(c, gin.H{
  406. "data": map[string]interface{}{
  407. "avg": fmt.Sprintf("%.2f", float64(len(userAction))/float64(len(days))),
  408. "list": res,
  409. },
  410. })
  411. } else if form.Type == 3 {
  412. //活跃设备发生率
  413. var userAction []string
  414. query := global.App.DB.Table("user_action")
  415. if len(form.Pf) > 0 {
  416. query = query.WhereIn("pf", form.Pf)
  417. }
  418. err = query.
  419. Where("gid", action.Gid).
  420. Where("actionId", action.ActionId).
  421. Pluck("DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt", &userAction).Error
  422. if err != nil {
  423. response.Fail(c, 1002, err.Error())
  424. return
  425. }
  426. actionCount := make(map[string]int)
  427. for _, v := range userAction {
  428. actionCount[v]++
  429. }
  430. //var userOnline model.UserOnline
  431. //query = global.App.DB.Table("user_online")
  432. //if len(form.Pf) > 0 {
  433. // query = query.WhereIn("gid", form.Pf)
  434. //}
  435. //err = query.
  436. // Where("gid", action.Gid).
  437. // Error
  438. //if err != nil {
  439. // response.Fail(c, 1002, err.Error())
  440. // return
  441. //}
  442. //userCount := make(map[string]map[int]bool)
  443. //for _, v := range userOnline {
  444. //
  445. //}
  446. } else if form.Type == 4 {
  447. //每次启动发生率
  448. var userLogin []string
  449. query := global.App.DB.Table("user_login")
  450. if len(form.Pf) > 0 {
  451. query = query.WhereIn("pf", form.Pf)
  452. }
  453. err = query.
  454. Where("gid", action.Gid).
  455. Pluck("DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt", &userLogin).Error
  456. if err != nil {
  457. response.Fail(c, 1001, err.Error())
  458. return
  459. }
  460. loginCount := make(map[string]int)
  461. for _, v := range userLogin {
  462. loginCount[v]++
  463. }
  464. var userAction []string
  465. query = global.App.DB.Table("user_action")
  466. if len(form.Pf) > 0 {
  467. query = query.WhereIn("pf", form.Pf)
  468. }
  469. err = query.
  470. Where("gid", action.Gid).
  471. Where("actionId", action.ActionId).
  472. Pluck("DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt", &userAction).Error
  473. if err != nil {
  474. response.Fail(c, 1002, err.Error())
  475. return
  476. }
  477. actionCount := make(map[string]int)
  478. for _, v := range userAction {
  479. actionCount[v]++
  480. }
  481. days := utils.GetTimeDayDateFormat(form.StartTime, form.EndTime)
  482. for _, v := range days {
  483. if loginCount[v] > 0 {
  484. res[v] = float64(actionCount[v]) / float64(loginCount[v])
  485. } else {
  486. res[v] = 0
  487. }
  488. }
  489. } else {
  490. response.Fail(c, 1003, errors.New("type 错误"))
  491. return
  492. }
  493. }