feat(packs): wire PackDrawTableImporter; retire ICardPoolProvider
Bootstrap Program.cs now calls PackDrawTableImporter after PackImporter. Delete DbCardPoolProvider, ICardPoolProvider, and the DbCardPoolProvider tests — the new IPackDrawTableRepository covers what GachaPointService needed (legendary-tier card_ids per pack) and PackOpenService takes the draw table directly. GachaPointService now resolves the legendary catalog from PackDrawTable.CardWeights filtered by Tier==Legendary, instead of ICardPoolProvider.GetPool then a rarity filter. Same end set, no DB pool walk. Test fallout: tests that fabricate custom card sets for gacha-point tests now call factory.SeedPackDrawTableFromSetAsync(packId, setId) to install a matching legendary-tier stub. Full suite: 647/647 green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,61 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SVSim.Database;
|
||||
using SVSim.Database.Enums;
|
||||
using SVSim.Database.Models;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Services;
|
||||
|
||||
public class DbCardPoolProvider : ICardPoolProvider
|
||||
{
|
||||
private readonly SVSimDbContext _db;
|
||||
public DbCardPoolProvider(SVSimDbContext db) { _db = db; }
|
||||
|
||||
public IReadOnlyList<ShadowverseCardEntry> GetPool(PackConfigEntry pack)
|
||||
{
|
||||
switch (pack.PackCategory)
|
||||
{
|
||||
case PackCategory.None:
|
||||
case PackCategory.LegendCardPack:
|
||||
{
|
||||
var pool = _db.CardSets
|
||||
.Where(s => s.Id == pack.BasePackId)
|
||||
.SelectMany(s => s.Cards)
|
||||
.Where(c => !c.IsFoil)
|
||||
.ToList();
|
||||
if (pool.Count > 0) return pool;
|
||||
|
||||
// BasePackId 90001 (and the 9xxxx range generally) is a synthetic "Throwback
|
||||
// Rotation" category that doesn't have a corresponding real card_set in the
|
||||
// prod card master — its real pool is a curated subset of rotation-eligible
|
||||
// older sets (Altersphere–Colosseum for 99047; see the gacha_detail string).
|
||||
// We don't have that membership map, so fall back to all in-rotation cards.
|
||||
// Broader pool than prod but produces a valid 8-card draw, which is what the
|
||||
// tutorial flow needs to advance to step 100.
|
||||
// TODO: import the real Throwback Rotation card-set membership and key the
|
||||
// pool off that. Source data is in the client's pack-pool master, not yet
|
||||
// captured.
|
||||
return _db.CardSets
|
||||
.Where(s => s.IsInRotation)
|
||||
.SelectMany(s => s.Cards)
|
||||
.Where(c => !c.IsFoil)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
}
|
||||
|
||||
case PackCategory.SpecialCardPack:
|
||||
case PackCategory.LimitedSpecialCardPack:
|
||||
return _db.CardSets
|
||||
.Where(s => s.IsInRotation)
|
||||
.SelectMany(s => s.Cards)
|
||||
.Where(c => !c.IsFoil)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
default:
|
||||
return Array.Empty<ShadowverseCardEntry>();
|
||||
}
|
||||
}
|
||||
|
||||
public ShadowverseCardEntry? TryGetFoilTwin(long baseCardId) =>
|
||||
_db.Cards.FirstOrDefault(c => c.Id == baseCardId + 1 && c.IsFoil);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
using SVSim.Database;
|
||||
using SVSim.Database.Enums;
|
||||
using SVSim.Database.Models;
|
||||
using SVSim.Database.Repositories.PackDrawTables;
|
||||
using SVSim.Database.Services;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos;
|
||||
|
||||
@@ -11,13 +12,13 @@ namespace SVSim.EmulatedEntrypoint.Services;
|
||||
public sealed class GachaPointService : IGachaPointService
|
||||
{
|
||||
private readonly SVSimDbContext _db;
|
||||
private readonly ICardPoolProvider _pools;
|
||||
private readonly IPackDrawTableRepository _drawTables;
|
||||
private readonly RewardGrantService _grants;
|
||||
|
||||
public GachaPointService(SVSimDbContext db, ICardPoolProvider pools, RewardGrantService grants)
|
||||
public GachaPointService(SVSimDbContext db, IPackDrawTableRepository drawTables, RewardGrantService grants)
|
||||
{
|
||||
_db = db;
|
||||
_pools = pools;
|
||||
_drawTables = drawTables;
|
||||
_grants = grants;
|
||||
}
|
||||
|
||||
@@ -26,7 +27,8 @@ public sealed class GachaPointService : IGachaPointService
|
||||
var pack = await _db.Packs.FirstOrDefaultAsync(p => p.Id == packId);
|
||||
if (pack?.GachaPointConfig is null) return Array.Empty<GachaPointRewardDto>();
|
||||
|
||||
var pool = _pools.GetPool(pack);
|
||||
var drawTable = await _drawTables.GetAsync(packId);
|
||||
if (drawTable is null) return Array.Empty<GachaPointRewardDto>();
|
||||
|
||||
// EF Core 8 has no ToHashSetAsync on IQueryable — materialize via ToListAsync then hash.
|
||||
var receivedCardIds = (await _db.Viewers
|
||||
@@ -36,9 +38,11 @@ public sealed class GachaPointService : IGachaPointService
|
||||
.Select(r => r.CardId)
|
||||
.ToListAsync()).ToHashSet();
|
||||
|
||||
var legendaryCardIds = pool
|
||||
.Where(c => c.Rarity == Rarity.Legendary && !c.IsFoil)
|
||||
.Select(c => c.Id)
|
||||
// Legendaries in the pack's draw table — exchange ignores foils (the alt-art foil
|
||||
// printing is gated separately) and tiers other than Legendary.
|
||||
var legendaryCardIds = drawTable.CardWeights
|
||||
.Where(w => w.Tier == DrawTier.Legendary && !w.IsAltArt)
|
||||
.Select(w => w.CardId)
|
||||
.ToHashSet();
|
||||
|
||||
// Re-query legendaries with Class loaded — pool provider doesn't include navs,
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
using SVSim.Database.Models;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Services;
|
||||
|
||||
/// <summary>Resolves the card pool a pack draws from. Pure function over master data.</summary>
|
||||
public interface ICardPoolProvider
|
||||
{
|
||||
IReadOnlyList<ShadowverseCardEntry> GetPool(PackConfigEntry pack);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the foil twin of <paramref name="baseCardId"/> if it exists in master data
|
||||
/// (foil card_id = base card_id + 1 by the cards.json convention), else null. One DB
|
||||
/// hit per call; expected ~0.64 calls per 8-card pack at the default 8% rate.
|
||||
/// TODO(caching): folds into the broader caching wave once one exists.
|
||||
/// </summary>
|
||||
ShadowverseCardEntry? TryGetFoilTwin(long baseCardId);
|
||||
}
|
||||
Reference in New Issue
Block a user