⟨/⟩ 50_Domain/Capture/ImageFrame.cs

106 строк · в начало

using System;
using Ban.Sdaid.Notation.Documents;
using Ban.Sdaid.Icd.Domain.Cards.Template;

namespace Ban.Sdaid.Icd.Domain.Capture
{
    /// <summary>Кадр — изображение страницы бумажной ИК в составе пакета ввода.</summary>
    [DomainEntity]
    public class ImageFrame
    {
        /// <summary>Идентификатор кадра.</summary>
        public Guid Id { get; init; }

        /// <summary>Порядковый номер кадра в пакете; задаёт имя файла.</summary>
        public int Order { get; init; }

        /// <summary>
        /// Страница формы, которой соответствует кадр; null — кадр к форме не отнесён.
        /// Определяется обработкой, переназначается пользователем.
        /// </summary>
        [Relation]
        public FormPage? Page { get; init; }

        /// <summary>Способ получения: камера, файл с диска, ссылка.</summary>
        [Relation]
        public ImageSource Source { get; init; }

        /// <summary>Исходное имя файла; пусто для кадров с камеры.</summary>
        public string? OriginalFileName { get; init; }

        /// <summary>Момент получения кадра.</summary>
        public DateTime CapturedAt { get; init; }

        /// <summary>Ключ хранения, назначаемый сервером при постановке пакета в очередь.</summary>
        public string StorageKey { get; init; }

        /// <summary>Признак: кадр отобран для распознавания при проверке пакета ввода.</summary>
        public bool AcceptedForRecognition { get; init; }

        /// <summary>Ключ хранения обработанного (нормализованного orthocover) изображения; null — не обработан.</summary>
        public string? NormalizedStorageKey { get; init; }

        /// <summary>Флаг качества/режима нормализации (напр. low_quality); null — нет.</summary>
        public string? NormalizationFlag { get; init; }

        /// <summary>Момент нормализации; null — кадр ещё не обрабатывался.</summary>
        public DateTime? NormalizedAt { get; init; }
    }

    /// <summary>Описание доменной сущности <see cref="ImageFrame"/>.</summary>
    public class ImageFrameSpec : IDomainEntityDocument
    {
        public Type Entity => typeof(ImageFrame);

        public string Name => "Кадр изображения";

        public string Description =>
            @"Изображение страницы бумажной ИК. Соответствие кадра странице формы определяет Сервис при обработке; пользователь может его исправить.";

        public string Version => "0.2";
        public string Status => "draft";
        public string[] Comments => new string[0];

        public static string S1_PageBinding = $"""
            ## Кадр и страница формы

            Кадр не несёт собственного «вида изображения»: он относится к **странице опознанной
            формы**. Так точнее — «страница 3 формы на рукопись» вместо абстрактной роли, — и это
            же снимает нужду в перечислении ролей, которое приходилось расширять под каждый новый
            вид карты.

            Соответствие проставляет обработка, разобрав кадры по составу страниц формы. Пользователь
            может переназначить: указать, что кадр относится к другой странице, или снять
            назначение вовсе.

            Кадр без страницы — **лишний**: он не распознаётся и в разборе не участвует. Удалять его
            необязательно, повторной обработки его удаление не требует.

            Решение — в {nameof(Ban.Sdaid.Icd.Arch.Adr.ADR_007_InputWithoutPlan)}.
            """;

        public static string S2_Invariants = """
            ## Инварианты

            - Страница может быть назначена не более чем одному кадру пакета: двум кадрам на одной
              странице соответствовать нечему.
            - Переназначение страницы, пересъёмка и удаление кадра со страницей возвращают пакет
              в очередь: исходные данные разбора изменились.
            - Ключ хранения формируется по схеме `<номер пакета>/<NN>.<расширение>` и не зависит
              ни от идентификаторов документа, ни от назначенной страницы.
            - Исходное имя файла хранится только для кадров, загруженных с диска или по ссылке.
            - Кадр может иметь обработанную (нормализованную) версию: `NormalizedStorageKey` — ключ обработанного
              PNG рядом с оригиналом (`<номер>/<NN>_norm.png`); заполняется при запуске обработки
              (ADR-SRV-005). До обработки поля нормализации пусты.
            """;

        public static string S99_Related = $"""
            ## Связанные артефакты

            - {nameof(Ban.Sdaid.Icd.Arch.Adr.ADR_007_InputWithoutPlan)} — решение о вводе без плана
            - {nameof(Ban.Sdaid.Icd.Arch.Adr.ADR_002_PacketIdentityAndFileKeys)} — решение об идентичности пакета и именах файлов изображений
            - {nameof(Ban.Sdaid.Icd.Arch.Tech.CSharp.ADR_SRV_005_ImageNormalizationOrthocover)} — нормализация изображений (обработанная версия кадра)
            """;
    }
}