Display rank-up vote winner on the post-voting upkeep screen
The post-voting (deep_upkeep) screen now names who won the rank-up vote and their new rank, instead of just "Voting complete!". Adds Game.last_rank_up_player_id (+ migration), set when votes are tallied and cleared when the next scene begins; falls back to a "no one ranked up" message when there were no votes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2
TODO.md
2
TODO.md
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
- [x] Visual feedback confirming hand refresh in Deep Upkeep
|
- [x] Visual feedback confirming hand refresh in Deep Upkeep
|
||||||
|
|
||||||
- [ ] On the screen after pirat rank up voting, it should display the winner
|
- [x] On the screen after pirat rank up voting, it should display the winner
|
||||||
|
|
||||||
- [ ] When Deep issues a challenge, stakes should be two fields, success and failure
|
- [ ] When Deep issues a challenge, stakes should be two fields, success and failure
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
$: hand = state.player.hand_cards ? JSON.parse(state.player.hand_cards) : [];
|
$: hand = state.player.hand_cards ? JSON.parse(state.player.hand_cards) : [];
|
||||||
|
// Winner of the rank-up vote, surfaced on the post-voting (deep_upkeep) screen.
|
||||||
|
$: rankUpWinner = state.game.last_rank_up_player_id
|
||||||
|
? state.players.find(p => p.id === state.game.last_rank_up_player_id)
|
||||||
|
: null;
|
||||||
|
|
||||||
// A nominee must be another living, in-play Pi-Rat: not the voter, not a
|
// A nominee must be another living, in-play Pi-Rat: not the voter, not a
|
||||||
// previous-scene Deep, and not dead / awaiting-recruit (they'd reset to
|
// previous-scene Deep, and not dead / awaiting-recruit (they'd reset to
|
||||||
@@ -202,7 +206,11 @@
|
|||||||
|
|
||||||
{#if state.game.phase === 'deep_upkeep'}
|
{#if state.game.phase === 'deep_upkeep'}
|
||||||
<div class="voted-confirmation-box glass-panel">
|
<div class="voted-confirmation-box glass-panel">
|
||||||
<p class="success-text">✔️ Voting complete! Results tallied.</p>
|
{#if rankUpWinner}
|
||||||
|
<p class="success-text">🏆 {displayName(rankUpWinner)} won the vote and ranked up to Rank {rankUpWinner.rank}!</p>
|
||||||
|
{:else}
|
||||||
|
<p class="success-text">✔️ Voting complete! No one ranked up this time.</p>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{:else if hasVoted}
|
{:else if hasVoted}
|
||||||
<div class="voted-confirmation-box glass-panel">
|
<div class="voted-confirmation-box glass-panel">
|
||||||
|
|||||||
@@ -83,7 +83,11 @@ def process_between_scenes_votes(db: Session, game: Game):
|
|||||||
Then sets players who were Deep to discard and redraw.
|
Then sets players who were Deep to discard and redraw.
|
||||||
"""
|
"""
|
||||||
votes = game.votes
|
votes = game.votes
|
||||||
|
# Reset the previous scene's winner before tallying this one.
|
||||||
|
game.last_rank_up_player_id = None
|
||||||
|
db.add(game)
|
||||||
if not votes:
|
if not votes:
|
||||||
|
db.commit()
|
||||||
return
|
return
|
||||||
|
|
||||||
# Count votes
|
# Count votes
|
||||||
@@ -101,6 +105,8 @@ def process_between_scenes_votes(db: Session, game: Game):
|
|||||||
winner = get_player(db, winner_id)
|
winner = get_player(db, winner_id)
|
||||||
if winner:
|
if winner:
|
||||||
change_player_rank(db, game, winner, 1)
|
change_player_rank(db, game, winner, 1)
|
||||||
|
game.last_rank_up_player_id = winner.id
|
||||||
|
db.add(game)
|
||||||
add_game_event(db, game.id, f"{winner.name} was voted to rank up! They are now Rank {winner.rank}.", kind="rank")
|
add_game_event(db, game.id, f"{winner.name} was voted to rank up! They are now Rank {winner.rank}.", kind="rank")
|
||||||
|
|
||||||
# Clear all votes
|
# Clear all votes
|
||||||
@@ -112,6 +118,7 @@ def begin_next_scene_setup(db: Session, game: Game):
|
|||||||
"""Advances to the next scene's setup: bump the scene counter and clear roles."""
|
"""Advances to the next scene's setup: bump the scene counter and clear roles."""
|
||||||
game.current_scene_number += 1
|
game.current_scene_number += 1
|
||||||
game.phase = "scene_setup"
|
game.phase = "scene_setup"
|
||||||
|
game.last_rank_up_player_id = None # Stale once we leave the post-voting screen
|
||||||
for p in game.players:
|
for p in game.players:
|
||||||
p.role = None
|
p.role = None
|
||||||
p.is_ready = False
|
p.is_ready = False
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
"""add last_rank_up_player_id to game
|
||||||
|
|
||||||
|
Revision ID: 3bbf6812c261
|
||||||
|
Revises: 19ee9ae5ca0e
|
||||||
|
Create Date: 2026-06-14 09:21:11.037751
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
import sqlmodel
|
||||||
|
|
||||||
|
|
||||||
|
revision = '3bbf6812c261'
|
||||||
|
down_revision = '19ee9ae5ca0e'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('game', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('last_rank_up_player_id', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('game', schema=None) as batch_op:
|
||||||
|
batch_op.drop_column('last_rank_up_player_id')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -19,6 +19,7 @@ class Game(SQLModel, table=True):
|
|||||||
completed_crew_3: bool = Field(default=False) # Commit Piracy
|
completed_crew_3: bool = Field(default=False) # Commit Piracy
|
||||||
captain_player_id: Optional[str] = Field(default=None) # Persistent captaincy; set once the crew controls a ship
|
captain_player_id: Optional[str] = Field(default=None) # Persistent captaincy; set once the crew controls a ship
|
||||||
teaching_deep_player_id: Optional[str] = Field(default=None) # Teaching mode: an admin who seeds themselves as the forced Rank-3 Deep for the first scene (set in the lobby, honored when starting ranks are rolled)
|
teaching_deep_player_id: Optional[str] = Field(default=None) # Teaching mode: an admin who seeds themselves as the forced Rank-3 Deep for the first scene (set in the lobby, honored when starting ranks are rolled)
|
||||||
|
last_rank_up_player_id: Optional[str] = Field(default=None) # Winner of the most recent rank-up vote, shown on the post-voting upkeep screen; cleared when the next scene begins
|
||||||
|
|
||||||
players: List["Player"] = Relationship(back_populates="game", cascade_delete=True)
|
players: List["Player"] = Relationship(back_populates="game", cascade_delete=True)
|
||||||
obstacles: List["Obstacle"] = Relationship(back_populates="game", cascade_delete=True)
|
obstacles: List["Obstacle"] = Relationship(back_populates="game", cascade_delete=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user