Партии: «выбывшие» игроки (красный крестик) = последнее место
Выбор места при завершении партии получает опцию «✕ выбыл»; выбывшему авто-проставляется общее последнее место (ничья последнего ранга), плюс флаг eliminated для отрисовки красным крестиком. В результатах и списке партий выбывшие показываются крестиком и идут в конец. Подсчёт очков не меняется (используются обычные числовые места). Бэкенд: модель MatchParticipant.eliminated + миграция 0009 (идемпотентная); схемы (place стал необязательным, +eliminated); match_service (хелпер _resolve_finish_places, finish/update); проброс eliminated в роутерах и stats. Фронт: выбор места с крестиком в MatchDetailPage и AdminMatchEdit, отрисовка в результатах и MatchList, стиль .place-badge.eliminated; регенерация schema.d.ts. Тесты: завершение с выбывшим (последнее место, засчитан), все-выбывшие → 422. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
"""Участник партии: признак выбытия (eliminated).
|
||||
|
||||
Идемпотентна: на свежей БД столбец создаёт 0001 (create_all из актуальных моделей) → no-op;
|
||||
на существующей БД добавляет столбец. render_as_batch включён в env.py (для SQLite).
|
||||
|
||||
Revision ID: 0009_participant_eliminated
|
||||
Revises: 0008_notifications
|
||||
Create Date: 2026-06-26
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import inspect
|
||||
|
||||
from alembic import op
|
||||
|
||||
revision: str = "0009_participant_eliminated"
|
||||
down_revision: Union[str, None] = "0008_notifications"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
bind = op.get_bind()
|
||||
insp = inspect(bind)
|
||||
cols = {c["name"] for c in insp.get_columns("match_participants")}
|
||||
if "eliminated" not in cols:
|
||||
with op.batch_alter_table("match_participants") as b:
|
||||
b.add_column(
|
||||
sa.Column("eliminated", sa.Boolean(), nullable=False, server_default="0")
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
bind = op.get_bind()
|
||||
insp = inspect(bind)
|
||||
cols = {c["name"] for c in insp.get_columns("match_participants")}
|
||||
if "eliminated" in cols:
|
||||
with op.batch_alter_table("match_participants") as b:
|
||||
b.drop_column("eliminated")
|
||||
Reference in New Issue
Block a user