package billboard_cv import ( "context" "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/resource/redisCli" "git.hilo.cn/hilo-common/utils" "hilo-group/_const/enum/gift_e" "hilo-group/_const/redis_key" "hilo-group/cv/gift_cv" "hilo-group/cv/user_cv" "sort" "strconv" "time" ) //榜单中用户信息 type BillboardUserInfo struct { //用户基本信息 UserBase user_cv.CvUserDetail `json:"userBase"` //数值 Num uint64 `json:"num"` } //榜单中用户信息 type GroupTop3ConsumeUser struct { //用户基本信息 UserBase user_cv.TopConsumersUser `json:"userBase"` //数值 Num uint64 `json:"num"` } func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ([]GroupTop3ConsumeUser, error) { now := time.Now() period := now.Format(utils.COMPACT_MONTH_FORMAT) data, err := getGroupTop3Consume(period, groupId) result := make([]BillboardUserInfo, 0) failed := false if err != nil { failed = true } else { model.Log.Infof("GetGroupTop3Consume, from redis: %+v", data) ts, err := strconv.ParseUint(data["timestamp"], 10, 64) if err != nil { failed = true } else { // 超过5分钟就认为是过期数据 if now.Unix()-int64(ts) >= 60*5 { failed = true } } } if failed { result, err := BuildMonthlyGroupConsumeBillboard(groupId, 3, myUserId) if err != nil { return nil, err } diamonds := make(map[uint64]uint64, 0) for _, i := range result { if i.UserBase.Id != nil { diamonds[*i.UserBase.Id] = i.Num } } model.Log.Infof("GetGroupTop3Consume, DB: %+v", diamonds) ret, err := saveGroupTop3Consume(period, groupId, diamonds) model.Log.Infof("GetGroupTop3Consume SAVE ret = %d, err: %v", ret, err) list := make([]GroupTop3ConsumeUser, 0, len(result)) for _, v := range result { list = append(list, GroupTop3ConsumeUser{ UserBase: user_cv.TopConsumersUser{Id: v.UserBase.Id, Avatar: v.UserBase.Avatar, ExternalId: v.UserBase.ExternalId, Nick: v.UserBase.Nick}, }) } return list, nil } userIds := make([]uint64, 0) diamonds := make(map[uint64]uint64, 0) for k, v := range data { if uid, err := strconv.ParseUint(k, 10, 64); err == nil { if num, err := strconv.ParseInt(v, 10, 64); err == nil { userIds = append(userIds, uid) diamonds[uid] = uint64(num) } } } users, err := user_cv.GetUserDetailMap(userIds, myUserId) if err != nil { return nil, err } for _, i := range userIds { if users[i] != nil { result = append(result, BillboardUserInfo{ UserBase: *users[i], Num: diamonds[i], }) } } list := make([]GroupTop3ConsumeUser, 0, len(result)) for _, v := range result { list = append(list, GroupTop3ConsumeUser{ UserBase: user_cv.TopConsumersUser{Id: v.UserBase.Id, Avatar: v.UserBase.Avatar, ExternalId: v.UserBase.ExternalId, Nick: v.UserBase.Nick}, }) } return list, nil } func getGroupTop3Consume(period string, groupId string) (map[string]string, error) { key := redis_key.GetGroupTop3ConsumeKey(period, groupId) return redisCli.GetRedis().HGetAll(context.Background(), key).Result() } func saveGroupTop3Consume(period string, groupId string, diamonds map[uint64]uint64) (int64, error) { values := make(map[string]interface{}, 0) for p, d := range diamonds { if d > 0 { values[strconv.FormatUint(p, 10)] = d } } if len(values) <= 0 { return 0, nil } values["timestamp"] = time.Now().Unix() key := redis_key.GetGroupTop3ConsumeKey(period, groupId) ret, err := redisCli.GetRedis().HSet(context.Background(), key, values).Result() if err == nil { // 设置一个TTL保险一些 TODO: 可以优化,保证数据总是有的 redisCli.GetRedis().Expire(context.Background(), key, time.Minute*15) } return ret, err } func BuildMonthlyGroupConsumeBillboard(groupId string, length int, myUserId uint64) ([]BillboardUserInfo, error) { //now := time.Now() //endDate := now.Format(common.DATE_FORMAT) //beginDate := common.GetFirstDay(now).Format(common.DATE_FORMAT) return BuildGroupConsumeBillboard(groupId, time.Now(), length, myUserId, "month") } func BuildGroupConsumeBillboard(groupId string, endDate time.Time, length int, myUserId uint64, dayWeekMonth string) ([]BillboardUserInfo, error) { g := gift_cv.GiftOperate{SceneType: gift_e.GroupSceneType} scores, err := g.GetGroupConsumeSummary(groupId, endDate, dayWeekMonth) if err != nil { return nil, err } userIds := make([]uint64, 0) for k, _ := range scores { userIds = append(userIds, k) } sort.SliceStable(userIds, func(i, j int) bool { return scores[userIds[i]] > scores[userIds[j]] }) if length > len(userIds) { length = len(userIds) } userIds = userIds[0:length] users, err := user_cv.GetUserDetailMap(userIds, myUserId) if err != nil { return nil, err } result := make([]BillboardUserInfo, 0) for _, i := range userIds { if users[i] != nil { result = append(result, BillboardUserInfo{ UserBase: *users[i], Num: scores[i], }) } } return result, nil }