Партия: общий черновик завершения и запрет результатов до финиша
Результаты (места и причина победы) теперь пишутся только в завершённую партию. Раньше их можно было проставить идущей: партия оставалась in_progress, висела в «Незавершённых», в статистику не попадала и очков не приносила — победитель есть, а игры как бы не было. Дату и общий комментарий по ходу партии править по-прежнему можно: двойственного состояния они не создают. Форма завершения получила общий черновик (match_finish_drafts): раскладка мест, ничьи, выбывшие, комментарии и причина победы видны всем, кто заполняет партию. Отдельная таблица, а не колонки в matches, намеренно — запись в строку партии дёргает onupdate у updated_at, то есть версию для оптимистичной блокировки, и «Завершить» у второго участника ловил бы STALE_WRITE на каждую чужую правку. Черновик удаляется при завершении и уходит каскадом при удалении партии. Черновик разъезжается отдельным типом SSE-события: он меняется на каждое движение тайла, и полная инвалидация (лидерборд, история, профили) по нему была бы расточительной. Автору правки событие не шлётся. #28 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BoiJK9ux8peeyjLb8TYjFf
This commit is contained in:
@@ -362,6 +362,37 @@ class MatchAttachment(SQLModel, table=True):
|
||||
created_at: datetime = Field(default_factory=utcnow, nullable=False)
|
||||
|
||||
|
||||
|
||||
class MatchFinishDraft(SQLModel, table=True):
|
||||
"""Общий черновик формы завершения партии: раскладка мест, ничьи, выбывшие,
|
||||
комментарии и причина победы, пока партию не завершили.
|
||||
|
||||
Отдельная таблица, а не колонки в matches, намеренно: запись в строку партии
|
||||
дёргает onupdate у matches.updated_at, а это версия для оптимистичной блокировки —
|
||||
«Завершить» у второго участника ловил бы STALE_WRITE на каждую чужую правку.
|
||||
Живёт только пока партия идёт: finish_match удаляет строку, удаление партии
|
||||
уносит её каскадом."""
|
||||
|
||||
__tablename__ = "match_finish_drafts"
|
||||
|
||||
match_id: int | None = Field(
|
||||
default=None,
|
||||
sa_column=Column(
|
||||
Integer, ForeignKey("matches.id", ondelete="CASCADE"), primary_key=True
|
||||
),
|
||||
)
|
||||
data: dict = Field(sa_column=Column(JSON, nullable=False))
|
||||
updated_by: int | None = Field(
|
||||
sa_column=Column(
|
||||
Integer, ForeignKey("users.id", ondelete="SET NULL"), nullable=True
|
||||
)
|
||||
)
|
||||
updated_at: datetime = Field(
|
||||
default_factory=utcnow,
|
||||
sa_column_kwargs={"onupdate": utcnow},
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
# ─── Уведомления ─────────────────────────────────────────────────────────────
|
||||
|
||||
class Notification(SQLModel, table=True):
|
||||
|
||||
Reference in New Issue
Block a user