Get in the Game Show — Host Dashboard
No session yet
Current Game: —
Current Round: —
Teams Registered
Running Scores
/* Game vault (preloaded games and rounds) */
const GAME_VAULT = [
{name:"Brain Candy", rounds:3},
{name:"Keep on Singin", rounds:4},
{name:"Diva Domination", rounds:4},
{name:"Popcorn Puzzler", rounds:5},
{name:"Think Fast", rounds:5},
{name:"Quantum Showdown", rounds:5},
{name:"POP Quiz", rounds:5},
{name:"Great Minds", rounds:2},
{name:"Who Said it?", rounds:2},
{name:"Turbo Tunes", rounds:4},
{name:"Word Pinata", rounds:2},
{name:"Soundtrax", rounds:5},
{name:"Caption Captain", rounds:1}
];
const BUZZ_SOUND_URL = "https://thedoctoroffun.com/wp-content/uploads/2025/08/PlayerBuzzIn.mp3";
/* UI references */
const createGameBtn = document.getElementById('createGameBtn');
const startSessionBtn = document.getElementById('startSessionBtn');
const game1Select = document.getElementById('game1Select');
const game2Select = document.getElementById('game2Select');
const game3Select = document.getElementById('game3Select');
const hostGameCodeArea = document.getElementById('hostGameCodeArea');
const teamsList = document.getElementById('teamsList');
const buzzedList = document.getElementById('buzzedList');
const clearAllBtn = document.getElementById('clearAllBtn');
const activateQBtn = document.getElementById('activateQBtn');
const deactivateQBtn = document.getElementById('deactivateQBtn');
const nextRoundBtn = document.getElementById('nextRoundBtn');
const backRoundBtn = document.getElementById('backRoundBtn');
const openScoreEntryBtn = document.getElementById('openScoreEntryBtn');
const revealScoresBtn = document.getElementById('revealScoresBtn');
const currentGameLabel = document.getElementById('currentGameLabel');
const currentRoundLabel = document.getElementById('currentRoundLabel');
const scoreboard = document.getElementById('scoreboard');
const hostSoundToggle = document.getElementById('hostSoundToggle');
const endSessionBtn = document.getElementById('endSessionBtn');
/* Populate selects */
function populateGameSelects(){
GAME_VAULT.forEach(g=>{
const o1 = document.createElement('option');
o1.value = JSON.stringify(g);
o1.textContent = `${g.name} (${g.rounds} rounds)`;
const o2 = o1.cloneNode(true);
const o3 = o1.cloneNode(true);
game1Select.appendChild(o1);
game2Select.appendChild(o2);
game3Select.appendChild(o3);
});
}
populateGameSelects();
/* helper */
function make6digit(){ return Math.floor(100000 + Math.random()*900000).toString(); }
function makeToken(){ return Math.random().toString(36).slice(2,10); }
/* state */
let currentGameCode = null;
let hostToken = null;
let gameRef = null;
let buzzAudio = new Audio(BUZZ_SOUND_URL);
createGameBtn.addEventListener('click', async ()=>{
createGameBtn.disabled = true;
createGameBtn.textContent = 'Checking...';
const code = await createUniqueCode();
currentGameCode = code;
hostGameCodeArea.textContent = `Game Code: ${code}`;
createGameBtn.textContent = 'Create Game';
createGameBtn.disabled = false;
});
async function createUniqueCode(){
// make sure not in use
for(let i=0;i<10;i++){
const candidate = make6digit();
const snapshot = await db.ref('games/'+candidate).get();
if(!snapshot.exists()) return candidate;
}
// fallback
return make6digit();
}
/* Start session (host chooses three games) */
startSessionBtn.addEventListener('click', async ()=>{
if(!currentGameCode){ alert('Click Create Game first'); return; }
hostToken = makeToken();
localStorage.setItem(`gitgs_hostToken_${currentGameCode}`, hostToken);
const g1 = JSON.parse(game1Select.value);
const g2 = JSON.parse(game2Select.value);
const g3 = JSON.parse(game3Select.value);
const gameOrder = [g1,g2,g3, {name:"Caption Captain", rounds:1}];
gameRef = db.ref('games/'+currentGameCode);
await gameRef.set({
createdAt: Date.now(),
hostToken,
gameOrder,
currentGameIndex:0,
currentRoundIndex:0,
questionActive:false,
scoreEntryOpen:false,
scoresRevealed:false,
teams:{},
players:{},
teamInStatus:{},
buzzed:{order:{}}
});
hostGameCodeArea.textContent = `Game Code: ${currentGameCode} — Session started`;
bindGameListeners();
listenForBuzzSound();
});
/* End session */
endSessionBtn.addEventListener('click', async ()=>{
if(!currentGameCode) return;
if(!confirm('End session and remove everything?')) return;
await db.ref('games/'+currentGameCode).remove();
location.reload();
});
/* Bind listeners */
function bindGameListeners(){
if(!currentGameCode) return;
gameRef = db.ref('games/'+currentGameCode);
// teams
db.ref(`games/${currentGameCode}/teams`).on('value', snap=>{
const teams = snap.val() || {};
renderTeams(teams);
renderScoreboard(teams);
});
// buzzed order
db.ref(`games/${currentGameCode}/buzzed/order`).on('value', snap=>{
const orderObj = snap.val() || {};
renderBuzzed(orderObj);
});
// game/round changes
gameRef.child('currentGameIndex').on('value', snap=>{
readGameLabels();
});
gameRef.child('currentRoundIndex').on('value', snap=>{
readGameLabels();
});
}
/* Render Teams */
function renderTeams(teams){
teamsList.innerHTML = '';
Object.entries(teams).forEach(([teamId, team])=>{
const li = document.createElement('li');
li.textContent = team.name || `Team ${teamId}`;
teamsList.appendChild(li);
});
}
/* Render Buzzed */
function renderBuzzed(orderObj){
buzzedList.innerHTML = '';
// orderObj keys are playerIDs in order they buzzed
Object.keys(orderObj).forEach(playerId=>{
const li = document.createElement('li');
const playerName = orderObj[playerId].name || playerId;
const teamName = orderObj[playerId].team || '';
li.innerHTML = `
${playerName} [${teamName}]`;
buzzedList.appendChild(li);
});
}
/* Render Scores */
function renderScoreboard(teams){
scoreboard.innerHTML = '';
Object.entries(teams).forEach(([teamId, team])=>{
const div = document.createElement('div');
div.className = 'scoreline';
div.innerHTML = `
${team.name || `Team ${teamId}`}
${team.score || 0}
`;
scoreboard.appendChild(div);
});
}
/* Update Game and Round labels */
function readGameLabels(){
if(!gameRef) return;
gameRef.get().then(snap=>{
if(!snap.exists()) return;
const data = snap.val();
const gameIndex = data.currentGameIndex || 0;
const roundIndex = data.currentRoundIndex || 0;
const games = data.gameOrder || [];
currentGameLabel.textContent = games[gameIndex] ? games[gameIndex].name : '—';
currentRoundLabel.textContent = `Round ${roundIndex+1}`;
});
}
/* Clear buzzed */
clearAllBtn.addEventListener('click', ()=>{
if(!currentGameCode) return;
db.ref(`games/${currentGameCode}/buzzed/order`).remove();
});
/* Sound toggle */
hostSoundToggle.addEventListener('change', e=>{
if(!e.target.checked){
buzzAudio.muted = true;
} else {
buzzAudio.muted = false;
}
});
/* Play buzz sound if hostSoundToggle checked */
function listenForBuzzSound(){
if(!gameRef) return;
db.ref(`games/${currentGameCode}/buzzed/order`).on('child_added', snap=>{
if(hostSoundToggle.checked) {
buzzAudio.play();
}
});
}
/* Round controls (Activate/Deactivate, Next/Back round, Open score entry, Reveal scores) */
activateQBtn.addEventListener('click', async ()=>{
if(!gameRef) return;
await gameRef.update({questionActive:true});
});
deactivateQBtn.addEventListener('click', async ()=>{
if(!gameRef) return;
await gameRef.update({questionActive:false});
});
nextRoundBtn.addEventListener('click', async ()=>{
if(!gameRef) return;
const snap = await gameRef.get();
if(!snap.exists()) return;
const data = snap.val();
let newRound = (data.currentRoundIndex || 0) + 1;
let maxRounds = 1;
if(data.gameOrder && data.currentGameIndex < data.gameOrder.length) {
maxRounds = data.gameOrder[data.currentGameIndex].rounds;
}
if(newRound >= maxRounds) newRound = maxRounds - 1;
await gameRef.update({currentRoundIndex:newRound});
});
backRoundBtn.addEventListener('click', async ()=>{
if(!gameRef) return;
const snap = await gameRef.get();
if(!snap.exists()) return;
let newRound = (snap.val().currentRoundIndex || 0) - 1;
if(newRound < 0) newRound = 0;
await gameRef.update({currentRoundIndex:newRound});
});
openScoreEntryBtn.addEventListener('click', async ()=>{
if(!gameRef) return;
await gameRef.update({scoreEntryOpen:true});
});
revealScoresBtn.addEventListener('click', async ()=>{
if(!gameRef) return;
await gameRef.update({scoresRevealed:true});
});