52 lines
2.0 KiB
C#
52 lines
2.0 KiB
C#
using SVSim.Database.Models;
|
|
|
|
namespace SVSim.Database.Services;
|
|
|
|
public class CurrencySpendService : ICurrencySpendService
|
|
{
|
|
private readonly IViewerEntitlements _entitlements;
|
|
|
|
public CurrencySpendService(IViewerEntitlements entitlements) => _entitlements = entitlements;
|
|
|
|
public Task<SpendResult> TrySpendAsync(Viewer viewer, SpendCurrency currency, long cost, CancellationToken ct = default)
|
|
{
|
|
if (cost < 0) cost = 0;
|
|
|
|
// Freeplay bypass applies only to the three main currencies; SpotPoint always real.
|
|
if (_entitlements.IsFreeplay && currency != SpendCurrency.SpotPoint)
|
|
{
|
|
return Task.FromResult(new SpendResult(
|
|
SpendOutcome.Success, _entitlements.EffectiveBalance(viewer, currency)));
|
|
}
|
|
|
|
ulong current = GetBalance(viewer, currency);
|
|
if (current < (ulong)cost)
|
|
return Task.FromResult(new SpendResult(SpendOutcome.Insufficient, (long)current));
|
|
|
|
ulong post = current - (ulong)cost;
|
|
SetBalance(viewer, currency, post);
|
|
return Task.FromResult(new SpendResult(SpendOutcome.Success, (long)post));
|
|
}
|
|
|
|
private static ulong GetBalance(Viewer v, SpendCurrency c) => c switch
|
|
{
|
|
SpendCurrency.Crystal => v.Currency.Crystals,
|
|
SpendCurrency.Rupee => v.Currency.Rupees,
|
|
SpendCurrency.RedEther => v.Currency.RedEther,
|
|
SpendCurrency.SpotPoint => v.Currency.SpotPoints,
|
|
_ => throw new ArgumentOutOfRangeException(nameof(c)),
|
|
};
|
|
|
|
private static void SetBalance(Viewer v, SpendCurrency c, ulong value)
|
|
{
|
|
switch (c)
|
|
{
|
|
case SpendCurrency.Crystal: v.Currency.Crystals = value; break;
|
|
case SpendCurrency.Rupee: v.Currency.Rupees = value; break;
|
|
case SpendCurrency.RedEther: v.Currency.RedEther = value; break;
|
|
case SpendCurrency.SpotPoint: v.Currency.SpotPoints = value; break;
|
|
default: throw new ArgumentOutOfRangeException(nameof(c));
|
|
}
|
|
}
|
|
}
|