Implement phase 5 critical branch extraction
This commit is contained in:
114
src/RolemasterDb.ImportTool/Parsing/CriticalCellTextParser.cs
Normal file
114
src/RolemasterDb.ImportTool/Parsing/CriticalCellTextParser.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
namespace RolemasterDb.ImportTool.Parsing;
|
||||
|
||||
internal static class CriticalCellTextParser
|
||||
{
|
||||
internal static CriticalCellParseContent Parse(IReadOnlyList<string> lines, ISet<string> affixLegendSymbols)
|
||||
{
|
||||
var validationErrors = new List<string>();
|
||||
var branchStartIndexes = FindBranchStartIndexes(lines);
|
||||
var baseLineCount = branchStartIndexes.Count == 0 ? lines.Count : branchStartIndexes[0];
|
||||
var baseLines = lines.Take(baseLineCount).ToList();
|
||||
var branches = new List<ParsedCriticalBranch>();
|
||||
|
||||
validationErrors.AddRange(ValidateSegmentCount(baseLines, affixLegendSymbols, "Base content"));
|
||||
|
||||
for (var branchIndex = 0; branchIndex < branchStartIndexes.Count; branchIndex++)
|
||||
{
|
||||
var startIndex = branchStartIndexes[branchIndex];
|
||||
var endIndex = branchIndex == branchStartIndexes.Count - 1
|
||||
? lines.Count
|
||||
: branchStartIndexes[branchIndex + 1];
|
||||
|
||||
branches.Add(ParseBranch(
|
||||
lines.Skip(startIndex).Take(endIndex - startIndex).ToList(),
|
||||
branchIndex + 1,
|
||||
affixLegendSymbols,
|
||||
validationErrors));
|
||||
}
|
||||
|
||||
var (rawCellText, descriptionText, rawAffixText) = BuildTextSections(baseLines, affixLegendSymbols);
|
||||
return new CriticalCellParseContent(baseLines, rawCellText, descriptionText, rawAffixText, branches, validationErrors);
|
||||
}
|
||||
|
||||
private static ParsedCriticalBranch ParseBranch(
|
||||
IReadOnlyList<string> branchLines,
|
||||
int sortOrder,
|
||||
ISet<string> affixLegendSymbols,
|
||||
List<string> validationErrors)
|
||||
{
|
||||
var firstLine = branchLines[0];
|
||||
var separatorIndex = firstLine.IndexOf(':', StringComparison.Ordinal);
|
||||
var conditionText = CriticalTableParserSupport.CollapseWhitespace(firstLine[..separatorIndex]);
|
||||
var firstPayloadLine = CriticalTableParserSupport.CollapseWhitespace(firstLine[(separatorIndex + 1)..]);
|
||||
var payloadLines = new List<string>();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(firstPayloadLine))
|
||||
{
|
||||
payloadLines.Add(firstPayloadLine);
|
||||
}
|
||||
|
||||
foreach (var continuationLine in branchLines.Skip(1))
|
||||
{
|
||||
var normalized = CriticalTableParserSupport.CollapseWhitespace(continuationLine);
|
||||
if (!string.IsNullOrWhiteSpace(normalized))
|
||||
{
|
||||
payloadLines.Add(normalized);
|
||||
}
|
||||
}
|
||||
|
||||
validationErrors.AddRange(ValidateSegmentCount(payloadLines, affixLegendSymbols, $"Branch '{conditionText}'"));
|
||||
|
||||
var (_, descriptionText, rawAffixText) = BuildTextSections(payloadLines, affixLegendSymbols);
|
||||
return new ParsedCriticalBranch(
|
||||
"conditional",
|
||||
CriticalTableParserSupport.NormalizeConditionKey(conditionText),
|
||||
conditionText,
|
||||
string.Join(Environment.NewLine, branchLines),
|
||||
descriptionText,
|
||||
rawAffixText,
|
||||
sortOrder);
|
||||
}
|
||||
|
||||
private static List<int> FindBranchStartIndexes(IReadOnlyList<string> lines)
|
||||
{
|
||||
var branchStartIndexes = new List<int>();
|
||||
|
||||
for (var index = 0; index < lines.Count; index++)
|
||||
{
|
||||
if (CriticalTableParserSupport.IsConditionalBranchStartLine(lines[index]))
|
||||
{
|
||||
branchStartIndexes.Add(index);
|
||||
}
|
||||
}
|
||||
|
||||
return branchStartIndexes;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<string> ValidateSegmentCount(
|
||||
IReadOnlyList<string> lines,
|
||||
ISet<string> affixLegendSymbols,
|
||||
string scope)
|
||||
{
|
||||
if (lines.Count == 0)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var segmentCount = CriticalTableParserSupport.CountLineTypeSegments(lines, affixLegendSymbols);
|
||||
return segmentCount > 2
|
||||
? [$"{scope} interleaves prose and affix lines."]
|
||||
: [];
|
||||
}
|
||||
|
||||
private static (string RawText, string DescriptionText, string? RawAffixText) BuildTextSections(
|
||||
IReadOnlyList<string> lines,
|
||||
ISet<string> affixLegendSymbols)
|
||||
{
|
||||
var rawText = string.Join(Environment.NewLine, lines);
|
||||
var rawAffixLines = lines.Where(line => CriticalTableParserSupport.IsAffixLikeLine(line, affixLegendSymbols)).ToList();
|
||||
var descriptionLines = lines.Where(line => !CriticalTableParserSupport.IsAffixLikeLine(line, affixLegendSymbols)).ToList();
|
||||
var descriptionText = CriticalTableParserSupport.CollapseWhitespace(string.Join(' ', descriptionLines));
|
||||
var rawAffixText = rawAffixLines.Count == 0 ? null : string.Join(Environment.NewLine, rawAffixLines);
|
||||
return (rawText, descriptionText, rawAffixText);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user