package models import ( "fmt" "math/rand" "time" mhayaTime "github.com/mhaya/extend/time" "github.com/mhaya/game/game_cluster/internal/data" "github.com/mhaya/game/game_cluster/internal/guid" clog "github.com/mhaya/logger" ) type PlayerLevelStat struct { Platform string `bson:"platform" json:"platform"` // platform: 用户所在的平台,例如“Android”或“IOS” Channel string `bson:"channel" json:"channel"` // channel: 用户来源渠道 ServerLevel map[string]int `json:"serverLevel" bson:"serverLevel"` UpdateTime int64 `bson:"updateTime" json:"updateTime"` } type PlayerServerLoadStat struct { Name string `bson:"name" json:"name"` TotalUser int64 `bson:"totalUser" json:"totalUser"` Load map[string]string `bson:"load" json:"load"` UpdateTime int64 `bson:"updateTime" json:"updateTime"` } type PlayerCountryStat struct { Daily int64 `bson:"daily" json:"daily"` // 日期 Platform string `bson:"platform" json:"platform"` // platform: 用户所在的平台,例如“Android”或“IOS” Channel string `bson:"channel" json:"channel"` // channel: 用户来源渠道 PlayerRegisterCountry map[string]int `bson:"playerRegisterCountry" json:"playerRegisterCountry"` // playerRegisterCountry 玩家注册国家 UpdateTime int64 `bson:"updateTime" json:"updateTime"` } type Preserve struct { ID int64 `json:"id"` Num int `json:"num"` Ratio string `json:"ratio"` } var preserveConfig = []int64{2, 3, 7, 14, 30} // GetPlayerPreserve 根据开始和结束时间获取玩家的保留数据。 // 该函数会检查时间参数是否合理,并限制查询时间范围不超过一周。 // 参数: // // startTime - 查询的开始时间戳。 // EndTime - 查询的结束时间戳。 // // 返回值: // // 一个map,键是日期的时间戳,值是该日期玩家的保留数据列表。 // 如果查询时间超过当前时间或查询范围超过一周,返回nil。 func GetPlayerPreserve(startTime, EndTime int64) map[int64][]*Preserve { // 检查开始和结束时间是否在将来,如果是,返回nil。 if startTime > mhayaTime.Now().Unix() || EndTime > mhayaTime.Now().Unix() { return nil } // 将开始时间转换为Timestamp类型。 sTime := mhayaTime.CreateFromTimestamp(startTime).TOTimeStamp() // 如果结束时间超过当前时间,则将结束时间设置为当前时间。 if EndTime > mhayaTime.Now().Unix() { EndTime = mhayaTime.Now().Unix() } // 将结束时间转换为Timestamp类型。 eTime := mhayaTime.CreateFromTimestamp(EndTime).TOTimeStamp() // 计算开始时间和结束时间的天数差。 day := mhayaTime.CreateFromTimestamp(sTime).DiffInDays(mhayaTime.CreateFromTimestamp(eTime)) // 如果天数差超过7天,返回nil。 if day > 7 { return nil } // 初始化返回的map。 var ret = make(map[int64][]*Preserve, 0) // 遍历每一天,获取每一天的玩家保留数据。 for i := 0; i < int(day); i++ { // 计算当前日期的时间戳。 curTime := mhayaTime.CreateFromTimestamp(sTime).Add(time.Duration(i) * 24 * time.Hour).Unix() // 获取并存储当前日期的玩家保留数据。 ret[curTime] = PlayerPreserve(curTime) } // 返回包含玩家保留数据的map。 return ret } // PlayerPreserve 计算玩家保留数据。 // // 参数: // // startTime - 统计周期的开始时间,用于确定从何时开始统计玩家保留数据。 // // 返回值: // // []*Preserve - 一个指向Preserve结构体切片的指针,其中每个Preserve结构体包含玩家保留的相关信息。 func PlayerPreserve(startTime int64) []*Preserve { // 初始化保存保留数据的切片。 var preserve []*Preserve // 获取新的玩家映射和当前周期内的新注册玩家数量。 cur, curNum := GetNewPlayerMap(startTime, DailyRecordNewRegistered) // 将第一天的新玩家保留数据添加到结果集中。 preserve = append(preserve, &Preserve{ID: 1, Num: curNum, Ratio: "100%"}) // 遍历保留配置,计算每个周期的保留数据。 for _, v := range preserveConfig { // 计算下一个统计周期的开始时间。 nextTime := mhayaTime.CreateFromTimestamp(startTime).Add(time.Duration(v-1) * 24 * time.Hour).Unix() // 获取下一个周期内的老玩家映射和该周期内的老玩家数量。 next, nextNum := GetNewPlayerMap(nextTime, DailyRecordOldLogin) // 如果下一个周期内没有老玩家登录,则将保留数据的数目记为0。 if nextNum == 0 { preserve = append(preserve, &Preserve{ID: v, Num: 0, Ratio: ""}) } else { // 计算在当前周期和下一个周期都出现过的玩家数量。 var num int for key, _ := range next { if _, ok := cur[key]; ok { num++ } } // 计算并添加该周期的保留数据到结果集中。 preserve = append(preserve, &Preserve{ID: v, Num: num, Ratio: fmt.Sprintf("%.2f", float64(num)/float64(curNum)*100)}) } } // 返回计算得到的保留数据。 return preserve } func GetNewPlayerMap(startTime int64, op int) (map[string]struct{}, int) { var user = make(map[string]struct{}) platformConfig := data.PlatformConfig.GatMap() channelConfig := data.ChannelConfig.GatMap() for _, v := range platformConfig { for _, v2 := range channelConfig { ret, err := GetAppointDailyRecordUserHash(v.Name, v2.Name, startTime, op) if err != nil { continue } for k, _ := range ret { if _, ok := user[k]; !ok { user[k] = struct{}{} } } } } return user, len(user) } func TestPreserve(startTime int64, num int) { sTime := mhayaTime.CreateFromTimestamp(startTime).TOTimeStamp() for i := 0; i < num; i++ { userID := guid.Next() clog.Debugf("num=%v, user =%v", i, userID) SetAppointDailyRecordNewUserRegisterHash("ios", "tg", userID, "1", sTime, DailyRecordNewRegistered) for _, v := range preserveConfig { r := rand.Intn(100) if r < 80 { nextTime := mhayaTime.CreateFromTimestamp(sTime).Add(time.Duration(v-1) * 24 * time.Hour).Unix() SetAppointDailyRecordNewUserRegisterHash("ios", "tg", userID, "1", nextTime, DailyRecordOldLogin) } } } }