gameAction.go 17 KB

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