feat: add rocket level contents api
This commit is contained in:
parent
39744caf2e
commit
2c5c247f12
@ -32,6 +32,14 @@ func registerVoiceRoomRocketRoutes(
|
||||
}
|
||||
writeOK(c, resp)
|
||||
})
|
||||
appGroup.GET("/level-contents", func(c *gin.Context) {
|
||||
resp, err := service.GetLevelContents(c.Request.Context(), mustAuthUser(c))
|
||||
if err != nil {
|
||||
writeError(c, err)
|
||||
return
|
||||
}
|
||||
writeOK(c, resp)
|
||||
})
|
||||
appGroup.GET("/status", func(c *gin.Context) {
|
||||
resp, err := service.GetStatus(c.Request.Context(), mustAuthUser(c), parseInt64(c.Query("roomId")))
|
||||
if err != nil {
|
||||
|
||||
@ -19,6 +19,23 @@ func (s *Service) GetConfig(ctx context.Context, user AuthUser) (*ConfigResponse
|
||||
return s.getConfigResponse(ctx, user.SysOrigin, 0)
|
||||
}
|
||||
|
||||
// GetLevelContents 返回 App 查看高等级所需的全部等级资源和每级奖励内容。
|
||||
func (s *Service) GetLevelContents(ctx context.Context, user AuthUser) (*LevelContentsResponse, error) {
|
||||
snapshot, err := s.loadConfig(ctx, user.SysOrigin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
levels, err := s.loadLevelConfigs(ctx, snapshot.SysOrigin, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rewards, err := s.loadRewardConfigs(ctx, snapshot.SysOrigin, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return levelContentsResponse(snapshot, levels, rewards), nil
|
||||
}
|
||||
|
||||
// GetRule 返回火箭规则说明。
|
||||
func (s *Service) GetRule(ctx context.Context, user AuthUser) (json.RawMessage, error) {
|
||||
snapshot, err := s.loadConfig(ctx, user.SysOrigin)
|
||||
|
||||
@ -83,3 +83,95 @@ func TestGetStatusReturnsRocketResourcesToApp(t *testing.T) {
|
||||
t.Fatalf("status levels = %+v", status.Levels)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLevelContentsReturnsEveryLevelRewards(t *testing.T) {
|
||||
service, _ := newTestService(t)
|
||||
ctx := context.Background()
|
||||
|
||||
_, err := service.SaveLevelConfigs(ctx, SaveLevelConfigsRequest{
|
||||
SysOrigin: "LIKEI",
|
||||
Levels: []LevelConfigPayload{
|
||||
{
|
||||
Level: 1,
|
||||
NeedEnergy: 100,
|
||||
ShakeThresholdPercent: "95.0000",
|
||||
PreviewRocketURL: "https://cdn.example.com/lv1.png",
|
||||
Enabled: true,
|
||||
Sort: 1,
|
||||
},
|
||||
{
|
||||
Level: 2,
|
||||
NeedEnergy: 200,
|
||||
ShakeThresholdPercent: "95.0000",
|
||||
PreviewRocketURL: "https://cdn.example.com/lv2.png",
|
||||
Enabled: true,
|
||||
Sort: 2,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("SaveLevelConfigs error = %v", err)
|
||||
}
|
||||
|
||||
_, err = service.SaveRewardConfigs(ctx, SaveRewardConfigsRequest{
|
||||
SysOrigin: "LIKEI",
|
||||
Rewards: []RewardConfigPayload{
|
||||
{
|
||||
Level: 1,
|
||||
RewardScene: rewardSceneTop1,
|
||||
RewardType: rewardTypeGold,
|
||||
RewardName: "Lv1 top1",
|
||||
RewardAmount: 100,
|
||||
Enabled: true,
|
||||
Sort: 1,
|
||||
},
|
||||
{
|
||||
Level: 2,
|
||||
RewardScene: rewardSceneIgnite,
|
||||
RewardType: rewardTypeGold,
|
||||
RewardName: "Lv2 ignite",
|
||||
RewardAmount: 200,
|
||||
Enabled: true,
|
||||
Sort: 1,
|
||||
},
|
||||
{
|
||||
Level: 2,
|
||||
RewardScene: rewardSceneInRoom,
|
||||
RewardType: rewardTypeNone,
|
||||
RewardName: "轮空",
|
||||
Enabled: true,
|
||||
Sort: 2,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("SaveRewardConfigs error = %v", err)
|
||||
}
|
||||
|
||||
resp, err := service.GetLevelContents(ctx, AuthUser{SysOrigin: "LIKEI"})
|
||||
if err != nil {
|
||||
t.Fatalf("GetLevelContents error = %v", err)
|
||||
}
|
||||
if len(resp.Levels) != 2 {
|
||||
t.Fatalf("level count = %d, want 2", len(resp.Levels))
|
||||
}
|
||||
levels := map[int]LevelContentPayload{}
|
||||
for _, item := range resp.Levels {
|
||||
levels[item.Level] = item
|
||||
}
|
||||
if levels[1].PreviewRocketURL != "https://cdn.example.com/lv1.png" {
|
||||
t.Fatalf("level 1 previewRocketUrl = %q", levels[1].PreviewRocketURL)
|
||||
}
|
||||
if got := levels[1].RewardPreview.Top1; len(got) != 1 || got[0].RewardName != "Lv1 top1" {
|
||||
t.Fatalf("level 1 top1 preview = %+v", got)
|
||||
}
|
||||
if got := levels[2].RewardPreview.Ignite; len(got) != 1 || got[0].RewardName != "Lv2 ignite" {
|
||||
t.Fatalf("level 2 ignite preview = %+v", got)
|
||||
}
|
||||
if len(levels[2].Rewards) != 2 {
|
||||
t.Fatalf("level 2 rewards = %+v", levels[2].Rewards)
|
||||
}
|
||||
if len(levels[2].RewardPreview.InRoom) != 0 {
|
||||
t.Fatalf("NONE reward should not appear in preview: %+v", levels[2].RewardPreview.InRoom)
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,16 +167,17 @@ func rewardPayload(row model.VoiceRoomRocketRewardConfig) RewardConfigPayload {
|
||||
}
|
||||
}
|
||||
|
||||
func rewardPayloads(rows []model.VoiceRoomRocketRewardConfig) []RewardConfigPayload {
|
||||
sorted := sortedRewardRows(rows)
|
||||
result := make([]RewardConfigPayload, 0, len(sorted))
|
||||
for _, row := range sorted {
|
||||
result = append(result, rewardPayload(row))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func rewardPreviewPayload(rows []model.VoiceRoomRocketRewardConfig) RewardPreviewResponse {
|
||||
sort.Slice(rows, func(i, j int) bool {
|
||||
if rows[i].RewardScene != rows[j].RewardScene {
|
||||
return rewardSceneOrder(rows[i].RewardScene) < rewardSceneOrder(rows[j].RewardScene)
|
||||
}
|
||||
if rows[i].Sort != rows[j].Sort {
|
||||
return rows[i].Sort < rows[j].Sort
|
||||
}
|
||||
return rows[i].ID < rows[j].ID
|
||||
})
|
||||
rows = sortedRewardRows(rows)
|
||||
resp := RewardPreviewResponse{}
|
||||
for _, row := range rows {
|
||||
if strings.EqualFold(strings.TrimSpace(row.RewardType), rewardTypeNone) {
|
||||
@ -195,6 +196,20 @@ func rewardPreviewPayload(rows []model.VoiceRoomRocketRewardConfig) RewardPrevie
|
||||
return resp
|
||||
}
|
||||
|
||||
func sortedRewardRows(rows []model.VoiceRoomRocketRewardConfig) []model.VoiceRoomRocketRewardConfig {
|
||||
sorted := append([]model.VoiceRoomRocketRewardConfig(nil), rows...)
|
||||
sort.Slice(sorted, func(i, j int) bool {
|
||||
if sorted[i].RewardScene != sorted[j].RewardScene {
|
||||
return rewardSceneOrder(sorted[i].RewardScene) < rewardSceneOrder(sorted[j].RewardScene)
|
||||
}
|
||||
if sorted[i].Sort != sorted[j].Sort {
|
||||
return sorted[i].Sort < sorted[j].Sort
|
||||
}
|
||||
return sorted[i].ID < sorted[j].ID
|
||||
})
|
||||
return sorted
|
||||
}
|
||||
|
||||
func rewardSceneOrder(scene string) int {
|
||||
switch strings.ToUpper(strings.TrimSpace(scene)) {
|
||||
case rewardSceneTop1:
|
||||
@ -224,6 +239,37 @@ func isSupportedRewardType(rewardType string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func levelContentsResponse(snapshot configSnapshot, levels []model.VoiceRoomRocketLevelConfig, rewards []model.VoiceRoomRocketRewardConfig) *LevelContentsResponse {
|
||||
sort.Slice(levels, func(i, j int) bool {
|
||||
if levels[i].Sort != levels[j].Sort {
|
||||
return levels[i].Sort < levels[j].Sort
|
||||
}
|
||||
return levels[i].Level < levels[j].Level
|
||||
})
|
||||
rewardsByLevel := make(map[int][]model.VoiceRoomRocketRewardConfig)
|
||||
for _, row := range rewards {
|
||||
rewardsByLevel[row.Level] = append(rewardsByLevel[row.Level], row)
|
||||
}
|
||||
levelPayloads := make([]LevelContentPayload, 0, len(levels))
|
||||
for _, row := range levels {
|
||||
levelRewards := rewardsByLevel[row.Level]
|
||||
levelPayloads = append(levelPayloads, LevelContentPayload{
|
||||
LevelConfigPayload: levelPayload(row),
|
||||
Rewards: rewardPayloads(levelRewards),
|
||||
RewardPreview: rewardPreviewPayload(levelRewards),
|
||||
})
|
||||
}
|
||||
return &LevelContentsResponse{
|
||||
Configured: snapshot.Configured,
|
||||
SysOrigin: snapshot.SysOrigin,
|
||||
Enabled: snapshot.Enabled,
|
||||
Timezone: snapshot.Timezone,
|
||||
MaxLevel: snapshot.MaxLevel,
|
||||
Levels: levelPayloads,
|
||||
UpdateTime: formatDateTime(snapshot.UpdateTime),
|
||||
}
|
||||
}
|
||||
|
||||
func configResponse(snapshot configSnapshot, levels []model.VoiceRoomRocketLevelConfig, rewards []model.VoiceRoomRocketRewardConfig) *ConfigResponse {
|
||||
levelPayloads := make([]LevelConfigPayload, 0, len(levels))
|
||||
sort.Slice(levels, func(i, j int) bool {
|
||||
|
||||
@ -348,6 +348,22 @@ type RewardPreviewResponse struct {
|
||||
InRoom []RewardConfigPayload `json:"inRoom"`
|
||||
}
|
||||
|
||||
type LevelContentPayload struct {
|
||||
LevelConfigPayload
|
||||
Rewards []RewardConfigPayload `json:"rewards"`
|
||||
RewardPreview RewardPreviewResponse `json:"rewardPreview"`
|
||||
}
|
||||
|
||||
type LevelContentsResponse struct {
|
||||
Configured bool `json:"configured"`
|
||||
SysOrigin string `json:"sysOrigin"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Timezone string `json:"timezone"`
|
||||
MaxLevel int `json:"maxLevel"`
|
||||
Levels []LevelContentPayload `json:"levels"`
|
||||
UpdateTime string `json:"updateTime,omitempty"`
|
||||
}
|
||||
|
||||
type ConfigResponse struct {
|
||||
Configured bool `json:"configured"`
|
||||
ID int64 `json:"id,string,omitempty"`
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user