Files
ai-images/Source/AIImages/Validation/SettingsValidator.cs

288 lines
9.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using AIImages.Settings;
namespace AIImages.Validation
{
/// <summary>
/// Валидатор для настроек мода AI Images
/// </summary>
public static class SettingsValidator
{
/// <summary>
/// Валидирует все настройки и возвращает список ошибок
/// </summary>
public static ValidationResult Validate(AIImagesModSettings settings)
{
var result = new ValidationResult();
if (settings == null)
{
result.AddError("Settings object is null");
return result;
}
// Валидация API endpoint
ValidateApiEndpoint(settings.apiEndpoint, result);
// Валидация размеров изображения
ValidateImageDimensions(settings.width, settings.height, result);
// Валидация steps
ValidateSteps(settings.steps, result);
// Валидация CFG scale
ValidateCfgScale(settings.cfgScale, result);
// Валидация sampler и scheduler
ValidateSamplerAndScheduler(
settings.selectedSampler,
settings.selectedScheduler,
result
);
// Валидация пути сохранения
ValidateSavePath(settings.savePath, result);
return result;
}
private static void ValidateApiEndpoint(string endpoint, ValidationResult result)
{
if (string.IsNullOrWhiteSpace(endpoint))
{
result.AddError("API endpoint cannot be empty");
return;
}
if (!Uri.TryCreate(endpoint, UriKind.Absolute, out Uri uri))
{
result.AddError($"Invalid API endpoint format: {endpoint}");
return;
}
if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)
{
result.AddWarning($"API endpoint should use HTTP or HTTPS protocol: {endpoint}");
}
// Проверка на localhost/127.0.0.1
if (
uri.Host != "localhost"
&& uri.Host != "127.0.0.1"
&& !uri.Host.StartsWith("192.168.")
)
{
result.AddWarning(
"API endpoint is not pointing to a local address. Make sure the API is accessible."
);
}
}
private static void ValidateImageDimensions(int width, int height, ValidationResult result)
{
const int minDimension = 64;
const int maxDimension = 2048;
const int recommendedMin = 512;
const int recommendedMax = 1024;
if (width < minDimension || width > maxDimension)
{
result.AddError(
$"Width must be between {minDimension} and {maxDimension}. Current: {width}"
);
}
if (height < minDimension || height > maxDimension)
{
result.AddError(
$"Height must be between {minDimension} and {maxDimension}. Current: {height}"
);
}
// Проверка кратности 8 (рекомендация для Stable Diffusion)
if (width % 8 != 0)
{
result.AddWarning(
$"Width should be divisible by 8 for optimal results. Current: {width}"
);
}
if (height % 8 != 0)
{
result.AddWarning(
$"Height should be divisible by 8 for optimal results. Current: {height}"
);
}
// Предупреждения о производительности
if (width > recommendedMax || height > recommendedMax)
{
result.AddWarning(
$"Large image dimensions ({width}x{height}) may result in slow generation and high memory usage"
);
}
if (width < recommendedMin || height < recommendedMin)
{
result.AddWarning(
$"Small image dimensions ({width}x{height}) may result in lower quality"
);
}
}
private static void ValidateSteps(int steps, ValidationResult result)
{
const int minSteps = 1;
const int maxSteps = 150;
const int recommendedMin = 20;
const int recommendedMax = 50;
if (steps < minSteps || steps > maxSteps)
{
result.AddError(
$"Steps must be between {minSteps} and {maxSteps}. Current: {steps}"
);
}
if (steps < recommendedMin)
{
result.AddWarning(
$"Low steps value ({steps}) may result in lower quality. Recommended: {recommendedMin}-{recommendedMax}"
);
}
if (steps > recommendedMax)
{
result.AddWarning(
$"High steps value ({steps}) may result in slow generation with minimal quality improvement"
);
}
}
private static void ValidateCfgScale(float cfgScale, ValidationResult result)
{
const float minCfg = 1.0f;
const float maxCfg = 30.0f;
const float recommendedMin = 5.0f;
const float recommendedMax = 15.0f;
if (cfgScale < minCfg || cfgScale > maxCfg)
{
result.AddError(
$"CFG Scale must be between {minCfg} and {maxCfg}. Current: {cfgScale}"
);
}
if (cfgScale < recommendedMin)
{
result.AddWarning(
$"Low CFG scale ({cfgScale}) may ignore prompt. Recommended: {recommendedMin}-{recommendedMax}"
);
}
if (cfgScale > recommendedMax)
{
result.AddWarning(
$"High CFG scale ({cfgScale}) may result in over-saturated or distorted images"
);
}
}
private static void ValidateSamplerAndScheduler(
string sampler,
string scheduler,
ValidationResult result
)
{
if (string.IsNullOrWhiteSpace(sampler))
{
result.AddWarning("Sampler is not selected. A default sampler will be used.");
}
if (string.IsNullOrWhiteSpace(scheduler))
{
result.AddWarning("Scheduler is not selected. A default scheduler will be used.");
}
}
private static void ValidateSavePath(string savePath, ValidationResult result)
{
if (string.IsNullOrWhiteSpace(savePath))
{
result.AddError("Save path cannot be empty");
return;
}
// Проверка на недопустимые символы в пути
char[] invalidChars = System.IO.Path.GetInvalidPathChars();
if (savePath.IndexOfAny(invalidChars) >= 0)
{
result.AddError($"Save path contains invalid characters: {savePath}");
}
}
}
/// <summary>
/// Результат валидации настроек
/// </summary>
public class ValidationResult
{
private readonly List<string> _errors = new List<string>();
private readonly List<string> _warnings = new List<string>();
public bool IsValid => _errors.Count == 0;
public bool HasWarnings => _warnings.Count > 0;
public IReadOnlyList<string> Errors => _errors;
public IReadOnlyList<string> Warnings => _warnings;
public void AddError(string error)
{
if (!string.IsNullOrWhiteSpace(error))
{
_errors.Add(error);
}
}
public void AddWarning(string warning)
{
if (!string.IsNullOrWhiteSpace(warning))
{
_warnings.Add(warning);
}
}
public string GetErrorsAsString()
{
return string.Join("\n", _errors);
}
public string GetWarningsAsString()
{
return string.Join("\n", _warnings);
}
public string GetAllMessagesAsString()
{
var messages = new List<string>();
if (_errors.Count > 0)
{
messages.Add("Errors:");
messages.AddRange(_errors);
}
if (_warnings.Count > 0)
{
if (messages.Count > 0)
messages.Add("");
messages.Add("Warnings:");
messages.AddRange(_warnings);
}
return string.Join("\n", messages);
}
}
}