/
docNemo
/
clothes-graph
Обзор
Документация
Войти
/
docNemo
/
clothes-graph
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/ClothesGraph.Model/Measurements/MeasurementSet.cs
116 строк
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> /// Значение мерки здесь — значение в базовом размере, то есть в том, в котором /// строится конструкция. Значения остальных размеров живут в размерной сетке /// (<see cref="SizeChart"/>): она задаёт весь ряд, а набор мерок — точку отсчёта. /// </remarks> public sealed class MeasurementSet { private readonly Dictionary<MeasurementId, Measurement> _byId = new(); private readonly Dictionary<string, Measurement> _byName = new(StringComparer.CurrentCultureIgnoreCase); public IReadOnlyCollection<Measurement> Measurements => _byId.Values; public int Count => _byId.Count; /// <summary>Добавляет мерку. Имя должно быть свободно.</summary> /// <exception cref="MeasurementNameConflictException">Имя занято другой меркой.</exception> public Measurement Add(string displayName, Length value, string? description = null) { var name = Measurement.NormalizeName(displayName); if (_byName.TryGetValue(name, out var conflicting)) throw new MeasurementNameConflictException(name, conflicting); var measurement = new Measurement(MeasurementId.New(), name, value, description); _byId.Add(measurement.Id, measurement); _byName.Add(name, measurement); return measurement; } /// <summary> /// Добавляет мерку с заданным идентификатором. /// </summary> /// <remarks> /// Нужно при чтении файла: формулы ссылаются на идентификаторы, и выдача /// новых при загрузке сделала бы весь сохранённый чертёж неразрешимым. /// </remarks> internal Measurement AddWithId( MeasurementId id, string displayName, Length value, string? description = null) { var name = Measurement.NormalizeName(displayName); if (_byId.ContainsKey(id)) throw new InvalidOperationException($"Мерка {id} уже есть в наборе"); if (_byName.TryGetValue(name, out var conflicting)) throw new MeasurementNameConflictException(name, conflicting); var measurement = new Measurement(id, name, value, description); _byId.Add(id, measurement); _byName.Add(name, measurement); return measurement; } /// <summary> /// Переименовывает мерку. Формулы ссылаются на идентификатор, поэтому /// построения, использующие мерку, остаются работоспособными. /// </summary> /// <exception cref="MeasurementNameConflictException">Имя занято другой меркой.</exception> public void Rename(MeasurementId id, string newDisplayName) { var measurement = Get(id); var name = Measurement.NormalizeName(newDisplayName); if (_byName.TryGetValue(name, out var conflicting) && conflicting.Id != id) throw new MeasurementNameConflictException(name, conflicting); _byName.Remove(measurement.DisplayName); measurement.DisplayName = name; _byName[name] = measurement; } public void SetValue(MeasurementId id, Length value) => Get(id).Value = value; public bool Remove(MeasurementId id) { if (!_byId.TryGetValue(id, out var measurement)) return false; _byId.Remove(id); _byName.Remove(measurement.DisplayName); return true; } public bool Contains(MeasurementId id) => _byId.ContainsKey(id); public Measurement Get(MeasurementId id) => _byId.TryGetValue(id, out var measurement) ? measurement : throw new KeyNotFoundException($"Мерка {id} не найдена"); public bool TryGet(MeasurementId id, out Measurement? measurement) => _byId.TryGetValue(id, out measurement); /// <summary>Поиск по отображаемому имени без учёта регистра.</summary> public Measurement? FindByName(string displayName) => string.IsNullOrWhiteSpace(displayName) ? null : _byName.GetValueOrDefault(displayName.Trim()); public IReadOnlyList<MeasurementId> Ids => _byId.Keys.ToArray(); }