Treasure Hunt

main
ilitirit 1 year ago
parent 29b0be78f7
commit c3b54a2f7c

@ -79,7 +79,7 @@ namespace Expedience.Api.Controllers
try
{
using var scope = _serviceScopeFactory.CreateScope();
var repository = scope.ServiceProvider.GetService<IExpedienceRepository>();
var repository = scope.ServiceProvider.GetRequiredService<IExpedienceRepository>();
var results = await repository.GetDutyCompletionRecords(expac, cancellationToken);
return Ok(results);
@ -92,14 +92,13 @@ namespace Expedience.Api.Controllers
return StatusCode(500);
}
[HttpGet("DeepDungeonRecords")]
public async Task<ActionResult> GetDeepDungeonRecords(CancellationToken cancellationToken)
{
try
{
using var scope = _serviceScopeFactory.CreateScope();
var repository = scope.ServiceProvider.GetService<IExpedienceRepository>();
var repository = scope.ServiceProvider.GetRequiredService<IExpedienceRepository>();
var results = await repository.GetDeepDungeonRecords(cancellationToken);
return Ok(results);
@ -112,13 +111,32 @@ namespace Expedience.Api.Controllers
return StatusCode(500);
}
[HttpGet("TreasureHuntRecords")]
public async Task<ActionResult> GetTreasureHuntRecords(CancellationToken cancellationToken)
{
try
{
using var scope = _serviceScopeFactory.CreateScope();
var repository = scope.ServiceProvider.GetRequiredService<IExpedienceRepository>();
var results = await repository.GetContentTypeRecords("Treasure Hunt", cancellationToken);
return Ok(results);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting Treasure Hunt Records: {errorMessage}", ex.Message);
}
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 repository = scope.ServiceProvider.GetRequiredService<IExpedienceRepository>();
var records = await repository.GetTopXRecords(recordType, territoryId, limit, cancellationToken);

@ -12,14 +12,12 @@ namespace Expedience.Infrastructure
}
public DbSet<DutyCompletionResult> DutyCompletionResults { get; set; }
public DbSet<DutyMember> DutyMembers { get; set; }
public DbSet<Territory> Territories { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<DutyCompletionRecord> DutyCompletionRecords { get; set; }
public DbSet<DeepDungeonRecord> DeepDungeonRecords { get; set; }
public DbSet<ContentTypeRecord> ContentTypeRecords { get; set; }
public DbSet<TopXCompletionResult> TopXRecords { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
@ -78,6 +76,10 @@ namespace Expedience.Infrastructure
.HasNoKey()
.ToTable(t => t.ExcludeFromMigrations());
modelBuilder.Entity<ContentTypeRecord>()
.HasNoKey()
.ToTable(t => t.ExcludeFromMigrations());
modelBuilder.Entity<TopXCompletionResult>(cfg =>
{
cfg.HasNoKey();

@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using EFCore.NamingConventions.Internal;
using Enyim.Caching;
using Expedience.Infrasctructure.Models;
using Expedience.Infrastructure.Models;
using Expedience.Models;
using Microsoft.EntityFrameworkCore;
@ -13,6 +10,7 @@ public interface IExpedienceRepository
{
ValueTask<List<DutyCompletionRecord>> GetDutyCompletionRecords(string expac, CancellationToken cancellationToken);
ValueTask<List<DeepDungeonRecord>> GetDeepDungeonRecords(CancellationToken cancellationToken);
ValueTask<List<ContentTypeRecord>> GetContentTypeRecords(string contentType, CancellationToken cancellationToken);
ValueTask<List<TopXCompletionResultDto>> GetTopXRecords(int recordType, int territoryId, int limit, CancellationToken cancellationToken);
}
@ -146,4 +144,15 @@ public class ExpedienceRepository : IExpedienceRepository
return records;
}
public async ValueTask<List<ContentTypeRecord>> GetContentTypeRecords(string contentType, CancellationToken cancellationToken)
{
var cacheKey = $"xpd-th";
var cacheSeconds = 600;
var records = await _memcachedClient.GetValueOrCreateAsync(cacheKey, cacheSeconds,
async () => await _dbContext.ContentTypeRecords.FromSqlInterpolated($"SELECT * FROM public.get_contenttyperecords({contentType})")
.ToListAsync(cancellationToken));
return records;
}
}

@ -0,0 +1,15 @@
using System;
namespace Expedience.Infrastructure.Models;
public class ContentTypeRecord
{
public int TerritoryId { get; set; }
public string PlaceName { get; set; } = null!;
public string ContentName { get; set; } = null!;
public int Level { get; set; }
public TimeSpan? MinParty { get; set; }
public TimeSpan? AvgParty { get; set; }
public TimeSpan? MinSolo { get; set; }
public TimeSpan? AvgSolo { get; set; }
}

@ -11,5 +11,6 @@ namespace Expedience.Models
public string UserId { get; set; }
public int WorldId { get; set; }
public string WorldName { get; set; }
}
public string UserName { get; set; }
}
}

