refactor(pack): type PackChildGachaEntry.TypeDetail as CardPackType enum
This commit is contained in:
@@ -125,7 +125,7 @@ public class PackController : SVSimController
|
||||
var today = DateTime.UtcNow.Date;
|
||||
bool ChildAvailable(PackChildGachaEntry c)
|
||||
{
|
||||
if (c.TypeDetail != 10) return true;
|
||||
if (c.TypeDetail != CardPackType.FreePacks) return true;
|
||||
if (c.FreeGachaCampaignId is not int campaignId) return true;
|
||||
if (!freeClaimsByCampaignId.TryGetValue(campaignId, out var claim)) return true;
|
||||
if (claim.LastClaimedAt.Date != today) return true;
|
||||
@@ -137,7 +137,8 @@ public class PackController : SVSimController
|
||||
// Ticket-only pack: every child is TICKET (4) or TICKET_MULTI (5). These are
|
||||
// gifted-currency packs (tutorial starter, throwback) that don't participate in
|
||||
// gacha-point accrual or exchange, even if GachaPointConfig is set in seed.
|
||||
bool isTicketOnly = visibleChildren.All(c => c.TypeDetail == 4 || c.TypeDetail == 5);
|
||||
bool isTicketOnly = visibleChildren.All(c =>
|
||||
c.TypeDetail == CardPackType.Ticket || c.TypeDetail == CardPackType.TicketMulti);
|
||||
|
||||
PackGachaPointDto? gachaPointDto = null;
|
||||
if (p.GachaPointConfig is not null && !isTicketOnly)
|
||||
@@ -174,7 +175,7 @@ public class PackController : SVSimController
|
||||
ChildGachaInfo = visibleChildren.Select(c => new PackChildGachaDto
|
||||
{
|
||||
GachaId = c.GachaId,
|
||||
TypeDetail = c.TypeDetail,
|
||||
TypeDetail = (int)c.TypeDetail,
|
||||
Cost = c.Cost,
|
||||
Count = c.CardCount,
|
||||
ItemId = c.ItemId?.ToString(CultureInfo.InvariantCulture),
|
||||
@@ -298,14 +299,17 @@ public class PackController : SVSimController
|
||||
// when buying a RUPY_MULTI (type_detail=7) child. The gacha_id alone disambiguates the
|
||||
// child; gacha_type validation against child.TypeDetail would falsely reject every buy.
|
||||
|
||||
// Supported type_details on the normal path:
|
||||
// 1 CRYSTAL / 2 CRYSTAL_MULTI -> spend crystals
|
||||
// 6 RUPY / 7 RUPY_MULTI -> spend rupees
|
||||
// 3 DAILY -> spend rupees, once per UTC day
|
||||
// 4 TICKET / 5 TICKET_MULTI -> consume child.ItemId from OwnedItemEntry
|
||||
// Skin-overload types (8/9/13) and free-pack overlays (10/11/12) need extra
|
||||
// selection / banner plumbing — kept 501 until the relevant flows land.
|
||||
if (!isTutorialPath && child.TypeDetail is not (1 or 2 or 3 or 4 or 5 or 6 or 7 or 10))
|
||||
// Supported on the normal path: Crystal / CrystalMulti -> spend crystals; Rupy /
|
||||
// RupyMulti -> spend rupees; Daily -> spend rupees, once per UTC day; Ticket /
|
||||
// TicketMulti -> consume child.ItemId from OwnedItemEntry; FreePacks -> no debit,
|
||||
// gated by per-campaign daily quota.
|
||||
// CrystalSpecial / CrystalSelectSkin / CrystalAcquireSkinCardPack and the
|
||||
// FreePackWithSkin / RotationStarterPack overlays need extra selection / banner
|
||||
// plumbing — kept 501 until the relevant flows land.
|
||||
if (!isTutorialPath && child.TypeDetail is not (
|
||||
CardPackType.Crystal or CardPackType.CrystalMulti or CardPackType.Daily or
|
||||
CardPackType.Ticket or CardPackType.TicketMulti or CardPackType.Rupy or
|
||||
CardPackType.RupyMulti or CardPackType.FreePacks))
|
||||
return StatusCode(StatusCodes.Status501NotImplemented, new { error = "currency_path_not_implemented" });
|
||||
|
||||
// Load viewer via InventoryService transaction with extra includes for pack-open needs.
|
||||
@@ -331,23 +335,23 @@ public class PackController : SVSimController
|
||||
{
|
||||
switch (child.TypeDetail)
|
||||
{
|
||||
case 1: // CRYSTAL (single)
|
||||
case 2: // CRYSTAL_MULTI (10-pack)
|
||||
case CardPackType.Crystal:
|
||||
case CardPackType.CrystalMulti:
|
||||
{
|
||||
long cost = (long)child.Cost * packNumber;
|
||||
var r = await tx.TrySpendAsync(SpendCurrency.Crystal, cost);
|
||||
if (!r.Success) return BadRequest(new { error = "insufficient_crystals" });
|
||||
break;
|
||||
}
|
||||
case 6: // RUPY (single)
|
||||
case 7: // RUPY_MULTI (10-pack)
|
||||
case CardPackType.Rupy:
|
||||
case CardPackType.RupyMulti:
|
||||
{
|
||||
long cost = (long)child.Cost * packNumber;
|
||||
var r = await tx.TrySpendAsync(SpendCurrency.Rupee, cost);
|
||||
if (!r.Success) return BadRequest(new { error = "insufficient_rupees" });
|
||||
break;
|
||||
}
|
||||
case 3: // DAILY single — once per UTC day
|
||||
case CardPackType.Daily:
|
||||
{
|
||||
// TODO(daily-reset): no project-wide daily-reset convention exists yet. Using UTC
|
||||
// midnight; revisit when the global reset boundary is settled.
|
||||
@@ -361,8 +365,8 @@ public class PackController : SVSimController
|
||||
if (!r.Success) return BadRequest(new { error = "insufficient_rupees" });
|
||||
break;
|
||||
}
|
||||
case 4: // TICKET (single)
|
||||
case 5: // TICKET_MULTI (10-pack)
|
||||
case CardPackType.Ticket:
|
||||
case CardPackType.TicketMulti:
|
||||
{
|
||||
if (child.ItemId is not long ticketItemId)
|
||||
return StatusCode(StatusCodes.Status501NotImplemented, new { error = "ticket_pack_missing_item_id" });
|
||||
@@ -372,7 +376,7 @@ public class PackController : SVSimController
|
||||
if (!debit.Success) return BadRequest(new { error = "insufficient_tickets" });
|
||||
break;
|
||||
}
|
||||
case 10: // FREE_PACKS — no currency, no ticket; gated by daily quota per campaign
|
||||
case CardPackType.FreePacks:
|
||||
{
|
||||
if (child.FreeGachaCampaignId is not int campaignId)
|
||||
return StatusCode(StatusCodes.Status501NotImplemented, new { error = "free_pack_missing_campaign_id" });
|
||||
@@ -417,7 +421,7 @@ public class PackController : SVSimController
|
||||
if (!isTutorialPath)
|
||||
{
|
||||
await _packs.IncrementOpenCount(viewerId, pack.Id, packNumber);
|
||||
if (child.TypeDetail == 3)
|
||||
if (child.TypeDetail == CardPackType.Daily)
|
||||
{
|
||||
await _packs.MarkDailyFreeUsed(viewerId, pack.Id, DateTime.UtcNow);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user