PlayerStat.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. package models
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "time"
  6. mhayaTime "github.com/mhaya/extend/time"
  7. "github.com/mhaya/game/game_cluster/internal/data"
  8. "github.com/mhaya/game/game_cluster/internal/guid"
  9. clog "github.com/mhaya/logger"
  10. )
  11. type PlayerLevelStat struct {
  12. Platform string `bson:"platform" json:"platform"` // platform: 用户所在的平台,例如“Android”或“IOS”
  13. Channel string `bson:"channel" json:"channel"` // channel: 用户来源渠道
  14. ServerLevel map[string]int `json:"serverLevel" bson:"serverLevel"`
  15. UpdateTime int64 `bson:"updateTime" json:"updateTime"`
  16. }
  17. type PlayerServerLoadStat struct {
  18. Name string `bson:"name" json:"name"`
  19. TotalUser int64 `bson:"totalUser" json:"totalUser"`
  20. Load map[string]string `bson:"load" json:"load"`
  21. UpdateTime int64 `bson:"updateTime" json:"updateTime"`
  22. }
  23. type PlayerCountryStat struct {
  24. Daily int64 `bson:"daily" json:"daily"` // 日期
  25. Platform string `bson:"platform" json:"platform"` // platform: 用户所在的平台,例如“Android”或“IOS”
  26. Channel string `bson:"channel" json:"channel"` // channel: 用户来源渠道
  27. PlayerRegisterCountry map[string]int `bson:"playerRegisterCountry" json:"playerRegisterCountry"` // playerRegisterCountry 玩家注册国家
  28. UpdateTime int64 `bson:"updateTime" json:"updateTime"`
  29. }
  30. type Preserve struct {
  31. ID int64 `json:"id"`
  32. Num int `json:"num"`
  33. Ratio string `json:"ratio"`
  34. }
  35. var preserveConfig = []int64{2, 3, 7, 14, 30}
  36. // GetPlayerPreserve 根据开始和结束时间获取玩家的保留数据。
  37. // 该函数会检查时间参数是否合理,并限制查询时间范围不超过一周。
  38. // 参数:
  39. //
  40. // startTime - 查询的开始时间戳。
  41. // EndTime - 查询的结束时间戳。
  42. //
  43. // 返回值:
  44. //
  45. // 一个map,键是日期的时间戳,值是该日期玩家的保留数据列表。
  46. // 如果查询时间超过当前时间或查询范围超过一周,返回nil。
  47. func GetPlayerPreserve(startTime, EndTime int64) map[int64][]*Preserve {
  48. // 检查开始和结束时间是否在将来,如果是,返回nil。
  49. if startTime > mhayaTime.Now().Unix() || EndTime > mhayaTime.Now().Unix() {
  50. return nil
  51. }
  52. // 将开始时间转换为Timestamp类型。
  53. sTime := mhayaTime.CreateFromTimestamp(startTime).TOTimeStamp()
  54. // 如果结束时间超过当前时间,则将结束时间设置为当前时间。
  55. if EndTime > mhayaTime.Now().Unix() {
  56. EndTime = mhayaTime.Now().Unix()
  57. }
  58. // 将结束时间转换为Timestamp类型。
  59. eTime := mhayaTime.CreateFromTimestamp(EndTime).TOTimeStamp()
  60. // 计算开始时间和结束时间的天数差。
  61. day := mhayaTime.CreateFromTimestamp(sTime).DiffInDays(mhayaTime.CreateFromTimestamp(eTime))
  62. // 如果天数差超过7天,返回nil。
  63. if day > 7 {
  64. return nil
  65. }
  66. // 初始化返回的map。
  67. var ret = make(map[int64][]*Preserve, 0)
  68. // 遍历每一天,获取每一天的玩家保留数据。
  69. for i := 0; i < int(day); i++ {
  70. // 计算当前日期的时间戳。
  71. curTime := mhayaTime.CreateFromTimestamp(sTime).Add(time.Duration(i) * 24 * time.Hour).Unix()
  72. // 获取并存储当前日期的玩家保留数据。
  73. ret[curTime] = PlayerPreserve(curTime)
  74. }
  75. // 返回包含玩家保留数据的map。
  76. return ret
  77. }
  78. // PlayerPreserve 计算玩家保留数据。
  79. //
  80. // 参数:
  81. //
  82. // startTime - 统计周期的开始时间,用于确定从何时开始统计玩家保留数据。
  83. //
  84. // 返回值:
  85. //
  86. // []*Preserve - 一个指向Preserve结构体切片的指针,其中每个Preserve结构体包含玩家保留的相关信息。
  87. func PlayerPreserve(startTime int64) []*Preserve {
  88. // 初始化保存保留数据的切片。
  89. var preserve []*Preserve
  90. // 获取新的玩家映射和当前周期内的新注册玩家数量。
  91. cur, curNum := GetNewPlayerMap(startTime, DailyRecordNewRegistered)
  92. // 将第一天的新玩家保留数据添加到结果集中。
  93. preserve = append(preserve, &Preserve{ID: 1, Num: curNum, Ratio: "100%"})
  94. // 遍历保留配置,计算每个周期的保留数据。
  95. for _, v := range preserveConfig {
  96. // 计算下一个统计周期的开始时间。
  97. nextTime := mhayaTime.CreateFromTimestamp(startTime).Add(time.Duration(v-1) * 24 * time.Hour).Unix()
  98. // 获取下一个周期内的老玩家映射和该周期内的老玩家数量。
  99. next, nextNum := GetNewPlayerMap(nextTime, DailyRecordOldLogin)
  100. // 如果下一个周期内没有老玩家登录,则将保留数据的数目记为0。
  101. if nextNum == 0 {
  102. preserve = append(preserve, &Preserve{ID: v, Num: 0, Ratio: ""})
  103. } else {
  104. // 计算在当前周期和下一个周期都出现过的玩家数量。
  105. var num int
  106. for key, _ := range next {
  107. if _, ok := cur[key]; ok {
  108. num++
  109. }
  110. }
  111. // 计算并添加该周期的保留数据到结果集中。
  112. preserve = append(preserve, &Preserve{ID: v, Num: num, Ratio: fmt.Sprintf("%.2f", float64(num)/float64(curNum)*100)})
  113. }
  114. }
  115. // 返回计算得到的保留数据。
  116. return preserve
  117. }
  118. func GetNewPlayerMap(startTime int64, op int) (map[string]struct{}, int) {
  119. var user = make(map[string]struct{})
  120. platformConfig := data.PlatformConfig.GatMap()
  121. channelConfig := data.ChannelConfig.GatMap()
  122. for _, v := range platformConfig {
  123. for _, v2 := range channelConfig {
  124. ret, err := GetAppointDailyRecordUserHash(v.Name, v2.Name, startTime, op)
  125. if err != nil {
  126. continue
  127. }
  128. for k, _ := range ret {
  129. if _, ok := user[k]; !ok {
  130. user[k] = struct{}{}
  131. }
  132. }
  133. }
  134. }
  135. return user, len(user)
  136. }
  137. func TestPreserve(startTime int64, num int) {
  138. sTime := mhayaTime.CreateFromTimestamp(startTime).TOTimeStamp()
  139. for i := 0; i < num; i++ {
  140. userID := guid.Next()
  141. clog.Debugf("num=%v, user =%v", i, userID)
  142. SetAppointDailyRecordNewUserRegisterHash("ios", "tg_sign", userID, "1", sTime, DailyRecordNewRegistered)
  143. for _, v := range preserveConfig {
  144. r := rand.Intn(100)
  145. if r < 80 {
  146. nextTime := mhayaTime.CreateFromTimestamp(sTime).Add(time.Duration(v-1) * 24 * time.Hour).Unix()
  147. SetAppointDailyRecordNewUserRegisterHash("ios", "tg_sign", userID, "1", nextTime, DailyRecordOldLogin)
  148. }
  149. }
  150. }
  151. }