624 lines
21 KiB
Go
624 lines
21 KiB
Go
package wheel
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"chatapp3-golang/internal/model"
|
|
"chatapp3-golang/internal/utils"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type configBundle struct {
|
|
Config *model.WheelConfig
|
|
Categories []model.WheelPoolConfig
|
|
Rewards []model.WheelRewardConfig
|
|
}
|
|
|
|
// GetConfig returns admin wheel configuration.
|
|
func (s *Service) GetConfig(ctx context.Context, sysOrigin string) (*ConfigResponse, error) {
|
|
bundle, err := s.loadConfigBundle(ctx, sysOrigin, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if bundle.Config == nil {
|
|
return defaultConfigResponse(sysOrigin), nil
|
|
}
|
|
return s.buildConfigResponse(bundle)
|
|
}
|
|
|
|
// GetAppConfig returns enabled wheel configuration for app clients.
|
|
func (s *Service) GetAppConfig(ctx context.Context, user AuthUser) (*ConfigResponse, error) {
|
|
bundle, err := s.loadConfigBundle(ctx, user.SysOrigin, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if bundle.Config == nil {
|
|
return &ConfigResponse{
|
|
Configured: false,
|
|
SysOrigin: normalizeSysOrigin(user.SysOrigin),
|
|
Timezone: defaultTimezone,
|
|
ProbabilityTotal: probabilityTotal,
|
|
Categories: defaultCategoryPayloads(false),
|
|
}, nil
|
|
}
|
|
return s.buildConfigResponse(bundle)
|
|
}
|
|
|
|
// SaveConfig saves admin wheel configuration.
|
|
func (s *Service) SaveConfig(ctx context.Context, req SaveConfigRequest) (*ConfigResponse, error) {
|
|
normalized, err := normalizeSaveRequest(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
configEnabled := false
|
|
for _, category := range normalized.Categories {
|
|
if category.Enabled {
|
|
configEnabled = true
|
|
break
|
|
}
|
|
}
|
|
|
|
now := time.Now()
|
|
if err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
var configRow model.WheelConfig
|
|
if err := tx.Where("sys_origin = ?", normalized.SysOrigin).First(&configRow).Error; errors.Is(err, gorm.ErrRecordNotFound) {
|
|
nextID, idErr := utils.NextID()
|
|
if idErr != nil {
|
|
return idErr
|
|
}
|
|
configRow = model.WheelConfig{
|
|
ID: nextID,
|
|
SysOrigin: normalized.SysOrigin,
|
|
CreateTime: now,
|
|
}
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
|
|
configRow.Enabled = configEnabled
|
|
configRow.Timezone = normalized.Timezone
|
|
configRow.UpdateTime = now
|
|
if configRow.CreateTime.IsZero() {
|
|
configRow.CreateTime = now
|
|
}
|
|
if err := tx.Save(&configRow).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := tx.Where("config_id = ?", configRow.ID).Delete(&model.WheelPoolConfig{}).Error; err != nil {
|
|
return err
|
|
}
|
|
if err := tx.Where("config_id = ?", configRow.ID).Delete(&model.WheelRewardConfig{}).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
poolRows := make([]model.WheelPoolConfig, 0, len(normalized.Categories))
|
|
rewardRows := make([]model.WheelRewardConfig, 0, 28)
|
|
for _, category := range normalized.Categories {
|
|
meta, _ := categoryMeta(category.Category)
|
|
poolID, idErr := utils.NextID()
|
|
if idErr != nil {
|
|
return idErr
|
|
}
|
|
poolRows = append(poolRows, model.WheelPoolConfig{
|
|
ID: poolID,
|
|
ConfigID: configRow.ID,
|
|
SysOrigin: normalized.SysOrigin,
|
|
Category: category.Category,
|
|
Enabled: category.Enabled,
|
|
PriceOneGold: category.PriceOneGold,
|
|
PriceTenGold: category.PriceTenGold,
|
|
PriceFiftyGold: category.PriceFiftyGold,
|
|
Sort: meta.Sort,
|
|
CreateTime: now,
|
|
UpdateTime: now,
|
|
})
|
|
|
|
for index, item := range category.Rewards {
|
|
nextID, rewardIDErr := utils.NextID()
|
|
if rewardIDErr != nil {
|
|
return rewardIDErr
|
|
}
|
|
sortValue := item.Sort
|
|
if sortValue <= 0 {
|
|
sortValue = index + 1
|
|
}
|
|
rewardRows = append(rewardRows, model.WheelRewardConfig{
|
|
ID: nextID,
|
|
ConfigID: configRow.ID,
|
|
SysOrigin: normalized.SysOrigin,
|
|
Category: category.Category,
|
|
RewardType: item.RewardType,
|
|
ResourceID: resourceIDPtr(item.ResourceID),
|
|
ResourceType: item.ResourceType,
|
|
ResourceName: strings.TrimSpace(item.ResourceName),
|
|
ResourceURL: strings.TrimSpace(item.ResourceURL),
|
|
CoverURL: strings.TrimSpace(item.CoverURL),
|
|
DurationDays: item.DurationDays,
|
|
DisplayGoldAmount: item.DisplayGoldAmount,
|
|
GoldAmount: item.GoldAmount,
|
|
Probability: item.Probability,
|
|
Sort: sortValue,
|
|
Enabled: item.Enabled,
|
|
CreateTime: now,
|
|
UpdateTime: now,
|
|
})
|
|
}
|
|
}
|
|
if len(poolRows) > 0 {
|
|
if err := tx.Create(&poolRows).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if len(rewardRows) > 0 {
|
|
return tx.Create(&rewardRows).Error
|
|
}
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s.GetConfig(ctx, normalized.SysOrigin)
|
|
}
|
|
|
|
// SaveCategoryConfig saves one admin wheel category without touching the other categories.
|
|
func (s *Service) SaveCategoryConfig(ctx context.Context, req SaveCategoryConfigRequest) (*ConfigResponse, error) {
|
|
normalized, err := normalizeSaveCategoryRequest(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
now := time.Now()
|
|
if err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
var configRow model.WheelConfig
|
|
if err := tx.Where("sys_origin = ?", normalized.SysOrigin).First(&configRow).Error; errors.Is(err, gorm.ErrRecordNotFound) {
|
|
nextID, idErr := utils.NextID()
|
|
if idErr != nil {
|
|
return idErr
|
|
}
|
|
configRow = model.WheelConfig{
|
|
ID: nextID,
|
|
SysOrigin: normalized.SysOrigin,
|
|
CreateTime: now,
|
|
}
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
|
|
configRow.Timezone = normalized.Timezone
|
|
configRow.UpdateTime = now
|
|
if configRow.CreateTime.IsZero() {
|
|
configRow.CreateTime = now
|
|
}
|
|
if err := tx.Save(&configRow).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
category := normalized.Category
|
|
meta, _ := categoryMeta(category.Category)
|
|
if err := tx.Where("config_id = ? AND category = ?", configRow.ID, category.Category).Delete(&model.WheelPoolConfig{}).Error; err != nil {
|
|
return err
|
|
}
|
|
if err := tx.Where("config_id = ? AND category = ?", configRow.ID, category.Category).Delete(&model.WheelRewardConfig{}).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
poolID, idErr := utils.NextID()
|
|
if idErr != nil {
|
|
return idErr
|
|
}
|
|
poolRow := model.WheelPoolConfig{
|
|
ID: poolID,
|
|
ConfigID: configRow.ID,
|
|
SysOrigin: normalized.SysOrigin,
|
|
Category: category.Category,
|
|
Enabled: category.Enabled,
|
|
PriceOneGold: category.PriceOneGold,
|
|
PriceTenGold: category.PriceTenGold,
|
|
PriceFiftyGold: category.PriceFiftyGold,
|
|
Sort: meta.Sort,
|
|
CreateTime: now,
|
|
UpdateTime: now,
|
|
}
|
|
if err := tx.Create(&poolRow).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
rewardRows := make([]model.WheelRewardConfig, 0, len(category.Rewards))
|
|
for index, item := range category.Rewards {
|
|
nextID, rewardIDErr := utils.NextID()
|
|
if rewardIDErr != nil {
|
|
return rewardIDErr
|
|
}
|
|
sortValue := item.Sort
|
|
if sortValue <= 0 {
|
|
sortValue = index + 1
|
|
}
|
|
rewardRows = append(rewardRows, model.WheelRewardConfig{
|
|
ID: nextID,
|
|
ConfigID: configRow.ID,
|
|
SysOrigin: normalized.SysOrigin,
|
|
Category: category.Category,
|
|
RewardType: item.RewardType,
|
|
ResourceID: resourceIDPtr(item.ResourceID),
|
|
ResourceType: item.ResourceType,
|
|
ResourceName: strings.TrimSpace(item.ResourceName),
|
|
ResourceURL: strings.TrimSpace(item.ResourceURL),
|
|
CoverURL: strings.TrimSpace(item.CoverURL),
|
|
DurationDays: item.DurationDays,
|
|
DisplayGoldAmount: item.DisplayGoldAmount,
|
|
GoldAmount: item.GoldAmount,
|
|
Probability: item.Probability,
|
|
Sort: sortValue,
|
|
Enabled: item.Enabled,
|
|
CreateTime: now,
|
|
UpdateTime: now,
|
|
})
|
|
}
|
|
if len(rewardRows) > 0 {
|
|
if err := tx.Create(&rewardRows).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
var enabledPools int64
|
|
if err := tx.Model(&model.WheelPoolConfig{}).
|
|
Where("config_id = ? AND enabled = ?", configRow.ID, true).
|
|
Count(&enabledPools).Error; err != nil {
|
|
return err
|
|
}
|
|
return tx.Model(&model.WheelConfig{}).
|
|
Where("id = ?", configRow.ID).
|
|
Updates(map[string]any{
|
|
"enabled": enabledPools > 0,
|
|
"timezone": normalized.Timezone,
|
|
"update_time": now,
|
|
}).Error
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s.GetConfig(ctx, normalized.SysOrigin)
|
|
}
|
|
|
|
func normalizeSaveRequest(req SaveConfigRequest) (SaveConfigRequest, error) {
|
|
sysOrigin := normalizeSysOrigin(req.SysOrigin)
|
|
if sysOrigin == "" {
|
|
return SaveConfigRequest{}, NewAppError(http.StatusBadRequest, "bad_request", "sysOrigin is required")
|
|
}
|
|
timezone := normalizeTimezone(req.Timezone)
|
|
if _, err := time.LoadLocation(timezone); err != nil {
|
|
return SaveConfigRequest{}, NewAppError(http.StatusBadRequest, "invalid_timezone", err.Error())
|
|
}
|
|
|
|
inputByCategory := make(map[string]CategoryConfigInput, len(req.Categories))
|
|
for _, category := range req.Categories {
|
|
normalizedCategory := normalizeCategory(category.Category)
|
|
if _, ok := categoryMeta(normalizedCategory); !ok {
|
|
return SaveConfigRequest{}, NewAppError(http.StatusBadRequest, "invalid_category", "category must be CLASSIC, LUXURY, or ADVANCED")
|
|
}
|
|
category.Category = normalizedCategory
|
|
inputByCategory[normalizedCategory] = category
|
|
}
|
|
|
|
categories := make([]CategoryConfigInput, 0, len(wheelCategories))
|
|
for _, meta := range wheelCategories {
|
|
category, exists := inputByCategory[meta.Category]
|
|
if !exists {
|
|
category = defaultCategoryInput(meta)
|
|
}
|
|
category.Category = meta.Category
|
|
if category.PriceOneGold <= 0 || category.PriceTenGold <= 0 || category.PriceFiftyGold <= 0 {
|
|
return SaveConfigRequest{}, NewAppError(http.StatusBadRequest, "invalid_price", fmt.Sprintf("%s draw prices must be greater than 0", meta.Category))
|
|
}
|
|
normalizedRewards, err := normalizeCategoryRewards(meta, category.Rewards, category.Enabled)
|
|
if err != nil {
|
|
return SaveConfigRequest{}, err
|
|
}
|
|
category.Rewards = normalizedRewards
|
|
categories = append(categories, category)
|
|
}
|
|
|
|
return SaveConfigRequest{
|
|
SysOrigin: sysOrigin,
|
|
Enabled: req.Enabled,
|
|
Timezone: timezone,
|
|
Categories: categories,
|
|
}, nil
|
|
}
|
|
|
|
func normalizeSaveCategoryRequest(req SaveCategoryConfigRequest) (SaveCategoryConfigRequest, error) {
|
|
sysOrigin := normalizeSysOrigin(req.SysOrigin)
|
|
if sysOrigin == "" {
|
|
return SaveCategoryConfigRequest{}, NewAppError(http.StatusBadRequest, "bad_request", "sysOrigin is required")
|
|
}
|
|
timezone := normalizeTimezone(req.Timezone)
|
|
if _, err := time.LoadLocation(timezone); err != nil {
|
|
return SaveCategoryConfigRequest{}, NewAppError(http.StatusBadRequest, "invalid_timezone", err.Error())
|
|
}
|
|
|
|
category := req.Category
|
|
category.Category = normalizeCategory(category.Category)
|
|
meta, ok := categoryMeta(category.Category)
|
|
if !ok {
|
|
return SaveCategoryConfigRequest{}, NewAppError(http.StatusBadRequest, "invalid_category", "category must be CLASSIC, LUXURY, or ADVANCED")
|
|
}
|
|
if category.PriceOneGold <= 0 || category.PriceTenGold <= 0 || category.PriceFiftyGold <= 0 {
|
|
return SaveCategoryConfigRequest{}, NewAppError(http.StatusBadRequest, "invalid_price", fmt.Sprintf("%s draw prices must be greater than 0", meta.Category))
|
|
}
|
|
rewards, err := normalizeCategoryRewards(meta, category.Rewards, category.Enabled)
|
|
if err != nil {
|
|
return SaveCategoryConfigRequest{}, err
|
|
}
|
|
category.Rewards = rewards
|
|
return SaveCategoryConfigRequest{
|
|
SysOrigin: sysOrigin,
|
|
Timezone: timezone,
|
|
Category: category,
|
|
}, nil
|
|
}
|
|
|
|
func normalizeCategoryRewards(meta CategoryMeta, rewards []RewardConfigInput, requireEnabled bool) ([]RewardConfigInput, error) {
|
|
if len(rewards) != meta.RewardCount {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_reward_count", fmt.Sprintf("%s rewards must contain exactly %d items", meta.Category, meta.RewardCount))
|
|
}
|
|
|
|
normalized := append([]RewardConfigInput(nil), rewards...)
|
|
sortRewardInputs(normalized)
|
|
enabledProbability := 0
|
|
enabledCount := 0
|
|
for index := range normalized {
|
|
item := &normalized[index]
|
|
item.RewardType = normalizeRewardType(item.RewardType)
|
|
item.ResourceType = strings.ToUpper(strings.TrimSpace(item.ResourceType))
|
|
item.ResourceName = strings.TrimSpace(item.ResourceName)
|
|
item.ResourceURL = strings.TrimSpace(item.ResourceURL)
|
|
item.CoverURL = strings.TrimSpace(item.CoverURL)
|
|
if item.Sort <= 0 {
|
|
item.Sort = index + 1
|
|
}
|
|
|
|
switch item.RewardType {
|
|
case rewardTypeResource:
|
|
if requireEnabled && item.ResourceID.Int64() <= 0 {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_resource", fmt.Sprintf("%s resource reward requires resourceId", meta.Category))
|
|
}
|
|
if requireEnabled && item.ResourceType == "" {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_resource_type", fmt.Sprintf("%s resource reward requires resourceType", meta.Category))
|
|
}
|
|
if requireEnabled && item.DurationDays <= 0 {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_duration_days", fmt.Sprintf("%s resource reward requires durationDays greater than 0", meta.Category))
|
|
}
|
|
if requireEnabled && item.DisplayGoldAmount <= 0 {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_display_gold_amount", fmt.Sprintf("%s resource reward display gold amount must be greater than 0", meta.Category))
|
|
}
|
|
if item.ResourceID.Int64() > 0 && item.ResourceName == "" {
|
|
item.ResourceName = fmt.Sprintf("资源 %d", item.ResourceID.Int64())
|
|
}
|
|
item.GoldAmount = 0
|
|
case rewardTypeGold:
|
|
if requireEnabled && item.GoldAmount <= 0 {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_gold_amount", fmt.Sprintf("%s gold reward requires goldAmount", meta.Category))
|
|
}
|
|
item.ResourceID = 0
|
|
item.ResourceType = ""
|
|
item.ResourceName = "金币"
|
|
item.ResourceURL = ""
|
|
item.CoverURL = ""
|
|
item.DurationDays = 0
|
|
item.DisplayGoldAmount = 0
|
|
default:
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_reward_type", "rewardType must be RESOURCE or GOLD")
|
|
}
|
|
|
|
if item.Probability < 0 {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_probability", "probability must be greater than or equal to 0")
|
|
}
|
|
if item.Enabled {
|
|
enabledCount++
|
|
if requireEnabled && item.Probability <= 0 {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_probability", fmt.Sprintf("%s enabled reward probability must be greater than 0", meta.Category))
|
|
}
|
|
enabledProbability += item.Probability
|
|
}
|
|
}
|
|
if requireEnabled {
|
|
if enabledCount != meta.RewardCount {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_enabled_reward_count", fmt.Sprintf("%s must enable exactly %d rewards", meta.Category, meta.RewardCount))
|
|
}
|
|
if enabledProbability != probabilityTotal {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_probability_total", fmt.Sprintf("%s enabled reward probability total must equal 10000", meta.Category))
|
|
}
|
|
}
|
|
return normalized, nil
|
|
}
|
|
|
|
func (s *Service) loadConfigBundle(ctx context.Context, sysOrigin string, onlyEnabledRewards bool) (*configBundle, error) {
|
|
sysOrigin = normalizeSysOrigin(sysOrigin)
|
|
if sysOrigin == "" {
|
|
return nil, NewAppError(http.StatusBadRequest, "bad_request", "sysOrigin is required")
|
|
}
|
|
|
|
var configRow model.WheelConfig
|
|
err := s.db.WithContext(ctx).Where("sys_origin = ?", sysOrigin).First(&configRow).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return &configBundle{}, nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var categoryRows []model.WheelPoolConfig
|
|
categoryQuery := s.db.WithContext(ctx).
|
|
Where("config_id = ?", configRow.ID).
|
|
Order("sort asc, id asc")
|
|
if err := categoryQuery.Find(&categoryRows).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rewardQuery := s.db.WithContext(ctx).
|
|
Where("config_id = ?", configRow.ID).
|
|
Order("category asc, sort asc, id asc")
|
|
if onlyEnabledRewards {
|
|
rewardQuery = rewardQuery.Where("enabled = ?", true)
|
|
}
|
|
var rewardRows []model.WheelRewardConfig
|
|
if err := rewardQuery.Find(&rewardRows).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &configBundle{Config: &configRow, Categories: categoryRows, Rewards: rewardRows}, nil
|
|
}
|
|
|
|
func defaultConfigResponse(sysOrigin string) *ConfigResponse {
|
|
return &ConfigResponse{
|
|
Configured: false,
|
|
SysOrigin: normalizeSysOrigin(sysOrigin),
|
|
Enabled: false,
|
|
Timezone: defaultTimezone,
|
|
ProbabilityTotal: probabilityTotal,
|
|
Categories: defaultCategoryPayloads(false),
|
|
}
|
|
}
|
|
|
|
func defaultCategoryInput(meta CategoryMeta) CategoryConfigInput {
|
|
return CategoryConfigInput{
|
|
Category: meta.Category,
|
|
Enabled: false,
|
|
PriceOneGold: meta.DefaultPriceOneGold,
|
|
PriceTenGold: meta.DefaultPriceTenGold,
|
|
PriceFiftyGold: meta.DefaultPriceFiftyGold,
|
|
Rewards: defaultRewardInputs(meta.RewardCount),
|
|
}
|
|
}
|
|
|
|
func defaultRewardInputs(count int) []RewardConfigInput {
|
|
rewards := make([]RewardConfigInput, 0, count)
|
|
for index := 0; index < count; index++ {
|
|
rewards = append(rewards, RewardConfigInput{
|
|
Enabled: true,
|
|
Sort: index + 1,
|
|
RewardType: rewardTypeResource,
|
|
Probability: 0,
|
|
})
|
|
}
|
|
return rewards
|
|
}
|
|
|
|
func defaultCategoryPayloads(enabled bool) []CategoryConfigPayload {
|
|
result := make([]CategoryConfigPayload, 0, len(wheelCategories))
|
|
for _, meta := range wheelCategories {
|
|
rewards := make([]RewardConfigPayload, 0, meta.RewardCount)
|
|
for index := 0; index < meta.RewardCount; index++ {
|
|
rewards = append(rewards, RewardConfigPayload{
|
|
Enabled: true,
|
|
Sort: index + 1,
|
|
RewardType: rewardTypeResource,
|
|
Probability: 0,
|
|
ProbabilityPercent: "0.00",
|
|
})
|
|
}
|
|
result = append(result, CategoryConfigPayload{
|
|
Category: meta.Category,
|
|
Label: meta.Label,
|
|
Enabled: enabled,
|
|
RewardCount: meta.RewardCount,
|
|
PriceOneGold: meta.DefaultPriceOneGold,
|
|
PriceTenGold: meta.DefaultPriceTenGold,
|
|
PriceFiftyGold: meta.DefaultPriceFiftyGold,
|
|
ProbabilityTotal: probabilityTotal,
|
|
Rewards: rewards,
|
|
})
|
|
}
|
|
return result
|
|
}
|
|
|
|
func (s *Service) buildConfigResponse(bundle *configBundle) (*ConfigResponse, error) {
|
|
configRow := bundle.Config
|
|
categoryByName := make(map[string]model.WheelPoolConfig, len(bundle.Categories))
|
|
for _, row := range bundle.Categories {
|
|
categoryByName[normalizeCategory(row.Category)] = row
|
|
}
|
|
rewardsByCategory := make(map[string][]model.WheelRewardConfig, len(wheelCategories))
|
|
for _, row := range bundle.Rewards {
|
|
category := normalizeCategory(row.Category)
|
|
rewardsByCategory[category] = append(rewardsByCategory[category], row)
|
|
}
|
|
|
|
categories := make([]CategoryConfigPayload, 0, len(wheelCategories))
|
|
for _, meta := range wheelCategories {
|
|
pool, exists := categoryByName[meta.Category]
|
|
if !exists {
|
|
pool = model.WheelPoolConfig{
|
|
Category: meta.Category,
|
|
Enabled: false,
|
|
PriceOneGold: meta.DefaultPriceOneGold,
|
|
PriceTenGold: meta.DefaultPriceTenGold,
|
|
PriceFiftyGold: meta.DefaultPriceFiftyGold,
|
|
Sort: meta.Sort,
|
|
}
|
|
}
|
|
rewards := make([]RewardConfigPayload, 0, len(rewardsByCategory[meta.Category]))
|
|
for _, row := range rewardsByCategory[meta.Category] {
|
|
rewards = append(rewards, rewardPayloadFromConfig(row))
|
|
}
|
|
for len(rewards) < meta.RewardCount {
|
|
rewards = append(rewards, RewardConfigPayload{
|
|
Enabled: true,
|
|
Sort: len(rewards) + 1,
|
|
RewardType: rewardTypeResource,
|
|
Probability: 0,
|
|
ProbabilityPercent: "0.00",
|
|
})
|
|
}
|
|
if len(rewards) > meta.RewardCount {
|
|
rewards = rewards[:meta.RewardCount]
|
|
}
|
|
categories = append(categories, CategoryConfigPayload{
|
|
Category: meta.Category,
|
|
Label: meta.Label,
|
|
Enabled: pool.Enabled,
|
|
RewardCount: meta.RewardCount,
|
|
PriceOneGold: pool.PriceOneGold,
|
|
PriceTenGold: pool.PriceTenGold,
|
|
PriceFiftyGold: pool.PriceFiftyGold,
|
|
ProbabilityTotal: probabilityTotal,
|
|
Rewards: rewards,
|
|
})
|
|
}
|
|
return &ConfigResponse{
|
|
Configured: true,
|
|
ID: configRow.ID,
|
|
SysOrigin: configRow.SysOrigin,
|
|
Enabled: configRow.Enabled,
|
|
Timezone: normalizeTimezone(configRow.Timezone),
|
|
ProbabilityTotal: probabilityTotal,
|
|
Categories: categories,
|
|
UpdateTime: formatDateTime(configRow.UpdateTime),
|
|
}, nil
|
|
}
|
|
|
|
func rewardPayloadFromConfig(row model.WheelRewardConfig) RewardConfigPayload {
|
|
return RewardConfigPayload{
|
|
ID: row.ID,
|
|
Enabled: row.Enabled,
|
|
Sort: row.Sort,
|
|
RewardType: row.RewardType,
|
|
ResourceID: resourceIDValue(row.ResourceID),
|
|
ResourceType: row.ResourceType,
|
|
ResourceName: row.ResourceName,
|
|
ResourceURL: row.ResourceURL,
|
|
CoverURL: row.CoverURL,
|
|
DurationDays: row.DurationDays,
|
|
DisplayGoldAmount: row.DisplayGoldAmount,
|
|
GoldAmount: row.GoldAmount,
|
|
Probability: row.Probability,
|
|
ProbabilityPercent: probabilityPercent(row.Probability),
|
|
}
|
|
}
|