Initial commit
This commit is contained in:
116
src/RolemasterDb.App/Features/LookupService.cs
Normal file
116
src/RolemasterDb.App/Features/LookupService.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using RolemasterDb.App.Data;
|
||||
|
||||
namespace RolemasterDb.App.Features;
|
||||
|
||||
public sealed class LookupService(IDbContextFactory<RolemasterDbContext> dbContextFactory)
|
||||
{
|
||||
public async Task<LookupReferenceData> GetReferenceDataAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var attackTables = await dbContext.AttackTables
|
||||
.AsNoTracking()
|
||||
.OrderBy(item => item.DisplayName)
|
||||
.Select(item => new LookupOption(item.Slug, item.DisplayName))
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var armorTypes = await dbContext.ArmorTypes
|
||||
.AsNoTracking()
|
||||
.OrderBy(item => item.SortOrder)
|
||||
.Select(item => new LookupOption(item.Code, item.Label))
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var criticalTables = await dbContext.CriticalTables
|
||||
.AsNoTracking()
|
||||
.AsSplitQuery()
|
||||
.Include(item => item.Columns)
|
||||
.Include(item => item.Groups)
|
||||
.OrderBy(item => item.DisplayName)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return new LookupReferenceData(
|
||||
attackTables,
|
||||
armorTypes,
|
||||
criticalTables.Select(item => new CriticalTableReference(
|
||||
item.Slug,
|
||||
item.DisplayName,
|
||||
item.Columns.OrderBy(column => column.SortOrder).Select(column => new LookupOption(column.ColumnKey, column.Label)).ToList(),
|
||||
item.Groups.OrderBy(group => group.SortOrder).Select(group => new LookupOption(group.GroupKey, group.Label)).ToList()))
|
||||
.ToList());
|
||||
}
|
||||
|
||||
public async Task<AttackLookupResponse?> LookupAttackAsync(AttackLookupRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var attackTable = NormalizeSlug(request.AttackTable);
|
||||
var armorType = request.ArmorType.Trim().ToUpperInvariant();
|
||||
|
||||
var attackResult = await dbContext.AttackResults
|
||||
.AsNoTracking()
|
||||
.Where(item =>
|
||||
item.AttackTable.Slug == attackTable &&
|
||||
item.ArmorType.Code == armorType &&
|
||||
request.Roll >= item.AttackRollBand.MinRoll &&
|
||||
(item.AttackRollBand.MaxRoll == null || request.Roll <= item.AttackRollBand.MaxRoll))
|
||||
.Select(item => new AttackLookupResponse(
|
||||
item.AttackTable.Slug,
|
||||
item.AttackTable.DisplayName,
|
||||
item.ArmorType.Code,
|
||||
item.ArmorType.Label,
|
||||
request.Roll,
|
||||
item.AttackRollBand.Label,
|
||||
item.Hits,
|
||||
item.CriticalType,
|
||||
item.CriticalSeverity,
|
||||
item.RawNotation,
|
||||
item.Notes,
|
||||
null))
|
||||
.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
if (attackResult is null || attackResult.CriticalType is null || attackResult.CriticalSeverity is null || request.CriticalRoll is null)
|
||||
{
|
||||
return attackResult;
|
||||
}
|
||||
|
||||
var autoCritical = await LookupCriticalAsync(
|
||||
new CriticalLookupRequest(attackResult.CriticalType, attackResult.CriticalSeverity, request.CriticalRoll.Value, null),
|
||||
cancellationToken);
|
||||
|
||||
return attackResult with { AutoCritical = autoCritical };
|
||||
}
|
||||
|
||||
public async Task<CriticalLookupResponse?> LookupCriticalAsync(CriticalLookupRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var criticalType = NormalizeSlug(request.CriticalType);
|
||||
var column = request.Column.Trim().ToUpperInvariant();
|
||||
var group = string.IsNullOrWhiteSpace(request.Group) ? null : NormalizeSlug(request.Group);
|
||||
|
||||
return await dbContext.CriticalResults
|
||||
.AsNoTracking()
|
||||
.Where(item =>
|
||||
item.CriticalTable.Slug == criticalType &&
|
||||
item.CriticalColumn.ColumnKey == column &&
|
||||
(group == null
|
||||
? item.CriticalGroupId == null
|
||||
: item.CriticalGroup != null && item.CriticalGroup.GroupKey == group) &&
|
||||
request.Roll >= item.CriticalRollBand.MinRoll &&
|
||||
(item.CriticalRollBand.MaxRoll == null || request.Roll <= item.CriticalRollBand.MaxRoll))
|
||||
.Select(item => new CriticalLookupResponse(
|
||||
item.CriticalTable.Slug,
|
||||
item.CriticalTable.DisplayName,
|
||||
item.CriticalGroup != null ? item.CriticalGroup.GroupKey : null,
|
||||
item.CriticalColumn.ColumnKey,
|
||||
request.Roll,
|
||||
item.CriticalRollBand.Label,
|
||||
item.DescriptionText,
|
||||
item.RawAffixText))
|
||||
.SingleOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private static string NormalizeSlug(string value) =>
|
||||
value.Trim().Replace(' ', '_').ToLowerInvariant();
|
||||
}
|
||||
Reference in New Issue
Block a user