Merge branch '141-richtig-schones-cooles-siegerpodest-2' into 'master'

Resolve "Richtig schönes, cooles Siegerpodest."

Closes #141

See merge request enrichment-2024/qivip!106
This commit is contained in:
ben8
2025-07-29 17:02:51 +00:00
12 changed files with 1256 additions and 126 deletions

View File

@@ -128,6 +128,15 @@ class GameConsumer(AsyncWebsocketConsumer):
host_id = text_data_json['host_id']
if await self.verify_host(host_id):
await self.advance_to_next_question()
elif message_type == 'winner_podest':
host_id = text_data_json['host_id']
if await self.verify_host(host_id):
await self.show_winner_podest()
elif message_type == 'scoreboard':
host_id = text_data_json['host_id']
if await self.verify_host(host_id):
await self.show_scoreboard()
elif message_type == 'finish_game':
host_id = text_data_json['host_id']
@@ -431,6 +440,26 @@ class GameConsumer(AsyncWebsocketConsumer):
'redirect_url': reverse('play:question', kwargs={'join_code': self.join_code})
}
)
elif result == 'winner_podest':
# Notify clients to redirect to next question
await self.channel_layer.group_send(
self.game_group_name,
{
'type': 'game_state_update',
'action': 'show_winner_podest',
'redirect_url': reverse('play:winner_podest', kwargs={'join_code': self.join_code})
}
)
elif result == 'scoreboard':
# Notify clients to redirect to next question
await self.channel_layer.group_send(
self.game_group_name,
{
'type': 'game_state_update',
'action': 'show_scoreboard',
'redirect_url': reverse('play:scoreboard', kwargs={'join_code': self.join_code})
}
)
@database_sync_to_async
def _show_scores(self):
@@ -477,3 +506,48 @@ class GameConsumer(AsyncWebsocketConsumer):
'redirect_url': reverse('play:finished', kwargs={'join_code': self.join_code})
}
)
@database_sync_to_async
def _show_winner_podest(self):
try:
quiz_game = QuizGame.objects.get(join_code=self.join_code)
quiz_game.current_state = 'winner_podest'
quiz_game.save()
return True
except QuizGame.DoesNotExist:
return False
async def show_winner_podest(self):
success = await self._show_winner_podest()
if success:
# Notify clients to redirect to finished page
await self.channel_layer.group_send(
self.game_group_name,
{
'type': 'game_state_update',
'action': 'show_winner_podest',
'redirect_url': reverse('play:winner_podest', kwargs={'join_code': self.join_code})
}
)
@database_sync_to_async
def _show_scoreboard(self):
try:
quiz_game = QuizGame.objects.get(join_code=self.join_code)
quiz_game.current_state = 'scoreboard'
quiz_game.save()
return True
except QuizGame.DoesNotExist:
return False
async def show_scoreboard(self):
success = await self._show_scoreboard()
if success:
# Notify clients to redirect to finished page
await self.channel_layer.group_send(
self.game_group_name,
{
'type': 'game_state_update',
'action': 'show_scoreboard',
'redirect_url': reverse('play:scoreboard', kwargs={'join_code': self.join_code})
}
)

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.1.7 on 2025-07-25 16:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('play', '0013_quizanswer_answer_text_quizanswer_answers_order_and_more'),
]
operations = [
migrations.AlterField(
model_name='quizgame',
name='current_state',
field=models.CharField(choices=[('lobby', 'In Lobby'), ('question', 'Frage läuft'), ('scores', 'Punkteübersicht'), ('winner_podest', 'Siegerpodest'), ('finished', 'Beendet')], default='lobby', max_length=20),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.1.7 on 2025-07-28 13:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('play', '0014_alter_quizgame_current_state'),
]
operations = [
migrations.AlterField(
model_name='quizgame',
name='current_state',
field=models.CharField(choices=[('lobby', 'In Lobby'), ('question', 'Frage läuft'), ('scores', 'Punkteübersicht'), ('winner_podest', 'Siegerpodest'), ('finished', 'Beendet'), ('scoreboard', 'Scoreboard')], default='lobby', max_length=20),
),
]

View File

@@ -10,7 +10,10 @@ class QuizGame(models.Model):
('lobby', 'In Lobby'),
('question', 'Frage läuft'),
('scores', 'Punkteübersicht'),
('finished', 'Beendet')
('winner_podest','Siegerpodest'),
('finished', 'Beendet'),
('scoreboard', 'Scoreboard'),
]
host_id = models.CharField(max_length=200, unique=True)

