80 lines
2.8 KiB
C#
80 lines
2.8 KiB
C#
using DysonNetwork.Shared.Cache;
|
|
using DysonNetwork.Shared.Models;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using NodaTime;
|
|
|
|
namespace DysonNetwork.Pass.Credit;
|
|
|
|
public class SocialCreditService(AppDatabase db, ICacheService cache)
|
|
{
|
|
private const string CacheKeyPrefix = "account:credits:";
|
|
|
|
public async Task<SnSocialCreditRecord> AddRecord(
|
|
string reasonType,
|
|
string reason,
|
|
double delta,
|
|
Guid accountId,
|
|
Instant? expiredAt
|
|
)
|
|
{
|
|
var record = new SnSocialCreditRecord
|
|
{
|
|
ReasonType = reasonType,
|
|
Reason = reason,
|
|
Delta = delta,
|
|
AccountId = accountId,
|
|
ExpiredAt = expiredAt
|
|
};
|
|
db.SocialCreditRecords.Add(record);
|
|
await db.SaveChangesAsync();
|
|
|
|
await db.AccountProfiles
|
|
.Where(p => p.AccountId == accountId)
|
|
.ExecuteUpdateAsync(p => p.SetProperty(v => v.SocialCredits, v => v.SocialCredits + record.Delta));
|
|
|
|
await cache.RemoveAsync($"{CacheKeyPrefix}{accountId}");
|
|
|
|
return record;
|
|
}
|
|
|
|
private const double BaseSocialCredit = 100;
|
|
|
|
public async Task<double> GetSocialCredit(Guid accountId)
|
|
{
|
|
var cached = await cache.GetAsync<double?>($"{CacheKeyPrefix}{accountId}");
|
|
if (cached.HasValue) return cached.Value;
|
|
|
|
var records = await db.SocialCreditRecords
|
|
.Where(x => x.AccountId == accountId && x.Status == SocialCreditRecordStatus.Active)
|
|
.SumAsync(x => x.Delta);
|
|
records += BaseSocialCredit;
|
|
|
|
await cache.SetAsync($"{CacheKeyPrefix}{accountId}", records);
|
|
return records;
|
|
}
|
|
|
|
public async Task ValidateSocialCredits()
|
|
{
|
|
var now = SystemClock.Instance.GetCurrentInstant();
|
|
var expiredRecords = await db.SocialCreditRecords
|
|
.Where(r => r.Status == SocialCreditRecordStatus.Active && r.ExpiredAt.HasValue && r.ExpiredAt <= now)
|
|
.Select(r => new { r.Id, r.AccountId, r.Delta })
|
|
.ToListAsync();
|
|
|
|
var groupedExpired = expiredRecords.GroupBy(er => er.AccountId)
|
|
.ToDictionary(g => g.Key, g => g.Sum(er => er.Delta));
|
|
|
|
foreach (var (accountId, totalDeltaSubtracted) in groupedExpired)
|
|
{
|
|
await db.AccountProfiles
|
|
.Where(p => p.AccountId == accountId)
|
|
.ExecuteUpdateAsync(p =>
|
|
p.SetProperty(v => v.SocialCredits, v => v.SocialCredits - totalDeltaSubtracted));
|
|
await cache.RemoveAsync($"{CacheKeyPrefix}{accountId}");
|
|
}
|
|
|
|
await db.SocialCreditRecords
|
|
.Where(r => r.Status == SocialCreditRecordStatus.Active && r.ExpiredAt.HasValue && r.ExpiredAt <= now)
|
|
.ExecuteUpdateAsync(r => r.SetProperty(x => x.Status, SocialCreditRecordStatus.Expired));
|
|
}
|
|
} |