Add manual critical table cell editor
This commit is contained in:
@@ -231,6 +231,7 @@ public sealed class LookupService(IDbContextFactory<RolemasterDbContext> dbConte
|
||||
.ThenBy(result => result.CriticalGroup?.SortOrder ?? 0)
|
||||
.ThenBy(result => result.CriticalColumn.SortOrder)
|
||||
.Select(result => new CriticalTableCellDetail(
|
||||
result.Id,
|
||||
result.CriticalRollBand.Label,
|
||||
result.CriticalColumn.ColumnKey,
|
||||
result.CriticalColumn.Label,
|
||||
@@ -262,6 +263,70 @@ public sealed class LookupService(IDbContextFactory<RolemasterDbContext> dbConte
|
||||
cells,
|
||||
legend);
|
||||
}
|
||||
|
||||
public async Task<CriticalCellEditorResponse?> GetCriticalCellEditorAsync(string slug, int resultId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var normalizedSlug = NormalizeSlug(slug);
|
||||
var result = await dbContext.CriticalResults
|
||||
.AsNoTracking()
|
||||
.AsSplitQuery()
|
||||
.Include(item => item.CriticalTable)
|
||||
.Include(item => item.CriticalColumn)
|
||||
.Include(item => item.CriticalGroup)
|
||||
.Include(item => item.CriticalRollBand)
|
||||
.Include(item => item.Effects)
|
||||
.Include(item => item.Branches)
|
||||
.ThenInclude(branch => branch.Effects)
|
||||
.SingleOrDefaultAsync(
|
||||
item => item.Id == resultId && item.CriticalTable.Slug == normalizedSlug,
|
||||
cancellationToken);
|
||||
|
||||
return result is null ? null : CreateCellEditorResponse(result);
|
||||
}
|
||||
|
||||
public async Task<CriticalCellEditorResponse?> UpdateCriticalCellAsync(
|
||||
string slug,
|
||||
int resultId,
|
||||
CriticalCellUpdateRequest request,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
await using var dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var normalizedSlug = NormalizeSlug(slug);
|
||||
var result = await dbContext.CriticalResults
|
||||
.AsSplitQuery()
|
||||
.Include(item => item.CriticalTable)
|
||||
.Include(item => item.CriticalColumn)
|
||||
.Include(item => item.CriticalGroup)
|
||||
.Include(item => item.CriticalRollBand)
|
||||
.Include(item => item.Effects)
|
||||
.Include(item => item.Branches)
|
||||
.ThenInclude(branch => branch.Effects)
|
||||
.SingleOrDefaultAsync(
|
||||
item => item.Id == resultId && item.CriticalTable.Slug == normalizedSlug,
|
||||
cancellationToken);
|
||||
|
||||
if (result is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
result.RawCellText = request.RawCellText.Trim();
|
||||
result.DescriptionText = request.DescriptionText.Trim();
|
||||
result.RawAffixText = NormalizeOptionalText(request.RawAffixText);
|
||||
result.ParseStatus = request.ParseStatus.Trim();
|
||||
result.ParsedJson = string.IsNullOrWhiteSpace(request.ParsedJson) ? "{}" : request.ParsedJson.Trim();
|
||||
|
||||
ReplaceBaseEffects(dbContext, result, request.Effects);
|
||||
ReplaceBranches(dbContext, result, request.Branches);
|
||||
|
||||
await dbContext.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return CreateCellEditorResponse(result);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<CriticalTableLegendEntry> BuildLegend(IReadOnlyList<CriticalTableCellDetail> cells)
|
||||
{
|
||||
var seenCodes = new HashSet<string>(StringComparer.Ordinal);
|
||||
@@ -320,6 +385,32 @@ public sealed class LookupService(IDbContextFactory<RolemasterDbContext> dbConte
|
||||
effect.SourceType,
|
||||
effect.SourceText);
|
||||
|
||||
private static CriticalCellEditorResponse CreateCellEditorResponse(CriticalResult result) =>
|
||||
new(
|
||||
result.Id,
|
||||
result.CriticalTable.Slug,
|
||||
result.CriticalTable.DisplayName,
|
||||
result.CriticalTable.SourceDocument,
|
||||
result.CriticalRollBand.Label,
|
||||
result.CriticalGroup?.GroupKey,
|
||||
result.CriticalGroup?.Label,
|
||||
result.CriticalColumn.ColumnKey,
|
||||
result.CriticalColumn.Label,
|
||||
result.CriticalColumn.Role,
|
||||
result.RawCellText,
|
||||
result.DescriptionText,
|
||||
result.RawAffixText,
|
||||
result.ParseStatus,
|
||||
result.ParsedJson,
|
||||
result.Effects
|
||||
.OrderBy(effect => effect.Id)
|
||||
.Select(CreateEffectEditorItem)
|
||||
.ToList(),
|
||||
result.Branches
|
||||
.OrderBy(branch => branch.SortOrder)
|
||||
.Select(CreateBranchEditorItem)
|
||||
.ToList());
|
||||
|
||||
private static CriticalBranchLookupResponse CreateBranchLookupResponse(CriticalBranch branch) =>
|
||||
new(
|
||||
branch.BranchKind,
|
||||
@@ -334,6 +425,108 @@ public sealed class LookupService(IDbContextFactory<RolemasterDbContext> dbConte
|
||||
branch.RawText,
|
||||
branch.SortOrder);
|
||||
|
||||
private static CriticalBranchEditorItem CreateBranchEditorItem(CriticalBranch branch) =>
|
||||
new(
|
||||
branch.BranchKind,
|
||||
branch.ConditionKey,
|
||||
branch.ConditionText,
|
||||
branch.ConditionJson,
|
||||
branch.RawText,
|
||||
branch.DescriptionText,
|
||||
branch.RawAffixText,
|
||||
branch.ParsedJson,
|
||||
branch.SortOrder,
|
||||
(branch.Effects ?? Enumerable.Empty<CriticalEffect>())
|
||||
.OrderBy(effect => effect.Id)
|
||||
.Select(CreateEffectEditorItem)
|
||||
.ToList());
|
||||
|
||||
private static CriticalEffectEditorItem CreateEffectEditorItem(CriticalEffect effect) =>
|
||||
new(
|
||||
effect.EffectCode,
|
||||
effect.Target,
|
||||
effect.ValueInteger,
|
||||
effect.ValueDecimal,
|
||||
effect.ValueExpression,
|
||||
effect.DurationRounds,
|
||||
effect.PerRound,
|
||||
effect.Modifier,
|
||||
effect.BodyPart,
|
||||
effect.IsPermanent,
|
||||
effect.SourceType,
|
||||
effect.SourceText);
|
||||
|
||||
private static void ReplaceBaseEffects(
|
||||
RolemasterDbContext dbContext,
|
||||
CriticalResult result,
|
||||
IReadOnlyList<CriticalEffectEditorItem>? effects)
|
||||
{
|
||||
dbContext.CriticalEffects.RemoveRange(result.Effects);
|
||||
result.Effects.Clear();
|
||||
|
||||
foreach (var effect in effects ?? Array.Empty<CriticalEffectEditorItem>())
|
||||
{
|
||||
result.Effects.Add(CreateEffectEntity(effect));
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReplaceBranches(
|
||||
RolemasterDbContext dbContext,
|
||||
CriticalResult result,
|
||||
IReadOnlyList<CriticalBranchEditorItem>? branches)
|
||||
{
|
||||
foreach (var branch in result.Branches)
|
||||
{
|
||||
dbContext.CriticalEffects.RemoveRange(branch.Effects);
|
||||
}
|
||||
|
||||
dbContext.CriticalBranches.RemoveRange(result.Branches);
|
||||
result.Branches.Clear();
|
||||
|
||||
foreach (var branch in branches ?? Array.Empty<CriticalBranchEditorItem>())
|
||||
{
|
||||
var branchEntity = new CriticalBranch
|
||||
{
|
||||
BranchKind = branch.BranchKind.Trim(),
|
||||
ConditionKey = NormalizeOptionalText(branch.ConditionKey),
|
||||
ConditionText = branch.ConditionText.Trim(),
|
||||
ConditionJson = string.IsNullOrWhiteSpace(branch.ConditionJson) ? "{}" : branch.ConditionJson.Trim(),
|
||||
RawText = branch.RawText.Trim(),
|
||||
DescriptionText = branch.DescriptionText.Trim(),
|
||||
RawAffixText = NormalizeOptionalText(branch.RawAffixText),
|
||||
ParsedJson = string.IsNullOrWhiteSpace(branch.ParsedJson) ? "{}" : branch.ParsedJson.Trim(),
|
||||
SortOrder = branch.SortOrder
|
||||
};
|
||||
|
||||
foreach (var effect in branch.Effects ?? Array.Empty<CriticalEffectEditorItem>())
|
||||
{
|
||||
branchEntity.Effects.Add(CreateEffectEntity(effect));
|
||||
}
|
||||
|
||||
result.Branches.Add(branchEntity);
|
||||
}
|
||||
}
|
||||
|
||||
private static CriticalEffect CreateEffectEntity(CriticalEffectEditorItem effect) =>
|
||||
new()
|
||||
{
|
||||
EffectCode = effect.EffectCode.Trim(),
|
||||
Target = NormalizeOptionalText(effect.Target),
|
||||
ValueInteger = effect.ValueInteger,
|
||||
ValueDecimal = effect.ValueDecimal,
|
||||
ValueExpression = NormalizeOptionalText(effect.ValueExpression),
|
||||
DurationRounds = effect.DurationRounds,
|
||||
PerRound = effect.PerRound,
|
||||
Modifier = effect.Modifier,
|
||||
BodyPart = NormalizeOptionalText(effect.BodyPart),
|
||||
IsPermanent = effect.IsPermanent,
|
||||
SourceType = effect.SourceType.Trim(),
|
||||
SourceText = NormalizeOptionalText(effect.SourceText)
|
||||
};
|
||||
|
||||
private static string? NormalizeOptionalText(string? value) =>
|
||||
string.IsNullOrWhiteSpace(value) ? null : value.Trim();
|
||||
|
||||
private static string NormalizeSlug(string value) =>
|
||||
value.Trim().Replace(' ', '_').ToLowerInvariant();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user