feat: discount lucky gift rocket energy

This commit is contained in:
hy001 2026-05-17 00:47:27 +08:00
parent 6d90ddeee0
commit c0d58525fe
2 changed files with 114 additions and 6 deletions

View File

@ -7,12 +7,13 @@ import (
)
type energyRuleConfig struct {
GoldRatio float64 `json:"goldRatio"`
AllowedGiftTypes []string `json:"allowedGiftTypes"`
AllowedGiftTabs []string `json:"allowedGiftTabs"`
BlockedGiftTypes []string `json:"blockedGiftTypes"`
BlockedGiftTabs []string `json:"blockedGiftTabs"`
GiftRules []giftEnergyRule `json:"giftRules"`
GoldRatio float64 `json:"goldRatio"`
AllowedGiftTypes []string `json:"allowedGiftTypes"`
AllowedGiftTabs []string `json:"allowedGiftTabs"`
BlockedGiftTypes []string `json:"blockedGiftTypes"`
BlockedGiftTabs []string `json:"blockedGiftTabs"`
GiftRules []giftEnergyRule `json:"giftRules"`
GiftTabRules []giftTabEnergyRule `json:"giftTabRules"`
}
type giftEnergyRule struct {
@ -25,6 +26,16 @@ type giftEnergyRule struct {
Ratio float64 `json:"ratio"`
}
type giftTabEnergyRule struct {
GiftTab string `json:"giftTab"`
GiftTabs []string `json:"giftTabs"`
Enabled *bool `json:"enabled"`
Allow *bool `json:"allow"`
Energy int64 `json:"energy"`
EnergyPerUnit int64 `json:"energyPerUnit"`
Ratio float64 `json:"ratio"`
}
func resolveGiftEnergy(event giftEvent, snapshot configSnapshot) (int64, string) {
rule, err := parseEnergyRule(snapshot.EnergyRuleJSON)
if err != nil {
@ -40,6 +51,9 @@ func resolveGiftEnergy(event giftEvent, snapshot configSnapshot) (int64, string)
if !isAllowedByGiftTypeAndTab(event, rule) {
return 0, "unsupported_gift"
}
if custom, ok, reason := applyGiftTabRule(event, base, rule); ok || reason != "" {
return custom, reason
}
ratio := rule.GoldRatio
if ratio <= 0 {
ratio = 1
@ -98,6 +112,41 @@ func applyGiftIDRule(event giftEvent, base int64, rule energyRuleConfig) (int64,
return 0, false, ""
}
func applyGiftTabRule(event giftEvent, base int64, rule energyRuleConfig) (int64, bool, string) {
giftTab := normalizeGiftToken(event.GiftConfig.GiftTab)
if giftTab == "" || len(rule.GiftTabRules) == 0 {
return 0, false, ""
}
for _, item := range rule.GiftTabRules {
if !giftTabRuleMatches(item, giftTab) {
continue
}
if item.Enabled != nil && !*item.Enabled {
return 0, true, "gift_tab_rule_disabled"
}
if item.Allow != nil && !*item.Allow {
return 0, true, "gift_tab_rule_blocked"
}
quantity := normalizedGiftQuantity(event)
acceptUserSize := normalizedAcceptUserSize(event)
if item.Energy > 0 {
return item.Energy * quantity * acceptUserSize, true, ""
}
if item.EnergyPerUnit > 0 {
return item.EnergyPerUnit * quantity * acceptUserSize, true, ""
}
if item.Ratio > 0 {
energy := int64(math.Floor(float64(base) * item.Ratio))
if energy <= 0 {
return 0, true, "zero_energy"
}
return energy, true, ""
}
return base, true, ""
}
return 0, false, ""
}
func giftRuleMatches(rule giftEnergyRule, giftID int64) bool {
if rule.GiftID.Int64() == giftID {
return true
@ -110,6 +159,18 @@ func giftRuleMatches(rule giftEnergyRule, giftID int64) bool {
return false
}
func giftTabRuleMatches(rule giftTabEnergyRule, giftTab string) bool {
if normalizeGiftToken(rule.GiftTab) == giftTab {
return true
}
for _, tab := range rule.GiftTabs {
if normalizeGiftToken(tab) == giftTab {
return true
}
}
return false
}
func isAllowedByGiftTypeAndTab(event giftEvent, rule energyRuleConfig) bool {
giftType := normalizeGiftToken(event.GiftConfig.Type)
giftTab := normalizeGiftToken(event.GiftConfig.GiftTab)

View File

@ -263,6 +263,53 @@ func TestGiftEnergyRulesRejectUnsupportedAndAllowConfiguredGift(t *testing.T) {
}
}
func TestGiftTabEnergyRuleDiscountsLuckyGiftOnly(t *testing.T) {
service, db := newTestService(t)
ctx := context.Background()
seedRocketConfig(t, db)
seedLevelConfigs(t, db, []int64{1000, 2000, 3000, 4000, 5000, 6000})
if err := db.Model(&model.VoiceRoomRocketConfig{}).
Where("sys_origin = ?", "LIKEI").
Update("energy_rule_json", `{"giftTabRules":[{"giftTab":"LUCKY_GIFT","ratio":0.1}]}`).Error; err != nil {
t.Fatalf("update energy rule: %v", err)
}
luckyPayload := `{
"trackId":"track-lucky-ratio",
"sysOrigin":"LIKEI",
"sendUserId":"1001",
"roomId":"9001",
"quantity":1,
"giftConfig":{"id":"11","giftCandy":100,"type":"GOLD","giftTab":"LUCKY_GIFT"},
"createTime":` + strconvFormatMillis(time.Now()) + `
}`
lucky, err := service.ProcessGiftPayload(ctx, luckyPayload)
if err != nil {
t.Fatalf("ProcessGiftPayload(lucky) error = %v", err)
}
if !lucky.Processed || lucky.AcceptedEnergy != 10 {
t.Fatalf("lucky = %+v, want 10 energy", lucky)
}
ordinaryPayload := `{
"trackId":"track-ordinary-ratio",
"sysOrigin":"LIKEI",
"sendUserId":"1001",
"roomId":"9001",
"quantity":1,
"giftConfig":{"id":"12","giftCandy":100,"type":"GOLD","giftTab":"ORDINARY"},
"createTime":` + strconvFormatMillis(time.Now().Add(time.Second)) + `
}`
ordinary, err := service.ProcessGiftPayload(ctx, ordinaryPayload)
if err != nil {
t.Fatalf("ProcessGiftPayload(ordinary) error = %v", err)
}
if !ordinary.Processed || ordinary.AcceptedEnergy != 100 {
t.Fatalf("ordinary = %+v, want 100 energy", ordinary)
}
}
func TestInRoomRewardWorkerSnapshotsSelectsAndGrants(t *testing.T) {
gateway := newFakeRocketGateway()
service, db, rdb, mr := newTestServiceWithRedis(t, gateway)