@ -11,8 +11,9 @@ namespace Expedience.Web.Pages
public List<DutyCompletionRecord>? DutyCompletionRecords { get; private set; }
public List<DeepDungeonRecord>? DeepDungeonRecords { get; private set; }
public List<ContentTypeRecord>? TreasureHuntRecords { get; private set; }
public IndexModel(IApiService apiService)
public IndexModel(IApiService apiService)
{
_apiService = apiService;
}
@ -24,10 +25,18 @@ namespace Expedience.Web.Pages
if (expac == "DeepDungeons")
{
DutyCompletionRecords = null;
TreasureHuntRecords = null;
DeepDungeonRecords = await _apiService.GetDeepDungeonRecordsAsync(cancellationToken);
}
else if (expac == "TreasureHunt")
{
TreasureHuntRecords = await _apiService.GetTreasureHuntRecordsAsync(cancellationToken);
DutyCompletionRecords = null;
DeepDungeonRecords = null;
}
else
{
TreasureHuntRecords = null;
DutyCompletionRecords = await _apiService.GetDutyCompletionRecordsAsync(expac, cancellationToken);
DeepDungeonRecords = null;
}

@ -48,6 +48,9 @@
<li class="nav-item">
<a class="nav-link text-@(Accessor.HttpContext.Request.Path.Value == "/DeepDungeons" ? "light" : "muted")" asp-page="/Index" asp-area="" asp-route-expac="DeepDungeons">Deep Dungeons</a>
</li>
<li class="nav-item">
<a class="nav-link text-@(Accessor.HttpContext.Request.Path.Value == "/TreasureHunt" ? "light" : "muted")" asp-page="/Index" asp-area="" asp-route-expac="TreasureHunt">Treasure Hunt</a>
</li>
</ul>
</div>
</div>

@ -0,0 +1,34 @@
@using Expedience.Infrastructure.Models;
@using Expedience.Web.Extensions;
@{
@model IEnumerable<ContentTypeRecord>
}
<table id="dutyTable" data-toggle="table">
<thead>
<tr>
<th></th>
<th colspan="2">Party</th>
<th colspan="2">Solo</th>
</tr>
<tr>
<th data-sortable="true">Deep Dungeon</th>
<th data-sortable="true" data-sorter="durationSorter">Min</th>
<th data-sortable="true" data-sorter="durationSorter">Avg</th>
<th data-sortable="true" data-sorter="durationSorter">Min</th>
<th data-sortable="true" data-sorter="durationSorter">Avg</th>
</tr>
</thead>
<tbody>
@foreach (var record in Model)
{
<tr>
<td>@record.ContentName</td>
<td><a href="./normal/@record.TerritoryId">@record.MinParty.Format()</a></td>
<td>@record.AvgParty.Format()</td>
<td><a href="./solo/@record.TerritoryId">@record.MinSolo.Format()</a></td>
<td>@record.AvgSolo.Format()</td>
</tr>
}
</tbody>
</table>

@ -8,13 +8,14 @@ public interface IApiService
{
public ValueTask<List<DutyCompletionRecord>?> GetDutyCompletionRecordsAsync(string expac, CancellationToken cancellationToken);
public ValueTask<List<DeepDungeonRecord>?> GetDeepDungeonRecordsAsync(CancellationToken cancellationToken);
public ValueTask<List<ContentTypeRecord>?> GetTreasureHuntRecordsAsync(CancellationToken cancellationToken);
public ValueTask<List<DutyCompletionResult>?> GetTopXRecords(int recordType, int territoryId, int limit, CancellationToken cancellationToken);
}
public class ApiService : IApiService
{
private ILogger _logger;
private HttpClient _httpClient { get; }
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
public ApiService(ILogger<ApiService> logger, HttpClient httpClient)
{
@ -37,7 +38,7 @@ public class ApiService : IApiService
expac, ex.Message);
}
return new List<DutyCompletionRecord>();
return [];
}
public async ValueTask<List<DeepDungeonRecord>?> GetDeepDungeonRecordsAsync(CancellationToken cancellationToken)
@ -54,7 +55,7 @@ public class ApiService : IApiService
_logger.LogError(ex, "An error occurred trying to retrieve Deep Dungeon Records: {errorMessage}", ex.Message);
}
return new List<DeepDungeonRecord>();
return [];
}
public async ValueTask<List<DutyCompletionResult>> GetTopXRecords(int recordType, int territoryId, int limit, CancellationToken cancellationToken)
@ -74,6 +75,24 @@ public class ApiService : IApiService
limit, territoryId, recordType, ex.Message);
}
return new List<DutyCompletionResult>();
return [];
}
public async ValueTask<List<ContentTypeRecord>?> GetTreasureHuntRecordsAsync(CancellationToken cancellationToken)
{
var stopwatch = Stopwatch.StartNew();
try
{
var records = await _httpClient.GetFromJsonAsync<List<ContentTypeRecord>?>($"/api/TreasureHuntRecords", cancellationToken);
_logger.LogInformation("Retrieved Treasure Hunt Records in {duration}ms", stopwatch.ElapsedMilliseconds);
return records;
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred trying to retrieve Treasure Hunt Records: {errorMessage}", ex.Message);
}
return [];
}
}

Loading…
Cancel
Save