/
docNemo
/
clothes-graph
Обзор
Документация
Войти
/
docNemo
/
clothes-graph
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/ClothesGraph.Model/Grading/GradingService.cs
143 строки
5 KB
docNemo
Фундамент продукта: параметрическое построение выкроек, печать, установщик
08 авг 2026, 22:17
08 авг 2026, 22:17
cd47cce
Код
Авторство
О чём код?
using System; using System.Collections.Generic; using System.Linq; using ClothesGraph.Geometry; using ClothesGraph.Model.Drafting; using ClothesGraph.Model.Measurements; namespace ClothesGraph.Model.Grading; /// <summary>Состояние одного размера ряда.</summary> public sealed record SizeReport( string Size, bool IsBase, IReadOnlyList<Measurement> MissingMeasurements, IReadOnlyList<NodeFailure> Failures, int AdjustmentCount) { /// <summary>Размер можно построить и вывести.</summary> public bool IsReady => MissingMeasurements.Count == 0 && Failures.Count == 0; public string Describe() { if (IsReady) return AdjustmentCount > 0 ? $"{Size}: готов, поправок {AdjustmentCount}" : $"{Size}: готов"; var problems = new List<string>(); if (MissingMeasurements.Count > 0) problems.Add($"не заданы мерки ({MissingMeasurements.Count})"); if (Failures.Count > 0) problems.Add($"неразрешимых построений {Failures.Count}"); return $"{Size}: {string.Join(", ", problems)}"; } } /// <summary> /// Получение размерного ряда из одной конструкции. /// </summary> /// <remarks> /// Каждый размер считается своим вычислителем: они хранят кэш геометрии, и /// один общий пришлось бы сбрасывать при каждом переключении размера, отчего /// наложенный просмотр ряда пересчитывал бы всё заново на каждый кадр. /// </remarks> public sealed class GradingService { private readonly PatternDocument _document; private readonly Dictionary<string, DraftEvaluator> _evaluators = new(StringComparer.CurrentCultureIgnoreCase); public GradingService(PatternDocument document) => _document = document; /// <summary>Вычисляет чертёж в указанном размере с учётом ручных поправок.</summary> public DraftEvaluation Evaluate(string size) { var resolution = _document.Sizes.Resolve(size, _document.Measurements); if (!_evaluators.TryGetValue(size, out var evaluator)) _evaluators[size] = evaluator = new DraftEvaluator(_document.Draft); return evaluator.Evaluate( resolution.Values, _document.FormulaUnit, _document.Adjustments.ForSize(size), cacheKey: size); } /// <summary>Состояние каждого размера ряда.</summary> public IReadOnlyList<SizeReport> Report() => _document.Sizes.Sizes.Select(ReportFor).ToArray(); public SizeReport ReportFor(string size) { var resolution = _document.Sizes.Resolve(size, _document.Measurements); // Размер с незаполненными мерками не строится вовсе: подставлять // вместо них нули значило бы выдать заведомо неверную выкройку. if (!resolution.IsComplete) return new SizeReport( size, IsBase(size), resolution.Missing, [], CountAdjustments(size)); var evaluation = Evaluate(size); return new SizeReport( size, IsBase(size), [], evaluation.Failures.Values.ToArray(), CountAdjustments(size)); } /// <summary>Размеры, которые нельзя вывести.</summary> public IReadOnlyList<SizeReport> ProblemSizes() => Report().Where(report => !report.IsReady).ToArray(); /// <summary> /// Записывает ручную поправку: смещение точки в одном размере. /// </summary> public void Adjust(string size, NodeId node, Offset2 offset) { _document.Adjustments.Set(size, node, offset); Forget(size); } public bool RemoveAdjustment(string size, NodeId node) { var removed = _document.Adjustments.Remove(size, node); if (removed) Forget(size); return removed; } public void RemoveAllAdjustments(string size) { if (_document.Adjustments.RemoveAll(size)) Forget(size); } /// <summary>Сбрасывает сохранённую геометрию размера. Вызывается при правках.</summary> public void Forget(string? size = null) { if (size is null) _evaluators.Clear(); else _evaluators.Remove(size); } private bool IsBase(string size) => string.Equals(size, _document.Sizes.BaseSize, StringComparison.CurrentCultureIgnoreCase); private int CountAdjustments(string size) => _document.Adjustments.All().Count( adjustment => string.Equals(adjustment.Size, size, StringComparison.CurrentCultureIgnoreCase)); }