feat(pack): gacha-point accrual with per-child override

This commit is contained in:
gamer147
2026-05-28 23:23:33 -04:00
parent e41ceff0be
commit 723a97e3af
2 changed files with 125 additions and 1 deletions

View File

@@ -123,7 +123,31 @@ public sealed class GachaPointService : IGachaPointService
private static bool IsLeaderCard(CardCosmeticReward? skin) => skin is not null;
public void Accrue(Viewer viewer, PackConfigEntry pack, PackChildGachaEntry child, int packNumber)
=> throw new NotImplementedException();
{
if (pack.GachaPointConfig is null) return;
if (packNumber <= 0) return;
// Per-child override wins when set (>0); fall back to the pack's default.
int perPack = child.OverrideIncreaseGachaPoint > 0
? child.OverrideIncreaseGachaPoint
: pack.GachaPointConfig.IncreaseGachaPoint;
if (perPack <= 0) return;
int delta = perPack * packNumber;
var existing = viewer.GachaPointBalances.FirstOrDefault(b => b.PackId == pack.Id);
if (existing is null)
{
viewer.GachaPointBalances.Add(new ViewerGachaPointBalance
{
PackId = pack.Id, Points = delta,
});
}
else
{
existing.Points += delta;
}
}
public Task<ExchangeOutcome> TryExchangeAsync(Viewer viewer, int packId, long cardId)
=> throw new NotImplementedException();

View File

@@ -183,4 +183,104 @@ public class GachaPointServiceTests
Assert.That(result, Has.Count.EqualTo(1));
Assert.That(result[0].IsReceived, Is.True);
}
[Test]
public async Task Accrue_uses_pack_increase_when_child_override_is_zero()
{
using var factory = new SVSimTestFactory();
long viewerId = await factory.SeedViewerAsync();
using var scope = factory.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SVSimDbContext>();
db.Packs.Add(new PackConfigEntry
{
Id = 10008, BasePackId = 10008, PackCategory = PackCategory.LegendCardPack,
CommenceDate = DateTime.UtcNow.AddDays(-1), CompleteDate = DateTime.UtcNow.AddDays(30),
GachaPointConfig = new PackGachaPointConfig { ExchangeablePoint = 400, IncreaseGachaPoint = 1 },
ChildGachas =
{
new PackChildGachaEntry
{
GachaId = 100081, TypeDetail = 2, Cost = 100, CardCount = 8,
OverrideIncreaseGachaPoint = 0,
},
},
});
await db.SaveChangesAsync();
var viewer = await db.Viewers
.Include(v => v.GachaPointBalances)
.FirstAsync(v => v.Id == viewerId);
var pack = await db.Packs.Include(p => p.ChildGachas).FirstAsync(p => p.Id == 10008);
var child = pack.ChildGachas[0];
var svc = scope.ServiceProvider.GetRequiredService<IGachaPointService>();
svc.Accrue(viewer, pack, child, packNumber: 10);
await db.SaveChangesAsync();
var balance = viewer.GachaPointBalances.Single(b => b.PackId == 10008);
Assert.That(balance.Points, Is.EqualTo(10));
}
[Test]
public async Task Accrue_child_override_takes_precedence_over_pack_increase()
{
using var factory = new SVSimTestFactory();
long viewerId = await factory.SeedViewerAsync();
using var scope = factory.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SVSimDbContext>();
db.Packs.Add(new PackConfigEntry
{
Id = 10008, BasePackId = 10008, PackCategory = PackCategory.LegendCardPack,
CommenceDate = DateTime.UtcNow.AddDays(-1), CompleteDate = DateTime.UtcNow.AddDays(30),
GachaPointConfig = new PackGachaPointConfig { ExchangeablePoint = 400, IncreaseGachaPoint = 1 },
ChildGachas =
{
new PackChildGachaEntry
{
GachaId = 100085, TypeDetail = 5, Cost = 0, CardCount = 8,
OverrideIncreaseGachaPoint = 3,
},
},
});
await db.SaveChangesAsync();
var viewer = await db.Viewers.Include(v => v.GachaPointBalances).FirstAsync(v => v.Id == viewerId);
var pack = await db.Packs.Include(p => p.ChildGachas).FirstAsync(p => p.Id == 10008);
var child = pack.ChildGachas[0];
var svc = scope.ServiceProvider.GetRequiredService<IGachaPointService>();
svc.Accrue(viewer, pack, child, packNumber: 2);
await db.SaveChangesAsync();
Assert.That(viewer.GachaPointBalances.Single().Points, Is.EqualTo(6));
}
[Test]
public async Task Accrue_is_noop_when_pack_has_no_gacha_point_config()
{
using var factory = new SVSimTestFactory();
long viewerId = await factory.SeedViewerAsync();
using var scope = factory.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SVSimDbContext>();
db.Packs.Add(new PackConfigEntry
{
Id = 99047, BasePackId = 99047, PackCategory = PackCategory.LegendCardPack,
CommenceDate = DateTime.UtcNow.AddDays(-1), CompleteDate = DateTime.UtcNow.AddDays(30),
GachaPointConfig = null,
ChildGachas = { new PackChildGachaEntry { GachaId = 990475, TypeDetail = 5, Cost = 0, CardCount = 8 } },
});
await db.SaveChangesAsync();
var viewer = await db.Viewers.Include(v => v.GachaPointBalances).FirstAsync(v => v.Id == viewerId);
var pack = await db.Packs.Include(p => p.ChildGachas).FirstAsync(p => p.Id == 99047);
var svc = scope.ServiceProvider.GetRequiredService<IGachaPointService>();
svc.Accrue(viewer, pack, pack.ChildGachas[0], packNumber: 5);
await db.SaveChangesAsync();
Assert.That(viewer.GachaPointBalances, Is.Empty);
}
}