fix: sync collectible upgrade preview pools
This commit is contained in:
parent
eba402946a
commit
de233a4c18
16 changed files with 552 additions and 136 deletions
|
|
@ -3,6 +3,7 @@ package domain
|
|||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -139,6 +140,7 @@ func (k StarGiftAttributeRarityKind) Valid() bool {
|
|||
|
||||
// StarGiftCollectibleAttribute 是已发布属性池的一项。RarityKind/RarityPermille
|
||||
// 是客户端展示事实;普通升级把非 crafted 的 permille 值当相对权重,不要求合计为 1000。
|
||||
// 每类仍必须提供至少两个客户端可区分的普通升级属性,否则 TDesktop 的升级滚动无法结束。
|
||||
type StarGiftCollectibleAttribute struct {
|
||||
ID int64
|
||||
CollectibleRevisionID int64
|
||||
|
|
@ -935,7 +937,10 @@ func ValidateStarGiftCollectibleDraft(write StarGiftCollectibleWrite) error {
|
|||
if err := validateStarGiftAttributes(write.Patterns, StarGiftCollectiblePattern, false); err != nil {
|
||||
return err
|
||||
}
|
||||
return validateStarGiftAttributes(write.Backdrops, StarGiftCollectibleBackdrop, false)
|
||||
if err := validateStarGiftAttributes(write.Backdrops, StarGiftCollectibleBackdrop, false); err != nil {
|
||||
return err
|
||||
}
|
||||
return validateStarGiftUpgradePreviewPool(write, false)
|
||||
}
|
||||
|
||||
// ValidateStarGiftCollectibleWrite validates a complete publish command. Published pools are
|
||||
|
|
@ -950,7 +955,62 @@ func ValidateStarGiftCollectibleWrite(write StarGiftCollectibleWrite) error {
|
|||
if err := validateStarGiftAttributes(write.Patterns, StarGiftCollectiblePattern, true); err != nil {
|
||||
return err
|
||||
}
|
||||
return validateStarGiftAttributes(write.Backdrops, StarGiftCollectibleBackdrop, true)
|
||||
if err := validateStarGiftAttributes(write.Backdrops, StarGiftCollectibleBackdrop, true); err != nil {
|
||||
return err
|
||||
}
|
||||
return validateStarGiftUpgradePreviewPool(write, true)
|
||||
}
|
||||
|
||||
// validateStarGiftUpgradePreviewPool protects the official-client animation contract. The
|
||||
// preview response includes the target attribute plus the published selectable pool; TDesktop
|
||||
// deduplicates models and patterns by document identity and needs a non-target item in every
|
||||
// category before its spinner can transition to the finished state.
|
||||
func validateStarGiftUpgradePreviewPool(write StarGiftCollectibleWrite, requireStoredAsset bool) error {
|
||||
validateAnimated := func(kind StarGiftCollectibleAttributeKind, attributes []StarGiftCollectibleAttribute) error {
|
||||
selectable := 0
|
||||
documents := make(map[int64]struct{}, len(attributes))
|
||||
for _, attribute := range attributes {
|
||||
if attribute.RarityKind != StarGiftRarityPermille || attribute.Crafted {
|
||||
continue
|
||||
}
|
||||
selectable++
|
||||
if requireStoredAsset {
|
||||
if attribute.Document == nil {
|
||||
return fmt.Errorf("%w: %s preview attribute has no document", ErrStarGiftCollectibleInvalid, kind)
|
||||
}
|
||||
documents[attribute.Document.ID] = struct{}{}
|
||||
}
|
||||
}
|
||||
if selectable < 2 {
|
||||
return fmt.Errorf("%w: %s preview requires at least two selectable attributes", ErrStarGiftCollectibleInvalid, kind)
|
||||
}
|
||||
if requireStoredAsset && len(documents) < 2 {
|
||||
return fmt.Errorf("%w: %s preview requires at least two distinct documents", ErrStarGiftCollectibleInvalid, kind)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := validateAnimated(StarGiftCollectibleModel, write.Models); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateAnimated(StarGiftCollectiblePattern, write.Patterns); err != nil {
|
||||
return err
|
||||
}
|
||||
seenBackdropIDs := make(map[int]struct{}, len(write.Backdrops))
|
||||
selectableBackdrops := 0
|
||||
for _, attribute := range write.Backdrops {
|
||||
if attribute.RarityKind != StarGiftRarityPermille || attribute.Crafted {
|
||||
continue
|
||||
}
|
||||
selectableBackdrops++
|
||||
if _, exists := seenBackdropIDs[attribute.BackdropID]; exists {
|
||||
return fmt.Errorf("%w: duplicate backdrop_id %d", ErrStarGiftCollectibleInvalid, attribute.BackdropID)
|
||||
}
|
||||
seenBackdropIDs[attribute.BackdropID] = struct{}{}
|
||||
}
|
||||
if selectableBackdrops < 2 {
|
||||
return fmt.Errorf("%w: backdrop preview requires at least two selectable attributes", ErrStarGiftCollectibleInvalid)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateStarGiftAttributes(attributes []StarGiftCollectibleAttribute, kind StarGiftCollectibleAttributeKind, requireStoredAsset bool) error {
|
||||
|
|
|
|||
|
|
@ -48,13 +48,16 @@ func validCollectibleDraft() StarGiftCollectibleWrite {
|
|||
GiftID: 1, UpgradeStars: 25, SupplyTotal: 100, SlugPrefix: "official-1", CommandID: "test",
|
||||
Models: []StarGiftCollectibleAttribute{
|
||||
{Kind: StarGiftCollectibleModel, Name: "Regular", RarityKind: StarGiftRarityPermille, RarityPermille: 922, Animation: animation},
|
||||
{Kind: StarGiftCollectibleModel, Name: "Regular Two", RarityKind: StarGiftRarityPermille, RarityPermille: 78, Animation: animation},
|
||||
{Kind: StarGiftCollectibleModel, Name: "Crafted", RarityKind: StarGiftRarityLegendary, Crafted: true, Animation: animation},
|
||||
},
|
||||
Patterns: []StarGiftCollectibleAttribute{
|
||||
{Kind: StarGiftCollectiblePattern, Name: "Pattern", RarityKind: StarGiftRarityPermille, RarityPermille: 989, Animation: animation},
|
||||
{Kind: StarGiftCollectiblePattern, Name: "Pattern Two", RarityKind: StarGiftRarityPermille, RarityPermille: 11, Animation: animation},
|
||||
},
|
||||
Backdrops: []StarGiftCollectibleAttribute{
|
||||
{Kind: StarGiftCollectibleBackdrop, Name: "Backdrop", BackdropID: 0, RarityKind: StarGiftRarityPermille, RarityPermille: 999},
|
||||
{Kind: StarGiftCollectibleBackdrop, Name: "Backdrop Two", BackdropID: 1, RarityKind: StarGiftRarityPermille, RarityPermille: 1},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -103,15 +106,59 @@ func storedCollectibleWrite() StarGiftCollectibleWrite {
|
|||
}
|
||||
write.Models[i].Blob = &FileBlob{LocationKey: "model"}
|
||||
}
|
||||
write.Patterns[0].Document = &Document{
|
||||
ID: 200, MimeType: "application/x-tgsticker",
|
||||
Attributes: []DocumentAttribute{{Kind: DocAttrCustomEmoji, Alt: "🎁", TextColor: true}},
|
||||
Thumbs: []PhotoSize{{Kind: PhotoSizeKindPath, Type: "j", Bytes: []byte{1}}},
|
||||
for i := range write.Patterns {
|
||||
write.Patterns[i].Document = &Document{
|
||||
ID: int64(200 + i), MimeType: "application/x-tgsticker",
|
||||
Attributes: []DocumentAttribute{{Kind: DocAttrCustomEmoji, Alt: "🎁", TextColor: true}},
|
||||
Thumbs: []PhotoSize{{Kind: PhotoSizeKindPath, Type: "j", Bytes: []byte{1}}},
|
||||
}
|
||||
write.Patterns[i].Blob = &FileBlob{LocationKey: "pattern"}
|
||||
}
|
||||
write.Patterns[0].Blob = &FileBlob{LocationKey: "pattern"}
|
||||
return write
|
||||
}
|
||||
|
||||
func TestValidateStarGiftCollectibleDraftRequiresClientSafePreviewPool(t *testing.T) {
|
||||
tests := map[string]func(*StarGiftCollectibleWrite){
|
||||
"one selectable model": func(write *StarGiftCollectibleWrite) {
|
||||
write.Models = append(write.Models[:1], write.Models[2:]...)
|
||||
},
|
||||
"one selectable pattern": func(write *StarGiftCollectibleWrite) {
|
||||
write.Patterns = write.Patterns[:1]
|
||||
},
|
||||
"one selectable backdrop": func(write *StarGiftCollectibleWrite) {
|
||||
write.Backdrops = write.Backdrops[:1]
|
||||
},
|
||||
"duplicate backdrop id": func(write *StarGiftCollectibleWrite) {
|
||||
write.Backdrops[1].BackdropID = write.Backdrops[0].BackdropID
|
||||
},
|
||||
}
|
||||
for name, mutate := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
write := validCollectibleDraft()
|
||||
mutate(&write)
|
||||
if err := ValidateStarGiftCollectibleDraft(write); !errors.Is(err, ErrStarGiftCollectibleInvalid) {
|
||||
t.Fatalf("err=%v, want ErrStarGiftCollectibleInvalid", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateStarGiftCollectibleWriteRequiresDistinctPreviewDocuments(t *testing.T) {
|
||||
for _, kind := range []StarGiftCollectibleAttributeKind{StarGiftCollectibleModel, StarGiftCollectiblePattern} {
|
||||
t.Run(string(kind), func(t *testing.T) {
|
||||
write := storedCollectibleWrite()
|
||||
if kind == StarGiftCollectibleModel {
|
||||
write.Models[1].Document = write.Models[0].Document
|
||||
} else {
|
||||
write.Patterns[1].Document = write.Patterns[0].Document
|
||||
}
|
||||
if err := ValidateStarGiftCollectibleWrite(write); !errors.Is(err, ErrStarGiftCollectibleInvalid) {
|
||||
t.Fatalf("err=%v, want ErrStarGiftCollectibleInvalid", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateStarGiftCollectibleWriteRequiresExactDocumentRoles(t *testing.T) {
|
||||
if err := ValidateStarGiftCollectibleWrite(storedCollectibleWrite()); err != nil {
|
||||
t.Fatalf("valid stored collectible: %v", err)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue