250 lines
7.4 KiB
C#
250 lines
7.4 KiB
C#
using System.Text;
|
|
|
|
namespace SessionZero.Data;
|
|
|
|
public class SzfGenerator
|
|
{
|
|
private readonly SzfGeneratorOptions _options;
|
|
|
|
public SzfGenerator(SzfGeneratorOptions? options = null)
|
|
{
|
|
_options = options ?? new SzfGeneratorOptions();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate SZF content from any SzfObject
|
|
/// </summary>
|
|
public string Generate(SzfObject obj)
|
|
{
|
|
var builder = new StringBuilder();
|
|
|
|
// Generate header
|
|
GenerateHeader(builder, obj);
|
|
|
|
// Generate metadata section
|
|
GenerateMetadataSection(builder, obj);
|
|
|
|
// Generate type-specific content
|
|
GenerateTypeSpecificContent(builder, obj);
|
|
|
|
return builder.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate the SZF header (!type: and !schema:)
|
|
/// </summary>
|
|
private void GenerateHeader(StringBuilder builder, SzfObject obj)
|
|
{
|
|
var objectTypeString = obj.ObjectType switch
|
|
{
|
|
SzfObjectType.Dataset => "dataset",
|
|
SzfObjectType.CharacterTemplate => "character_template",
|
|
SzfObjectType.Character => "character",
|
|
SzfObjectType.Session => "session",
|
|
_ => throw new SzfGenerateException($"Unsupported object type: {obj.ObjectType}")
|
|
};
|
|
|
|
builder.AppendLine($"!type: {objectTypeString}");
|
|
builder.AppendLine($"!schema: {obj.SchemaVersion}");
|
|
builder.AppendLine();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate the common metadata section
|
|
/// </summary>
|
|
private void GenerateMetadataSection(StringBuilder builder, SzfObject obj)
|
|
{
|
|
builder.AppendLine("[Metadata]");
|
|
|
|
// Standard metadata fields
|
|
WriteField(builder, "Name", "text", obj.Name);
|
|
WriteField(builder, "Version", "text", obj.Version);
|
|
WriteField(builder, "GUID", "text", obj.Id.ToString());
|
|
WriteField(builder, "Description", "text-field", obj.Description);
|
|
WriteField(builder, "Author", "text", obj.Author);
|
|
|
|
// Type-specific metadata
|
|
GenerateTypeSpecificMetadata(builder, obj);
|
|
|
|
builder.AppendLine();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate type-specific metadata fields
|
|
/// </summary>
|
|
private void GenerateTypeSpecificMetadata(StringBuilder builder, SzfObject obj)
|
|
{
|
|
switch (obj)
|
|
{
|
|
case Dataset dataset:
|
|
WriteField(builder, "Type", "text", dataset.DatasetType);
|
|
if (!string.IsNullOrEmpty(dataset.ImageUrl))
|
|
WriteField(builder, "ImageUrl", "text", dataset.ImageUrl);
|
|
break;
|
|
// Add other types as they're implemented
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate type-specific content sections
|
|
/// </summary>
|
|
private void GenerateTypeSpecificContent(StringBuilder builder, SzfObject obj)
|
|
{
|
|
switch (obj)
|
|
{
|
|
case Dataset dataset:
|
|
GenerateDatasetContent(builder, dataset);
|
|
break;
|
|
// Add other types as they're implemented
|
|
default:
|
|
throw new SzfGenerateException($"Content generation not implemented for type: {obj.GetType().Name}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate dataset-specific content (entries, sections, fields)
|
|
/// </summary>
|
|
private void GenerateDatasetContent(StringBuilder builder, Dataset dataset)
|
|
{
|
|
foreach (var entry in dataset.Entries)
|
|
{
|
|
// Entry header
|
|
builder.AppendLine($"[Entry: {entry.Name}]");
|
|
|
|
// Entry fields
|
|
foreach (var field in entry.Fields)
|
|
{
|
|
WriteDatasetField(builder, field);
|
|
}
|
|
|
|
// Entry sections
|
|
foreach (var section in entry.Sections)
|
|
{
|
|
GenerateDatasetSection(builder, section, $"Entry.{entry.Name}");
|
|
}
|
|
|
|
builder.AppendLine();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate dataset sections recursively
|
|
/// </summary>
|
|
private void GenerateDatasetSection(StringBuilder builder, DatasetSection section, string parentPath)
|
|
{
|
|
var sectionPath = $"{parentPath}.{section.Name}";
|
|
builder.AppendLine($"[{sectionPath}]");
|
|
|
|
// Section fields
|
|
foreach (var field in section.Fields)
|
|
{
|
|
WriteDatasetField(builder, field);
|
|
}
|
|
|
|
// Subsections
|
|
foreach (var subsection in section.Subsections)
|
|
{
|
|
GenerateDatasetSection(builder, subsection, sectionPath);
|
|
}
|
|
|
|
builder.AppendLine();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write a dataset field in SZF format
|
|
/// </summary>
|
|
private void WriteDatasetField(StringBuilder builder, DatasetField field)
|
|
{
|
|
var typeString = field.Type switch
|
|
{
|
|
DatasetFieldType.Text => "text",
|
|
DatasetFieldType.TextField => "text-field",
|
|
DatasetFieldType.Number => "number",
|
|
DatasetFieldType.Boolean => "bool",
|
|
DatasetFieldType.Group => "group",
|
|
DatasetFieldType.Calculated => "calculated",
|
|
DatasetFieldType.System => "system",
|
|
DatasetFieldType.DatasetReference => "dataset-reference",
|
|
DatasetFieldType.DatasetType => "dataset-type",
|
|
DatasetFieldType.DatasetReferenceMultiple => "dataset-reference-multiple",
|
|
DatasetFieldType.DatasetTypeMultiple => "dataset-type-multiple",
|
|
_ => "text"
|
|
};
|
|
|
|
var value = FormatFieldValue(field.Value, field.Type);
|
|
WriteField(builder, field.Name, typeString, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write a field in SZF format: Name (type) = value
|
|
/// </summary>
|
|
private void WriteField(StringBuilder builder, string name, string type, object? value)
|
|
{
|
|
var formattedValue = value?.ToString() ?? string.Empty;
|
|
|
|
if (_options.IndentFields)
|
|
{
|
|
builder.AppendLine($"{_options.Indent}{name} ({type}) = {formattedValue}");
|
|
}
|
|
else
|
|
{
|
|
builder.AppendLine($"{name} ({type}) = {formattedValue}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Format field values based on their type
|
|
/// </summary>
|
|
private string FormatFieldValue(object? value, DatasetFieldType fieldType)
|
|
{
|
|
if (value == null)
|
|
return string.Empty;
|
|
|
|
return fieldType switch
|
|
{
|
|
DatasetFieldType.Boolean => (bool)value ? "true" : "false",
|
|
DatasetFieldType.Number => value.ToString() ?? "0",
|
|
_ => value.ToString() ?? string.Empty
|
|
};
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configuration options for SZF generation
|
|
/// </summary>
|
|
public class SzfGeneratorOptions
|
|
{
|
|
/// <summary>
|
|
/// Whether to indent field lines within sections
|
|
/// </summary>
|
|
public bool IndentFields { get; set; } = false;
|
|
|
|
/// <summary>
|
|
/// Indent string to use for fields (if IndentFields is true)
|
|
/// </summary>
|
|
public string Indent { get; set; } = " ";
|
|
|
|
/// <summary>
|
|
/// Whether to include empty sections
|
|
/// </summary>
|
|
public bool IncludeEmptySections { get; set; } = false;
|
|
|
|
/// <summary>
|
|
/// Whether to include fields with null/empty values
|
|
/// </summary>
|
|
public bool IncludeEmptyFields { get; set; } = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Exception thrown during SZF generation
|
|
/// </summary>
|
|
public class SzfGenerateException : Exception
|
|
{
|
|
public SzfGenerateException(string message) : base(message)
|
|
{
|
|
}
|
|
|
|
public SzfGenerateException(string message, Exception innerException) : base(message, innerException)
|
|
{
|
|
}
|
|
} |