Files
SHiNE-server/Черновик_дополнений_каналов_и_типов_сообщений_SHiNE.md
T

724 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Черновик дополнений каналов и типов сообщений SHiNE
## Статус документа
Этот файл является рабочим черновиком первой итерации.
Важно:
- это не финальная спецификация;
- формат блокчейна этим документом пока не меняется автоматически;
- документ фиксирует согласованную на текущий момент концепцию;
- в первую итерацию входят только `TEXT` и `STATUS_ACTION`;
- всё, что касается `CHANNEL_MEMBERSHIP`, вынесено в отдельный отложенный черновик:
- `Черновик_CHANNEL_MEMBERSHIP_для_каналов.md`
## Цель
Нужно расширить текущую модель каналов SHiNE так, чтобы канал был не только лентой обычных постов, но и пространством:
- материалов;
- упражнений;
- услуг / процедур;
- курсов;
- входных страниц каналов;
- истории действий пользователей по этим материалам.
При этом важно:
- не ломать существующий блокчейн без отдельного согласованного шага;
- минимально менять верхнеуровневые `type`;
- по возможности переиспользовать уже существующий текстовый тип сообщений;
- отделять собственно контент от событий состояния.
## Базовая идея первой итерации
На текущий момент согласована следующая модель:
- старый `type=1`, который раньше назывался `TEXT`, по коду можно не менять;
- в документации и логике его можно трактовать шире как основной контентный тип сообщений;
- все новые смысловые материалы каналов добавляются как новые `subType` внутри `type=1`;
- отдельным верхнеуровневым `type` в первой итерации становится только:
- `type=5` — действия пользователя по материалам.
Иначе говоря:
- `type=1` = сообщения и материалы;
- `type=5` = статусные действия пользователя;
- `type=6` = тема вынесена в отдельный отложенный черновик и в первую итерацию не входит.
## Текущие старые верхнеуровневые типы
Они сохраняются:
- `type=0``TECH`
- `type=1``TEXT`
- `type=2``REACTION`
- `type=3``CONNECTION`
- `type=4``USER_PARAM`
## Верхнеуровневые типы первой итерации
Используются:
- `0``TECH`
- `1``TEXT`
- `2``REACTION`
- `3``CONNECTION`
- `4``USER_PARAM`
- `5``STATUS_ACTION`
Отдельно:
- `6``CHANNEL_MEMBERSHIP`
- зарезервирован как следующая тема;
- вынесен в отдельный черновик;
- в текущую реализацию не входит.
## Подтипы внутри `type=1`
Согласованная таблица первой итерации:
- `subType=10``TEXT_POST`
- `subType=11``TEXT_EDIT_POST`
- `subType=20``TEXT_REPLY`
- `subType=21``TEXT_EDIT_REPLY`
- `subType=30``TEXT_RATING`
- `subType=50``TEXT_REPOST`
- `subType=90``TEXT_CHANNEL_META`
- `subType=100``TEXT_ENTRYPOINT`
- `subType=110``TEXT_EXERCISE`
- `subType=120``TEXT_SERVICE`
- `subType=130``TEXT_COURSE`
## Принцип форматов внутри `type=1`
### Line-based сообщения
Следующие подтипы считаются line-based и используют тот же body, что и обычный `TEXT_POST`:
- `TEXT_POST`
- `TEXT_REPOST`
- `TEXT_CHANNEL_META`
- `TEXT_ENTRYPOINT`
- `TEXT_EXERCISE`
- `TEXT_SERVICE`
- `TEXT_COURSE`
### Target-based сообщения
Следующие подтипы считаются target-based:
- `TEXT_REPLY`
- `TEXT_EDIT_REPLY`
- `TEXT_RATING`
### Edit для `TEXT`
В первой итерации согласовано оставить в коде два технических edit-подтипа:
- `TEXT_EDIT_POST`
- edit для сообщений линии канала;
- `TEXT_EDIT_REPLY`
- edit для reply-сообщений.
То есть в документации больше не используется старое упрощённое описание “один общий `TEXT_EDIT`”.
## Смысл подтипов `type=1`
### `TEXT_POST`
Обычный текстовый пост в канале.
### `TEXT_EDIT_POST`
Редактирование line-based текстового сообщения канала.
Принцип:
- edit всегда ссылается на оригинальный блок;
- edit не должен ссылаться на предыдущий edit;
- фактический тип и правила берутся из оригинального сообщения.
### `TEXT_REPLY`
Обычный ответ / комментарий на сообщение.
Важно:
- reply остаётся единым;
- отвечать можно на `post`, `rating`, `exercise`, `service`, `course`, `entrypoint`, `status_action`;
- reply сам является target-based сообщением.
### `TEXT_EDIT_REPLY`
Редактирование reply-сообщения.
### `TEXT_RATING`
Текстовый отзыв / мнение / оценка на конкретный блок.
Смысл:
- это не line-based пост;
- это target-based сообщение-отзыв;
- оно всегда ссылается на конкретный блок, который оценивает;
- оценку пользователя как отдельную сущность в эту итерацию не включаем.
### `TEXT_REPOST`
Отложенная будущая заготовка.
На текущем этапе:
- код зарезервирован;
- бизнес-логика не входит в первую итерацию;
- детальная реализация может быть возвращена позже.
### `TEXT_CHANNEL_META`
Специальное скрытое сообщение метаданных канала.
Через него задаются:
- красивое имя канала;
- аватар;
- описание;
- и другие общие channel meta.
Оно:
- не является обычным пользовательским сообщением;
- не должно показываться в ленте как обычный пост;
- должно парситься по отдельным техническим правилам.
### `TEXT_ENTRYPOINT`
Входная / главная страница канала.
Смысл:
- это не отдельный верхнеуровневый тип;
- это специальный line-based текстовый материал;
- он служит входной страницей канала;
- он может объяснять структуру канала, давать ссылки, вводить человека в тему.
Принцип:
- `TEXT_ENTRYPOINT` не редактируется через `TEXT_EDIT_POST`;
- новая версия создаётся новым сообщением `TEXT_ENTRYPOINT`;
- если в канале несколько `entrypoint`, актуальным считается последний.
### `TEXT_EXERCISE`
Упражнение или комплекс упражнений.
Смысл:
- материал, который можно выполнять много раз;
- материал, который можно выучить;
- по нему удобно строить статистику выполнений и освоения.
### `TEXT_SERVICE`
Услуга / процедура.
Смысл:
- материал, который пользователь проходит;
- обычно не “учится выполнять”, а именно получает / проходит;
- прохождение фиксируется отдельным `STATUS_ACTION`.
### `TEXT_COURSE`
Курс.
Смысл:
- материал, по которому есть путь обучения;
- пользователь может заинтересоваться, начать, учиться, завершить, бросить.
## Канал `0`
Согласована новая трактовка канала `0`.
Канал `0` становится:
- обычным каналом публикаций пользователя по умолчанию;
- местом его основной ленты;
- местом его главной страницы, если там есть `entrypoint`.
### Что это значит
Если у пользователя в канале `0` существует `TEXT_ENTRYPOINT`, тогда:
- ссылка `SHiNE/<login>` открывает именно этот последний `entrypoint`.
Если `entrypoint` в канале `0` нет, тогда:
- `SHiNE/<login>` открывает обычную ленту публикаций канала `0`.
## Правила открытия каналов и ссылок
Согласована следующая логика:
- `SHiNE/<login>`
- главная страница пользователя, то есть канал `0`;
- `SHiNE/<login>/<channel>`
- основная ссылка канала.
### Как открывается `SHiNE/<login>/<channel>`
Если у канала есть хотя бы один `TEXT_ENTRYPOINT`, тогда:
- по умолчанию открывается последний актуальный `entrypoint`;
- UI показывает, сколько после него было новых сообщений;
- UI показывает кнопку перехода в конец канала.
Если `entrypoint` нет:
- открывается обычная лента канала.
Для подписанного пользователя:
- логичнее вести его в место новых непрочитанных сообщений;
- а не всегда принудительно открывать entrypoint;
- при этом сверху можно показывать кнопку `Открыть entrypoint`.
### Ссылки на конкретные сообщения
Остаются обычные формы:
- `SHiNE/<login>/<channel>/<messageNumber>`
- `SHiNE/<login>/<channel>/<messageNumber>/<hash>`
Если нужно показать старую конкретную версию `entrypoint`, даётся ссылка именно на номер нужного сообщения.
## Новый тип `STATUS_ACTION`
`type=5` вводится для действий пользователя по контенту.
## Принцип `STATUS_ACTION`
Согласовано:
- `STATUS_ACTION` всегда является target-based сообщением;
- статусное действие всегда ссылается на конкретный блок-материал;
- это не обычный пост в канале;
- из таких сообщений можно собирать виртуальную ленту пользователя.
### Как трактуется текст в `STATUS_ACTION`
Основной смысл блока задаётся самим статусным событием.
Текст внутри такого блока:
- это комментарий пользователя к действию, если он есть;
- не является главным смыслом записи;
- служит пояснением.
Примеры:
- “Начал сегодня”
- “Решил пройти серьёзно”
- “Сделал это после практики”
- “Выучил базовый комплекс”
## Подтипы `STATUS_ACTION`
Предлагаемая таблица:
- `subType=10``STATUS_DONE_ONCE`
- `subType=20``STATUS_INTERESTED`
- `subType=30``STATUS_STARTED`
- `subType=40``STATUS_IN_STUDY`
- `subType=50``STATUS_COMPLETED`
- `subType=60``STATUS_ABANDONED`
- `subType=70``STATUS_LEARNED`
- `subType=80``STATUS_CONFIRMED`
## Смысл подтипов `STATUS_ACTION`
### `STATUS_DONE_ONCE`
Факт одного выполнения / прохождения.
Это накопительное событие.
### `STATUS_INTERESTED`
Пользователя заинтересовал материал.
### `STATUS_STARTED`
Пользователь начал.
Это начальный статус процесса, но ещё не “устойчивое обучение”.
### `STATUS_IN_STUDY`
Пользователь уже полноценно находится в обучении.
Смысл:
- не просто попробовал;
- а реально учится;
- это отдельный статус, более сильный, чем `started`.
### `STATUS_COMPLETED`
Пользователь завершил курс / прохождение.
### `STATUS_ABANDONED`
Пользователь бросил.
### `STATUS_LEARNED`
Пользователь выучил упражнение или комплекс и знает, как его делать.
Это не то же самое, что “сделал один раз”.
### `STATUS_CONFIRMED`
Подтверждение чужого status-события.
Важно:
- подтверждается не курс вообще;
- не упражнение вообще;
- а конкретный `STATUS_ACTION` конкретного пользователя.
## Кто ставит статусы
Согласовано правило:
- любой базовый статус ставит сам пользователь от своего имени;
- другие люди не ставят статус за него;
- другие люди могут только подтверждать его status-событие через `STATUS_CONFIRMED`.
То есть:
- `INTERESTED`, `STARTED`, `IN_STUDY`, `COMPLETED`, `ABANDONED`, `LEARNED`, `DONE_ONCE`
- ставит сам пользователь;
- `CONFIRMED`
- ставят другие люди на конкретный статусный блок.
### Вес подтверждений
В базовой версии веса подтверждений не вводятся.
Но в будущем можно добавить:
- более значимое подтверждение от создателя курса;
- более значимое подтверждение от создателя упражнения;
- весовые коэффициенты от близких / доверенных людей;
- слабые подтверждения от обычных пользователей.
## Матрица допустимости статусов по типам контента
### Для `TEXT_SERVICE`
Разрешены:
- `STATUS_DONE_ONCE`
- `STATUS_CONFIRMED`
Не разрешены:
- `INTERESTED`
- `STARTED`
- `IN_STUDY`
- `COMPLETED`
- `ABANDONED`
- `LEARNED`
### Для `TEXT_EXERCISE`
Разрешены:
- `STATUS_DONE_ONCE`
- `STATUS_LEARNED`
- `STATUS_CONFIRMED`
Логика:
- упражнение можно выполнять много раз;
- упражнение можно выучить;
- `LEARNED` и `DONE_ONCE` не конфликтуют и живут параллельно.
### Для `TEXT_COURSE`
Разрешены:
- `STATUS_INTERESTED`
- `STATUS_STARTED`
- `STATUS_IN_STUDY`
- `STATUS_COMPLETED`
- `STATUS_ABANDONED`
- `STATUS_CONFIRMED`
### Для `TEXT_ENTRYPOINT`
Статусные действия не ставятся.
### Для `TEXT_POST`, `TEXT_REPLY`, `TEXT_RATING`, `TEXT_CHANNEL_META`
Статусные действия не ставятся.
## Накопительные и текущие состояния
Нужно различать:
- накопительные события;
- текущий статус.
### Накопительные события
К ним относится:
- `STATUS_DONE_ONCE`
Они могут встречаться сколько угодно раз.
### Текущий статус
Для некоторых статусов есть “актуальное состояние”.
Например:
- `INTERESTED`
- `STARTED`
- `IN_STUDY`
- `COMPLETED`
- `ABANDONED`
- `LEARNED`
Текущий статус определяется как последнее событие соответствующей оси.
### Для упражнения
У упражнения есть две независимые оси:
- количественная: сколько раз выполнено;
- качественная: выучено или нет.
Это значит:
- `STATUS_DONE_ONCE` накапливается;
- `STATUS_LEARNED` живёт как отдельный качественный статус.
### Для курса
У курса текущий статус вычисляется по последнему из:
- `INTERESTED`
- `STARTED`
- `IN_STUDY`
- `COMPLETED`
- `ABANDONED`
## Виртуальная лента достижений пользователя
Согласована важная идея:
- не нужно создавать отдельный физический канал для истории выполнений пользователя;
- вместо этого строится виртуальная лента из его `STATUS_ACTION`.
### Что это даёт
Можно одновременно получить:
- историю человека;
- статистику по самому материалу.
Например, по упражнению можно увидеть:
- сколько разных людей его выполняли;
- сколько всего выполнений было;
- сколько раз конкретный человек его выполнял;
- кто его выучил.
### Что попадает в виртуальную ленту
Попадают status-события пользователя:
- выполненные упражнения;
- выученные упражнения;
- интерес к курсам;
- начатые курсы;
- обучение в процессе;
- завершённые курсы;
- брошенные курсы;
- прохождения услуг;
- подтверждения к этим событиям.
### Можно ли это обсуждать
Да.
Такие статусные сообщения остаются обычными объектами обсуждения:
- на них можно отвечать;
- их можно комментировать;
- на них можно писать отзывы;
- их можно подтверждать.
То есть:
- лента виртуальная;
- но сами записи реальные и обсуждаемые.
## Как это должно выглядеть в интерфейсе
### В каналах
Для разных типов сообщений UI должен понимать роль сообщения.
Например:
- у `TEXT_EXERCISE` можно показать кнопки:
- `Выполнил`
- `Выучил`
- у `TEXT_SERVICE`:
- `Прошёл`
- у `TEXT_COURSE`:
- `Интересно`
- `Начал`
- `Учусь`
- `Завершил`
- `Бросил`
### Для `entrypoint`
Если канал открывается по основной ссылке и у него есть `entrypoint`, UI:
- показывает сам последний `entrypoint`;
- показывает число новых сообщений после него;
- показывает кнопку перехода в конец канала.
Если пользователь уже подписан на канал:
- открывать лучше место новых непрочитанных сообщений;
- но с кнопкой открытия последнего `entrypoint`.
### Для виртуальной ленты достижений
В профиле пользователя UI может показывать:
- отдельную вкладку / раздел;
- где лента строится из его `STATUS_ACTION`.
## Что именно не нужно делать в первой итерации
### Не нужен отдельный физический канал достижений
Технически не нужен.
### Не нужны отдельные edit-подтипы для каждого вида контента
Не нужны:
- `TEXT_EDIT_EXERCISE`
- `TEXT_EDIT_SERVICE`
- `TEXT_EDIT_COURSE`
Достаточно текущего разделения:
- `TEXT_EDIT_POST`
- `TEXT_EDIT_REPLY`
### Не нужен отдельный верхнеуровневый тип для `entrypoint`
Он остаётся подтипом `type=1`.
### Не нужен `EDIT` для status-событий
`STATUS_ACTION` не редактируются.
Если нужно изменить смысл, пишется новое событие.
### Не нужен `CHANNEL_MEMBERSHIP` в первой итерации
Эта тема отложена в отдельный черновик.
## Сводная таблица
### Верхнеуровневые `type`
| Код | Имя | Статус |
|---|---|---|
| 0 | TECH | старый |
| 1 | TEXT | старый код, новое расширенное смысловое описание |
| 2 | REACTION | старый |
| 3 | CONNECTION | старый |
| 4 | USER_PARAM | старый |
| 5 | STATUS_ACTION | первая итерация |
| 6 | CHANNEL_MEMBERSHIP | вынесено в отдельный отложенный черновик |
### Подтипы `type=1`
| subType | Имя | Смысл |
|---|---|---|
| 10 | TEXT_POST | обычный post в линии канала |
| 11 | TEXT_EDIT_POST | edit line-based сообщения |
| 20 | TEXT_REPLY | target-based reply |
| 21 | TEXT_EDIT_REPLY | edit reply |
| 30 | TEXT_RATING | target-based отзыв на конкретный блок |
| 50 | TEXT_REPOST | отложенная будущая заготовка |
| 90 | TEXT_CHANNEL_META | скрытые метаданные канала |
| 100 | TEXT_ENTRYPOINT | входная страница канала |
| 110 | TEXT_EXERCISE | упражнение |
| 120 | TEXT_SERVICE | услуга / процедура |
| 130 | TEXT_COURSE | курс |
### Подтипы `type=5`
| subType | Имя | Смысл |
|---|---|---|
| 10 | STATUS_DONE_ONCE | выполнил / прошёл один раз |
| 20 | STATUS_INTERESTED | заинтересовался |
| 30 | STATUS_STARTED | начал |
| 40 | STATUS_IN_STUDY | учится полноценно |
| 50 | STATUS_COMPLETED | завершил |
| 60 | STATUS_ABANDONED | бросил |
| 70 | STATUS_LEARNED | выучил |
| 80 | STATUS_CONFIRMED | подтверждение status-события |
## Что ещё нужно отдельно утвердить перед реализацией
Перед началом реальной реализации желательно отдельно утвердить:
- точный байтовый формат новых line-based `subType` внутри `type=1`;
- точный байтовый формат `TEXT_RATING` как target-based отзыва;
- точный байтовый формат `STATUS_ACTION`;
- правила target-ссылок для status-событий;
- правила target-ссылок для отзывов на status-события;
- поведение удаления:
- можно ли логически удалять `TEXT_EXERCISE` / `TEXT_SERVICE` / `TEXT_COURSE`;
- можно ли удалять старые `entrypoint` или только оставлять их в истории;
- серверные read-model таблицы и индексы.
## Предварительная оценка готовности к реализации
На текущий момент концепция уже достаточно зрелая, чтобы начинать проектирование реализации первой итерации.
Реализовывать это уже можно, если дополнительно утвердить:
- байтовые форматы;
- правила валидации;
- API чтения новых сущностей;
- UI-матрицу действий по каждому типу контента.
## Краткий итог
Согласованная модель первой итерации сейчас такая:
- почти всё новое содержимое каналов живёт внутри `type=1`;
- `entrypoint` — это специальное текстовое сообщение, а не отдельный верхнеуровневый тип;
- `entrypoint` не редактируется, а версионируется новыми сообщениями;
- канал `0` становится каналом публикаций пользователя и его главной страницей;
- действия пользователя по материалам выносятся в `STATUS_ACTION`;
- `TEXT_RATING` трактуется как target-based отзыв на конкретный блок;
- `CHANNEL_MEMBERSHIP` отложен в отдельный черновик и в первую итерацию не входит.