roundriot

XSS Test — 2 players — single-elimination

+ new tournament
","winner":"alice","score1":null,"score2":null}]]; const roundNames=["Final"]; function renderBracket(){ const el=document.getElementById('bracket'); let html=''; bracket.forEach((round,ri)=>{ html+='
'+roundNames[ri]+'
'; round.forEach(m=>{ html+='
'; const p1class=m.winner===m.p1?'player winner':m.p1===null?'player bye':'player'; const p2class=m.winner===m.p2?'player winner':m.p2===null?'player bye':'player'; html+='
'+(m.p1||'BYE')+''+(m.score1!==null?''+m.score1+'':'')+'
'; html+='
'+(m.p2||'BYE')+''+(m.score2!==null?''+m.score2+'':'')+'
'; html+='
'; }); html+='
'; }); el.innerHTML=html; } function esc(s){return s?s.replace(/'/g,"\\'"):'';} async function reportWin(matchId,winner){ if(!winner||winner==='BYE')return; try{ const res=await fetch('/api/tournaments/'+TID+'/match/'+matchId,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({winner})}); const data=await res.json(); if(data.ok){bracket=data.bracket;renderBracket();showToast(winner+' wins!')} else showToast(data.error||'error'); }catch(e){showToast('network error')} } function copyLink(){ navigator.clipboard.writeText(location.href).then(()=>showToast('link copied!')); } function showToast(msg){const t=document.getElementById('toast');t.textContent=msg;t.style.display='block';setTimeout(()=>t.style.display='none',2500)} renderBracket();