fix: enrich weekly star reward groups
This commit is contained in:
parent
0adef2ee26
commit
3ed3f85837
@ -32,8 +32,9 @@ type weeklyStarGiftData struct {
|
||||
}
|
||||
|
||||
type weeklyStarRewardData struct {
|
||||
RankNo int32 `json:"rank_no"`
|
||||
ResourceGroupID int64 `json:"resource_group_id"`
|
||||
RankNo int32 `json:"rank_no"`
|
||||
ResourceGroupID int64 `json:"resource_group_id"`
|
||||
ResourceGroup *achievementResourceGroupData `json:"resource_group,omitempty"`
|
||||
}
|
||||
|
||||
type weeklyStarEntryData struct {
|
||||
@ -98,8 +99,12 @@ func (h *Handler) getWeeklyStarCurrent(writer http.ResponseWriter, request *http
|
||||
return
|
||||
}
|
||||
users := h.resolveWeeklyStarUsers(request, weeklyStarUserIDs(resp.GetTopEntries(), resp.GetMyEntry()))
|
||||
resourceGroups, ok := h.resolveWeeklyStarResourceGroups(writer, request, resp.GetCycle())
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
data := weeklyStarCurrentData{
|
||||
Cycle: weeklyStarCycleFromProto(resp.GetCycle()),
|
||||
Cycle: weeklyStarCycleFromProto(resp.GetCycle(), resourceGroups),
|
||||
TopEntries: weeklyStarEntriesFromProto(resp.GetTopEntries(), users),
|
||||
ServerTimeMS: resp.GetServerTimeMs(),
|
||||
}
|
||||
@ -133,8 +138,12 @@ func (h *Handler) listWeeklyStarLeaderboard(writer http.ResponseWriter, request
|
||||
return
|
||||
}
|
||||
users := h.resolveWeeklyStarUsers(request, weeklyStarUserIDs(resp.GetEntries(), nil))
|
||||
resourceGroups, ok := h.resolveWeeklyStarResourceGroups(writer, request, resp.GetCycle())
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
httpkit.WriteOK(writer, request, weeklyStarLeaderboardData{
|
||||
Cycle: weeklyStarCycleFromProto(resp.GetCycle()),
|
||||
Cycle: weeklyStarCycleFromProto(resp.GetCycle(), resourceGroups),
|
||||
Entries: weeklyStarEntriesFromProto(resp.GetEntries(), users),
|
||||
NextPageToken: resp.GetNextPageToken(),
|
||||
Total: resp.GetTotal(),
|
||||
@ -162,14 +171,20 @@ func (h *Handler) listWeeklyStarHistory(writer http.ResponseWriter, request *htt
|
||||
return
|
||||
}
|
||||
ids := make([]int64, 0)
|
||||
cycleItems := make([]*activityv1.WeeklyStarCycle, 0, len(resp.GetCycles()))
|
||||
for _, cycle := range resp.GetCycles() {
|
||||
cycleItems = append(cycleItems, cycle.GetCycle())
|
||||
ids = append(ids, weeklyStarUserIDs(cycle.GetTopEntries(), nil)...)
|
||||
}
|
||||
users := h.resolveWeeklyStarUsers(request, ids)
|
||||
resourceGroups, ok := h.resolveWeeklyStarResourceGroups(writer, request, cycleItems...)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
cycles := make([]weeklyStarHistoryCycleData, 0, len(resp.GetCycles()))
|
||||
for _, item := range resp.GetCycles() {
|
||||
cycles = append(cycles, weeklyStarHistoryCycleData{
|
||||
Cycle: weeklyStarCycleFromProto(item.GetCycle()),
|
||||
Cycle: weeklyStarCycleFromProto(item.GetCycle(), resourceGroups),
|
||||
TopEntries: weeklyStarEntriesFromProto(item.GetTopEntries(), users),
|
||||
})
|
||||
}
|
||||
@ -213,7 +228,13 @@ func (h *Handler) resolveWeeklyStarUsers(request *http.Request, ids []int64) map
|
||||
return users
|
||||
}
|
||||
|
||||
func weeklyStarCycleFromProto(item *activityv1.WeeklyStarCycle) *weeklyStarCycleData {
|
||||
func (h *Handler) resolveWeeklyStarResourceGroups(writer http.ResponseWriter, request *http.Request, cycles ...*activityv1.WeeklyStarCycle) (map[int64]achievementResourceGroupData, bool) {
|
||||
// 周星周期只存奖励资源组 ID,资源名称、类型、素材和数量仍由 wallet-service 资源库统一维护。
|
||||
// gateway 在 App 出口补齐这些展示字段,避免 activity-service 复制资源库快照,也让后台改资源组后 App 读取保持一致。
|
||||
return h.resolveAchievementResourceGroups(writer, request, weeklyStarResourceGroupIDs(cycles...))
|
||||
}
|
||||
|
||||
func weeklyStarCycleFromProto(item *activityv1.WeeklyStarCycle, resourceGroups map[int64]achievementResourceGroupData) *weeklyStarCycleData {
|
||||
if item == nil {
|
||||
return nil
|
||||
}
|
||||
@ -235,11 +256,25 @@ func weeklyStarCycleFromProto(item *activityv1.WeeklyStarCycle) *weeklyStarCycle
|
||||
cycle.Gifts = append(cycle.Gifts, weeklyStarGiftData{GiftID: gift.GetGiftId(), SortOrder: gift.GetSortOrder()})
|
||||
}
|
||||
for _, reward := range item.GetRewards() {
|
||||
cycle.Rewards = append(cycle.Rewards, weeklyStarRewardData{RankNo: reward.GetRankNo(), ResourceGroupID: reward.GetResourceGroupId()})
|
||||
rewardData := weeklyStarRewardData{RankNo: reward.GetRankNo(), ResourceGroupID: reward.GetResourceGroupId()}
|
||||
if group, ok := resourceGroups[reward.GetResourceGroupId()]; ok {
|
||||
rewardData.ResourceGroup = &group
|
||||
}
|
||||
cycle.Rewards = append(cycle.Rewards, rewardData)
|
||||
}
|
||||
return cycle
|
||||
}
|
||||
|
||||
func weeklyStarResourceGroupIDs(cycles ...*activityv1.WeeklyStarCycle) []int64 {
|
||||
ids := make([]int64, 0)
|
||||
for _, cycle := range cycles {
|
||||
for _, reward := range cycle.GetRewards() {
|
||||
ids = append(ids, reward.GetResourceGroupId())
|
||||
}
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func weeklyStarEntriesFromProto(items []*activityv1.WeeklyStarLeaderboardEntry, users map[int64]weeklyStarUserData) []weeklyStarEntryData {
|
||||
entries := make([]weeklyStarEntryData, 0, len(items))
|
||||
for _, item := range items {
|
||||
|
||||
@ -552,6 +552,16 @@ type fakeAchievementClient struct {
|
||||
err error
|
||||
}
|
||||
|
||||
type fakeWeeklyStarClient struct {
|
||||
lastCurrent *activityv1.GetWeeklyStarCurrentRequest
|
||||
currentResp *activityv1.GetWeeklyStarCurrentResponse
|
||||
lastLeaderboard *activityv1.ListWeeklyStarLeaderboardRequest
|
||||
leaderboardResp *activityv1.ListWeeklyStarLeaderboardResponse
|
||||
lastHistory *activityv1.ListWeeklyStarHistoryRequest
|
||||
historyResp *activityv1.ListWeeklyStarHistoryResponse
|
||||
err error
|
||||
}
|
||||
|
||||
type fakeBroadcastClient struct {
|
||||
lastRemove *activityv1.RemoveRegionBroadcastMemberRequest
|
||||
err error
|
||||
@ -1084,6 +1094,39 @@ func (f *fakeAchievementClient) SetBadgeDisplay(_ context.Context, req *activity
|
||||
return &activityv1.SetBadgeDisplayResponse{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeWeeklyStarClient) GetWeeklyStarCurrent(_ context.Context, req *activityv1.GetWeeklyStarCurrentRequest) (*activityv1.GetWeeklyStarCurrentResponse, error) {
|
||||
f.lastCurrent = req
|
||||
if f.err != nil {
|
||||
return nil, f.err
|
||||
}
|
||||
if f.currentResp != nil {
|
||||
return f.currentResp, nil
|
||||
}
|
||||
return &activityv1.GetWeeklyStarCurrentResponse{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeWeeklyStarClient) ListWeeklyStarLeaderboard(_ context.Context, req *activityv1.ListWeeklyStarLeaderboardRequest) (*activityv1.ListWeeklyStarLeaderboardResponse, error) {
|
||||
f.lastLeaderboard = req
|
||||
if f.err != nil {
|
||||
return nil, f.err
|
||||
}
|
||||
if f.leaderboardResp != nil {
|
||||
return f.leaderboardResp, nil
|
||||
}
|
||||
return &activityv1.ListWeeklyStarLeaderboardResponse{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeWeeklyStarClient) ListWeeklyStarHistory(_ context.Context, req *activityv1.ListWeeklyStarHistoryRequest) (*activityv1.ListWeeklyStarHistoryResponse, error) {
|
||||
f.lastHistory = req
|
||||
if f.err != nil {
|
||||
return nil, f.err
|
||||
}
|
||||
if f.historyResp != nil {
|
||||
return f.historyResp, nil
|
||||
}
|
||||
return &activityv1.ListWeeklyStarHistoryResponse{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeBroadcastClient) RemoveRegionBroadcastMember(_ context.Context, req *activityv1.RemoveRegionBroadcastMemberRequest) (*activityv1.RemoveRegionBroadcastMemberResponse, error) {
|
||||
f.lastRemove = req
|
||||
if f.err != nil {
|
||||
@ -4669,6 +4712,126 @@ func TestAchievementAndBadgeRoutesEmbedResourceMaterials(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWeeklyStarCurrentEmbedsRewardResourceGroups(t *testing.T) {
|
||||
rewardResource := &walletv1.Resource{
|
||||
ResourceId: 8101,
|
||||
ResourceCode: "weekly_star_frame",
|
||||
ResourceType: "avatar_frame",
|
||||
Name: "Weekly Star Frame",
|
||||
Status: "active",
|
||||
Grantable: true,
|
||||
GrantStrategy: "new_entitlement",
|
||||
UsageScopes: []string{"profile"},
|
||||
AssetUrl: "https://cdn.example/weekly-star-frame.png",
|
||||
SortOrder: 10,
|
||||
}
|
||||
weeklyStarClient := &fakeWeeklyStarClient{
|
||||
currentResp: &activityv1.GetWeeklyStarCurrentResponse{
|
||||
Cycle: &activityv1.WeeklyStarCycle{
|
||||
CycleId: "wstar-test",
|
||||
ActivityCode: "weekly_star",
|
||||
RegionId: 686,
|
||||
Title: "Weekly Star",
|
||||
Status: "active",
|
||||
StartMs: 1778256000000,
|
||||
EndMs: 1778860800000,
|
||||
Gifts: []*activityv1.WeeklyStarGift{{GiftId: "308", SortOrder: 1}},
|
||||
Rewards: []*activityv1.WeeklyStarReward{{RankNo: 1, ResourceGroupId: 23}},
|
||||
},
|
||||
TopEntries: []*activityv1.WeeklyStarLeaderboardEntry{{RankNo: 1, UserId: 88, Score: 120000, FirstScoredAtMs: 1778256001000, LastScoredAtMs: 1778256002000}},
|
||||
ServerTimeMs: 1778256003000,
|
||||
},
|
||||
}
|
||||
walletClient := &fakeWalletClient{
|
||||
resourceGroupsByID: map[int64]*walletv1.ResourceGroup{23: {
|
||||
GroupId: 23,
|
||||
GroupCode: "weekly_star_top1",
|
||||
Name: "Top 1 Resource Group",
|
||||
Status: "active",
|
||||
Items: []*walletv1.ResourceGroupItem{{
|
||||
GroupItemId: 101,
|
||||
ItemType: "resource",
|
||||
ResourceId: rewardResource.GetResourceId(),
|
||||
Resource: rewardResource,
|
||||
Quantity: 1,
|
||||
DurationMs: 7 * 24 * int64(time.Hour/time.Millisecond),
|
||||
SortOrder: 10,
|
||||
}},
|
||||
}},
|
||||
}
|
||||
userClient := &fakeUserProfileClient{
|
||||
usersByID: map[int64]*userv1.User{
|
||||
42: {UserId: 42, DisplayUserId: "163000", Username: "viewer", RegionId: 686},
|
||||
88: {UserId: 88, DisplayUserId: "163088", Username: "weekly_ranker", Avatar: "https://cdn.example/ranker.png", RegionId: 686},
|
||||
},
|
||||
}
|
||||
handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, userClient)
|
||||
handler.SetWeeklyStarClient(weeklyStarClient)
|
||||
handler.SetWalletClient(walletClient)
|
||||
router := handler.Routes(auth.NewVerifier("secret"))
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, "/api/v1/activities/weekly-star/current", nil)
|
||||
request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42))
|
||||
recorder := httptest.NewRecorder()
|
||||
router.ServeHTTP(recorder, request)
|
||||
if recorder.Code != http.StatusOK {
|
||||
t.Fatalf("weekly star status mismatch: got %d body=%s", recorder.Code, recorder.Body.String())
|
||||
}
|
||||
var envelope struct {
|
||||
Code string `json:"code"`
|
||||
Data struct {
|
||||
Cycle struct {
|
||||
Rewards []struct {
|
||||
ResourceGroupID int64 `json:"resource_group_id"`
|
||||
ResourceGroup struct {
|
||||
GroupID int64 `json:"group_id"`
|
||||
Name string `json:"name"`
|
||||
Items []struct {
|
||||
ResourceID int64 `json:"resource_id"`
|
||||
Resource struct {
|
||||
ResourceID int64 `json:"resource_id"`
|
||||
ResourceType string `json:"resource_type"`
|
||||
Name string `json:"name"`
|
||||
AssetURL string `json:"asset_url"`
|
||||
} `json:"resource"`
|
||||
Quantity int64 `json:"quantity"`
|
||||
DurationMS int64 `json:"duration_ms"`
|
||||
} `json:"items"`
|
||||
} `json:"resource_group"`
|
||||
} `json:"rewards"`
|
||||
} `json:"cycle"`
|
||||
TopEntries []struct {
|
||||
User struct {
|
||||
Username string `json:"username"`
|
||||
} `json:"user"`
|
||||
} `json:"top_entries"`
|
||||
} `json:"data"`
|
||||
}
|
||||
if err := json.NewDecoder(recorder.Body).Decode(&envelope); err != nil {
|
||||
t.Fatalf("decode weekly star response failed: %v", err)
|
||||
}
|
||||
if weeklyStarClient.lastCurrent == nil || weeklyStarClient.lastCurrent.GetUserId() != 42 || weeklyStarClient.lastCurrent.GetRegionId() != 686 {
|
||||
t.Fatalf("weekly star request mismatch: %+v", weeklyStarClient.lastCurrent)
|
||||
}
|
||||
if envelope.Code != httpkit.CodeOK || len(envelope.Data.Cycle.Rewards) != 1 {
|
||||
t.Fatalf("weekly star response missing rewards: %+v", envelope)
|
||||
}
|
||||
firstReward := envelope.Data.Cycle.Rewards[0]
|
||||
if firstReward.ResourceGroupID != 23 || firstReward.ResourceGroup.GroupID != 23 || firstReward.ResourceGroup.Name != "Top 1 Resource Group" {
|
||||
t.Fatalf("weekly star reward group mismatch: %+v", firstReward)
|
||||
}
|
||||
if len(firstReward.ResourceGroup.Items) != 1 {
|
||||
t.Fatalf("weekly star reward group items mismatch: %+v", firstReward.ResourceGroup)
|
||||
}
|
||||
firstItem := firstReward.ResourceGroup.Items[0]
|
||||
if firstItem.ResourceID != 8101 || firstItem.Quantity != 1 || firstItem.DurationMS == 0 || firstItem.Resource.ResourceID != 8101 || firstItem.Resource.ResourceType != "avatar_frame" || firstItem.Resource.Name != "Weekly Star Frame" || firstItem.Resource.AssetURL == "" {
|
||||
t.Fatalf("weekly star reward group item must embed resource material: %+v", firstItem)
|
||||
}
|
||||
if len(envelope.Data.TopEntries) != 1 || envelope.Data.TopEntries[0].User.Username != "weekly_ranker" {
|
||||
t.Fatalf("weekly star top entry user mismatch: %+v", envelope.Data.TopEntries)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppearanceAggregatesEquippedResourcesAndBadges(t *testing.T) {
|
||||
frameResource := &walletv1.Resource{
|
||||
ResourceId: 8101,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user