/
docNemo
/
clothes-graph
Обзор
Документация
Войти
/
docNemo
/
clothes-graph
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/ClothesGraph.Model/Measurements/SizeChart.cs
145 строк
5 KB
docNemo
Фундамент продукта: параметрическое построение выкроек, печать, установщик
08 авг 2026, 22:17
08 авг 2026, 22:17
cd47cce
Код
Авторство
О чём код?
using System; using System.Collections.Generic; using System.Linq; using ClothesGraph.Geometry; namespace ClothesGraph.Model.Measurements; /// <summary> /// Размерная сетка: значения мерок для каждого размера ряда. /// </summary> /// <remarks> /// Базовый размер — тот, в котором строится конструкция. Для него значения /// берутся из набора мерок, если сетка их не переопределяет: это позволяет /// работать с одним размером, вовсе не заполняя сетку, и не заводит второго /// источника истины для базовых значений. /// </remarks> public sealed class SizeChart { private readonly List<string> _sizes = []; private readonly Dictionary<string, Dictionary<MeasurementId, Length>> _values = new(StringComparer.CurrentCultureIgnoreCase); private string _baseSize; public SizeChart(string baseSize = "Базовый") { _baseSize = NormalizeSize(baseSize); _sizes.Add(_baseSize); _values[_baseSize] = []; } public IReadOnlyList<string> Sizes => _sizes; /// <summary>Размер, в котором строится конструкция.</summary> public string BaseSize => _baseSize; public bool ContainsSize(string size) => _values.ContainsKey(NormalizeSize(size)); public void AddSize(string size) { var name = NormalizeSize(size); if (_values.ContainsKey(name)) throw new InvalidOperationException($"Размер «{name}» уже есть в сетке"); _sizes.Add(name); _values[name] = []; } public bool RemoveSize(string size) { var name = NormalizeSize(size); if (string.Equals(name, _baseSize, StringComparison.CurrentCultureIgnoreCase)) throw new InvalidOperationException( "Базовый размер нельзя удалить: в нём строится конструкция"); if (!_values.Remove(name)) return false; _sizes.RemoveAll(existing => string.Equals(existing, name, StringComparison.CurrentCultureIgnoreCase)); return true; } /// <summary> /// Назначает базовый размер. Конструкция после этого пересчитывается /// по меркам выбранного размера. /// </summary> public void SetBaseSize(string size) { var name = NormalizeSize(size); if (!_values.ContainsKey(name)) throw new InvalidOperationException($"Размера «{name}» нет в сетке"); _baseSize = name; } public void SetValue(string size, MeasurementId measurement, Length value) { var name = NormalizeSize(size); if (!_values.TryGetValue(name, out var row)) throw new InvalidOperationException($"Размера «{name}» нет в сетке"); row[measurement] = value; } public bool ClearValue(string size, MeasurementId measurement) => _values.TryGetValue(NormalizeSize(size), out var row) && row.Remove(measurement); public bool TryGetValue(string size, MeasurementId measurement, out Length value) { value = Length.Zero; return _values.TryGetValue(NormalizeSize(size), out var row) && row.TryGetValue(measurement, out value); } /// <summary> /// Собирает значения всех мерок набора для указанного размера и /// перечисляет те, значения которых не заданы. /// </summary> public SizeResolution Resolve(string size, MeasurementSet measurements) { var name = NormalizeSize(size); if (!_values.TryGetValue(name, out var row)) throw new InvalidOperationException($"Размера «{name}» нет в сетке"); var isBase = string.Equals(name, _baseSize, StringComparison.CurrentCultureIgnoreCase); var values = new Dictionary<MeasurementId, Length>(); var missing = new List<Measurement>(); foreach (var measurement in measurements.Measurements) { if (row.TryGetValue(measurement.Id, out var value)) values[measurement.Id] = value; else if (isBase) values[measurement.Id] = measurement.Value; else missing.Add(measurement); } return new SizeResolution(name, values, missing); } /// <summary>Размеры, для которых заданы не все мерки набора.</summary> public IReadOnlyList<SizeResolution> FindIncompleteSizes(MeasurementSet measurements) => _sizes.Select(size => Resolve(size, measurements)) .Where(resolution => !resolution.IsComplete) .ToArray(); private static string NormalizeSize(string size) { if (string.IsNullOrWhiteSpace(size)) throw new ArgumentException("Название размера не может быть пустым", nameof(size)); return size.Trim(); } }