Commit critical import artifacts
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Text.Json;
|
||||
|
||||
using RolemasterDb.App.Data;
|
||||
using RolemasterDb.App.Domain;
|
||||
using RolemasterDb.ImportTool.Parsing;
|
||||
@@ -35,7 +34,8 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
return removedTableCount;
|
||||
}
|
||||
|
||||
public async Task<ImportCommandResult> LoadAsync(ParsedCriticalTable table, CancellationToken cancellationToken = default)
|
||||
public async Task<ImportCommandResult> LoadAsync(ParsedCriticalTable table,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
await using var dbContext = CreateDbContext();
|
||||
await dbContext.Database.EnsureCreatedAsync(cancellationToken);
|
||||
@@ -48,16 +48,16 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
.Include(item => item.Columns)
|
||||
.Include(item => item.RollBands)
|
||||
.Include(item => item.Results)
|
||||
.ThenInclude(result => result.CriticalGroup)
|
||||
.ThenInclude(result => result.CriticalGroup)
|
||||
.Include(item => item.Results)
|
||||
.ThenInclude(result => result.CriticalColumn)
|
||||
.ThenInclude(result => result.CriticalColumn)
|
||||
.Include(item => item.Results)
|
||||
.ThenInclude(result => result.CriticalRollBand)
|
||||
.ThenInclude(result => result.CriticalRollBand)
|
||||
.Include(item => item.Results)
|
||||
.ThenInclude(result => result.Effects)
|
||||
.ThenInclude(result => result.Effects)
|
||||
.Include(item => item.Results)
|
||||
.ThenInclude(result => result.Branches)
|
||||
.ThenInclude(branch => branch.Effects)
|
||||
.ThenInclude(result => result.Branches)
|
||||
.ThenInclude(branch => branch.Effects)
|
||||
.SingleOrDefaultAsync(item => item.Slug == table.Slug, cancellationToken);
|
||||
|
||||
if (entity is null)
|
||||
@@ -78,7 +78,8 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
var columnsByKey = SynchronizeColumns(entity, table);
|
||||
var rollBandsByLabel = SynchronizeRollBands(entity, table);
|
||||
var existingResultsByKey = entity.Results.ToDictionary(
|
||||
item => CreateResultKey(item.CriticalGroup?.GroupKey, item.CriticalColumn.ColumnKey, item.CriticalRollBand.Label),
|
||||
item => CreateResultKey(item.CriticalGroup?.GroupKey, item.CriticalColumn.ColumnKey,
|
||||
item.CriticalRollBand.Label),
|
||||
StringComparer.Ordinal);
|
||||
var importedKeys = new HashSet<string>(StringComparer.Ordinal);
|
||||
|
||||
@@ -109,7 +110,8 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
}
|
||||
|
||||
foreach (var unmatchedResult in entity.Results
|
||||
.Where(item => !importedKeys.Contains(CreateResultKey(item.CriticalGroup?.GroupKey, item.CriticalColumn.ColumnKey, item.CriticalRollBand.Label)))
|
||||
.Where(item => !importedKeys.Contains(CreateResultKey(item.CriticalGroup?.GroupKey,
|
||||
item.CriticalColumn.ColumnKey, item.CriticalRollBand.Label)))
|
||||
.ToList())
|
||||
{
|
||||
if (unmatchedResult.IsCurated)
|
||||
@@ -128,7 +130,8 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
return new ImportCommandResult(entity.Slug, entity.Columns.Count, entity.RollBands.Count, entity.Results.Count);
|
||||
}
|
||||
|
||||
public async Task<int> RefreshImageArtifactsAsync(ParsedCriticalTable table, CancellationToken cancellationToken = default)
|
||||
public async Task<int> RefreshImageArtifactsAsync(ParsedCriticalTable table,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
await using var dbContext = CreateDbContext();
|
||||
await dbContext.Database.EnsureCreatedAsync(cancellationToken);
|
||||
@@ -138,20 +141,22 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
var entity = await dbContext.CriticalTables
|
||||
.AsSplitQuery()
|
||||
.Include(item => item.Results)
|
||||
.ThenInclude(result => result.CriticalGroup)
|
||||
.ThenInclude(result => result.CriticalGroup)
|
||||
.Include(item => item.Results)
|
||||
.ThenInclude(result => result.CriticalColumn)
|
||||
.ThenInclude(result => result.CriticalColumn)
|
||||
.Include(item => item.Results)
|
||||
.ThenInclude(result => result.CriticalRollBand)
|
||||
.ThenInclude(result => result.CriticalRollBand)
|
||||
.SingleOrDefaultAsync(item => item.Slug == table.Slug, cancellationToken);
|
||||
|
||||
if (entity is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Critical table '{table.Slug}' does not exist in the target database.");
|
||||
throw new InvalidOperationException(
|
||||
$"Critical table '{table.Slug}' does not exist in the target database.");
|
||||
}
|
||||
|
||||
var existingResultsByKey = entity.Results.ToDictionary(
|
||||
item => CreateResultKey(item.CriticalGroup?.GroupKey, item.CriticalColumn.ColumnKey, item.CriticalRollBand.Label),
|
||||
item => CreateResultKey(item.CriticalGroup?.GroupKey, item.CriticalColumn.ColumnKey,
|
||||
item.CriticalRollBand.Label),
|
||||
StringComparer.Ordinal);
|
||||
|
||||
var refreshedCount = 0;
|
||||
@@ -172,6 +177,66 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
return refreshedCount;
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<CriticalImageArtifactMetadata>> LoadImageArtifactMetadataAsync(
|
||||
string tableSlug,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
await using var dbContext = CreateDbContext();
|
||||
await dbContext.Database.EnsureCreatedAsync(cancellationToken);
|
||||
await RolemasterDbSchemaUpgrader.EnsureLatestAsync(dbContext, cancellationToken);
|
||||
|
||||
var rows = await dbContext.CriticalResults
|
||||
.AsNoTracking()
|
||||
.Where(item => item.CriticalTable.Slug == tableSlug)
|
||||
.OrderBy(item => item.Id)
|
||||
.Select(item => new
|
||||
{
|
||||
item.Id,
|
||||
item.SourcePageNumber,
|
||||
item.SourceImagePath,
|
||||
item.SourceImageCropJson
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (rows.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Critical table '{tableSlug}' does not exist in the target database.");
|
||||
}
|
||||
|
||||
var metadata = new List<CriticalImageArtifactMetadata>(rows.Count);
|
||||
foreach (var row in rows)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(row.SourceImagePath))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Critical result {row.Id} in table '{tableSlug}' is missing SourceImagePath.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(row.SourceImageCropJson))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Critical result {row.Id} in table '{tableSlug}' is missing SourceImageCropJson.");
|
||||
}
|
||||
|
||||
var crop = JsonSerializer.Deserialize<CriticalSourceImageCrop>(row.SourceImageCropJson);
|
||||
if (crop is null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Critical result {row.Id} in table '{tableSlug}' has invalid SourceImageCropJson.");
|
||||
}
|
||||
|
||||
if (row.SourcePageNumber is not null && row.SourcePageNumber != crop.PageNumber)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Critical result {row.Id} in table '{tableSlug}' has mismatched source page metadata.");
|
||||
}
|
||||
|
||||
metadata.Add(new CriticalImageArtifactMetadata(row.Id, row.SourceImagePath, crop));
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private RolemasterDbContext CreateDbContext()
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<RolemasterDbContext>()
|
||||
@@ -205,7 +270,8 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
return groupsByKey;
|
||||
}
|
||||
|
||||
private static Dictionary<string, CriticalColumn> SynchronizeColumns(CriticalTable entity, ParsedCriticalTable table)
|
||||
private static Dictionary<string, CriticalColumn> SynchronizeColumns(CriticalTable entity,
|
||||
ParsedCriticalTable table)
|
||||
{
|
||||
var columnsByKey = entity.Columns.ToDictionary(item => item.ColumnKey, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
@@ -230,7 +296,8 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
return columnsByKey;
|
||||
}
|
||||
|
||||
private static Dictionary<string, CriticalRollBand> SynchronizeRollBands(CriticalTable entity, ParsedCriticalTable table)
|
||||
private static Dictionary<string, CriticalRollBand> SynchronizeRollBands(CriticalTable entity,
|
||||
ParsedCriticalTable table)
|
||||
{
|
||||
var rollBandsByLabel = entity.RollBands.ToDictionary(item => item.Label, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
@@ -300,7 +367,8 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
: JsonSerializer.Serialize(item.SourceImageCrop, JsonOptions);
|
||||
}
|
||||
|
||||
private static void ReplaceResultChildren(RolemasterDbContext dbContext, CriticalResult result, ParsedCriticalResult item)
|
||||
private static void ReplaceResultChildren(RolemasterDbContext dbContext, CriticalResult result,
|
||||
ParsedCriticalResult item)
|
||||
{
|
||||
foreach (var branch in result.Branches)
|
||||
{
|
||||
@@ -346,7 +414,8 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var group in entity.Groups
|
||||
.Where(item => !activeGroupKeys.Contains(item.GroupKey) && !importedGroupKeys.Contains(item.GroupKey))
|
||||
.Where(item =>
|
||||
!activeGroupKeys.Contains(item.GroupKey) && !importedGroupKeys.Contains(item.GroupKey))
|
||||
.ToList())
|
||||
{
|
||||
dbContext.CriticalGroups.Remove(group);
|
||||
@@ -361,7 +430,8 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var column in entity.Columns
|
||||
.Where(item => !activeColumnKeys.Contains(item.ColumnKey) && !importedColumnKeys.Contains(item.ColumnKey))
|
||||
.Where(item =>
|
||||
!activeColumnKeys.Contains(item.ColumnKey) && !importedColumnKeys.Contains(item.ColumnKey))
|
||||
.ToList())
|
||||
{
|
||||
dbContext.CriticalColumns.Remove(column);
|
||||
@@ -376,7 +446,8 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var rollBand in entity.RollBands
|
||||
.Where(item => !activeRollBandLabels.Contains(item.Label) && !importedRollBandLabels.Contains(item.Label))
|
||||
.Where(item =>
|
||||
!activeRollBandLabels.Contains(item.Label) && !importedRollBandLabels.Contains(item.Label))
|
||||
.ToList())
|
||||
{
|
||||
dbContext.CriticalRollBands.Remove(rollBand);
|
||||
@@ -437,4 +508,4 @@ public sealed class CriticalImportLoader(string databasePath)
|
||||
|
||||
private static string NormalizeKey(string? value) =>
|
||||
string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim().ToUpperInvariant();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user