Buddha Garden Club logo Buddha Garden Club
BGC · FIND YOUR FLOW. GROW YOUR GAME.

Let's get playing. 🏓

Connecting to your session…
📅 UPCOMING BOOKINGS

Loading schedule…

🏟️ Courts

Your current games

Loading courts…

⏭️ Up next

Suggested matchup, subject to change

THE LATEST ACTION

📋 Recent games

A quick look at your latest results

⏱ AVG GAME · —
LAST 5

👋 Players

');win.document.close();win.focus()} function openDisplay(){if(!state){toast('Wait for the session to load.');return}display=window.open('','BGCLive','width=1100,height=850');if(!display){toast('Allow pop-ups in your browser.');return}display.document.open();display.document.write('BGC Live
');display.document.close();renderDisplay();display.focus()}function winRate(p){var games=Number(p.games)||0,wins=Number(p.wins)||0;return games>0?Math.round(100*wins/games)+'%':'—'} function ratingHTML(p){var rating=Number(p.rating);if(!Number.isFinite(rating))rating=Number(p.skill)||3;var change=Number(p.ratingChange)||0,delta=change>0?'↑ +'+change.toFixed(2):change<0?'↓ '+change.toFixed(2):'— 0.00',klass=change>0?'up':change<0?'down':'flat',provisional=(Number(p.ratedGames)||0)<5;return '⭐ '+rating.toFixed(2)+' BGC '+delta+''+(provisional?' PROV.':'')+''} function renderDisplay(){if(!state||!display||display.closed)return;try{var active=state.matches.filter(function(m){return m.status==='playing'}),leaders=state.players.filter(function(p){return p.status!=='registered'}).sort(function(a,b){return (b.wins||0)-(a.wins||0)||(b.games||0)-(a.games||0)}),waiting=state.players.filter(function(p){return p.status==='waiting'}).sort(function(a,b){return a.joined-b.joined}),medals=['🥇','🥈','🥉'];display.document.getElementById('live').innerHTML='

Buddha Garden Club logo Buddha Garden Club

'+(state.ended?'SESSION ENDED':'LIVE SESSION')+' · Updates while organizer window is open

🏟️ On court

'+(active.length?'
'+active.map(function(m){return '

Court '+m.court+'● LIVE

'+teamsMarkup(m.teams)+'
'}).join('')+'
':'Courts are ready')+'

⏭️ Up next

'+(state.upNext?teamsMarkup(state.upNext):'Waiting for four eligible players')+'

⏳ Waiting

'+waiting.map(function(p){return '
'+escapeText(p.name)+'
'}).join('')+'

🏆 Leaderboard

Ranked by wins · BGC ratings are session-only and provisional for the first 5 games.

'+[1,0,2].filter(function(i){return !!leaders[i]}).map(function(i){var p=leaders[i];return '
'+medals[i]+''+avatar(p.id)+''+escapeText(p.name)+''+(p.wins||0)+'W · '+Math.max(0,(p.games||0)-(p.wins||0))+'L · '+(p.games||0)+' games'+winRate(p)+' WIN RATE'+ratingHTML(p)+'
'+(i+1)+''+(i===0?'FIRST PLACE':i===1?'SECOND PLACE':'THIRD PLACE')+'
'}).join('')+'
'+leaders.slice(3).map(function(p,i){return '
'+(i+4)+'. '+avatar(p.id)+' '+escapeText(p.name)+' · '+(p.wins||0)+'W – '+Math.max(0,(p.games||0)-(p.wins||0))+'L · '+winRate(p)+' win rate '+ratingHTML(p)+'
'}).join('')+'
';paintPhotos(display.document)}catch(e){}} function announce(){if(!state)return;var games=state.matches.filter(function(m){return m.status==='playing'});if(!games.length){toast('No active courts.');return}if(!window.speechSynthesis){toast('Speech is not supported.');return}var text=games.map(function(m){return 'Court '+m.court+'. '+m.teams[0].map(playerName).join(' and ')+' versus '+m.teams[1].map(playerName).join(' and ')+'.'}).join(' ');window.speechSynthesis.cancel();window.speechSynthesis.speak(new SpeechSynthesisUtterance(text))} document.addEventListener('change',function(event){if(event.target&&(event.target.id==='booking-kind'||event.target.id==='booking-start'))adjustOpenPlayEnd()}); document.addEventListener('click',function(event){var button=event.target.closest('[data-action]');if(!button)return;var a=button.getAttribute('data-action'),id=button.getAttribute('data-id');try{ if(a==='schedule-manage')scheduleManage();else if(a==='open-booking-sheet'){var sheetWindow=window.open('about:blank','_blank');call('getBookingWeeklySheetUrl',[],function(url){if(sheetWindow)sheetWindow.location.href=url;else window.location.href=url})}else if(a==='sync-reclub-bookings'){var syncPin=needPin();if(syncPin)call('syncReclubBookings',[syncPin],function(r){scheduleData=r.schedule;scheduleManage();toast('Reclub sync: '+r.added+' added, '+r.updated+' updated, '+r.skipped+' skipped (missing time/duration or conflict)')})}else if(a==='calendar-day')dayBookings(id);else if(a==='new-booking')bookingForm(id||todayYmd(),null);else if(a==='booking-details')bookingDetails(id);else if(a==='edit-booking')bookingForm(null,id);else if(a==='save-venue'){var venuePin=getPin();if(!venuePin){toast('Enter your organizer PIN.');return}call('setVenueCourts',[venuePin,Number(el('venue-courts').value)],function(result){updateScheduleResult(result);toast('Physical court count updated');scheduleManage()})}else if(a==='save-booking'){var bookingPin=getPin();if(!bookingPin){toast('Enter your organizer PIN.');return}var choices=document.querySelectorAll('.booking-court:checked'),chosenCourts=[];for(var k=0;k🌿 Loading public activities…

