Top X Records

main
ilitirit 1 year ago
parent 30d1df4b5e
commit b0491e7471

@ -2,6 +2,7 @@
using System.Text.Json;
using Expedience.Api.Encryption;
using Expedience.Infrastructure;
using Expedience.Infrastructure.Models;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@ -110,5 +111,52 @@ namespace Expedience.Api.Controllers
return StatusCode(500);
}
}
[HttpGet("TopX/{recordType}/{territoryId}/{limit}")]
public async Task<ActionResult> GetTopXRecords(int recordType, int territoryId, int limit, CancellationToken cancellationToken)
{
try
{
using var scope = _serviceScopeFactory.CreateScope();
var repository = scope.ServiceProvider.GetService<IExpedienceRepository>();
var records = await repository.GetTopXRecords(recordType, territoryId, limit, cancellationToken);
var results = new List<DutyCompletionResult>();
foreach (var record in records)
{
var dutyCompletionResult = new DutyCompletionResult
{
Id = record.Id,
UserId = record.UserId,
TerritoryId = record.TerritoryId,
IsMinILevel = recordType == 3,
HasNpcMembers = recordType == 4,
StartTime = record.StartTime,
EndTime = record.EndTime,
Hours = record.Duration.Hours,
Minutes = record.Duration.Minutes,
Seconds = record.Duration.Seconds,
Milliseconds = record.Duration.Milliseconds,
GameVersion = record.GameVersion,
PluginVersion = record.PluginVersion,
Territory = record.Territory,
User = record.User,
DataCenter = record.DutyCompletionResult.DataCenter,
UploadedAt = record.UploadedAt,
Lang = record.DutyCompletionResult.Lang,
};
results.Add(dutyCompletionResult);
}
return Ok(results);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting Top X Records: {errorMessage}", ex.Message);
}
return StatusCode(500);
}
}
}
}

@ -19,6 +19,7 @@ namespace Expedience.Infrastructure
public DbSet<User> Users { get; set; }
public DbSet<DutyCompletionRecord> DutyCompletionRecords { get; set; }
public DbSet<DeepDungeonRecord> DeepDungeonRecords { get; set; }
public DbSet<TopXCompletionResult> TopXRecords { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
@ -76,6 +77,37 @@ namespace Expedience.Infrastructure
.HasNoKey()
.ToTable(t => t.ExcludeFromMigrations());
modelBuilder.Entity<TopXCompletionResult>(cfg =>
{
cfg.HasNoKey();
cfg.ToView("TopXCompletionResults"); // This is just a placeholder name
// If you want to include navigation properties:
cfg.HasOne(e => e.Territory)
.WithMany()
.HasForeignKey(e => e.TerritoryId)
.OnDelete(DeleteBehavior.NoAction);
cfg.HasOne(e => e.User)
.WithMany()
.HasForeignKey(e => e.UserId)
.OnDelete(DeleteBehavior.NoAction);
// Configure the relationship with DutyMembers
cfg.HasMany(e => e.DutyMembers)
.WithOne()
.HasForeignKey("UploadId") // Assuming UploadId in DutyMember corresponds to Id in TopXCompletionResult
.OnDelete(DeleteBehavior.NoAction);
// Configure the one-to-one relationship with DutyCompletionResult
cfg.HasOne(e => e.DutyCompletionResult)
.WithOne()
.HasForeignKey<TopXCompletionResult>("Id")
.OnDelete(DeleteBehavior.NoAction);
});
base.OnModelCreating(modelBuilder);
base.OnModelCreating(modelBuilder);
}
}

@ -9,6 +9,7 @@ public interface IExpedienceRepository
{
ValueTask<List<DutyCompletionRecord>> GetDutyCompletionRecords(string expac, CancellationToken cancellationToken);
ValueTask<List<DeepDungeonRecord>> GetDeepDungeonRecords(CancellationToken cancellationToken);
ValueTask<List<TopXCompletionResult>> GetTopXRecords(int recordType, int territoryId, int limit, CancellationToken cancellationToken);
}
public class ExpedienceRepository : IExpedienceRepository
@ -43,4 +44,46 @@ public class ExpedienceRepository : IExpedienceRepository
return records;
}
public async ValueTask<List<TopXCompletionResult>> GetTopXRecords(int recordType, int territoryId, int limit, CancellationToken cancellationToken)
{
var cacheKey = $"xpd-topx-{recordType}-{territoryId}-{limit}";
var cacheSeconds = 600;
var records = await _memcachedClient.GetValueOrCreateAsync(cacheKey, cacheSeconds,
async () =>
{
var topXResults = await _dbContext.TopXRecords.FromSqlInterpolated($"SELECT * FROM public.get_topxcompletionresults({recordType}, {territoryId}, {limit})")
.ToListAsync(cancellationToken);
// Get the IDs we need for our related entities
var topXIds = topXResults.Select(r => r.Id).ToList();
var userIds = topXResults.Select(r => r.UserId).Distinct().ToList();
// Then, fetch the related DutyMembers and DutyCompletionResults
var dutyMembers = await _dbContext.DutyMembers
.Where(dm => topXIds.Contains(dm.UploadId))
.ToListAsync();
var dutyCompletionResults = await _dbContext.DutyCompletionResults
.Where(dcr => topXIds.Contains(dcr.Id))
.ToListAsync();
var users = await _dbContext.Users
.Where(u => userIds.Contains(u.UserId))
.ToListAsync();
// Now, associate the DutyMembers and DutyCompletionResults with their corresponding TopXCompletionResults
foreach (var result in topXResults)
{
result.DutyMembers = dutyMembers.Where(dm => dm.UploadId == result.Id).ToList();
result.DutyCompletionResult = dutyCompletionResults.First(dcr => dcr.Id == result.Id);
result.User = users.First(u => u.UserId == result.UserId);
}
return topXResults;
});
return records;
}
}

@ -0,0 +1,31 @@
using Expedience.Models;
using System;
namespace Expedience.Infrastructure.Models;
public class TopXCompletionResult
{
public int Position { get; set; }
public Guid Id { get; set; }
public int TerritoryId { get; set; }
public string PlaceName { get; set; }
public string ContentName { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public TimeSpan Duration { get; set; }
public int Level { get; set; }
public string ContentType { get; set; }
public string Expac { get; set; }
public DateTime UploadedAt { get; set; }
public int UserId { get; set; }
public string Username { get; set; }
public int WorldId { get; set; }
public string Datacenter { get; set; }
public string PluginVersion { get; set; }
public string GameVersion { get; set; }
public Territory Territory { get; set; } = null!;
public User User { get; set; } = null!;
public ICollection<DutyMember> DutyMembers { get; set; } = null!;
public DutyCompletionResult DutyCompletionResult { get; set; } = null!;
}
Loading…
Cancel
Save