Fix false editor compare warnings

This commit is contained in:
2026-03-15 13:08:00 +01:00
parent 7b07477133
commit ea328e65bd
4 changed files with 186 additions and 65 deletions

View File

@@ -667,26 +667,29 @@
return ["Generated comparison is unavailable."]; return ["Generated comparison is unavailable."];
} }
var comparisonSourceModel = GetComparisonSourceModel(model, comparisonBaseline);
var comparisonSourceEffects = BuildPreviewEffects(comparisonSourceModel);
var comparisonSourceBranches = BuildPreviewBranches(comparisonSourceModel);
var items = new List<string>(); var items = new List<string>();
if (DescriptionDiffers(model, comparisonBaseline)) if (CriticalCellComparisonEvaluator.DescriptionDiffers(comparisonSourceModel.DescriptionText, model.GeneratedState.DescriptionText))
{ {
items.Add("Result text differs"); items.Add("Result text differs");
} }
if (EffectsDiffer(model, comparisonBaseline)) if (CriticalCellComparisonEvaluator.EffectsDiffer(comparisonSourceEffects, model.GeneratedState.Effects))
{ {
items.Add("Base effects differ"); items.Add("Base effects differ");
} }
if (BranchesDiffer(model, comparisonBaseline)) if (CriticalCellComparisonEvaluator.BranchesDiffer(comparisonSourceBranches, model.GeneratedState.Branches))
{ {
items.Add("Conditions differ"); items.Add("Conditions differ");
} }
if (items.Count == 0) if (items.Count == 0)
{ {
items.Add("Current card matches the fresh parse"); items.Add("Current card matches the fresh generation");
} }
if (model.GeneratedState.ValidationMessages.Count > 0) if (model.GeneratedState.ValidationMessages.Count > 0)
@@ -699,75 +702,22 @@
private static int GetComparisonDifferenceCount(CriticalCellEditorModel model, CriticalCellEditorModel? comparisonBaseline) private static int GetComparisonDifferenceCount(CriticalCellEditorModel model, CriticalCellEditorModel? comparisonBaseline)
{ {
var count = 0; if (model.GeneratedState is null)
if (DescriptionDiffers(model, comparisonBaseline))
{ {
count++; return 0;
} }
if (EffectsDiffer(model, comparisonBaseline)) var comparisonSourceModel = GetComparisonSourceModel(model, comparisonBaseline);
{ return CriticalCellComparisonEvaluator.GetDifferenceCount(
count++; comparisonSourceModel.DescriptionText,
} BuildPreviewEffects(comparisonSourceModel),
BuildPreviewBranches(comparisonSourceModel),
if (BranchesDiffer(model, comparisonBaseline)) model.GeneratedState);
{
count++;
}
return count;
} }
private static bool HasComparisonDifferences(CriticalCellEditorModel? model, CriticalCellEditorModel? comparisonBaseline) => private static bool HasComparisonDifferences(CriticalCellEditorModel? model, CriticalCellEditorModel? comparisonBaseline) =>
model is not null && GetComparisonDifferenceCount(model, comparisonBaseline) > 0; model is not null && GetComparisonDifferenceCount(model, comparisonBaseline) > 0;
private static bool DescriptionDiffers(CriticalCellEditorModel model, CriticalCellEditorModel? comparisonBaseline) =>
model.GeneratedState is not null &&
!string.Equals(
NormalizeDisplayText(GetComparisonSourceModel(model, comparisonBaseline).DescriptionText),
NormalizeDisplayText(model.GeneratedState.DescriptionText),
StringComparison.Ordinal);
private static bool EffectsDiffer(CriticalCellEditorModel model, CriticalCellEditorModel? comparisonBaseline) =>
model.GeneratedState is not null &&
SerializeComparisonValue(BuildPreviewEffects(GetComparisonSourceModel(model, comparisonBaseline)).Select(ProjectEffectForComparison).ToList()) !=
SerializeComparisonValue(model.GeneratedState.Effects.Select(ProjectEffectForComparison).ToList());
private static bool BranchesDiffer(CriticalCellEditorModel model, CriticalCellEditorModel? comparisonBaseline) =>
model.GeneratedState is not null &&
SerializeComparisonValue(BuildPreviewBranches(GetComparisonSourceModel(model, comparisonBaseline)).Select(ProjectBranchForComparison).ToList()) !=
SerializeComparisonValue(model.GeneratedState.Branches.Select(ProjectBranchForComparison).ToList());
private static string NormalizeDisplayText(string? value) =>
value?.Trim() ?? string.Empty;
private static string SerializeComparisonValue<TValue>(TValue value) =>
JsonSerializer.Serialize(value, DiagnosticJsonOptions);
private static object ProjectEffectForComparison(CriticalEffectLookupResponse effect) => new
{
effect.EffectCode,
effect.Target,
effect.ValueInteger,
effect.ValueExpression,
effect.DurationRounds,
effect.PerRound,
effect.Modifier,
effect.BodyPart,
effect.IsPermanent,
SourceText = NormalizeDisplayText(effect.SourceText)
};
private static object ProjectBranchForComparison(CriticalBranchLookupResponse branch) => new
{
Condition = NormalizeDisplayText(branch.ConditionText),
Description = NormalizeDisplayText(branch.Description),
Effects = branch.Effects
.Select(ProjectEffectForComparison)
.ToList()
};
private static CriticalCellEditorModel GetComparisonSourceModel( private static CriticalCellEditorModel GetComparisonSourceModel(
CriticalCellEditorModel model, CriticalCellEditorModel model,
CriticalCellEditorModel? comparisonBaseline) => CriticalCellEditorModel? comparisonBaseline) =>

