594 lines
21 KiB
HTML
594 lines
21 KiB
HTML
{% extends 'base.html' %}
|
||
|
||
{% block content %}
|
||
|
||
{% if is_last_question and is_host %}
|
||
<!-- Siegerpodest -->
|
||
<div class="min-h-screen">
|
||
<h2 class="w-full flex justify-center dark:text-white font-bold text-2xl ">🏆 Siegerpodest</h2>
|
||
<h4 class="w-full flex justify-center dark:text-white font-bold">Wer ist hier der Quiz-Master? </h4>
|
||
|
||
{% with participant=participants.0 %}
|
||
<div class="w-full flex justify-center">
|
||
<h1 id="winner-text" class="bg-gradient-to-r from-yellow-400 via-yellow-300 to-yellow-600 bg-clip-text text-transparent font-bold hidden animate-ping px-2 max-w-screen-sm text-center break-words">
|
||
Glückwunsch, {{ participant.display_name }}!
|
||
</h1>
|
||
</div>
|
||
{% endwith %}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<div id="podest-container" class="w-full absolute bottom-0 flex justify-center items-end gap-2 md:gap-4 mb-2 dark:text-white">
|
||
|
||
|
||
<!-- Platz 2 links -->
|
||
{% with participant=participants.1 %}
|
||
<div class="flex flex-col shrink items-center break-words max-w-[6rem] md:max-w-[8rem] lg:max-w-[10rem] overflow-x-auto pt-10">
|
||
<span class="display_name p-2 text-gray-600 font-black text-xl md:text-2xl lg:text-3xl opacity-0 transition-opacity duration-1000 dark:text-white hyphens-auto" id="display_name-1">{{ participant.display_name }}</span>
|
||
<p data-score="{{ participant.score }}" data-last-score="{{ participant.last_score }}" class="opacity-0 transition-opacity duration-1000 dark:text-white font-bold show-score text-sm md:text-lg lg:text-xl text-gray-400" id="score-1">{{ participant.score }}</p>
|
||
<div data-final-height="33" id="podium-1" class="border-2 border-gray-200 transition-all duration-1000 ease-out overflow-hidden podium h-24 md:h-[12rem] lg:h-[16rem] w-24 md:w-32 lg:w-40 rounded-t-md font-bold text-center text-base shadow-lg bg-gradient-to-b from-gray-400 via-gray-300 to-gray-300 flex flex-col items-center justify-center text-black dark:text-white cursor-pointer leading-tight">
|
||
<span class="size-10 md:size-18 rounded-full bg-white text-black text-center flex items-center justify-center font-bold text-3xl md:text-5xl lg:text-6xl">🥈</span>
|
||
</div>
|
||
</div>
|
||
{% endwith %}
|
||
|
||
<!-- Platz 1 mitte -->
|
||
{% with participant=participants.0 %}
|
||
<div class="flex flex-col shrink items-center break-words max-w-[6rem] md:max-w-[8rem] lg:max-w-[10rem] overflow-x-auto pt-10">
|
||
<div id="resultFirst"></div>
|
||
<span class="display_name p-2 text-gray-600 font-black text-xl md:text-3xl lg:text-4xl opacity-0 transition-opacity duration-1000 bg-gradient-to-r from-yellow-400 via-yellow-300 to-yellow-600 bg-clip-text text-transparent hyphens-auto" id="display_name-0">{{ participant.display_name }}</span>
|
||
<p data-score="{{ participant.score }}" data-last-score="{{ participant.last_score }}" class="opacity-0 transition-opacity duration-1000 dark:text-white text-yellow-500 font-bold show-score text-sm md:text-lg lg:text-xl" id="score-0">{{ participant.score }}</p>
|
||
<div data-final-height="45" id="podium-0" class="border-2 border-yellow-500 transition-all duration-1000 ease-out overflow-hidden podium h-32 md:h-[16rem] lg:h-[22rem] w-24 md:w-32 lg:w-40 rounded-t-md font-bold text-center text-base shadow-lg bg-gradient-to-b from-yellow-400 via-yellow-300 to-yellow-600 flex flex-col items-center justify-center text-black dark:text-white cursor-pointer leading-tight">
|
||
<span id="firstMedal" class="size-12 md:size-22 rounded-full bg-white text-black text-center flex items-center justify-center font-bold text-4xl md:text-6xl lg:text-7xl">🥇</span><br>
|
||
</div>
|
||
</div>
|
||
{% endwith %}
|
||
|
||
<!-- Platz 3 rechts -->
|
||
{% with participant=participants.2 %}
|
||
<div class="flex flex-col shrink items-center break-words max-w-[6rem] md:max-w-[8rem] lg:max-w-[10rem] overflow-x-auto pt-10">
|
||
<span class="display_name p-2 text-gray-600 font-black text-xl md:text-2xl lg:text-3xl dark:text-white opacity-0 transition-opacity duration-1000 hyphens-auto" id="display_name-2">{{ participant.display_name }}</span>
|
||
<p data-score="{{ participant.score }}" data-last-score="{{ participant.last_score }}" class="opacity-0 transition-opacity duration-1000 dark:text-white text-orange-500 font-bold show-score text-sm md:text-lg lg:text-xl" id="score-2">{{ participant.score }}</p>
|
||
<div data-final-height="25" id="podium-2" class="border-2 border-orange-500 transition-all duration-1000 ease-out overflow-hidden podium h-20 md:h-[10rem] lg:h-[14rem] w-24 md:w-32 lg:w-40 rounded-t-md font-bold text-center text-base shadow-lg bg-gradient-to-b from-orange-500 via-orange-400 to-orange-700 flex flex-col items-center justify-center text-black dark:text-white cursor-pointer leading-tight">
|
||
<span class="size-10 md:size-18 rounded-full bg-white text-black text-center flex items-center justify-center font-bold text-3xl md:text-5xl lg:text-6xl">🥉</span>
|
||
</div>
|
||
</div>
|
||
{% endwith %}
|
||
|
||
</div>
|
||
|
||
|
||
</div>
|
||
<div id="thanks" class="hidden -mt-10">
|
||
<div class="w-full flex justify-center">
|
||
<h1 class="bg-gradient-to-r from-yellow-400 via-yellow-300 to-yellow-600 bg-clip-text text-transparent font-bold px-2 max-w-screen-sm text-center break-words">
|
||
Vielen Dank fürs Spielen!
|
||
</h1>
|
||
</div>
|
||
|
||
<div class="flex justify-center">
|
||
<button id="finish-button" class=" w-3/4 md:w-1/2 bottom-0 left-0 p-3 rounded-full bg-blue-600 text-white font-bold hover:bg-blue-700 transition-colors duration-200">
|
||
Quiz beenden
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
{% else %}
|
||
|
||
|
||
<div class="container mx-auto px-4">
|
||
|
||
|
||
{% with participant=participants.0 %}
|
||
<div class="w-full flex justify-center">
|
||
<h1 id="winner-text" class="bg-gradient-to-r from-yellow-400 via-yellow-300 to-yellow-600 bg-clip-text text-transparent font-bold hidden animate-ping px-2 max-w-screen-sm text-center break-words">
|
||
Glückwunsch, {{ participant.display_name }}!
|
||
</h1>
|
||
</div>
|
||
{% endwith %}
|
||
|
||
<div class="bg-white rounded-lg shadow-md p-6 mb-6 dark:bg-transparent dark:text-white">
|
||
<h1 id="result-text" class="text-3xl w-full flex justify-center dark:text-white font-bold">🏆 Wer ist hier der Quiz-Master?</h1>
|
||
|
||
<h4 id="info" class="mt-4 w-full flex justify-center dark:text-white font-bold">Nach der Siegerehrung siehst du deine Platzierung!</h4>
|
||
|
||
|
||
|
||
<div id="participant-score" class="mb-6 ">
|
||
|
||
|
||
<div id="scoreboard" class="leading-relaxed">
|
||
{% for participant in participants %}
|
||
{% if request.session.mode != "learn" %}
|
||
{% if participant == my_participant or is_host %}
|
||
<div id="player_score" class="hidden dark:bg-transparent mt-2 shadow-sm p-4 bg-gray-100 rounded-lg border-2 border {% if forloop.counter <= 3 %}
|
||
{% if forloop.counter == 1 %}border-yellow-400{% endif %}
|
||
{% if forloop.counter == 2 %}border-gray-400{% endif %}
|
||
{% if forloop.counter == 3 %}border-orange-400{% endif %}
|
||
{% else %}
|
||
border-transparent{% endif %}">
|
||
<div class="flex flex-col items-start gap-1">
|
||
<div class="text-4xl font-bold flex items-center gap-2">
|
||
{% if forloop.counter == 1 %}
|
||
🥇
|
||
{% elif forloop.counter == 2 %}
|
||
🥈
|
||
{% elif forloop.counter == 3 %}
|
||
🥉
|
||
{% else %}
|
||
{{ forloop.counter }}.
|
||
{% endif %}
|
||
<span class="display_name text-gray-600 font-black text-3xl dark:text-white " id="display_name-{{ forloop.counter0 }}">{{ participant.display_name }}</span>
|
||
</div class="flex flex-col items-start">
|
||
|
||
<p data-score="{{ participant.score }}" data-last-score="{{ participant.last_score }}" class="dark:text-white text-gray-600 font-bold show-score text-xl" id="score-{{ forloop.counter0 }}">{{ participant.score }} Punkte</p>
|
||
|
||
{% endif %}
|
||
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
{% endif %}
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
|
||
|
||
{% endif %}
|
||
|
||
|
||
|
||
<style>
|
||
.podium {
|
||
height: 0;
|
||
|
||
}
|
||
.spotlight-wrapper::before {
|
||
content: "";
|
||
position: absolute;
|
||
top: -800px; /* Start oben außerhalb */
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 15rem;
|
||
height: 700px;
|
||
pointer-events: none;
|
||
|
||
background: radial-gradient(
|
||
ellipse 60% 100% at center bottom,
|
||
rgba(254, 254, 178, 0.9) 0%,
|
||
rgba(252, 236, 132, 0.7) 25%,
|
||
rgba(255, 230, 130, 0.5) 55%,
|
||
rgba(255, 210, 100, 0.1) 85%,
|
||
rgba(255, 180, 70, 0) 100%
|
||
);
|
||
|
||
filter: blur(24px) brightness(1.2);
|
||
opacity: 0; /* Start unsichtbar */
|
||
animation: slideInOutSpotlight 6s ease forwards , fadeOutSpotlight 6s 6s ease forwards; /* Dauer anpassen */
|
||
z-index: -1;
|
||
|
||
box-shadow: 0 0 60px 30px rgba(255, 240, 150, 0.15);
|
||
}
|
||
|
||
@keyframes slideInOutSpotlight {
|
||
0% {
|
||
top: -800px;
|
||
opacity: 0;
|
||
}
|
||
20% {
|
||
top: -640px; /* Endposition */
|
||
opacity: 1;
|
||
}
|
||
|
||
100% {
|
||
top: -640px;
|
||
opacity: 1;
|
||
|
||
}
|
||
}
|
||
|
||
|
||
@keyframes fadeOutSpotlight {
|
||
0% {
|
||
top: -640px;
|
||
opacity: 1;
|
||
|
||
}
|
||
|
||
|
||
100% {
|
||
top: -640px;
|
||
opacity: 0;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
</style>
|
||
|
||
|
||
|
||
{% endblock %}
|
||
</div>
|
||
|
||
{% block extra_js %}
|
||
{% if is_last_question %}
|
||
|
||
<script>
|
||
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
|
||
const animationDuration = 1500; // Dauer der Wachstumsanimation
|
||
const waitTime=3000;
|
||
const podiums = [
|
||
|
||
{ id: 'podium-2', delay: 2000 }, // immer vorheriges von Bedeutung
|
||
{ id: 'podium-1', delay: 2000 },
|
||
{ id: 'podium-0', delay: 0 },
|
||
];
|
||
|
||
|
||
let totalDelay = 0;
|
||
|
||
podiums.forEach(({ delay }) => {
|
||
totalDelay += delay + waitTime;
|
||
});
|
||
const totalAnimationTime = totalDelay + animationDuration;
|
||
setTimeout(() => {
|
||
show_score();
|
||
}, totalAnimationTime);
|
||
|
||
totalDelay = 0;
|
||
|
||
|
||
|
||
podiums.forEach(({ id, delay }) => {
|
||
|
||
const podium = document.getElementById(id);
|
||
if (!podium) return;
|
||
|
||
const finalHeight = parseInt(podium.dataset.finalHeight) || 160;
|
||
podium.style.transition = `height ${animationDuration}ms ease-in-out`;
|
||
podium.style.height = '0px';
|
||
|
||
// Wachstum starten nach gesamter Wartezeit
|
||
setTimeout(() => {
|
||
podium.style.height = `${finalHeight}vh`;
|
||
}, totalDelay);
|
||
|
||
// Name & Score anzeigen nach Balken-Animation
|
||
setTimeout(() => {
|
||
|
||
if (id === 'podium-0') {
|
||
let name = document.getElementById(`display_name-0`);
|
||
let score = document.getElementById(`score-0`);
|
||
let winnerText= document.getElementById(`winner-text`);
|
||
|
||
let thanks= document.getElementById(`thanks`);
|
||
// 1. Lichtkegel anzeigen
|
||
if (resultFirst) {
|
||
resultFirst.classList.add('spotlight-wrapper');
|
||
score.classList.add('opacity-0');
|
||
name.classList.add('opacity-0');
|
||
}
|
||
|
||
|
||
|
||
// 2. Nach kurzer Wartezeit Name & Score anzeigen
|
||
setTimeout(() => {
|
||
|
||
if (name) {
|
||
name.classList.add('opacity-100', 'animate-bounce','spotlight-text'); // z. B. sichtbar + Effekt
|
||
}
|
||
|
||
if (winnerText) {
|
||
winnerText.classList.remove('hidden');
|
||
}
|
||
|
||
if (thanks) {
|
||
thanks.classList.remove('hidden');
|
||
}
|
||
|
||
if (score) {
|
||
score.classList.add('opacity-100'); // z. B. sichtbar + Effekt
|
||
}
|
||
triggerConfetti();
|
||
|
||
}, 2000);
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
document.body.style.overflow = 'auto';
|
||
return;
|
||
}
|
||
|
||
const index = id.split('-')[1];
|
||
const name = document.getElementById(`display_name-${index}`);
|
||
const score = document.getElementById(`score-${index}`);
|
||
|
||
document.body.style.overflow = 'hidden';
|
||
|
||
if (name && id !== 'podium-0') setTimeout(() => {
|
||
name.classList.add('opacity-100');
|
||
name.classList.add('animate-bounce');
|
||
|
||
if (score) score.classList.add('opacity-100');
|
||
}, waitTime);
|
||
|
||
}, totalDelay + animationDuration);
|
||
|
||
|
||
totalDelay += delay + waitTime; // wichtig: aufsummieren
|
||
|
||
|
||
});
|
||
|
||
|
||
|
||
});
|
||
|
||
// Hilfsfunktion für Pausen
|
||
function sleep(ms) {
|
||
return new Promise(resolve => setTimeout(resolve, ms));
|
||
}
|
||
|
||
|
||
function triggerConfetti() {
|
||
const end = Date.now() + 30 * 1000;
|
||
(function frame() {
|
||
confetti({ particleCount: 2, angle: 60, spread: 55, origin: { x: 0 } });
|
||
confetti({ particleCount: 2, angle: 120, spread: 55, origin: { x: 1 } });
|
||
if (Date.now() < end) requestAnimationFrame(frame);
|
||
})();
|
||
}
|
||
|
||
function show_score() {
|
||
|
||
let player_score=document.getElementById('player_score');
|
||
player_score.classList.remove('hidden');
|
||
info=document.getElementById('info');
|
||
info.classList.add('hidden');
|
||
resultText=document.getElementById('result-text');
|
||
resultText.textContent="Dein Ergebnis";
|
||
|
||
|
||
|
||
const myName = "{{ my_participant.id|escapejs }}";
|
||
const firstPlaceName = "{{ participants.0.id|escapejs }}";
|
||
|
||
if (myName === firstPlaceName) {
|
||
let winnerText= document.getElementById(`winner-text`);
|
||
winnerText.classList.remove('hidden');
|
||
triggerConfetti();
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
</script>
|
||
{% endif %}
|
||
{% include 'play/game/common_scripts.html' %}
|
||
{% if is_host %}
|
||
{% include 'play/game/sound.html' %}
|
||
{% endif %}
|
||
|
||
|
||
|
||
|
||
<script>
|
||
async function start() {
|
||
|
||
elements=document.getElementsByClassName("show-score");
|
||
for (let i = 0; i < elements.length; i++) {
|
||
const el = elements[i];
|
||
|
||
let counter=Number(el.getAttribute('data-score'))-Number(el.getAttribute('data-last-score'));
|
||
let goal=Number(el.getAttribute('data-score'));
|
||
let interval= setInterval(function(){
|
||
el.innerHTML = counter + " Punkte";
|
||
|
||
|
||
if(counter<=goal){
|
||
el.innerHTML = counter + " Punkte";
|
||
counter+=8;
|
||
|
||
}
|
||
else{
|
||
|
||
el.innerHTML = goal + " Punkte";
|
||
clearInterval(interval);
|
||
}
|
||
|
||
}, 20);}}
|
||
|
||
function bounce(){
|
||
|
||
const names = document.getElementsByClassName("display_name");
|
||
for (let i = 0; i < names.length; i++) {
|
||
names[i].classList.add("animate-bounce");
|
||
}
|
||
}
|
||
|
||
|
||
{% if is_last_question %}
|
||
start();
|
||
bounce();
|
||
|
||
|
||
{% else %}
|
||
start();
|
||
{% endif %}
|
||
|
||
const richtigeAntworten = [
|
||
"Deine Antwort ist nicht falsch. Sie ist richtig!",
|
||
"Ja, du kannst es!",
|
||
"So kann es weiter gehen.",
|
||
"Ja, deine Antwort ist korrekt. Was soll ich dazu noch sagen? SUPER!",
|
||
"SUPER GUT.",
|
||
"Volltreffer!",
|
||
"Bravo! Das sitzt!",
|
||
"Na bitte, geht doch!",
|
||
"Schön. Einfach schön.",
|
||
"Exzellent kombiniert, Sherlock!",
|
||
"Punkt für dich!",
|
||
"Das war meisterhaft.",
|
||
"Korrekt - du scheinst das zu können!",
|
||
"So sieht Erfolg aus!",
|
||
"Glänzend gelöst!",
|
||
"Das war keine Glückssache - das war Können!",
|
||
"Treffer, versenkt!",
|
||
"Du hast es drauf!",
|
||
"Da merkt man: Profi am Werk.",
|
||
"Richtige Antwort - dafür gibt es viele Punkte!",
|
||
"Weiter so!",
|
||
"Wow - das war richtig gut!"
|
||
];
|
||
|
||
const falscheAntworten = [
|
||
"Oops! War wohl nicht dein Tag.",
|
||
"Knapp daneben ist auch vorbei!",
|
||
"Das war... kreativ!",
|
||
"Wenn man schon alles wüsste, wäre das Quiz doch sinnlos.",
|
||
"Deine Antwort war einzigartig - leider falsch!",
|
||
"Na gut, wenigstens hast du es probiert.",
|
||
"Das war eine interessante Theorie...",
|
||
"Ein Genie irrt sich auch mal.",
|
||
"Eine gute Antwort - aber nicht auf diese Frage.",
|
||
"Das ist leider falsch. Mehr gibt es nicht zu sagen.",
|
||
"Gute Idee! Aber leider nicht richtig.",
|
||
"Oh weh! Ein Fehler. Naja, einer ist keiner.",
|
||
"Die Antwort klang richtig, sie ist es aber nicht.",
|
||
"Interessanter Ansatz. Nicht hilfreich, aber interessant.",
|
||
"Nenn das lieber „alternative Fakten“.",
|
||
"Du hast die richtige Antwort doch gewusst: 'Die Seite hat nur nicht geladen.'",
|
||
"Jeder fängt mal klein an!",
|
||
"Kopf hoch - weiter geht's!",
|
||
"Nobody is perfect!",
|
||
"Du schaffst das - vielleicht ab jetzt.",
|
||
"Falsche Antwort, aber guter Wille!",
|
||
"Übung macht den Quiz-Meister.",
|
||
"Beim nächsten Mal triffst du!",
|
||
"Das war nur zum Aufwärmen, oder?",
|
||
"Kein Problem - weiter geht's.",
|
||
"Gute Frage - aber falsche Antwort."
|
||
];
|
||
|
||
|
||
const antwortRichtig = document.getElementById("antwort-richtig");
|
||
const antwortFalsch = document.getElementById("antwort-falsch");
|
||
|
||
if (antwortRichtig) {
|
||
antwortRichtig.textContent = richtigeAntworten[Math.floor(Math.random() * richtigeAntworten.length)];
|
||
} else if (antwortFalsch) {
|
||
antwortFalsch.textContent = falscheAntworten[Math.floor(Math.random() * falscheAntworten.length)];
|
||
}
|
||
const joinCode = '{{ quiz_game.join_code }}';
|
||
const hostId = '{{ host_id }}';
|
||
const wsScheme = window.location.protocol === 'https:' ? 'wss' : 'ws';
|
||
const gameSocket = new WebSocket(
|
||
`${wsScheme}://${window.location.host}/ws/game/${joinCode}/`
|
||
);
|
||
|
||
gameSocket.onmessage = function(e) {
|
||
const data = JSON.parse(e.data);
|
||
if (data.type === 'game_state_update' &&
|
||
data.redirect_url &&
|
||
(data.action === 'next_question' || data.action === 'finish_game' || data.action === 'show_winner_podest')) {
|
||
window.location.href = data.redirect_url;
|
||
}
|
||
else if (data.type === 'answer_stats') {
|
||
updateAnswerStats(data.stats);
|
||
}
|
||
};
|
||
|
||
gameSocket.onclose = function(e) {
|
||
// Normal closure (code 1000) oder Navigation zu einer anderen Seite (code 1001)
|
||
if (e.code === 1000 || e.code === 1001) {
|
||
console.log('Game socket closed normally');
|
||
} else {
|
||
console.error('Game socket closed unexpectedly', e.code);
|
||
}
|
||
};
|
||
|
||
{% if is_host %}
|
||
// Add click handlers for host buttons
|
||
{% if is_last_question %}
|
||
var finishButton = document.getElementById('finish-button');
|
||
if (finishButton) {
|
||
finishButton.addEventListener('click', function() {
|
||
gameSocket.send(JSON.stringify({
|
||
'type': 'finish_game',
|
||
'host_id': hostId
|
||
}));
|
||
});
|
||
}
|
||
|
||
var podestButton = document.getElementById('winner-button');
|
||
if (podestButton) {
|
||
podestButton.addEventListener('click', function() {
|
||
gameSocket.send(JSON.stringify({
|
||
'type': 'winner_podest',
|
||
'host_id': hostId
|
||
}));
|
||
});
|
||
}
|
||
|
||
{% else %}
|
||
|
||
var nextButton = document.getElementById('next-button');
|
||
if (nextButton) {
|
||
nextButton.addEventListener('click', function() {
|
||
gameSocket.send(JSON.stringify({
|
||
'type': 'next_question',
|
||
'host_id': hostId
|
||
}));
|
||
}, { once: true });
|
||
}
|
||
{% endif %}
|
||
{% endif %}
|
||
|
||
function updateAnswerStats(stats) {
|
||
const total = Object.values(stats).reduce((a, b) => a + b, 0) || 1;
|
||
|
||
for (var optionIndex in stats) {
|
||
if (stats.hasOwnProperty(optionIndex)) {
|
||
var countElement = document.getElementById('option-count-' + optionIndex);
|
||
var fillElement = document.getElementById('option-fill-' + optionIndex);
|
||
|
||
if (countElement) {
|
||
countElement.textContent = stats[optionIndex] + ' Antwort(en)';
|
||
}
|
||
|
||
if (fillElement) {
|
||
const percentage = Math.round((stats[optionIndex] / total) * 100);
|
||
fillElement.style.width = percentage + '%';
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Request answer stats when page loads
|
||
gameSocket.onopen = function(e) {
|
||
gameSocket.send(JSON.stringify({
|
||
'type': 'get_answer_stats'
|
||
}));
|
||
};
|
||
</script>
|
||
|
||
{% endblock %} |