/** * PK10 Polling & Countdown * Depends on: pk10-sound.js, pk10-race.js, pk10-bet.js * Globals expected: GAME_ID, periodData, historyCache, I18N, localCountdown, * localLockCountdown, lastPollStatus, lastPeriodId, drawnResultShown, * cachedRaceResult, raceTriggered, pendingRaceHeader, raceAnimState, * PK10_CONFIG (for status labels) */ // ===== Countdown interval ===== setInterval(function(){if(localCountdown>0)localCountdown--;if(localLockCountdown>0)localLockCountdown--;var m=Math.floor(localCountdown/60),s=localCountdown%60;document.getElementById('countdown').textContent=localCountdown>0?m+':'+(s<10?'0':'')+s:'--'; var badge=document.getElementById('statusBadge'); if(lastPollStatus==='pending'&&localLockCountdown>0){var lm=Math.floor(localLockCountdown/60),ls=localLockCountdown%60;badge.textContent=lm+':'+(ls<10?'0':'')+ls;badge.style.cssText='color:var(--success)';} else if(lastPollStatus==='pending'&&localLockCountdown<=0){badge.textContent=PK10_CONFIG.lang.sealed;badge.style.cssText='color:var(--danger)';} if(raceAnimState==='waiting')updateRaceOverlayTimer(localCountdown); if(localCountdown>0&&localCountdown<=10&&raceAnimState==='waiting')SoundFX.tick(); },1000); // ===== Trigger race sequence ===== function triggerRaceSequence(){ if(raceTriggered||raceAnimState!=='waiting')return; raceTriggered=true; var remaining=localCountdown*1000; var readyDur=3000; var raceDur=Math.max(5500,remaining-readyDur-500); raceDur=Math.min(raceDur,25000); var waitBeforeRace=Math.max(0,remaining-readyDur-raceDur); startReadyAnimation(); setTimeout(function(){ if(cachedRaceResult&&raceAnimState==='ready'){ var raceRes=cachedRaceResult;cachedRaceResult=null; pendingRaceHeader=raceRes._raw||null; animateRace(raceRes.arr,raceDur); } },readyDur+waitBeforeRace); } // ===== Poll period ===== function pollPeriod(){return fetch('/api/period/current?game_id='+GAME_ID).then(function(r){return r.json();}).then(function(d){if(!d.success)return;periodData=d.data; var serverRemaining=periodData.remaining_seconds||0;var periodChanged=(periodData.id&&periodData.id!==lastPeriodId);var statusChanged=(periodData.status!==lastPollStatus);var driftTooMuch=Math.abs(localCountdown-serverRemaining)>3; if(periodChanged||statusChanged||driftTooMuch||localCountdown<=0)localCountdown=serverRemaining; var serverLockCountdown=periodData.lock_countdown||0;if(periodChanged||statusChanged||Math.abs(localLockCountdown-serverLockCountdown)>3)localLockCountdown=serverLockCountdown; if(d.balance!==null&&d.balance!==undefined)document.getElementById('balanceDisplay').textContent=parseFloat(d.balance).toFixed(2); // Status badge var badge=document.getElementById('statusBadge');var statusMap={pending:[PK10_CONFIG.lang.betting,'seal-status','color:var(--success)'],locked:[PK10_CONFIG.lang.sealed,'seal-status','color:var(--danger)'],drawn:[I18N.drawing,'seal-status','color:var(--warn)'],settled:[I18N.settled_label,'seal-status','color:var(--warn)']};var s=statusMap[periodData.status]||statusMap.pending;badge.textContent=s[0];badge.className=s[1];badge.style.cssText=s[2]; switchVideoOrAnim(periodData.status,statusChanged); // Period number var fullPn=periodData.period_number||'---';var shortPn=fullPn.length>8?fullPn.slice(0,-4)+'-'+fullPn.slice(-4):fullPn;var pnEl=document.getElementById('periodNum');pnEl.textContent=shortPn;pnEl.title=fullPn; // Extract result array function extractResultArr(res){if(!res)return null;var arr=[res.rank_1,res.rank_2,res.rank_3,res.rank_4,res.rank_5,res.rank_6,res.rank_7,res.rank_8,res.rank_9,res.rank_10];return arr.every(function(v){return v;})?arr:null;} // Scene header sync if(raceAnimState!=='racing'&&raceAnimState!=='finished'&&raceAnimState!=='ready'){ if(d.last_result) updateSceneHeader(d.last_result, d.last_result.period_number||fullPn); } // === Pending → idle === if(periodData.status==='pending'){ cachedRaceResult=null;raceTriggered=false; if(d.last_result){ var lp=d.last_result.period_number||''; document.getElementById('lastPeriodNum').textContent=lp.length>4?'#'+lp.slice(-4):lp; renderResult(d.last_result,'lastResult'); } if(raceAnimState==='finished'||raceAnimState==='racing'||raceAnimState==='ready'){ if(!window._podiumTimer){ var protectMs=8000; if(raceAnimState==='ready')protectMs=16000; else if(raceAnimState==='racing')protectMs=12000; window._podiumTimer=setTimeout(function(){ resetRace(); startIdleAnimation(); window._podiumTimer=null; },protectMs); } } else if(raceAnimState!=='waiting'){ resetRace(); startIdleAnimation(); } } // === Locked → cache result + trigger sprint === if(periodData.status==='locked'){ var raceRes=extractResultArr(d.race_result); if(raceRes&&!cachedRaceResult){ cachedRaceResult={arr:raceRes,_raw:d.race_result}; } if(cachedRaceResult)triggerRaceSequence(); } // === Drawn/Settled → show result + podium === if(d.last_result&&(periodData.status==='drawn'||periodData.status==='settled')){ if(statusChanged||periodChanged){ var lp=d.last_result.period_number||''; document.getElementById('lastPeriodNum').textContent=lp.length>4?'#'+lp.slice(-4):lp; var ra=extractResultArr(d.last_result); if(ra&&raceAnimState!=='finished'&&raceAnimState!=='racing'&&raceAnimState!=='ready'){ cachedRaceResult=null; pendingRaceHeader=d.last_result; animateRace(ra); } else if(raceAnimState!=='racing'&&raceAnimState!=='ready'){ updateSceneHeader(d.last_result, lp); } setTimeout(function(){renderResult(d.last_result,'lastResult');},5500); } } // === First load === if(d.last_result&&!lastAnimatedResult&&raceAnimState==='idle'){ var ra=extractResultArr(d.last_result); if(ra){ var lp=d.last_result.period_number||''; document.getElementById('lastPeriodNum').textContent=lp.length>4?'#'+lp.slice(-4):lp; renderResult(d.last_result,'lastResult'); startIdleAnimation(); } } renderMyBets(d.my_bets||[]);renderLastMyBets(d.last_my_bets||[]); // History if(d.history&&periodChanged){historyCache=d.history;var hl=document.getElementById('historyList');hl.innerHTML='';d.history.forEach(function(h){var row=document.createElement('div');row.className='card';row.style.cssText='padding:6px 8px;margin-bottom:4px';var pn=h.period_number||'';var sp=pn.length>4?'#'+pn.slice(-4):pn;var balls='';['rank_1','rank_2','rank_3','rank_4','rank_5','rank_6','rank_7','rank_8','rank_9','rank_10'].forEach(function(k){if(h[k])balls+='
'+h[k]+'
';});row.innerHTML='
'+sp+'
'+balls+'
';hl.appendChild(row);});if(!document.getElementById('panelDragon').classList.contains('hidden'))renderDragonStreak();} lastPollStatus=periodData.status;lastPeriodId=periodData.id||0; }).catch(function(e){console.error('pollPeriod error:',e);});} // ===== Start polling ===== pollPeriod(); (function dynamicPoll(){var delay=(lastPollStatus==='locked'||lastPollStatus==='drawn'||lastPollStatus==='settled')?1500:3000;setTimeout(function(){pollPeriod().then(dynamicPoll).catch(dynamicPoll);},delay);})();