View File

@@ -0,0 +1,80 @@
using System.Text.Json;
namespace RolemasterDb.App.Features;
public static class CriticalCellComparisonEvaluator
{
private static readonly JsonSerializerOptions ComparisonJsonOptions = new(JsonSerializerDefaults.Web);
public static int GetDifferenceCount(
string? currentDescription,
IReadOnlyList<CriticalEffectLookupResponse> currentEffects,
IReadOnlyList<CriticalBranchLookupResponse> currentBranches,
CriticalCellComparisonState generatedState)
{
var count = 0;
if (DescriptionDiffers(currentDescription, generatedState.DescriptionText))
{
count++;
}
if (EffectsDiffer(currentEffects, generatedState.Effects))
{
count++;
}
if (BranchesDiffer(currentBranches, generatedState.Branches))
{
count++;
}
return count;
}
public static bool DescriptionDiffers(string? currentDescription, string? generatedDescription) =>
!string.Equals(
NormalizeText(currentDescription),
NormalizeText(generatedDescription),
StringComparison.Ordinal);
public static bool EffectsDiffer(
IReadOnlyList<CriticalEffectLookupResponse> currentEffects,
IReadOnlyList<CriticalEffectLookupResponse> generatedEffects) =>
SerializeComparisonValue(currentEffects.Select(ProjectEffectForComparison).ToList()) !=
SerializeComparisonValue(generatedEffects.Select(ProjectEffectForComparison).ToList());
public static bool BranchesDiffer(
IReadOnlyList<CriticalBranchLookupResponse> currentBranches,
IReadOnlyList<CriticalBranchLookupResponse> generatedBranches) =>
SerializeComparisonValue(currentBranches.Select(ProjectBranchForComparison).ToList()) !=
SerializeComparisonValue(generatedBranches.Select(ProjectBranchForComparison).ToList());
private static string NormalizeText(string? value) =>
value?.Trim() ?? string.Empty;
private static string SerializeComparisonValue<TValue>(TValue value) =>
JsonSerializer.Serialize(value, ComparisonJsonOptions);
private static object ProjectEffectForComparison(CriticalEffectLookupResponse effect) => new
{
effect.EffectCode,
Target = NormalizeText(effect.Target),
effect.ValueInteger,
ValueExpression = NormalizeText(effect.ValueExpression),
effect.DurationRounds,
effect.PerRound,
effect.Modifier,
BodyPart = NormalizeText(effect.BodyPart),
effect.IsPermanent
};
private static object ProjectBranchForComparison(CriticalBranchLookupResponse branch) => new
{
Condition = NormalizeText(branch.ConditionText),
Description = NormalizeText(branch.Description),
Effects = branch.Effects
.Select(ProjectEffectForComparison)
.ToList()
};
}

View File

@@ -0,0 +1,90 @@
using RolemasterDb.App.Domain;
using RolemasterDb.App.Features;
namespace RolemasterDb.ImportTool.Tests;
public sealed class CriticalCellComparisonEvaluatorTests
{
[Fact]
public void Effects_do_not_differ_when_only_source_metadata_changes()
{
var currentEffects = new[]
{
new CriticalEffectLookupResponse(
CriticalEffectCodes.MustParryRounds,
"foe",
null,
null,
1,
null,
null,
null,
false,
"symbol",
"π")
};
var generatedEffects = new[]
{
new CriticalEffectLookupResponse(
CriticalEffectCodes.MustParryRounds,
"foe",
null,
null,
1,
null,
null,
null,
false,
"quick",
"1mp")
};
Assert.False(CriticalCellComparisonEvaluator.EffectsDiffer(currentEffects, generatedEffects));
}
[Fact]
public void Difference_count_detects_actual_visible_effect_changes()
{
var currentEffects = new[]
{
new CriticalEffectLookupResponse(
CriticalEffectCodes.DirectHits,
"foe",
5,
null,
null,
null,
null,
null,
false,
"import",
"+5")
};
var generatedState = new CriticalCellComparisonState(
"Arcane force staggers the foe.",
[
new CriticalEffectLookupResponse(
CriticalEffectCodes.DirectHits,
"foe",
10,
null,
null,
null,
null,
null,
false,
"quick",
"+10")
],
[],
[]);
var differenceCount = CriticalCellComparisonEvaluator.GetDifferenceCount(
"Arcane force staggers the foe.",
currentEffects,
[],
generatedState);
Assert.Equal(1, differenceCount);
}
}

View File

@@ -19,6 +19,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\RolemasterDb.App\RolemasterDb.App.csproj" />
<ProjectReference Include="..\RolemasterDb.CriticalParsing\RolemasterDb.CriticalParsing.csproj" /> <ProjectReference Include="..\RolemasterDb.CriticalParsing\RolemasterDb.CriticalParsing.csproj" />
<ProjectReference Include="..\RolemasterDb.ImportTool\RolemasterDb.ImportTool.csproj" /> <ProjectReference Include="..\RolemasterDb.ImportTool\RolemasterDb.ImportTool.csproj" />
</ItemGroup> </ItemGroup>