Fetching the BGC club listing.

');call('previewReclubClub',[browsePin],function(result){renderClubEvents(result)})}else if(a==='choose-reclub-event'){var clubUrl='https://reclub.co/m/'+id;reclubSource='club';reclubPreviewLink=clubUrl;var browseSecret=pin;modal('

🏓 Loading event roster…

Fetching confirmed players.

');call('previewReclub',[browseSecret,clubUrl],function(result){modal('

📥 Import from Reclub

Preview loaded: '+escapeText(result.title)+'

');renderReclubPreview(result)})}else if(a==='preview-reclub'){var requestedLink=eventLink();if(!requestedLink){el('reclub-status').textContent='Enter the event code using letters and numbers.';toast('Enter a valid event code.');return}reclubSource='link';reclubHtml='';reclubFingerprint='';reclubPreviewLink='';el('reclub-status').textContent='Loading public event…';call('previewReclub',[getPin(),requestedLink],function(result){reclubPreviewLink=requestedLink;var status=el('reclub-status');if(status)status.textContent='Preview loaded.';renderReclubPreview(result)})}else if(a==='preview-reclub-file'){var file=el('reclub-file').files[0];if(!file){toast('Choose a saved HTML file first.');return}if(file.size>2000000){toast('HTML file must be under 2 MB.');return}var secret='',reader=new FileReader();reclubFingerprint='';reclubSource='file';el('reclub-status').textContent='Reading saved page…';reader.onload=function(){try{reclubRoster=parseRosterInBrowser(String(reader.result||''));reclubHtml='';el('reclub-status').textContent='Found '+reclubRoster.players.length+' players. Preparing preview…';call('previewReclubRoster',[reclubRoster],function(result){var status=el('reclub-status');if(status)status.textContent='Preview loaded from saved file.';renderReclubPreview(result)})}catch(err){el('reclub-status').textContent=err.message||String(err);toast(err.message||'Could not read the page.')}};reader.onerror=function(){el('reclub-status').textContent='Could not read the selected file.'};reader.readAsText(file)}else if(a==='confirm-import'){if(reclubSource==='link'&&eventLink()!==reclubPreviewLink){toast('The event code changed. Please preview again.');return}var boxes=document.querySelectorAll('.reclub-choice:checked'),selected=[];for(var j=0;j⏹ End and clear this session?

This permanently deletes the current roster, payment statuses, game history, and session ratings. A fresh empty session will be ready immediately. Active games will be cancelled and removed. Court count, venue bookings, monthly check-in records, and Drive photos are kept.

'+pinField()+'
')}else if(a==='confirm-session')call('endSession',[getPin()],function(){close();toast('Session cleared. Ready for a new session.')}) }catch(e){showError('Interface error: '+(e.message||e));toast('Something went wrong. See the message on screen.')}}); function setupHeaderOffset(){try{var header=document.querySelector('body > header');if(!header)return;var sync=function(){document.documentElement.style.setProperty('--bgc-header-height',Math.ceil(header.getBoundingClientRect().height)+'px')};sync();if(window.ResizeObserver)new window.ResizeObserver(sync).observe(header);if(window.addEventListener)window.addEventListener('resize',sync)}catch(e){}} setupHeaderOffset(); var started=false;function start(location){if(started)return;started=true;checkin=!!(location&&location.parameter&&location.parameter.page==='checkin');if(checkin){document.body.classList.add('checkin-mode');document.querySelector('header').style.display='none';document.querySelector('main').style.display='none';modal('

Loading players…

Please wait.

');call('getState',[],checkinHome)}else{loadTheme();startWidgets();refresh();setInterval(updateTimers,1000);setInterval(refresh,15000);refreshSchedule();setInterval(refreshSchedule,30000)}} try{google.script.url.getLocation(start);setTimeout(function(){start(null)},5000)}catch(e){start(null)} })();