SessionZeroWasm/SessionZero/Data/CharacterTemplate.cs

209 lines
7.3 KiB
C#

using System.Collections.Generic;
using System.Linq;
namespace SessionZero.Data;
[SzfObject("character_template")]
public class CharacterTemplate : SzfObject
{
public string GameSystem { get; set; } = string.Empty;
public List<RequiredDatasetReference> RequiredDatasets { get; set; } = new();
public List<TemplateSection> Sections { get; set; } = new();
public override void PopulateFromMetadata(Dictionary<string, SzfField> metadata)
{
base.PopulateFromMetadata(metadata);
if (metadata.TryGetValue("GameSystem", out var gameSystemField))
GameSystem = gameSystemField.Value?.ToString() ?? string.Empty;
}
public override void ParseSections(List<SzfSection> sections)
{
// Parse [Required Datasets] section
var requiredDatasetsSection =
sections.FirstOrDefault(s => s.Name.Equals("Required Datasets", StringComparison.OrdinalIgnoreCase));
if (requiredDatasetsSection != null)
{
foreach (var field in requiredDatasetsSection.Fields)
{
var reference = DatasetReference.Parse(field.Value?.ToString() ?? string.Empty);
if (reference != null)
{
RequiredDatasets.Add(new RequiredDatasetReference
{
Alias = field.Name,
Reference = reference
});
}
}
}
// Parse [Section: ...] and [Section....] sections
foreach (var szfSection in sections)
{
if (szfSection.Name.StartsWith("Section:", StringComparison.OrdinalIgnoreCase))
{
var templateSection = new TemplateSection
{
Name = szfSection.Name.Replace("Section:", "").Trim()
};
foreach (var field in szfSection.Fields)
{
templateSection.Fields.Add(ConvertToTemplateField(field));
}
Sections.Add(templateSection);
}
else if (szfSection.Name.StartsWith("Section.", StringComparison.OrdinalIgnoreCase))
{
// Handle subsections by finding their parent
var parts = szfSection.Name.Split('.');
if (parts.Length >= 2)
{
var parentSectionName = parts[0] + ":" + parts[1].Trim(); // Reconstruct parent name
var parentSection = Sections.FirstOrDefault(s =>
s.Name.Equals(parentSectionName.Replace("Section:", "").Trim(),
StringComparison.OrdinalIgnoreCase));
if (parentSection != null)
{
var subSection = new TemplateSection
{
Name = string.Join(".", parts.Skip(2)).Trim() // Name for the subsection
};
foreach (var field in szfSection.Fields)
{
subSection.Fields.Add(ConvertToTemplateField(field));
}
parentSection.Subsections.Add(subSection);
}
}
}
}
}
private TemplateField ConvertToTemplateField(SzfField szfField)
{
return new TemplateField
{
Name = szfField.Name,
Type = ParseDatasetFieldType(szfField.Type),
Value = szfField.Value
};
}
private DatasetFieldType ParseDatasetFieldType(string typeString)
{
return typeString.ToLower() switch
{
"text" => DatasetFieldType.Text,
"text-field" => DatasetFieldType.TextField,
"number" => DatasetFieldType.Number,
"bool" => DatasetFieldType.Boolean,
"calculated" => DatasetFieldType.Calculated,
"system" => DatasetFieldType.System,
"dataset-reference" => DatasetFieldType.DatasetReference,
"dataset-type" => DatasetFieldType.DatasetType,
"dataset-reference-multiple" => DatasetFieldType.DatasetReferenceMultiple,
"dataset-type-multiple" => DatasetFieldType.DatasetTypeMultiple,
"group" => DatasetFieldType.Group,
_ => DatasetFieldType.Text // Default to text if unknown
};
}
public override void GenerateMetadata(SzfFieldWriter writer)
{
// Call base to ensure common metadata is generated first if base had any specific generation logic
base.GenerateMetadata(writer);
writer.WriteField("GameSystem", "text", GameSystem);
}
public override void GenerateContent(SzfFieldWriter writer)
{
// Generate [Required Datasets] section
if (RequiredDatasets.Any() || writer.Options.IncludeEmptySections)
{
writer.AppendSectionHeader("Required Datasets");
foreach (var reqDataset in RequiredDatasets)
{
writer.WriteField(reqDataset.Alias, "dataset-reference", reqDataset.Reference?.ToString());
}
writer.AppendLine();
}
// Generate Template Sections
foreach (var section in Sections)
{
GenerateTemplateSection(writer, section, "Section");
writer.AppendLine();
}
}
private void GenerateTemplateSection(SzfFieldWriter writer, TemplateSection section, string parentPath)
{
var currentPath = $"{parentPath}: {section.Name}";
writer.AppendSectionHeader(currentPath);
foreach (var field in section.Fields)
{
writer.WriteField(field.Name, field.Type, field.Value);
}
foreach (var subSection in section.Subsections)
{
GenerateTemplateSubSection(writer, subSection, $"Section.{section.Name}");
}
}
private void GenerateTemplateSubSection(SzfFieldWriter writer, TemplateSection subSection, string parentPath)
{
var currentPath = $"{parentPath}.{subSection.Name}";
writer.AppendSectionHeader(currentPath);
foreach (var field in subSection.Fields)
{
writer.WriteField(field.Name, field.Type, field.Value);
}
foreach (var nestedSubSection in subSection.Subsections)
{
// Handle deeper nesting if needed, recursively calling this method
GenerateTemplateSubSection(writer, nestedSubSection, currentPath);
}
}
public override SzfValidationResult Validate()
{
var result = base.Validate(); // Run base validation first
if (string.IsNullOrWhiteSpace(GameSystem))
result.AddError("GameSystem is required for CharacterTemplate");
return result;
}
}
public class RequiredDatasetReference
{
public string Alias { get; set; } = string.Empty;
public DatasetReference? Reference { get; set; }
}
public class TemplateSection
{
public string Name { get; set; } = string.Empty;
public List<TemplateField> Fields { get; set; } = new();
public List<TemplateSection> Subsections { get; set; } = new(); // For nested sections
}
public class TemplateField
{
public string Name { get; set; } = string.Empty;
public DatasetFieldType Type { get; set; }
public object? Value { get; set; }
}