Update wiki page 'База данных'

2026-04-24 13:30:18 +03:00
parent 20f3529efc
commit 569a4a5243
@@ -1,16 +1,17 @@
# База данных # База данных
GM-Relay использует PostgreSQL. Изменения схемы управляются DbUp-миграциями, встроенными в `GmRelay.Bot`. GM-Relay **v1.2.0** использует PostgreSQL. Изменения схемы управляются DbUp-миграциями, встроенными в `GmRelay.Bot` как embedded resources.
## Миграции ## Миграции
Текущие миграции: Текущие миграции:
- `V001__initial_schema.sql` — базовые таблицы для игроков, групп, сессий и участников. - `V001__initial_schema.sql` — базовые таблицы игроков, групп, сессий и участников.
- `V002__add_session_batch.sql` — поле `sessions.batch_id` для пачек сессий. - `V002__add_session_batch.sql` — поле `sessions.batch_id` для пачек сессий.
- `V003__add_thread_id.sql` — поле `sessions.thread_id` для Telegram forum topics. - `V003__add_thread_id.sql` — поле `sessions.thread_id` для Telegram forum topics.
- `V004__add_reschedule_proposals.sql` — таблицы предложений переноса и голосов. - `V004__add_reschedule_proposals.sql` — таблицы предложений переноса и голосов.
- `V005__add_batch_message_id.sql` — поле `sessions.batch_message_id` для редактирования исходного сообщения расписания. - `V005__add_batch_message_id.sql` — поле `sessions.batch_message_id` для редактирования исходного сообщения расписания.
- `V006__add_session_capacity_waitlist.sql` — лимит мест `sessions.max_players`, статус участника `session_participants.registration_status`, время постановки в очередь `session_participants.created_at` и индексы для waitlist.
## Основные таблицы ## Основные таблицы
@@ -21,7 +22,7 @@ GM-Relay использует PostgreSQL. Изменения схемы упра
Важные поля: Важные поля:
- `telegram_id` — уникальный Telegram ID пользователя. - `telegram_id` — уникальный Telegram ID пользователя.
- `display_name` — актуальное отображаемое имя, полученное из Telegram. - `display_name` — актуальное отображаемое имя из Telegram.
- `telegram_username` — username пользователя, если он есть. - `telegram_username` — username пользователя, если он есть.
### game_groups ### game_groups
@@ -32,11 +33,11 @@ Telegram-группы, где организуются игры.
- `telegram_chat_id` — уникальный Telegram chat ID. - `telegram_chat_id` — уникальный Telegram chat ID.
- `name` — актуальное название Telegram-чата. - `name` — актуальное название Telegram-чата.
- `gm_telegram_id` — Telegram ID ГМа для этой группы. - `gm_telegram_id` — Telegram ID GM для этой группы.
### game_group_members ### game_group_members
Таблица связи групп и игроков. Текущая функциональность в основном работает через участие в конкретных сессиях и `gm_telegram_id`; таблица остаётся частью базовой схемы для группового membership. Таблица связи группы и игроков. Сейчас основная проверка роли GM идёт через `game_groups.gm_telegram_id`; таблица остаётся базовой схемой для группового membership.
### sessions ### sessions
@@ -47,11 +48,12 @@ Telegram-группы, где организуются игры.
- `batch_id` — объединяет несколько сессий, созданных одной командой `/newsession`. - `batch_id` — объединяет несколько сессий, созданных одной командой `/newsession`.
- `group_id` — Telegram-группа, которой принадлежит сессия. - `group_id` — Telegram-группа, которой принадлежит сессия.
- `title` — название игры. - `title` — название игры.
- `join_link` — ссылка для подключения, отправляемая перед началом игры. - `join_link` — ссылка для подключения.
- `scheduled_at` — дата и время в UTC. - `scheduled_at` — дата и время в UTC.
- `status``Planned`, `ConfirmationSent`, `Confirmed` или `Cancelled`. - `status``Planned`, `ConfirmationSent`, `Confirmed` или `Cancelled`.
- `confirmation_message_id` — ID Telegram-сообщения с RSVP-подтверждением. - `max_players` — необязательный лимит основного состава; `NULL` означает запись без лимита.
- `link_message_id` — ID Telegram-сообщения с pre-game ссылкой. - `confirmation_message_id` — ID Telegram-сообщения RSVP-подтверждения.
- `link_message_id` — ID Telegram-сообщения со ссылкой перед игрой.
- `thread_id` — ID Telegram forum topic, если тема была создана. - `thread_id` — ID Telegram forum topic, если тема была создана.
- `batch_message_id` — ID исходного Telegram-сообщения с расписанием пачки. - `batch_message_id` — ID исходного Telegram-сообщения с расписанием пачки.
@@ -59,43 +61,38 @@ Telegram-группы, где организуются игры.
### session_participants ### session_participants
Участники конкретных сессий и их RSVP-состояние. Участники сессий, их RSVP-состояние и положение в основном составе или очереди.
Важные поля: Важные поля:
- `session_id` и `player_id` — уникальная пара сессии и игрока. - `session_id` и `player_id` — уникальная пара сессии и игрока.
- `is_gm` — признак, что участник является ГМом. - `is_gm` — признак, что участник является GM.
- `registration_status``Active` для основного состава или `Waitlisted` для листа ожидания.
- `rsvp_status``Pending`, `Confirmed` или `Declined`. - `rsvp_status``Pending`, `Confirmed` или `Declined`.
- `responded_at` — время RSVP-ответа. - `responded_at` — время RSVP-ответа.
- `created_at` — время записи; используется для порядка листа ожидания.
Индексы:
- `ix_session_participants_session_registration_status` ускоряет подсчёт основного состава и waitlist.
- `ix_session_participants_waitlist_order` ускоряет выбор первого игрока из очереди.
## Таблицы переноса сессий ## Таблицы переноса сессий
### reschedule_proposals ### reschedule_proposals
Отслеживает один активный сценарий переноса для сессии. Активные предложения переноса.
Важные поля: Статусы:
- `session_id` — целевая сессия. - `AwaitingTime` — GM нажал перенос, бот ждёт новое время.
- `proposed_at` — новое предложенное время в UTC; `NULL`, пока бот ждёт ввод времени от ГМа. - `Voting` — идёт голосование активных участников.
- `proposed_by` — Telegram ID ГМа. - `Approved` — перенос принят.
- `status``AwaitingTime`, `Voting`, `Approved`, `Rejected`. - `Rejected` — перенос отклонён.
- `vote_message_id` и `vote_chat_id` — где находится Telegram-сообщение голосования.
Partial unique index разрешает только одно активное предложение переноса на сессию, пока статус `AwaitingTime` или `Voting`.
### reschedule_votes ### reschedule_votes
Хранит голоса участников по предложению переноса. Голоса активных участников по предложению переноса. Уникальная пара `proposal_id + player_id` не даёт одному участнику проголосовать несколько раз; повторный голос обновляет значение.
Важные поля:
- `proposal_id` — предложение переноса.
- `player_id` — игрок, который голосует.
- `vote``yes` или `no`.
- `voted_at` — время голосования.
У каждого участника один голос на предложение. Повторное голосование обновляет сохранённый голос.
## Модель статусов ## Модель статусов
@@ -105,15 +102,14 @@ Partial unique index разрешает только одно активное
Planned -> ConfirmationSent -> Confirmed Planned -> ConfirmationSent -> Confirmed
Planned -> Cancelled Planned -> Cancelled
ConfirmationSent -> Cancelled ConfirmationSent -> Cancelled
Confirmed -> ConfirmationSent, если подтвердивший участник позже отказался Confirmed -> ConfirmationSent, если активный участник отказался после подтверждения
``` ```
Статусы переноса: Статусы участия в составе:
```text ```text
AwaitingTime -> Voting -> Approved Active
AwaitingTime -> Voting -> Rejected Waitlisted -> Active, когда GM повышает игрока из листа ожидания
AwaitingTime -> Approved, если участников нет
``` ```
RSVP-статусы: RSVP-статусы:
@@ -127,6 +123,4 @@ Declined -> Confirmed
## Работа со временем ## Работа со временем
Пользовательский ввод и вывод работают в московском времени (`UTC+3`). `MoscowTime.TryParseMoscow` преобразует поддерживаемые локальные форматы в UTC перед сохранением в `scheduled_at`. Пользовательский ввод и вывод работают в московском времени `UTC+3`. В базе `scheduled_at` хранится в UTC. `MoscowTime.TryParseMoscow` преобразует поддерживаемые локальные форматы в UTC перед сохранением.
Web-форма редактирования показывает московское время, а перед обновлением БД преобразует его обратно в UTC.