This commit is contained in:
ryan
2026-01-18 16:22:43 -05:00
parent 96716d95b6
commit e431ba45e9
9 changed files with 235 additions and 5 deletions

View File

@@ -113,13 +113,16 @@ class Game(db.Model):
is_active = db.Column(db.Boolean, default=False) # Only one game active at a time
current_question_index = db.Column(db.Integer, default=0) # Track current question
is_template = db.Column(db.Boolean, default=False) # Mark as reusable template
current_turn_team_id = db.Column(db.Integer, db.ForeignKey('teams.id'), nullable=True) # Track whose turn it is
# Relationships
teams = db.relationship('Team', back_populates='game', cascade='all, delete-orphan')
teams = db.relationship('Team', back_populates='game', cascade='all, delete-orphan',
foreign_keys='Team.game_id')
game_questions = db.relationship('GameQuestion', back_populates='game',
cascade='all, delete-orphan',
order_by='GameQuestion.order')
scores = db.relationship('Score', back_populates='game', cascade='all, delete-orphan')
current_turn_team = db.relationship('Team', foreign_keys=[current_turn_team_id], post_update=True)
@classmethod
def get_active(cls):
@@ -141,7 +144,9 @@ class Game(db.Model):
'is_active': self.is_active,
'current_question_index': self.current_question_index,
'total_questions': len(self.game_questions),
'is_template': self.is_template
'is_template': self.is_template,
'current_turn_team_id': self.current_turn_team_id,
'current_turn_team_name': self.current_turn_team.name if self.current_turn_team else None
}
if include_questions:

View File

@@ -302,3 +302,25 @@ def seek_audio(game_id):
return jsonify({'message': f'Audio seeked to {position}s'}), 200
except Exception as e:
return jsonify({'error': str(e)}), 500
@bp.route('/game/<int:game_id>/advance-turn', methods=['POST'])
@require_auth
def advance_turn(game_id):
"""Advance to the next team's turn"""
game = Game.query.get_or_404(game_id)
try:
next_team = game_service.advance_turn(game, socketio)
if next_team:
return jsonify({
'message': 'Turn advanced',
'current_turn_team_id': next_team.id,
'current_turn_team_name': next_team.name
}), 200
else:
return jsonify({'error': 'No teams in game'}), 400
except Exception as e:
db.session.rollback()
return jsonify({'error': str(e)}), 500

View File

@@ -1,7 +1,12 @@
from backend.models import db, Game, Score
from backend.models import db, Game, Score, Team
from flask_socketio import emit
def get_ordered_teams(game):
"""Get teams sorted by ID for consistent turn ordering"""
return sorted(game.teams, key=lambda t: t.id)
def get_game_state(game):
"""Get current game state with all necessary information"""
current_question = game.get_current_question()
@@ -12,7 +17,9 @@ def get_game_state(game):
'current_question_index': game.current_question_index,
'total_questions': len(game.game_questions),
'is_active': game.is_active,
'teams': [team.to_dict() for team in game.teams]
'teams': [team.to_dict() for team in game.teams],
'current_turn_team_id': game.current_turn_team_id,
'current_turn_team_name': game.current_turn_team.name if game.current_turn_team else None
}
if current_question:
@@ -42,6 +49,14 @@ def start_game(game, socketio_instance):
game.is_active = True
game.current_question_index = 0
# Set initial turn to the first team (by ID order)
ordered_teams = get_ordered_teams(game)
if ordered_teams:
game.current_turn_team_id = ordered_teams[0].id
else:
game.current_turn_team_id = None
db.session.commit()
# Emit game_started event
@@ -60,6 +75,9 @@ def start_game(game, socketio_instance):
# Emit first question
broadcast_question_change(game, socketio_instance)
# Emit initial turn
broadcast_turn_change(game, socketio_instance)
def next_question(game, socketio_instance):
"""Move to next question"""
@@ -209,6 +227,7 @@ def restart_game(game, socketio_instance):
# Reset game state
game.is_active = False
game.current_question_index = 0
game.current_turn_team_id = None # Reset turn
# Reset phone-a-friend lifelines for all teams
for team in game.teams:
@@ -283,3 +302,52 @@ def broadcast_audio_seek(game, position, socketio_instance):
'game_id': game.id,
'position': position
}, room=f'game_{game.id}_contestant')
def advance_turn(game, socketio_instance):
"""Advance to the next team's turn (cycles through teams by ID order)"""
ordered_teams = get_ordered_teams(game)
if not ordered_teams:
return None
if game.current_turn_team_id is None:
# No current turn, set to first team
next_team = ordered_teams[0]
else:
# Find current team index and advance to next
current_index = None
for i, team in enumerate(ordered_teams):
if team.id == game.current_turn_team_id:
current_index = i
break
if current_index is None:
# Current team not found, set to first
next_team = ordered_teams[0]
else:
# Cycle to next team (modulo for wrap-around)
next_index = (current_index + 1) % len(ordered_teams)
next_team = ordered_teams[next_index]
game.current_turn_team_id = next_team.id
db.session.commit()
# Broadcast turn change to both rooms
broadcast_turn_change(game, socketio_instance)
return next_team
def broadcast_turn_change(game, socketio_instance):
"""Broadcast turn change to all connected clients"""
ordered_teams = get_ordered_teams(game)
turn_data = {
'current_turn_team_id': game.current_turn_team_id,
'current_turn_team_name': game.current_turn_team.name if game.current_turn_team else None,
'all_teams': [{'id': t.id, 'name': t.name} for t in ordered_teams]
}
socketio_instance.emit('turn_changed', turn_data, room=f'game_{game.id}_contestant')
socketio_instance.emit('turn_changed', turn_data, room=f'game_{game.id}_admin')