From e4be33862129b1b7f3d37948a038483a3883021f Mon Sep 17 00:00:00 2001 From: Frank Tovar Date: Sat, 14 Mar 2026 12:51:59 +0100 Subject: [PATCH] Fix duplicate critical affix import fragments --- src/RolemasterDb.App/rolemaster.db | Bin 3137536 -> 3149824 bytes ...dardCriticalTableParserIntegrationTests.cs | 21 +++++++ .../Parsing/CriticalTableParserSupport.cs | 54 +++++++++++++++++- 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/RolemasterDb.App/rolemaster.db b/src/RolemasterDb.App/rolemaster.db index 050f09d38d8ab24ef15e50828be8bc5b9a8e576b..8934083500e72bc3a79701794e70339fecd27040 100644 GIT binary patch delta 46543 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 string.Equals(item.Slug, "arcane-aether", StringComparison.Ordinal)); + var parseResult = await LoadParseResultAsync(entry); + var result = parseResult.Table.Results.Single(item => + item.GroupKey is null && + string.Equals(item.RollBandLabel, "31-40", StringComparison.Ordinal) && + string.Equals(item.ColumnKey, "C", StringComparison.Ordinal)); + + var bleedEffects = result.Effects + .Where(effect => effect.EffectCode == CriticalEffectCodes.BleedPerRound) + .ToList(); + + Assert.Equal("+15H – ∑ – ∫", result.RawAffixText); + Assert.Single(bleedEffects); + Assert.Equal(1, bleedEffects.Single().PerRound); + } + [Fact] public async Task Slash_boundary_repair_keeps_56_60_a_prose_first() { diff --git a/src/RolemasterDb.ImportTool/Parsing/CriticalTableParserSupport.cs b/src/RolemasterDb.ImportTool/Parsing/CriticalTableParserSupport.cs index 088fb15..a6666ab 100644 --- a/src/RolemasterDb.ImportTool/Parsing/CriticalTableParserSupport.cs +++ b/src/RolemasterDb.ImportTool/Parsing/CriticalTableParserSupport.cs @@ -30,7 +30,7 @@ internal static class CriticalTableParserSupport var document = XDocument.Load(xmlReader); - return document.Descendants("page") + var fragments = document.Descendants("page") .SelectMany(page => { var pageNumber = int.Parse(page.Attribute("number")?.Value ?? "1"); @@ -45,6 +45,8 @@ internal static class CriticalTableParserSupport .Where(item => !string.IsNullOrWhiteSpace(item.Text)); }) .ToList(); + + return RemoveRedundantContainedFragments(fragments); } internal static List FindRowLabelFragments( @@ -263,6 +265,56 @@ internal static class CriticalTableParserSupport .Replace('’', '\'') .Trim(); + private static List RemoveRedundantContainedFragments(IReadOnlyList fragments) + { + var redundant = new HashSet(); + + foreach (var group in fragments.GroupBy(item => (item.PageNumber, item.Top, item.Height))) + { + var ordered = group + .OrderByDescending(item => item.Width) + .ThenBy(item => item.Left) + .ToList(); + + for (var index = 0; index < ordered.Count; index++) + { + var container = ordered[index]; + if (container.Text.Length <= 1) + { + continue; + } + + for (var candidateIndex = index + 1; candidateIndex < ordered.Count; candidateIndex++) + { + var candidate = ordered[candidateIndex]; + if (candidate.Width > container.Width || + !container.Text.Contains(candidate.Text, StringComparison.Ordinal) || + !IsHorizontallyContained(candidate, container)) + { + continue; + } + + redundant.Add(candidate); + } + } + } + + return fragments + .Where(item => !redundant.Contains(item)) + .ToList(); + } + + private static bool IsHorizontallyContained(XmlTextFragment candidate, XmlTextFragment container) + { + const int containmentTolerance = 1; + + var candidateRight = candidate.Left + candidate.Width; + var containerRight = container.Left + container.Width; + + return candidate.Left >= container.Left - containmentTolerance && + candidateRight <= containerRight + containmentTolerance; + } + internal static string? NormalizeConditionKey(string conditionText) { var normalized = CollapseWhitespace(conditionText)