using System.Text.Json; using System.Text.Json.Serialization; using Repoverse.Core.Model; namespace Repoverse.Core.Generation; /// /// Hand-authored world design (ยง83). Overrides augment procedural output; any repo /// not listed is generated normally. /// public sealed class Overrides { public sealed record Entry { public SemanticCategory? Category { get; init; } public District? District { get; init; } public BuildingArchetype? Archetype { get; init; } public bool Landmark { get; init; } } private readonly Dictionary _entries; public string Source { get; } public Overrides(IReadOnlyDictionary entries, string source) { _entries = entries.ToDictionary(kv => kv.Key.ToLowerInvariant(), kv => kv.Value); Source = source; } public static Overrides Empty { get; } = new(new Dictionary(), "(none)"); public static Overrides Load(string path) { var entries = JsonSerializer.Deserialize>(File.ReadAllText(path), Json.Options) ?? throw new InvalidDataException($"Override file '{path}' is empty."); return new Overrides(entries, Path.GetFileName(path)); } private Entry? Get(RepoId id) => _entries.GetValueOrDefault(id.Key); public SemanticCategory? Category(RepoId id) => Get(id)?.Category; public District? District(RepoId id) => Get(id)?.District; public BuildingArchetype? Archetype(RepoId id) => Get(id)?.Archetype; public bool Landmark(RepoId id) => Get(id)?.Landmark ?? false; } /// Shared serializer settings: enums as strings so manifests stay human-readable and diffable. public static class Json { public static JsonSerializerOptions Options { get; } = new() { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase), new RepoIdConverter() }, }; private sealed class RepoIdConverter : JsonConverter { public override RepoId Read(ref Utf8JsonReader reader, Type t, JsonSerializerOptions o) => RepoId.Parse(reader.GetString()!); public override void Write(Utf8JsonWriter writer, RepoId value, JsonSerializerOptions o) => writer.WriteStringValue($"{value.Owner}/{value.Name}"); } }