⟨/⟩ 45_Api/Endpoints/InputPackets/SubmitInputPacket.cs

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

using System;
using Ban.Sdaid.Notation.Documents;
using Ban.Sdaid.Icd;
using Ban.Sdaid.Icd.Api.Based;
using Ban.Sdaid.Icd.Domain.Capture;

namespace Ban.Sdaid.Icd.Api.Endpoints.InputPackets.SubmitInputPacket
{
    /// <summary>Документ-обёртка над endpoint постановки пакета ввода в очередь.</summary>
    public class DOC_SubmitInputPacket : IApiContractDocument, IFolder<ApiFolder>, IHasStructuralLinks
    {
        public SdaidLink[] Links => new[]
        {
            Rel.Uses<Ban.Sdaid.Icd.Backend.Handlers.InputPackets.SubmitInputPacketHandler>(),
        };

        public static string _refName = "Endpoint SubmitInputPacket";

        public string Name => "Endpoint: SubmitInputPacket";

        public string Description =>
            @"Постановка собранного пакета ввода в очередь: произвольный набор кадров одной ИК, без плана. Поведение — SubmitInputPacketHandler.";

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

        public static string Transport = """
            ## Транспорт

            `POST /api/InputPacket`, **multipart/form-data**:

            - часть `payload` — JSON метаданных пакета (форма `SubmitInputPacketCommand` ниже);
            - части `files` — бинарное содержимое кадров; кадр ссылается на свой файл по `FileIndex`.

            Кадр-ссылка (`Source = Url`) содержимого не несёт — сервер скачивает изображение по `Url` сам.
            """;

        public static string Body = $"""
            ## Endpoint

            {SdaidCode.OfClass<SubmitInputPacketEndpoint>()}

            ## Command (часть `payload`)

            {SdaidCode.OfClass<SubmitInputPacketCommand>()}

            ## FrameItem

            {SdaidCode.OfClass<SubmitFrameItem>()}

            ## Result

            {SdaidCode.OfClass<SubmitInputPacketResult>()}

            ## Payload

            {SdaidCode.OfClass<SubmittedPacketPayload>()}
            """;
    }

    /// <summary>Endpoint постановки пакета в очередь.</summary>
    public class SubmitInputPacketEndpoint
    {
        public SubmitInputPacketCommand? Input { get; set; }
        public SubmitInputPacketResult? Output { get; set; }
    }

    /// <summary>Метаданные сдаваемого пакета (JSON-часть multipart).</summary>
    public class SubmitInputPacketCommand : BasedCommand
    {
        /// <summary>Кадры пакета (минимум один — пакет не может быть пустым). Роль на вводе не задаётся.</summary>
        public SubmitFrameItem[] Frames { get; init; } = new SubmitFrameItem[0];
    }

    /// <summary>Описание одного кадра: метаданные + привязка к содержимому (файл или URL).</summary>
    public class SubmitFrameItem
    {
        /// <summary>Способ получения: камера, диск, ссылка.</summary>
        [Relation]
        public ImageSource Source { get; init; }

        /// <summary>Порядок кадра в пакете.</summary>
        public int Order { get; init; }

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

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

        /// <summary>Индекс файла в части `files` (для источников камера/диск).</summary>
        public int? FileIndex { get; init; }

        /// <summary>URL изображения (для источника «ссылка»); сервер скачивает содержимое.</summary>
        public string? Url { get; init; }
    }

    /// <summary>Результат постановки в очередь.</summary>
    public class SubmitInputPacketResult : BasedResult
    {
        /// <summary>Сведения о сданном пакете; null при ошибке.</summary>
        public SubmittedPacketPayload? Payload { get; init; }
    }

    /// <summary>Сданный пакет — номер, время и состав (для списка «сдано за смену»).</summary>
    public class SubmittedPacketPayload
    {
        public Guid Id { get; init; }

        /// <summary>Присвоенный сервером номер вида П-ГГГГММДД-NNN.</summary>
        public string Number { get; init; } = "";

        public DateTime QueuedAt { get; init; }
        public int FramesCount { get; init; }
    }
}