⟨/⟩ 60_Epics/RecognitionStand/UseCases/ApplyTemplate/ApplyTemplateUseCase.cs

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

using Ban.Sdaid.Notation.Documents;

namespace Ban.Sdaid.Icd.Epics.RecognitionStand.UseCases
{
    /// <summary>Use-case: применение трафарета к скану и чтение зон (отметки офлайн + текст движком).</summary>
    public class ApplyTemplateUseCase : IUseCaseDocument, IHasStructuralLinks
    {
        public static string _refName = "сценарий «Применение трафарета и чтение зон»";

        public string Name => "Применение трафарета и чтение зон";

        public string Description =>
            @"Аналитик загружает трафарет и скан того же вида, выравнивает скан, читает отметки офлайн и текст выбранным движком; результат — JSON и читаемый список полей.";

        public string Version => "0.1";
        public string Status => "draft";
        public string[] Comments => new[]
        {
            "2026-08-24. Первичная фиксация сценария применения трафарета.",
        };

        public string PrimaryActor => "Аналитик";

        public SdaidLink[] Links => new[]
        {
            Rel.Realizes<EPIC_RecognitionStand>(),
        };

        public static string S1_Given = """
            ## Given

            - Открыт экран применения (`editor/apply-template.html`) через локальный прокси.
            - Есть трафарет нужного вида (JSON) и скан того же вида страницы.
            - По умолчанию: нормализация выключена, deskew включён.
            """;

        public static string S2_When = """
            ## When

            1. Аналитик загружает трафарет и скан; скан выравнивается по вертикали (deskew).
            2. Клетки трафарета накладываются на скан по своим координатам (для «плывущих»
               родственных сканов включается опциональная привязка по линиям сетки).
            3. Аналитик жмёт «Читать зоны»:
               - **отметки** считаются офлайн прототип-вычитанием (клетка темнее «пустого» прототипа
                 колонки = метка), чувствительность регулируется ползунком;
               - **текст**: перед каждым полем — офлайн-проверка «есть чернила»; непустые уходят
                 в выбранный движок (Qwen-VL по клетке / Yandex OCR одним запросом на страницу).
            4. Аналитик сверяет результат по подсветке зон и списку распознанных полей.
            """;

        public static string S3_Then = """
            ## Then

            - Получен JSON: `marks[]` (отметка true/false + score) и `fields[]` (значение + путь/подпись).
            - Пустые клетки помечены и не отправлялись в модель.
            - Справа — читаемый список «поле → значение» для быстрой сверки.
            """;

        public static string S4_Alternatives = """
            ## Альтернативы и ошибки

            | Ситуация | Поведение |
            |---|---|
            | Скан «плывёт» относительно эталона | Включается привязка по линиям (кусочная интерполяция, регуляризованная к аффинной): на «своём» скане вырождается в тождество и не вредит |
            | Слабая рукописная метка | Разделение метка/пусто на пределе; крутится чувствительность, помогает более крупная съёмка |
            | Крупный бокс Комментария с редким текстом | Не считается пустым по абсолютному числу тёмных пикселей, а не по доле |
            | Лимит частоты облачного OCR | Yandex — один запрос на всю страницу, слова раскладываются по клеткам через геометрию |
            """;

        public static string S5_Trace = $"""
            ## Трассировка

            | Шаг | Инструмент |
            |---|---|
            | Наложение трафарета, deskew, привязка, чтение зон | `editor/apply-template.html` |
            | Отметки | офлайн прототип-вычитание (в странице) |
            | Текст | Qwen-VL / Yandex OCR через `server/` |

            Эпик — {nameof(EPIC_RecognitionStand)}. Продуктовая цель — {nameof(Ban.Sdaid.Icd.Epics.CardExtraction.EPIC_CardExtraction)}.
            """;
    }
}