🎯 Момент, ради которого всё затевалось
Перед вами — сердце новой версии. Документ «Тест бинарное дерево» № 0000000009 от 19.09.2026, респондент Test. Слева — «История ответов»: пять шагов, пять «Да/Нет», которые вели пользователя по веткам дерева. Справа — диалог, в котором пользователь не согласился с результатом и нажал «Предложить свой ответ»: «Уточняющий вопрос, отличающий ваш вариант от остальных. Заканчивайте знаком „?“».
Это самообучение в действии. Пользователь дошёл до листа — и вместо тупика получил возможность научить систему. Пять ответов «Да/Нет», тупик на листе — и вместо него диалог «Предложить свой ответ». Это момент, когда тест перестаёт быть просто тестом и начинает учиться у пользователя.
📖 Что это
Это продолжение публикации «Бинарные тесты — деревья решений, как в игре „Угадай животное“» от 27.10.25. Первая версия (альфа) дала ядро: дерево решений, документ «Тест бинарное дерево», справочник «Шаблоны бинарных деревьев», регистр «Структура бинарного дерева» и назначение опросов. Завершалась она TODO-листом «Реализовать механизм самообучения дерева с модерацией». О том, как этот план воплощён, — ниже.
Бинарные тесты — деревья решений с ответами «Да/Нет» для 1С: инструмент диагностики, обучения и проверки знаний. Что нового. Модерация с самообучением: пользователи предлагают свои ветки, модератор их утверждает — база знаний растёт. Кому нужно. Разработчикам 1С, службам поддержки, методистам, тем, кто строит интерактивные сценарии. Проверено 58 автотестами.
Оглавление
🆕 Что нового в версии 2.0
🔁 Модерация с самообучением
Полный жизненный цикл ветки: от предложения респондента до утверждения модератором.
! Подтверждение отгадки
В конце теста: «Это то, что вы загадали?» с Да/Нет — вместо резкого завершения.
📝 Корректный порядок уточнения
Сначала название варианта, потом уточняющий вопрос, отличающий его от остальных.
🛡 Защита целостности
Устранение задвоений, выявление дублей базы знаний, пометка дублей шаблонов.
📋 Назначение опросов
Исправлена автонумерация, кнопка «Назначить» сразу создаёт документ из шаблона.
🖨 Печать и диагностика
Иерархическая печать дерева связей, диагностика доступных тестов, учёт физлиц.
🛠 Процесс модерации: пошаговый разбор
В модерации участвуют два действующих лица: респондент (проходит тест и предлагает новые ветки) и модератор (проверяет предложения и управляет жизненным циклом веток). Вся жизнь ветки хранится в регистре СтруктураБинарногоДерева в виде состояния связи СостояниеСвязи.
Три состояния ветки
| Состояние | Кто видит | Смысл |
|---|---|---|
СвязьАктивна |
все | утверждённая ветка, «золотой стандарт»; по ней идут прохождения |
ВременноУдаленаИлиВРазработке |
только модератор | предложенная ветка на модерации, «песочница» |
СвязьНеактивна |
только модератор | отклонённая или архивная ветка, «корзина» |
Ключевой принцип: записи регистра никогда не удаляются — меняется только СостояниеСвязи. Поэтому история предложений и анализ «какие неверные пути чаще предлагают пользователи» сохраняются полностью.
Шаг 1. Респондент предлагает ветку
- Респондент проходит дерево по «Да/Нет» до листа. В конце его спрашивают: «Ваш результат: Краб. Это то, что вы загадали?».
- Если он отвечает «Нет», открывается «Предложить свой ответ». Ввод идёт в строгом порядке: сначала название своего варианта, затем уточняющий вопрос, который отличает его от остальных.
- Валидация (на клиенте и на сервере) отсекает мусор:
Код 1С.
// вопрос: не пустой, не «Да»/«Нет», обязан заканчиваться «?»
Если ПустаяСтрока(СокрЛП(ТекстУточняющегоВопроса))
ИЛИ СокрЛП(ТекстУточняющегоВопроса) = "Да"
ИЛИ СокрЛП(ТекстУточняющегоВопроса) = "Нет" Тогда
ПоказатьОповещениеПользователя("Вопрос не может быть пустым, «Да» или «Нет»");
Продолжить;
КонецЕсли;
Если Прав(СокрЛП(ТекстУточняющегоВопроса), 1) <> "?" Тогда
ПоказатьОповещениеПользователя("Уточняющий вопрос должен заканчиваться знаком «?»");
Продолжить;
КонецЕсли;
// ответ: не пустой, не «Да»/«Нет», не заканчивается «?»
Если Прав(СокрЛП(ТекстПравильногоОтвета), 1) = "?" Тогда
ПоказатьОповещениеПользователя("Название варианта не должно заканчиваться знаком «?»");
Продолжить;
КонецЕсли;
- Предпросмотр (Да/Нет): «Ваш вариант ответа: … / Уточняющий вопрос: … Отправить на модерацию?».
- Защита от дублей: если имя вопроса или ответа уже встречается в дереве этого шаблона, предложение отклоняется с понятным сообщением.
- В регистре создаются новый узел-вопрос и новый узел-лист; связи между ними получают состояние «в разработке». Респондент видит «Спасибо! Ваше предложение принято и будет рассмотрено модератором».
Шаг 2. Модератор видит предложение
В форме элемента справочника «Шаблоны бинарных деревьев» есть таблица всех связей, где первая колонка — «Состояние»:
- [V] Активна;
- [X] На модерации;
- [O] В корзине.
Строки подсвечиваются цветом (активная — зелёным, на модерации — жёлтым, архив — серым). Есть и иерархическая печатная форма «Дерево связей» с отступами и той же подсветкой состояний.
Шаг 3. Модератор принимает решение
| Команда | Доступна для состояния | Результат |
|---|---|---|
| Утвердить | На модерации | → Активна (соседние активные ветки архивируются) |
| Отклонить | На модерации | → В корзине |
| Архивировать | Активна | → В корзине |
| Восстановить | В корзине | → Активна |
| Редактировать | любое | меняет текст вопроса и ответа (с той же проверкой «?») |
Инвариант — «одна активная связь на узел». На каждом узле для каждого типа ответа (родитель + «Да»/«Нет») активной может быть ровно одна ветка. Поэтому «Утвердить» не просто меняет состояние новой ветки, но и переводит в архив другие активные ветки с тем же «родитель + тип ответа». Записи при этом не удаляются — только меняют состояние.
Шаг 4. Результат — наполнение базы знаний
После «Утвердить» новый вопрос становится активной связью и реально участвует в навигации следующих тестов: респондент, дошедший до того же узла, увидит уточняющий вопрос и (при нужном ответе) придёт к новому листу. Так база знаний в регистре растёт с каждым утверждением — это проверяется отдельным автотестом, который проходит новым вопросом до конца.
Защита от накопления дублей
- Проверить целостность: если на одном «родитель + тип ответа» оказалось несколько активных веток, команда оставляет одну по детерминированным правилам — вопрос приоритетнее листа → больше исходящих связей → лексикографически меньшее имя, — остальные переводятся в архив.
- Выявление дублей базы знаний: группировка записей по «вопрос + ответ + узел» показывает смысловые дубли.
- Пометка дублей шаблонов: по одному рабочему шаблону на наименование, остальные помечаются на удаление.
👤 Как работает модератор: подробный разбор
Модератор — это человек, который превращает «сырые» предложения респондентов в рабочие ветки дерева. Он не пишет код и не редактирует регистр вручную: всё делается командами в форме элемента справочника «Шаблоны бинарных деревьев». Его задача — держать дерево в порядке: утверждать полезное, отклонять мусор, чистить дубли и следить, чтобы дерево оставалось связным.
Ключевая идея — звеновая модель. Ветка дерева — это не одиночное ребро, а неделимое звено: узел-вопрос Q и три его ребра — входящее (Родитель, Тип → Q), «Да» (Q → лист-отгадка), «Нет» (Q → следующий узел). Все команды модерации работают над целым звеном, а не над отдельной строкой регистра. Благодаря этому ни утверждение, ни архивация, ни восстановление не «рвут» дерево и не теряют ранее накопленные отгадки.
Рабочее место модератора
Модератор открывает справочник «Шаблоны бинарных деревьев» и выбирает нужный шаблон. В форме элемента есть:

