feat: add rocket level contents api
This commit is contained in:
parent
39744caf2e
commit
2c5c247f12
@ -32,6 +32,14 @@ func registerVoiceRoomRocketRoutes(
|
|||||||
}
|
}
|
||||||
writeOK(c, resp)
|
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) {
|
appGroup.GET("/status", func(c *gin.Context) {
|
||||||
resp, err := service.GetStatus(c.Request.Context(), mustAuthUser(c), parseInt64(c.Query("roomId")))
|
resp, err := service.GetStatus(c.Request.Context(), mustAuthUser(c), parseInt64(c.Query("roomId")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -19,6 +19,23 @@ func (s *Service) GetConfig(ctx context.Context, user AuthUser) (*ConfigResponse
|
|||||||
return s.getConfigResponse(ctx, user.SysOrigin, 0)
|
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 返回火箭规则说明。
|
// GetRule 返回火箭规则说明。
|
||||||
func (s *Service) GetRule(ctx context.Context, user AuthUser) (json.RawMessage, error) {
|
func (s *Service) GetRule(ctx context.Context, user AuthUser) (json.RawMessage, error) {
|
||||||
snapshot, err := s.loadConfig(ctx, user.SysOrigin)
|
snapshot, err := s.loadConfig(ctx, user.SysOrigin)
|
||||||
|
|||||||
@ -83,3 +83,95 @@ func TestGetStatusReturnsRocketResourcesToApp(t *testing.T) {
|
|||||||
t.Fatalf("status levels = %+v", status.Levels)
|
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 {
|
func rewardPreviewPayload(rows []model.VoiceRoomRocketRewardConfig) RewardPreviewResponse {
|
||||||
sort.Slice(rows, func(i, j int) bool {
|
rows = sortedRewardRows(rows)
|
||||||
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
|
|
||||||
})
|
|
||||||
resp := RewardPreviewResponse{}
|
resp := RewardPreviewResponse{}
|
||||||
for _, row := range rows {
|
for _, row := range rows {
|
||||||
if strings.EqualFold(strings.TrimSpace(row.RewardType), rewardTypeNone) {
|
if strings.EqualFold(strings.TrimSpace(row.RewardType), rewardTypeNone) {
|
||||||
@ -195,6 +196,20 @@ func rewardPreviewPayload(rows []model.VoiceRoomRocketRewardConfig) RewardPrevie
|
|||||||
return resp
|
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 {
|
func rewardSceneOrder(scene string) int {
|
||||||
switch strings.ToUpper(strings.TrimSpace(scene)) {
|
switch strings.ToUpper(strings.TrimSpace(scene)) {
|
||||||
case rewardSceneTop1:
|
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 {
|
func configResponse(snapshot configSnapshot, levels []model.VoiceRoomRocketLevelConfig, rewards []model.VoiceRoomRocketRewardConfig) *ConfigResponse {
|
||||||
levelPayloads := make([]LevelConfigPayload, 0, len(levels))
|
levelPayloads := make([]LevelConfigPayload, 0, len(levels))
|
||||||
sort.Slice(levels, func(i, j int) bool {
|
sort.Slice(levels, func(i, j int) bool {
|
||||||
|
|||||||
@ -348,6 +348,22 @@ type RewardPreviewResponse struct {
|
|||||||
InRoom []RewardConfigPayload `json:"inRoom"`
|
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 {
|
type ConfigResponse struct {
|
||||||
Configured bool `json:"configured"`
|
Configured bool `json:"configured"`
|
||||||
ID int64 `json:"id,string,omitempty"`
|
ID int64 `json:"id,string,omitempty"`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user