✨ Pass rewind service and account rewind service
This commit is contained in:
6
DysonNetwork.Pass/Rewind/AccountRewindController.cs
Normal file
6
DysonNetwork.Pass/Rewind/AccountRewindController.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace DysonNetwork.Pass.Rewind;
|
||||
|
||||
public class AccountRewindController
|
||||
{
|
||||
|
||||
}
|
||||
75
DysonNetwork.Pass/Rewind/AccountRewindService.cs
Normal file
75
DysonNetwork.Pass/Rewind/AccountRewindService.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using DysonNetwork.Shared.Models;
|
||||
using DysonNetwork.Shared.Proto;
|
||||
using Grpc.Net.Client;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DysonNetwork.Pass.Rewind;
|
||||
|
||||
public class AccountRewindService(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
AppDatabase db,
|
||||
PassRewindService passRewindSrv
|
||||
)
|
||||
{
|
||||
private static string CapitalizeFirstLetter(string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str))
|
||||
return str;
|
||||
|
||||
// Capitalize the first character and append the rest of the string in lowercase
|
||||
return char.ToUpper(str[0]) + str[1..].ToLower();
|
||||
}
|
||||
|
||||
private RewindService.RewindServiceClient CreateRewindServiceClient(string serviceId)
|
||||
{
|
||||
var httpClient = httpClientFactory.CreateClient(
|
||||
$"{nameof(AccountRewindService)}+{CapitalizeFirstLetter(serviceId)}"
|
||||
);
|
||||
var channel = GrpcChannel.ForAddress($"http://{serviceId}", new GrpcChannelOptions { HttpClient = httpClient });
|
||||
return new RewindService.RewindServiceClient(channel);
|
||||
}
|
||||
|
||||
private async Task<SnRewindPoint> CreateRewindPoint(Guid accountId)
|
||||
{
|
||||
var currentYear = DateTime.UtcNow.Year;
|
||||
var rewindRequest = new RequestRewindEvent { AccountId = accountId.ToString(), Year = currentYear};
|
||||
|
||||
var rewindEventTasks = new List<Task<RewindEvent>>
|
||||
{
|
||||
passRewindSrv.CreateRewindEvent(accountId, currentYear),
|
||||
CreateRewindServiceClient("sphere").GetRewindEventAsync(rewindRequest).ResponseAsync
|
||||
};
|
||||
var rewindEvents = await Task.WhenAll(rewindEventTasks);
|
||||
|
||||
var rewindData = rewindEvents.ToDictionary<RewindEvent, string, Dictionary<string, object?>>(
|
||||
rewindEvent => rewindEvent.ServiceId,
|
||||
rewindEvent => GrpcTypeHelper.ConvertByteStringToObject<Dictionary<string, object?>>(rewindEvent.Data) ??
|
||||
new Dictionary<string, object?>()
|
||||
);
|
||||
|
||||
var point = new SnRewindPoint
|
||||
{
|
||||
SchemaVersion = 1,
|
||||
AccountId = accountId,
|
||||
Data = rewindData.ToDictionary(kvp => kvp.Key, object? (kvp) => kvp.Value)
|
||||
};
|
||||
|
||||
db.RewindPoints.Add(point);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
public async Task<SnRewindPoint> GetOrCreateRewindPoint(Guid accountId)
|
||||
{
|
||||
var currentYear = DateTime.UtcNow.Year;
|
||||
|
||||
var existingRewind = await db.RewindPoints
|
||||
.Where(p => p.AccountId == accountId && p.Year == currentYear)
|
||||
.OrderBy(p => p.CreatedAt)
|
||||
.FirstOrDefaultAsync();
|
||||
if (existingRewind is not null) return existingRewind;
|
||||
|
||||
return await CreateRewindPoint(accountId);
|
||||
}
|
||||
}
|
||||
49
DysonNetwork.Pass/Rewind/PassRewindService.cs
Normal file
49
DysonNetwork.Pass/Rewind/PassRewindService.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Linq;
|
||||
using DysonNetwork.Shared.Proto;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NodaTime;
|
||||
|
||||
namespace DysonNetwork.Pass.Rewind;
|
||||
|
||||
/// <summary>
|
||||
/// Although the pass uses the rewind service call internally, no need for grpc.
|
||||
/// But we created a service that produce the grpc type for consistency.
|
||||
/// </summary>
|
||||
public class PassRewindService(AppDatabase db)
|
||||
{
|
||||
public async Task<RewindEvent> CreateRewindEvent(Guid accountId, int year)
|
||||
{
|
||||
var startDate = Instant.FromDateTimeUtc(new DateTime(year - 1, 12, 26));
|
||||
var endDate = Instant.FromDateTimeUtc(new DateTime(year, 12, 26));
|
||||
|
||||
var checkInDates = await db.AccountCheckInResults
|
||||
.Where(a => a.CreatedAt >= startDate && a.CreatedAt < endDate)
|
||||
.Where(a => a.AccountId == accountId)
|
||||
.Select(a => a.CreatedAt.ToDateTimeUtc().Date)
|
||||
.Distinct()
|
||||
.OrderBy(d => d)
|
||||
.ToListAsync();
|
||||
|
||||
var maxCheckInStrike = 0;
|
||||
if (checkInDates.Count != 0)
|
||||
{
|
||||
maxCheckInStrike = checkInDates
|
||||
.Select((d, i) => new { Date = d, Index = i })
|
||||
.GroupBy(x => x.Date.Subtract(new TimeSpan(x.Index, 0, 0, 0)))
|
||||
.Select(g => g.Count())
|
||||
.Max();
|
||||
}
|
||||
|
||||
var data = new Dictionary<string, object?>
|
||||
{
|
||||
["max_check_in_strike"] = maxCheckInStrike,
|
||||
};
|
||||
|
||||
return new RewindEvent
|
||||
{
|
||||
ServiceId = "pass",
|
||||
AccountId = accountId.ToString(),
|
||||
Data = GrpcTypeHelper.ConvertObjectToByteString(data)
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user