feat(pack): gacha-point accrual with per-child override
This commit is contained in:
@@ -123,7 +123,31 @@ public sealed class GachaPointService : IGachaPointService
|
|||||||
private static bool IsLeaderCard(CardCosmeticReward? skin) => skin is not null;
|
private static bool IsLeaderCard(CardCosmeticReward? skin) => skin is not null;
|
||||||
|
|
||||||
public void Accrue(Viewer viewer, PackConfigEntry pack, PackChildGachaEntry child, int packNumber)
|
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)
|
public Task<ExchangeOutcome> TryExchangeAsync(Viewer viewer, int packId, long cardId)
|
||||||
=> throw new NotImplementedException();
|
=> throw new NotImplementedException();
|
||||||
|
|||||||
@@ -183,4 +183,104 @@ public class GachaPointServiceTests
|
|||||||
Assert.That(result, Has.Count.EqualTo(1));
|
Assert.That(result, Has.Count.EqualTo(1));
|
||||||
Assert.That(result[0].IsReceived, Is.True);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user