View File

@@ -12,6 +12,8 @@ urlpatterns = [
path('game/<str:join_code>/waiting', views.waiting_room, name='waiting'),
path('game/<str:join_code>/scores', views.scores, name='scores'),
path('game/<str:join_code>/finished', views.finished, name='finished'),
path('game/<str:join_code>/winner_podest', views.winner_podest, name='winner_podest'),
path('game/<str:join_code>/scoreboard', views.scoreboard, name='scoreboard'),
path('select_mode/<str:join_code>', views.select_mode, name='select_mode'),
path('selected_mode/<str:join_code>', views.selected_mode, name='selected_mode'),
]

View File

@@ -188,6 +188,49 @@ def scores(request, join_code):
'question_index': quiz_game.current_question_index,
'total_questions': len(questions)
})
def scoreboard(request, join_code):
quiz_game = get_object_or_404(QuizGame, join_code=join_code)
# Verify game state
if quiz_game.current_state != 'scoreboard':
return redirect('play:lobby', join_code=join_code)
# Get participants sorted by score
participants = QuizGameParticipant.objects.filter(quiz_game=quiz_game).order_by('-score')
# Check if user is host
is_host = False
if 'host_id' in request.COOKIES and request.COOKIES['host_id'] == quiz_game.host_id:
is_host = True
# Get current question for context
questions = quiz_game.quiz_id.questions.all()
current_question = questions[quiz_game.current_question_index]
question_data = json.loads(current_question.data)
try:
my_participant = request.session.get('my_participant-participant_id')
participant = QuizGameParticipant.objects.get(participant_id=my_participant)
my_participant=participant
except:
participant = QuizGameParticipant.objects.none()
return render(request, 'play/game/scoreboard.html', {
'quiz_game': quiz_game,
'participants': participants,
'participant': participant,
'my_participant':my_participant,
'is_host': is_host,
'host_id': quiz_game.host_id if is_host else None,
'is_last_question': quiz_game.current_question_index + 1 >= len(questions),
'question_data': question_data,
'question_index': quiz_game.current_question_index,
'total_questions': len(questions)
})
"""
def finished(request, join_code):
@@ -225,6 +268,45 @@ def finished(request, join_code):
"""
def winner_podest(request, join_code):
quiz_game = get_object_or_404(QuizGame, join_code=join_code)
# Verify game state
if quiz_game.current_state != 'winner_podest':
return redirect('play:lobby', join_code=join_code)
# Get participants sorted by score
participants = QuizGameParticipant.objects.filter(quiz_game=quiz_game).order_by('-score')
# Check if user is host
is_host = False
if 'host_id' in request.COOKIES and request.COOKIES['host_id'] == quiz_game.host_id:
is_host = True
# Get current question for context
questions = quiz_game.quiz_id.questions.all()
current_question = questions[quiz_game.current_question_index]
question_data = json.loads(current_question.data)
try:
my_participant = request.session.get('my_participant-participant_id')
participant = QuizGameParticipant.objects.get(participant_id=my_participant)
my_participant=participant
except:
participant = QuizGameParticipant.objects.none()
return render(request, 'play/game/winner_podest.html', {
'quiz_game': quiz_game,
'participants': participants,
'participant': participant,
'my_participant':my_participant,
'is_host': is_host,
'host_id': quiz_game.host_id if is_host else None,
'is_last_question': quiz_game.current_question_index + 1 >= len(questions),
'question_data': question_data,
'question_index': quiz_game.current_question_index,
'total_questions': len(questions)
})
def finished(request, join_code):
quiz_game = get_object_or_404(QuizGame, join_code=join_code)
@@ -260,8 +342,7 @@ def finished(request, join_code):
return render(request, 'play/game/finished.html', context)
except QuizGame.DoesNotExist:
return redirect('home')
def question(request, join_code):
quiz_game = get_object_or_404(QuizGame, join_code=join_code)