- Таблица связей — все ветки дерева в одном списке. Первая колонка — «Состояние»: Активна (зелёная строка), На модерации (жёлтая строка), 🗑 В корзине (серая строка).
- Панель команд — кнопки управления жизненным циклом выделенной ветки.
- Кнопка «Назначить» — создать документ «Назначение опросов» прямо из шаблона.
- Команды диагностики — «Проверить целостность», «Выявление дублей базы знаний», «Пометка дублей шаблонов».
- Печать «Дерево связей» — иерархическая печатная форма с ветками, отступами и подсветкой состояния.
Дополнительно есть обработка «Диагностика доступных тестов» — она показывает, какие шаблоны и тесты реально доступны конкретному пользователю с учётом связанного физлица и статуса прохождения.
Карта состояний ветки
| Состояние | Что означает | Кто видит при прохождении |
|---|---|---|
СвязьАктивна |
Утверждённая рабочая ветка | Все респонденты |
ВременноУдаленаИлиВРазработке |
Новая ветка, ждёт решения модератора | Никто (кроме модератора) |
СвязьНеактивна |
Отклонена или устарела, «корзина» | Никто |
Записи регистра не удаляются — меняется только СостояниеСвязи. Поэтому история всех предложений сохраняется и доступна для анализа: видно, какие варианты предлагали пользователи, что было отклонено и когда.
Полный цикл работы модератора: пошагово
Шаг 1. Модератор открывает форму шаблона и видит новые предложения
В таблице связей жёлтым подсвечены строки со статусом «На модерации». Это предложения от респондентов. Каждое предложение — это узел-вопрос и узел-лист, связанные в звено тремя рёбрами: входящее (Родитель → вопрос), «Да» (вопрос → лист-отгадка) и «Нет» (вопрос → прежний узел). Все три ребра получают состояние «в разработке».
Модератор видит текст вопроса, текст ответа, родительский узел и тип ответа («Да» или «Нет»), к которому привязана ветка.
Шаг 2. Модератор проверяет корректность формулировок
Даже если предложение прошло клиентскую и серверную валидацию, формулировка может быть неудачной: слишком общая, двусмысленная, не по теме дерева. Если нужно — модератор нажимает «Редактировать» и правит текст вопроса или ответа.
При редактировании работают те же правила, что и при вводе: вопрос не пустой, не «Да» и не «Нет», заканчивается знаком «?»; ответ не пустой, не «Да» и не «Нет», не заканчивается знаком «?».
Шаг 3. Модератор принимает решение одной из команд
| Команда | Доступна, когда ветка | Что произойдёт |
|---|---|---|
| Утвердить | На модерации | Врезка звена: ветка активна, прежний узел на этом месте сдвигается под «Нет» нового вопроса |
| Отклонить | На модерации | Ветка в корзину, не удаляется |
| Архивировать | Активна | Шунтирование: три ребра звена в корзину, родитель соединяется напрямую с выходом «Нет» |
| Восстановить | В корзине | Проверка дефектов D1/D2/D4; если звено цело — возврат на модерацию, иначе блокировка с причиной |
| Редактировать | Любое | Правка текста вопроса и ответа (с проверкой формата) |
Кнопки, недоступные для текущего состояния, заблокированы, и при попытке их нажать модератор получает подсказку: «b88;A039; Утвердить можно только ветки на модерации», «b88;A039; Восстановить можно только ветки из корзины» и т.п.
Шаг 4. Врезка звена при утверждении
Утверждение — это не простая смена статуса, а врезка целого звена в дерево:
- Новая ветка становится активной на месте (Родитель, Тип).
- Прежний узел, стоявший на этом месте, не отрезается — он автоматически уходит под ветку «Нет» нового вопроса.
- Лист-отгадка нового вопроса встаёт на ветку «Да».
В итоге на каждом узле для каждого типа ответа остаётся ровно одна активная ветка, а старые отгадки не пропадают — они просто смещаются глубже по «Нет».
Шаг 5. Наполнение базы знаний
После «Утвердить» ветка сразу попадает в навигацию. Прохождение от того же узла, что и раньше, теперь ведёт по новому вопросу; при нужном ответе пользователь придёт к новому листу, а при ответе «Нет» — к прежней отгадке. База знаний в регистре растёт с каждым утверждением.
Шаг 6. Периодическая гигиена: чистка дублей
- «Проверить целостность»: если на одном «родитель + тип ответа» оказалось несколько активных веток, команда оставляет одну по детерминированным правилам, а остальные переводит в архив. Эта же команда разрывает циклы и выстраивает параллельные ветки.
- «Выявление дублей базы знаний»: группирует записи по «вопрос + ответ + узел» и показывает смысловые повторы. Это не удаление, а диагностика.
- «Пометка дублей шаблонов»: по одному рабочему шаблону на наименование, остальные помечаются на удаление.
Шаг 7. Анализ отклонённого
Отклонённые предложения не удаляются — они остаются в корзине и доступны модератору. Это позволяет посмотреть, какие неверные пути чаще всего предлагают пользователи; обнаружить пробелы в дереве; восстановить ветку, если решение об отклонении оказалось ошибочным.
Что модератор видит на печатной форме «Дерево связей»
Печатная форма строится рекурсивным обходом от корневого узла. Каждый уровень — с отступом. Рядом с каждым узлом — его состояние:
- 🟢 зелёный — активная ветка;
- 🟡 жёлтый — на модерации (ветка уже встроена в топологию, но ещё не утверждена);
- серый - ветки из корзины в печать не выводятся, чтобы не путать топологию живого дерева.
Форма удобна для: ревью логики дерева целиком перед публикацией шаблона; понимания, куда именно врежется новое предложение; передачи структуры коллеге; приложения к документации проекта.
Крайние случаи и защита от ошибок
[X] Попытка утвердить активную ветку
Команда «Утвердить» просто недоступна, а при попытке вызвать её программно выводится сообщение «Утвердить можно только ветки на модерации».
[X] Попытка восстановить битое звено
Перед возвратом из корзины система проверяет целостность: D1 — обрыв листа «Да», D2 — обрыв выхода «Нет», D4 — самопетля. При повреждении восстановление блокируется с причиной.
[X] Предложение с существующим именем
Метод проверяет имя нового вопроса и ответа по всему дереву шаблона. Совпадение — предложение отклоняется ещё на стороне респондента.
[X] Зацикливание в регистре
Рекурсивный обход ограничен лимитом глубины (100) и детекцией повтора узла в текущей ветке. Циклы также разрываются автоматически при модерации.
Роли и права: что видит модератор и что — респондент
| Что | Респондент | Модератор |
|---|---|---|
| Ветки «Активна» | видит, идёт по ним | видит, может архивировать |
| Ветки «На модерации» | не видит | видит, может утвердить/отклонить/редактировать |
| Ветки «В корзине» | не видит | видит, может восстановить |
| Форма шаблона | недоступна | полный доступ |
| Кнопки жизненного цикла | недоступны | доступны по состоянию ветки |
| Диагностика целостности | недоступна | доступна |
| Предложение нового варианта | доступно из теста | тоже доступно |
Такое разделение закрывает главный риск: обычный пользователь не может случайно изменить рабочее дерево, а модератор не тратит время на прохождение тестов ради правок — он работает прямо со структурой.
Итог
Работа модератора сводится к четырём действиям:
- Утвердить полезное предложение — звено врежется в дерево, прежняя отгадка сохранится под «Нет», а новая попадёт в базу знаний.
- Отклонить ненужное — оно уйдёт в корзину, но сохранится для анализа.
- Архивировать/восстановить ветки — архивация шунтирует звено (поддерево не рвётся), а восстановление возвращает ветку на модерацию после проверки целостности.
- Почистить дубли, задвоения, параллели и циклы командами диагностики.
Всё остальное — контроль формата, звеновая целостность, инвариант «одна активная связь на узел», защита от зацикливания и клиентская валидация — работает автоматически. Модератор не может случайно сломать дерево: система либо не даст выполнить опасное действие, либо сохранит данные в архиве, откуда их можно вернуть.
🔧 Инженерные решения и подводные камни
Асинхронные диалоги
Ввод строки и вопрос «Да/Нет» переведены с модальных окон на асинхронный вызов ВвестиСтрокуАсинх / ВопросАсинх с оператором Ждать (доступно с платформы 8.3.18). Это убрало ошибку «Использование модальных окон в данном режиме запрещено».
Клиентский тест открытия формы
Компиляция модуля управляемой формы проверяется только при открытии формы на клиенте — серверный прогон такие ошибки не увидит (например, обращение к серверному методу из клиентского кода). Поэтому в автотестах есть один клиентский тест, который открывает форму элемента шаблона и ловит ошибки инициализации. Он ограничен 10 шаблонами и только шаблонами с активной структурой — иначе с ростом числа накопленных шаблонов полный прогон «зависал» на открытии сотен форм.
Защита от зацикливания
Рекурсивный обход дерева ограничен лимитом глубины (100) и детекцией повтора узла в текущей ветке — циклические ссылки в регистре не вешают форму.
📦 Функции и возможности
Объекты: документ «Тест бинарное дерево», справочник «Шаблоны бинарных деревьев», регистр сведений «Структура бинарного дерева», справочник «Пользователи», обработки «Список респондента», «Назначение опросов», «Диагностика доступных тестов».
Программа умеет: проводить опрос «Да/Нет» до итогового листа; обучаться через предложение + модерацию; назначать тесты респондентам и создавать персональные прохождения; подтверждать отгадку; защищать данные от дублей и битых ссылок; печатать дерево и диагностировать доступность тестов.
Эталоном данных остаётся регистр, документ лишь фиксирует результат прохождения. Это важно: один источник правды (узлы и связи в регистре) позволяет менять логику навигации и модерации, не трогая уже записанные прохождения и не ломая их «след».
🧪 Автотесты
Обработка автозапуска прогоняет 58 тестов: 57 серверных + 1 клиентский. Каждый тест создаёт собственный уникальный шаблон («наименование + код»), поэтому пользовательские данные и регистр не затрагиваются. Итог прогона — === ИТОГО: УСПЕШНО 58 ИЗ 58 ===.
| Группа | Кол-во | Примеры тестов |
|---|---|---|
| Построение дерева и связи | 4 | Тест_ПостроениеДерева, Тест_СозданиеСвязи |
| Навигация и прохождение | 13 | Тест_НавигацияПоДереву, Тест_ПолныйЦиклБинарногоДерева |
| Счётчики и запись в ТЧ | 11 | Тест_КоличествоОтветовПовышается, Тест_ЗаписьВопросовВТабличнуюЧасть |
| Регистры | 4 | Тест_РаботаСРегистрами, Тест_ВосстановлениеСостоянияИзРегистра |
| База знаний | 3 | Тест_БазаЗнанийДобавление, Тест_ВыявлениеДублейБазыЗнаний |
| Модерация | 3 | Тест_МодерацияВеток, Тест_МодерацияНаполнениеБазыЗнаний |
| Целостность и очистка | 9 | Тест_УстранениеЗадвоенныхЗаписейДерева |
| Назначение и документы | 6 | Тест_НазначитьИПройтиТест |
| Обработка ошибок | 1 | Тест_JSONОшибки |
| Клиентская проверка | 1 | Тест_ОткрытиеФормыШаблона |
Дополнительные тесты модерации:
Тест_ПерестроениеПараллельныхВеток— параллельные активные ветки на одном «родитель + тип» выстраиваются в последовательную цепочку, лист замыкает её; самопетли и циклы разрываются.Тест_Модерация_ШунтированиеПриАрхивации— при архивации вопроса связи звена уходят в корзину, родитель шунтируется напрямую на выход «Нет», поддерево не отваливается.Тест_Модерация_БлокировкаВосстановленияПриДефектах— восстановление битого звена (без листа «Да») блокируется с кодом дефекта D1.
Полный перечень — в репозитории (модуль ТестированиеУтверждения и обработка ЗапускТестов).
🎬 Видеопрезентация
[I>] Как проходит тест
Демонстрация прохождения дерева «Да/Нет» до итогового листа, подтверждение отгадки и предложение своего ответа.
[I>] Как выполняется модерация
Модератор открывает печатную форму шаблона, видит дерево с подсветкой и утверждает новую ветку.
Модератор открывает печатную форму шаблона и видит всё дерево вопросов и отгадок: активные связи подсвечены зелёным, предложенные пользователями ветки — жёлтым, архивные — серым. Утверждая ветку, он добавляет в дерево новое звено «уточняющий вопрос + ответ-отгадка»: прежняя отгадка не удаляется, а автоматически сдвигается под ответ «Нет» нового вопроса. Параллельные ветки выстраиваются в последовательную цепочку, циклы разрываются — дерево остаётся строго бинарным и связным, без потери накопленных ранее ответов. Подсистема модерации работает стабильно, инварианты соблюдены, регрессионный щит 58/58 зелёный.
🔄 Совместимость с версией 1.0
Структура метаданных не менялась: измерения регистра СтруктураБинарногоДерева и реквизиты документов прежние. Данные первой версии остаются валидными, перепроведение документов не требуется. Накопленные за время разработки дубли шаблонов и связей можно вычистить командой «Проверить целостность» в форме шаблона.
📌 TODO-лист третьей версии: два типа узлов дерева
Суть архитектурного нововведения
Сейчас дерево однородно: любой узел может быть и вопросом, и листом в любом месте. Это порождает «вопросы-пустышки» — узлы, где обе ветки ведут в один и тот же лист (как «У него есть плавники?» → «Новый ответ»), и листья, растущие бессистемно.
В третьей версии узел делится на два типа:
- Стволовые узлы — «ствол» дерева, его скелет. На стволовом узле и по «Да», и по «Нет» всегда предлагается новая развилка (следующий вопрос). Листьев на стволе быть не может — ствол состоит только из последовательности уточняющих вопросов без терминальных ответов.
- Обычные ветки с листьями — крепятся к стволу и содержат отгадки. Именно здесь появляются листья-ответы.
Зачем это
Стволовые узлы можно автоматически заполнять через самообучение. Раз на стволе нет листьев, любое предложение пользователя на стволовом узле всегда означает «добавить ещё один уточняющий вопрос» (новую развилку), а не «заменить отгадку». Это делает самообучение детерминированным: система однозначно знает, где создавать новую развилку, а где — новый лист.
Что осталось не сделано на текущий момент
- Заполнить вопрос-«пустышку». В шаблоне 000001053 узел «У него есть плавники?» ведёт по «Да» и по «Нет» в один и тот же лист «Новый ответ». Заменить на осмысленные отгадки либо перевести в стволовой узел с двумя развилками.
- Физическая очистка корзины (garbage collection). Накопленные исторические связи «В корзине» сейчас только меняют состояние и не удаляются. Добавить команду явной очистки корзины по действию модератора.
- Два типа узлов — сама доработка третьей версии: признак «стволовой / обычный» у узла, правило «на стволе нет листьев, обе ветки — развилки» и авто-заполнение ствола через самообучение.
=> РЕЗЮМЕ
Первая версия задала направление, эта — закрыла план по модерации с самообучением и добавила подтверждение отгадки, защиту целостности и 58 автотестов. Система протестирована и работает; замечания и найденные проблемы приветствуются.
📄 Информация о лицензии (MIT License)
Полный текст — в файле LICENSE. Разработка предоставляется «как есть» (as is), без гарантий. Требуется «1С:Предприятие» и «Библиотека стандартных подсистем» (БСП).
Copyright (c) 2025–2026, Фёдор Космачев, Сергей Космачев
Авторы разработки
Фёдор Космачев, Сергей Космачев
Обязательная ссылка для указания: //infostart.ru/1c/tools/2794584/
Исходный код на Гитхабе: https://github.com/Menestre1/binary-tests-decision-trees
Реализовано на платформе 1С:Предприятие 8.3 (8.3.27.1989), версия для разработчиков.
Проверено на следующих конфигурациях и релизах:
- 1С:Библиотека стандартных подсистем, редакция 2, релизы 2.3.1.62
Вступайте в нашу телеграмм-группу Инфостарт