Skip to content

Commit 1bc5564

Browse files
Clean up existing boss content, part 2 (V3 Milestone 5)
- Isshin: the fight now starts with a Genichiro, Way of Tomoe phase holding only the moves both wikis agree on (his lightning is left out: the wikis conflict). A data migration moves existing Isshin attempts up one phase. - Optional move-level source fields (source_name / source_url, set together or not at all), used for moves taken from another page; the moveset shows them under the move. - Both Owls gain Mikiri Counter (Fandom). - Remove actions that cannot end an attempt: Owl's zig-zag, Guardian Ape's roar, Lady Butterfly's rafter jump, Great Shinobi Owl's charm. - Guardian Ape's diving lunge loses its inferred telegraph; Isshin's phase-3 distance slash is no longer called a lightning variant. - Consistent move types: backflips are combos, lightning attacks are lightning, deflectable moves are not marked unblockable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent fbd19ab commit 1bc5564

18 files changed

Lines changed: 899 additions & 329 deletions
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""add move source
2+
3+
Revision ID: 6849ddf003e3
4+
Revises: 4b0d6abd4d80
5+
Create Date: 2026-10-03 02:32:35.605013
6+
7+
"""
8+
from typing import Sequence, Union
9+
10+
from alembic import op
11+
import sqlalchemy as sa
12+
13+
14+
# revision identifiers, used by Alembic.
15+
revision: str = '6849ddf003e3'
16+
down_revision: Union[str, Sequence[str], None] = '4b0d6abd4d80'
17+
branch_labels: Union[str, Sequence[str], None] = None
18+
depends_on: Union[str, Sequence[str], None] = None
19+
20+
21+
def upgrade() -> None:
22+
"""Upgrade schema: an optional per-move source, for a move whose data comes from a
23+
different page than its boss's. Null means the move uses the boss's source.
24+
"""
25+
op.add_column('moves', sa.Column('source_name', sa.String(length=200), nullable=True))
26+
op.add_column('moves', sa.Column('source_url', sa.Text(), nullable=True))
27+
# Autogenerate does not detect check constraints; this mirrors models.Move.
28+
op.create_check_constraint('ck_moves_source_complete', 'moves', '(source_name IS NULL) = (source_url IS NULL)')
29+
30+
31+
def downgrade() -> None:
32+
"""Downgrade schema."""
33+
op.drop_constraint('ck_moves_source_complete', 'moves', type_='check')
34+
op.drop_column('moves', 'source_url')
35+
op.drop_column('moves', 'source_name')
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""shift isshin attempts for way of tomoe phase
2+
3+
The Isshin, the Sword Saint fight starts with Genichiro, Way of Tomoe. The seed data
4+
now records that as phase 1, so Isshin's own phases move from 1-3 to 2-4. Existing
5+
attempts keep pointing at the same part of the fight by moving up one phase.
6+
7+
Revision ID: 76532dd774e5
8+
Revises: 6849ddf003e3
9+
Create Date: 2026-10-03 02:32:51.211107
10+
11+
"""
12+
from typing import Sequence, Union
13+
14+
from alembic import op
15+
import sqlalchemy as sa
16+
17+
18+
# revision identifiers, used by Alembic.
19+
revision: str = '76532dd774e5'
20+
down_revision: Union[str, Sequence[str], None] = '6849ddf003e3'
21+
branch_labels: Union[str, Sequence[str], None] = None
22+
depends_on: Union[str, Sequence[str], None] = None
23+
24+
25+
ISSHIN = "(SELECT id FROM bosses WHERE slug = 'isshin-sword-saint')"
26+
27+
28+
def upgrade() -> None:
29+
"""Upgrade data: Isshin attempts move up one phase."""
30+
op.execute(f"UPDATE attempts SET phase_reached = phase_reached + 1 WHERE boss_id = {ISSHIN}")
31+
32+
33+
def downgrade() -> None:
34+
"""Downgrade data: attempts in the Way of Tomoe phase have no older equivalent; keep them at phase 1."""
35+
op.execute(f"UPDATE attempts SET phase_reached = GREATEST(phase_reached - 1, 1) WHERE boss_id = {ISSHIN}")

‎backend/app/db/models.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class Move(Base):
7676
CheckConstraint(
7777
"(name_zh_source = 'wiki') = (name_zh_source_url IS NOT NULL)", name="ck_moves_name_zh_source_url"
7878
),
79+
CheckConstraint("(source_name IS NULL) = (source_url IS NULL)", name="ck_moves_source_complete"),
7980
)
8081

8182
id: Mapped[int] = mapped_column(primary_key=True)
@@ -92,6 +93,10 @@ class Move(Base):
9293
telegraph_zh: Mapped[str | None] = mapped_column(Text)
9394
counter_zh: Mapped[str | None] = mapped_column(Text)
9495
common_mistakes_zh: Mapped[str | None] = mapped_column(Text)
96+
# Only for a move whose data comes from a different page than its boss's;
97+
# null means the move uses the boss's source_name / source_url.
98+
source_name: Mapped[str | None] = mapped_column(String(200))
99+
source_url: Mapped[str | None] = mapped_column(Text)
95100
# Chinese name: either the name used by a Chinese wiki ('wiki', with the page in
96101
# name_zh_source_url) or a translation ('translation'), never presented as official.
97102
name_zh: Mapped[str | None] = mapped_column(String(200))

‎backend/app/models/boss.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ class BossMove(BaseModel):
1616
telegraph_zh: str | None = None
1717
counter_zh: str | None = None
1818
common_mistakes_zh: str | None = None
19+
# Set only when this move's data comes from a different page than the boss's source.
20+
source_name: str | None = None
21+
source_url: str | None = None
1922
# "wiki": the name used by a Chinese wiki, see name_zh_source_url.
2023
# "translation": translated for this app; not an official name.
2124
name_zh_source: Literal["wiki", "translation"] | None = None

‎backend/app/seed.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
"telegraph_zh",
3131
"counter_zh",
3232
"common_mistakes_zh",
33+
"source_name",
34+
"source_url",
3335
)
3436

3537
# Every English text field that has a value needs its Chinese version.

‎backend/app/services/boss_service.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ def get_boss(session: Session, boss_slug: str) -> Boss | None:
5656
telegraph_zh=link.move.telegraph_zh,
5757
counter_zh=link.move.counter_zh,
5858
common_mistakes_zh=link.move.common_mistakes_zh,
59+
source_name=link.move.source_name,
60+
source_url=link.move.source_url,
5961
name_zh_source=link.move.name_zh_source,
6062
name_zh_source_url=link.move.name_zh_source_url,
6163
)

0 commit comments

Comments
 (0)