using System.Text.Json; namespace HSchool.Server.Game; /// Generation defaults and prompt templates loaded from swarmui.json next to the server. internal sealed class SwarmUiSettings { public string Model { get; init; } = ""; public int Steps { get; init; } = 8; public double CfgScale { get; init; } = 1; public int ClipSkip { get; init; } = 1; public string Sampler { get; init; } = "euler"; public string Scheduler { get; init; } = ""; public long Seed { get; init; } = -1; public string Positive { get; init; } = ""; public string Negative { get; init; } = ""; public SwarmUiPreset Avatar { get; init; } = new(); public SwarmUiPreset Custom { get; init; } = new(); public SwarmUiPreset FullBody { get; init; } = new(); public SwarmUiPreset PresetFor(PortraitKind kind) => kind switch { PortraitKind.Avatar => Avatar, PortraitKind.Custom => Custom, PortraitKind.Full => FullBody, _ => throw new ArgumentOutOfRangeException(nameof(kind)), }; internal sealed class SwarmUiPreset { public int Width { get; init; } = 512; public int Height { get; init; } = 512; public string Positive { get; init; } = ""; } private static readonly JsonSerializerOptions Json = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, PropertyNameCaseInsensitive = true, }; public static SwarmUiSettings Load(IHostEnvironment environment, ILogger logger) { var path = Path.Combine(environment.ContentRootPath, "swarmui.json"); if (!File.Exists(path)) { logger.LogWarning("SwarmUI settings file {Path} is missing; portrait generation will use empty defaults.", path); return new SwarmUiSettings(); } try { var json = File.ReadAllText(path); return JsonSerializer.Deserialize(json, Json) ?? new SwarmUiSettings(); } catch (Exception ex) { logger.LogWarning(ex, "Could not read SwarmUI settings from {Path}.", path); return new SwarmUiSettings(); } } }