/
docNemo
/
clothes-graph
Обзор
Документация
Войти
/
docNemo
/
clothes-graph
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/ClothesGraph.Model/Storage/DocumentDto.cs
247 строк
9 KB
docNemo
Запрос на слияние 'interface-to-spec' (
#1
) из interface-to-spec в main
09 авг 2026, 20:28
Верифицирован
09 авг 2026, 20:28
1bbc436
Код
Авторство
О чём код?
using System; using System.Collections.Generic; using System.Text.Json.Serialization; namespace ClothesGraph.Model.Storage; /// <summary> /// Представление документа для записи в файл. /// </summary> /// <remarks> /// Отдельный слой, а не разметка доменных типов атрибутами: формат файла /// обязан меняться независимо от модели. Иначе любая перестановка полей /// в модели молча ломала бы чужие файлы. /// </remarks> internal sealed class DocumentDto { public int FormatVersion { get; set; } = FileFormat.CurrentVersion; public string Application { get; set; } = "Clothes Graph"; public string FormulaUnit { get; set; } = "Centimetre"; public string DisplayUnit { get; set; } = "Centimetre"; public List<MeasurementDto> Measurements { get; set; } = []; public SizeChartDto Sizes { get; set; } = new(); public List<NodeDto> Nodes { get; set; } = []; public List<PieceDto> Pieces { get; set; } = []; public PrintSettingsDto Print { get; set; } = new(); public List<AdjustmentDto> Adjustments { get; set; } = []; public List<UnderlayDto> Underlays { get; set; } = []; public List<SeamDto> Seams { get; set; } = []; } /// <summary>Шов между участками контуров двух деталей.</summary> internal sealed class SeamDto { public Guid Id { get; set; } public string Name { get; set; } = string.Empty; public Guid FirstPiece { get; set; } public int FirstSegment { get; set; } public Guid SecondPiece { get; set; } public int SecondSegment { get; set; } public bool Reversed { get; set; } public ExpressionDto? Ease { get; set; } public long ToleranceUnits { get; set; } = 200; } /// <summary> /// Подложенное изображение. /// </summary> /// <remarks> /// Само изображение лежит отдельной записью архива, здесь — только имя этой /// записи и параметры размещения. Держать картинку в тексте описания значило бы /// кодировать её и раздувать файл на треть. /// </remarks> internal sealed class UnderlayDto { public Guid Id { get; set; } public string Name { get; set; } = string.Empty; public string Entry { get; set; } = string.Empty; public int PixelWidth { get; set; } public int PixelHeight { get; set; } public long OriginXUnits { get; set; } public long OriginYUnits { get; set; } public double RotationDegrees { get; set; } public double Opacity { get; set; } = 0.6; public double UnitsPerPixel { get; set; } public int Order { get; set; } public bool IsVisible { get; set; } = true; /// <summary> /// Соотнесён ли масштаб с натурой. /// </summary> /// <remarks> /// Допускает отсутствие: в файлах, записанных до разделения масштаба показа /// и калибровки, признака нет, и калиброванной там считалась подложка с /// ненулевым масштабом. Восстановление держится этого правила, поэтому /// версию формата поднимать не требуется. /// </remarks> public bool? IsCalibrated { get; set; } } /// <summary>Ручная поправка к положению построения в одном размере.</summary> internal sealed class AdjustmentDto { public string Size { get; set; } = string.Empty; public Guid Node { get; set; } public long OffsetXUnits { get; set; } public long OffsetYUnits { get; set; } } internal sealed class PlacementDto { public Guid Piece { get; set; } public long OffsetXUnits { get; set; } public long OffsetYUnits { get; set; } public double RotationDegrees { get; set; } } internal sealed class PrintSettingsDto { public List<PlacementDto> Placements { get; set; } = []; public string PageSizeName { get; set; } = "A4"; public long PageWidthUnits { get; set; } = 21_000; public long PageHeightUnits { get; set; } = 29_700; public bool IsLandscape { get; set; } public long MarginUnits { get; set; } = 800; public bool JoinWithOverlap { get; set; } = true; public long OverlapUnits { get; set; } = 1_500; /// <summary>Детали, исключённые из вывода.</summary> public List<Guid> ExcludedFromPrint { get; set; } = []; } internal sealed class MeasurementDto { public Guid Id { get; set; } public string Name { get; set; } = string.Empty; public long Units { get; set; } public string? Description { get; set; } } internal sealed class SizeChartDto { public string BaseSize { get; set; } = "Базовый"; public List<string> Sizes { get; set; } = []; /// <summary>Значения по размерам: имя размера — список значений мерок.</summary> public Dictionary<string, List<SizeValueDto>> Values { get; set; } = []; } internal sealed class SizeValueDto { public Guid Measurement { get; set; } public long Units { get; set; } } /// <summary> /// Построение чертежа. /// </summary> /// <remarks> /// Тип узла записан строкой, а не номером: номера перемешиваются при /// перестановке членов перечисления, и файл, записанный вчера, начинает /// читаться неверно, не вызывая ошибки. /// </remarks> internal sealed class NodeDto { public Guid Id { get; set; } public string Kind { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public Guid? Origin { get; set; } public Guid? Second { get; set; } public Guid? Third { get; set; } public Guid? Fourth { get; set; } public ExpressionDto? First { get; set; } public ExpressionDto? SecondFormula { get; set; } public string? Mode { get; set; } /// <summary>Точки обведённой кривой, привязанные к каркасу.</summary> public List<AnchoredPointDto>? Anchored { get; set; } } internal sealed class AnchoredPointDto { public Guid AnchorFrom { get; set; } public Guid AnchorTo { get; set; } public double Along { get; set; } public double Across { get; set; } } /// <summary> /// Узел дерева формулы. /// </summary> /// <remarks> /// Формула хранится деревом со ссылками по идентификаторам, а не текстом: /// текст пришлось бы разбирать по именам, а имена мерок и построений /// пользователь меняет свободно, и старый файл перестал бы читаться. /// </remarks> internal sealed class ExpressionDto { public string Kind { get; set; } = string.Empty; public double? Value { get; set; } public Guid? Reference { get; set; } public string? Property { get; set; } public string? Operator { get; set; } public string? Function { get; set; } public List<ExpressionDto>? Operands { get; set; } } internal sealed class PieceDto { public Guid Id { get; set; } public string Name { get; set; } = string.Empty; public int Quantity { get; set; } = 1; public string? Note { get; set; } public int? FoldSegmentIndex { get; set; } public ExpressionDto? SeamAllowance { get; set; } public ExpressionDto? GrainlineAngle { get; set; } public List<SegmentDto> Contour { get; set; } = []; public List<AllowanceOverrideDto> AllowanceOverrides { get; set; } = []; public List<NotchDto> Notches { get; set; } = []; } internal sealed class SegmentDto { public Guid Curve { get; set; } public bool Reversed { get; set; } } internal sealed class AllowanceOverrideDto { public int SegmentIndex { get; set; } public ExpressionDto? Width { get; set; } } internal sealed class NotchDto { public ExpressionDto? Distance { get; set; } public string? Label { get; set; } } [JsonSerializable(typeof(DocumentDto))] [JsonSourceGenerationOptions( WriteIndented = true, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] internal sealed partial class DocumentSerializerContext : JsonSerializerContext;