From 366a71688d455905d5c3c32626f0fb3389fe598a Mon Sep 17 00:00:00 2001 From: gamer147 Date: Tue, 9 Jun 2026 20:39:10 -0400 Subject: [PATCH] feat(gift): add GiftRewardTypes supported-set helper Centralizes which UserGoodsType values IInventoryTransaction.GrantAsync can handle in the gift-inbox flow; both GiftController (post-fix) and CampaignController will consult this instead of duplicating the set. Co-Authored-By: Claude Sonnet 4.6 --- .../Services/GiftRewardTypes.cs | 42 ++++++++++++++++++ .../Services/GiftRewardTypesTests.cs | 43 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 SVSim.EmulatedEntrypoint/Services/GiftRewardTypes.cs create mode 100644 SVSim.UnitTests/Services/GiftRewardTypesTests.cs diff --git a/SVSim.EmulatedEntrypoint/Services/GiftRewardTypes.cs b/SVSim.EmulatedEntrypoint/Services/GiftRewardTypes.cs new file mode 100644 index 0000000..3e6099d --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Services/GiftRewardTypes.cs @@ -0,0 +1,42 @@ +using SVSim.Database.Enums; + +namespace SVSim.EmulatedEntrypoint.Services; + +/// +/// The subset of that IInventoryTransaction.GrantAsync +/// can grant via the gift-inbox claim flow. Producers (serial codes, future event mailers) +/// validate against this before creating ViewerPresent rows so unsupported types +/// fail at production time rather than at the player's claim. +/// +/// +/// Excluded from gift grants: +/// +/// SpotCard, SpotCardOnlyLatestCardPack — InventoryTransaction throws NotSupportedException. +/// FreeGachaCount — InventoryTransaction has no grant case (default arm throws NotImplementedException). +/// +/// +public static class GiftRewardTypes +{ + public static bool IsSupported(UserGoodsType type) => type switch + { + UserGoodsType.Crystal => true, + UserGoodsType.Rupy => true, + UserGoodsType.RedEther => true, + UserGoodsType.SpotCardPoint => true, + UserGoodsType.Item => true, + UserGoodsType.Card => true, + UserGoodsType.Sleeve => true, + UserGoodsType.Emblem => true, + UserGoodsType.Degree => true, + UserGoodsType.Skin => true, + UserGoodsType.MyPageBG => true, + UserGoodsType.SpotCard => false, + UserGoodsType.SpotCardOnlyLatestCardPack => false, + UserGoodsType.FreeGachaCount => false, + _ => false, + }; + + public static bool IsSupported(int wireType) => + Enum.IsDefined(typeof(UserGoodsType), wireType) && + IsSupported((UserGoodsType)wireType); +} diff --git a/SVSim.UnitTests/Services/GiftRewardTypesTests.cs b/SVSim.UnitTests/Services/GiftRewardTypesTests.cs new file mode 100644 index 0000000..5524a1f --- /dev/null +++ b/SVSim.UnitTests/Services/GiftRewardTypesTests.cs @@ -0,0 +1,43 @@ +using SVSim.Database.Enums; +using SVSim.EmulatedEntrypoint.Services; + +namespace SVSim.UnitTests.Services; + +public class GiftRewardTypesTests +{ + [TestCase(UserGoodsType.Crystal)] + [TestCase(UserGoodsType.Rupy)] + [TestCase(UserGoodsType.RedEther)] + [TestCase(UserGoodsType.SpotCardPoint)] + [TestCase(UserGoodsType.Item)] + [TestCase(UserGoodsType.Card)] + [TestCase(UserGoodsType.Sleeve)] + [TestCase(UserGoodsType.Emblem)] + [TestCase(UserGoodsType.Degree)] + [TestCase(UserGoodsType.Skin)] + [TestCase(UserGoodsType.MyPageBG)] + public void IsSupported_returns_true_for_inventory_service_grant_set(UserGoodsType type) + { + Assert.That(GiftRewardTypes.IsSupported(type), Is.True); + } + + [TestCase(UserGoodsType.SpotCard)] + [TestCase(UserGoodsType.SpotCardOnlyLatestCardPack)] + [TestCase(UserGoodsType.FreeGachaCount)] + public void IsSupported_returns_false_for_inventory_service_unsupported_types(UserGoodsType type) + { + Assert.That(GiftRewardTypes.IsSupported(type), Is.False); + } + + [TestCase(1, ExpectedResult = true)] // RedEther + [TestCase(2, ExpectedResult = true)] // Crystal + [TestCase(3, ExpectedResult = false)] // gap in UserGoodsType enum + [TestCase(4, ExpectedResult = true)] // Item + [TestCase(11, ExpectedResult = false)] // SpotCard + [TestCase(14, ExpectedResult = false)] // FreeGachaCount + [TestCase(15, ExpectedResult = true)] // MyPageBG + [TestCase(99, ExpectedResult = false)] // out of range + [TestCase(-1, ExpectedResult = false)] // negative + public bool IsSupported_int_overload_validates_enum_definition(int wireType) => + GiftRewardTypes.IsSupported(wireType); +}