Add boss battles, level caps, and badge tracking
Introduces full boss battle system: data models (BossBattle, BossPokemon, BossResult), API endpoints for CRUD and per-run defeat tracking, and frontend UI including a sticky level cap bar with badge display on the run page, interleaved boss battle cards in the encounter list, and an admin panel section for managing boss battles and their pokemon teams. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
"""add boss battles
|
||||
|
||||
Revision ID: c2d3e4f5a6b7
|
||||
Revises: b1c2d3e4f5a6
|
||||
Create Date: 2026-02-08 12:00:00.000000
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'c2d3e4f5a6b7'
|
||||
down_revision: Union[str, Sequence[str], None] = 'b1c2d3e4f5a6'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.create_table(
|
||||
'boss_battles',
|
||||
sa.Column('id', sa.Integer(), primary_key=True),
|
||||
sa.Column('game_id', sa.Integer(), sa.ForeignKey('games.id'), nullable=False, index=True),
|
||||
sa.Column('name', sa.String(100), nullable=False),
|
||||
sa.Column('boss_type', sa.String(20), nullable=False),
|
||||
sa.Column('badge_name', sa.String(100), nullable=True),
|
||||
sa.Column('badge_image_url', sa.String(500), nullable=True),
|
||||
sa.Column('level_cap', sa.SmallInteger(), nullable=False),
|
||||
sa.Column('order', sa.SmallInteger(), nullable=False),
|
||||
sa.Column('after_route_id', sa.Integer(), sa.ForeignKey('routes.id'), nullable=True, index=True),
|
||||
sa.Column('location', sa.String(200), nullable=False),
|
||||
sa.Column('sprite_url', sa.String(500), nullable=True),
|
||||
)
|
||||
|
||||
op.create_table(
|
||||
'boss_pokemon',
|
||||
sa.Column('id', sa.Integer(), primary_key=True),
|
||||
sa.Column('boss_battle_id', sa.Integer(), sa.ForeignKey('boss_battles.id', ondelete='CASCADE'), nullable=False, index=True),
|
||||
sa.Column('pokemon_id', sa.Integer(), sa.ForeignKey('pokemon.id'), nullable=False, index=True),
|
||||
sa.Column('level', sa.SmallInteger(), nullable=False),
|
||||
sa.Column('order', sa.SmallInteger(), nullable=False),
|
||||
)
|
||||
|
||||
op.create_table(
|
||||
'boss_results',
|
||||
sa.Column('id', sa.Integer(), primary_key=True),
|
||||
sa.Column('run_id', sa.Integer(), sa.ForeignKey('nuzlocke_runs.id', ondelete='CASCADE'), nullable=False, index=True),
|
||||
sa.Column('boss_battle_id', sa.Integer(), sa.ForeignKey('boss_battles.id'), nullable=False, index=True),
|
||||
sa.Column('result', sa.String(10), nullable=False),
|
||||
sa.Column('attempts', sa.SmallInteger(), nullable=False, server_default='1'),
|
||||
sa.Column('completed_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.UniqueConstraint('run_id', 'boss_battle_id', name='uq_boss_results_run_boss'),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_table('boss_results')
|
||||
op.drop_table('boss_pokemon')
|
||||
op.drop_table('boss_battles')
|
||||
Reference in New Issue
Block a user