Multi-Platform Package Manager for Stable Diffusion
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

130 lines
5.2 KiB

using System.Collections.Immutable;
using System.Diagnostics;
namespace StabilityMatrix.Core.Models;
public readonly record struct LaunchOptionCard
{
public required string Title { get; init; }
public required LaunchOptionType Type { get; init; }
public required IReadOnlyList<LaunchOption> Options { get; init; }
public string? Description { get; init; }
public static LaunchOptionCard FromDefinition(LaunchOptionDefinition definition)
{
return new LaunchOptionCard
{
Title = definition.Name,
Description = definition.Description,
Type = definition.Type,
Options = definition.Options.Select(s =>
{
var option = new LaunchOption
{
Name = s,
Type = definition.Type,
DefaultValue = definition.DefaultValue
};
return option;
}).ToImmutableArray()
};
}
/// <summary>
/// Yield LaunchOptionCards given definitions and launch args to load
/// </summary>
/// <param name="definitions"></param>
/// <param name="launchArgs"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public static IEnumerable<LaunchOptionCard> FromDefinitions(
IEnumerable<LaunchOptionDefinition> definitions,
IEnumerable<LaunchOption> launchArgs)
{
// During card creation, store dict of options with initial values
var initialOptions = new Dictionary<string, object>();
// To dictionary ignoring duplicates
var launchArgsDict = launchArgs
.ToLookup(launchArg => launchArg.Name)
.ToDictionary(
group => group.Key,
group => group.First()
);
// Create cards
foreach (var definition in definitions)
{
// Check that non-bool types have exactly one option
if (definition.Type != LaunchOptionType.Bool && definition.Options.Count != 1)
{
throw new InvalidOperationException(
$"Definition: '{definition.Name}' has {definition.Options.Count} options," +
$" it must have exactly 1 option for non-bool types");
}
// Store initial values
if (definition.InitialValue != null)
{
// For bool types, initial value can be string (single/multiple options) or bool (single option)
if (definition.Type == LaunchOptionType.Bool)
{
// For single option, check bool
if (definition.Options.Count == 1 && definition.InitialValue is bool boolValue)
{
initialOptions[definition.Options.First()] = boolValue;
}
else
{
// For single/multiple options (string only)
var option = definition.Options.FirstOrDefault(opt => opt.Equals(definition.InitialValue));
if (option == null)
{
throw new InvalidOperationException(
$"Definition '{definition.Name}' has InitialValue of '{definition.InitialValue}', but it was not found in options:" +
$" '{string.Join(",", definition.Options)}'");
}
initialOptions[option] = true;
}
}
else
{
// Otherwise store initial value for first option
initialOptions[definition.Options.First()] = definition.InitialValue;
}
}
// Create the new card
var card = new LaunchOptionCard
{
Title = definition.Name,
Description = definition.Description,
Type = definition.Type,
Options = definition.Options.Select(s =>
{
// Parse defaults and user loaded values here
var userOption = launchArgsDict.GetValueOrDefault(s);
var userValue = userOption?.OptionValue;
// If no user value, check set initial value
if (userValue is null)
{
var initialValue = initialOptions.GetValueOrDefault(s);
userValue ??= initialValue;
Debug.WriteLineIf(initialValue != null,
$"Using initial value {initialValue} for option {s}");
}
var option = new LaunchOption
{
Name = s,
Type = definition.Type,
DefaultValue = definition.DefaultValue,
OptionValue = userValue
};
return option;
}).ToImmutableArray()
};
yield return card;
}
}
}