add show answer
This commit is contained in:
parent
985a70abf3
commit
6fc98c48d9
28
app.py
28
app.py
@ -53,7 +53,8 @@ def host():
|
||||
games[secret] = {
|
||||
'players': {}, 'order': [],
|
||||
'current_q': 0, 'answered': [],
|
||||
'started': False, 'finished': False
|
||||
'started': False, 'finished': False,
|
||||
'revealed': False
|
||||
}
|
||||
|
||||
# build join URL + QR
|
||||
@ -256,6 +257,8 @@ def on_submit_answer(data):
|
||||
if not secret or secret not in games or pid not in games[secret]['players']:
|
||||
return
|
||||
game = games[secret]
|
||||
if game.get('revealed'):
|
||||
return
|
||||
if any(pid == p for p,_ in game['answered']):
|
||||
return
|
||||
|
||||
@ -301,7 +304,22 @@ def on_rejoin_game():
|
||||
join_room('player')
|
||||
join_room(pid)
|
||||
_send_sync_state(pid, game)
|
||||
|
||||
|
||||
|
||||
@socketio.on('show_answer')
|
||||
def on_show_answer():
|
||||
secret = session.get('secret')
|
||||
if session.get('role') != 'host' or not secret or secret not in games:
|
||||
return
|
||||
game = games[secret]
|
||||
game['revealed'] = True
|
||||
# find the correct answer text for current question
|
||||
correct = questions[game['current_q']]['correct']
|
||||
# emit to host so they can display it
|
||||
emit('answer_revealed', {'correct': correct}, room='host')
|
||||
# emit to all players so they can highlight it
|
||||
socketio.emit('answer_revealed', {'correct': correct}, room='player')
|
||||
|
||||
|
||||
# helpers
|
||||
|
||||
@ -337,6 +355,7 @@ def _send_sync_state(pid, game):
|
||||
|
||||
def _send_question(secret):
|
||||
game = games[secret]
|
||||
game['revealed'] = False
|
||||
q = questions[game['current_q']]
|
||||
# clear previous answers
|
||||
game['answered'].clear()
|
||||
@ -403,4 +422,9 @@ def _score_and_emit(secret):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# show own IP address
|
||||
import socket
|
||||
hostname = socket.gethostname()
|
||||
ip_address = socket.gethostbyname(hostname)
|
||||
print(f"Running on http://{ip_address}:5000/")
|
||||
socketio.run(app, host='0.0.0.0', port=5000)
|
||||
@ -25,14 +25,15 @@
|
||||
<!-- Question & Current Leaderboard -->
|
||||
<div id="host-question" style="display:none;">
|
||||
<h2 id="qText" style="font-size:5rem;"></h2>
|
||||
<button id="nextBtn" class="btn btn-warning mt-3">Nächste Frage</button>
|
||||
<div id="host-results" style="display:none; margin:20px;">
|
||||
<ul id="perQ" class="list-group mb-3 text-center"></ul>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<button id="showAnswerBtn" class="btn btn-info">Antwort zeigen</button>
|
||||
<button id="nextBtn" class="btn btn-warning" disabled>Nächste Frage</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Per-Question and Overall Results -->
|
||||
<div id="host-results" style="display:none;">
|
||||
<h4>Question Results</h4>
|
||||
<ul id="perQ" class="list-group mb-3"></ul>
|
||||
</div>
|
||||
|
||||
<!-- Final Top-10 Leaderboard -->
|
||||
<div id="final-results" style="display:none;" class="mt-4">
|
||||
@ -90,6 +91,9 @@
|
||||
$('#qrContainer, #startBtn, #rosterHeader, #roster').hide();
|
||||
$('#host-question').show();
|
||||
$('#qText').text(data.question);
|
||||
$('#host-results').hide();
|
||||
$('#showAnswerBtn').prop({ disabled: false }).show();
|
||||
$('#nextBtn').prop('disabled', true);
|
||||
});
|
||||
|
||||
// Overall leaderboard updates (max 5 rows)
|
||||
@ -103,21 +107,31 @@
|
||||
});
|
||||
});
|
||||
|
||||
// Per-question results
|
||||
socket.on('question_leader', data => {
|
||||
console.log('Question leader:', data.results);
|
||||
$('#perQ').empty();
|
||||
data.results.forEach(r => {
|
||||
$('#perQ').append(`<li class="list-group-item">${r.name}: +${r.points}</li>`);
|
||||
});
|
||||
});
|
||||
|
||||
// Next question
|
||||
$('#nextBtn').off('click').on('click', () => {
|
||||
console.log('Next question clicked');
|
||||
socket.emit('next_question');
|
||||
});
|
||||
|
||||
// when host clicks “Show Answer”
|
||||
$('#showAnswerBtn').off('click').on('click', () => {
|
||||
socket.emit('show_answer');
|
||||
});
|
||||
|
||||
// once server confirms the answer is revealed
|
||||
socket.on('answer_revealed', data => {
|
||||
// display the correct answer on host screen
|
||||
$('#perQ').empty();
|
||||
$('#perQ').append(
|
||||
`<li class="list-group-item list-group-item-success" style="font-size:5rem;">${data.correct}</li>`
|
||||
);
|
||||
$('#host-results').show();
|
||||
|
||||
// disable Show Answer button, enable Next
|
||||
$('#showAnswerBtn').prop('disabled', true);
|
||||
$('#nextBtn').prop('disabled', false);
|
||||
});
|
||||
|
||||
// Show final top-10 when game_over arrives
|
||||
socket.on('game_over', data => {
|
||||
if (data.board) {
|
||||
|
||||
@ -3,12 +3,15 @@
|
||||
{% block content %}
|
||||
<style>
|
||||
.option.selected {
|
||||
background-color: #0d6efd; /* bootstrap “primary” bg */
|
||||
color: white;
|
||||
background-color:rgb(110, 168, 255); /* bootstrap “primary” bg */
|
||||
color: black;
|
||||
}
|
||||
.option.disabled {
|
||||
background-color: #6c757d; /* bootstrap “secondary” bg */
|
||||
color: white;
|
||||
background-color:rgb(148, 148, 148); /* bootstrap “secondary” bg */
|
||||
color: black;
|
||||
}
|
||||
.option.correct {
|
||||
border: 5px solid #198754 !important; /* bootstrap “success” green */
|
||||
}
|
||||
</style>
|
||||
<div class="container" id="player-app">
|
||||
@ -93,6 +96,30 @@
|
||||
renderOptions(data.options, false);
|
||||
});
|
||||
|
||||
|
||||
// when the right answer is revealed
|
||||
socket.on('answer_revealed', data => {
|
||||
$('.option').each(function() {
|
||||
const $opt = $(this);
|
||||
if ($opt.text() === data.correct) {
|
||||
// highlight as correct with green outline
|
||||
$opt
|
||||
.addClass('correct')
|
||||
.removeClass('btn-outline-primary disabled')
|
||||
.prop('disabled', true);
|
||||
} else {
|
||||
// any un-clicked options become permanently disabled
|
||||
if (!$opt.hasClass('selected')) {
|
||||
$opt
|
||||
.addClass('disabled')
|
||||
.removeClass('btn-outline-primary btn-primary')
|
||||
.prop('disabled', true);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Handle answer clicks
|
||||
$(document).on('click', '.option', function() {
|
||||
const $all = $('.option');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user