billboard.go 4.17 KB
Newer Older
hujiebin's avatar
hujiebin committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
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"`
}

func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ([]BillboardUserInfo, 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)
		return result, 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],
			})
		}
	}
	return result, 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
}