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

26 KiB
Raw Permalink Blame History

Черновик дополнений каналов и типов сообщений 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=0TECH
  • type=1TEXT
  • type=2REACTION
  • type=3CONNECTION
  • type=4USER_PARAM

Верхнеуровневые типы первой итерации

Используются:

  • 0TECH
  • 1TEXT
  • 2REACTION
  • 3CONNECTION
  • 4USER_PARAM
  • 5STATUS_ACTION

Отдельно:

  • 6CHANNEL_MEMBERSHIP
    • зарезервирован как следующая тема;
    • вынесен в отдельный черновик;
    • в текущую реализацию не входит.

Подтипы внутри type=1

Согласованная таблица первой итерации:

  • subType=10TEXT_POST
  • subType=11TEXT_EDIT_POST
  • subType=20TEXT_REPLY
  • subType=21TEXT_EDIT_REPLY
  • subType=30TEXT_RATING
  • subType=50TEXT_REPOST
  • subType=90TEXT_CHANNEL_META
  • subType=100TEXT_ENTRYPOINT
  • subType=110TEXT_EXERCISE
  • subType=120TEXT_SERVICE
  • subType=130TEXT_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=10STATUS_DONE_ONCE
  • subType=20STATUS_INTERESTED
  • subType=30STATUS_STARTED
  • subType=40STATUS_IN_STUDY
  • subType=50STATUS_COMPLETED
  • subType=60STATUS_ABANDONED
  • subType=70STATUS_LEARNED
  • subType=80STATUS_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 отложен в отдельный черновик и в первую итерацию не входит.