diff --git a/SVSim.EmulatedEntrypoint/Services/GachaPointService.cs b/SVSim.EmulatedEntrypoint/Services/GachaPointService.cs index c273b93..a4717fd 100644 --- a/SVSim.EmulatedEntrypoint/Services/GachaPointService.cs +++ b/SVSim.EmulatedEntrypoint/Services/GachaPointService.cs @@ -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 TryExchangeAsync(Viewer viewer, int packId, long cardId) => throw new NotImplementedException(); diff --git a/SVSim.UnitTests/Services/GachaPointServiceTests.cs b/SVSim.UnitTests/Services/GachaPointServiceTests.cs index 0086db5..209b485 100644 --- a/SVSim.UnitTests/Services/GachaPointServiceTests.cs +++ b/SVSim.UnitTests/Services/GachaPointServiceTests.cs @@ -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(); + + 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(); + 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(); + + 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(); + 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(); + + 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(); + svc.Accrue(viewer, pack, pack.ChildGachas[0], packNumber: 5); + await db.SaveChangesAsync(); + + Assert.That(viewer.GachaPointBalances, Is.Empty); + } }