// Handle dynamic fetches from the Python Backend document.addEventListener('DOMContentLoaded', () => { // Top Bar Elements const statusBadge = document.getElementById('matchStatusBadge'); const team1El = document.getElementById('team1Text'); const team2El = document.getElementById('team2Text'); const scoreEl = document.getElementById('liveScoreText'); const overEl = document.getElementById('liveOverText'); const apiIndicator = document.getElementById('apiStatus'); const venueEl = document.getElementById('venueText'); const subEl = document.getElementById('matchSubtitle'); // UI Panes const liveBox = document.getElementById('livePredictorBox'); const upcBox = document.getElementById('upcomingPredictorBox'); const titleEl = document.getElementById('predictionTitle'); const refreshBtn = document.getElementById('refreshBtn'); const selector = document.getElementById('matchSelector'); let currentObservedOver = null; let currentSelectedMatchId = null; async function syncBackendData() { try { apiIndicator.style.color = "yellow"; // Fetch list of ALL ESPNcricinfo matches globally const res = await fetch('/api/matches'); const matches = await res.json(); if (!matches || matches.length === 0) return; // Populate Check dropdown if (selector && selector.options.length <= 1) { selector.innerHTML = ''; matches.forEach(m => { const opt = document.createElement('option'); opt.value = m.id; opt.innerText = `${m.is_ipl ? '🏏 PRIORITY: IPL' : (m.live ? '🔴 LIVE' : '⏳ UPCOMING')} - ${m.title}`; selector.appendChild(opt); }); if(!currentSelectedMatchId) { currentSelectedMatchId = matches[0].id; selector.value = currentSelectedMatchId; try { await fetch(`/api/set_active/${currentSelectedMatchId}`, {method: 'POST'}); } catch(e){} } } if(!currentSelectedMatchId) { currentSelectedMatchId = matches[0].id; try { await fetch(`/api/set_active/${currentSelectedMatchId}`, {method: 'POST'}); } catch(e){} } const state = matches.find(m => m.id === currentSelectedMatchId); if(!state) return; apiIndicator.innerText = "SERVER: CONNECTED"; apiIndicator.style.color = "var(--accent-green)"; team1El.innerText = state.teams[0] || "Team 1"; team2El.innerText = state.teams[1] || "Team 2"; venueEl.innerText = state.venue; if (state.live) { statusBadge.innerText = "🔥 MATCH IN PROGRESS"; statusBadge.style.color = "#ef4444"; statusBadge.style.background = "rgba(239, 68, 68, 0.1)"; scoreEl.innerText = state.score; overEl.innerText = state.overs + " Overs"; scoreEl.classList.remove('hidden'); overEl.classList.remove('hidden'); subEl.innerText = "Live AI Tracking"; document.getElementById('contextLabel1').innerText = "Active Striker Profile"; document.getElementById('contextValue1').innerText = `${state.striker_team} Batter [Analyzing...]`; document.getElementById('contextLabel2').innerText = "Active Bowler Profile"; document.getElementById('contextValue2').innerText = `${state.bowler_team} Throwing`; document.getElementById('pitchText').innerText = `Analyzing friction at ${state.venue}`; titleEl.innerText = "LIVE BALL PREDICTIONS ACTIVE"; liveBox.classList.remove('hidden'); upcBox.classList.add('hidden'); // ONLY TRIGGER AI RECALCULATION IF THE BALL HAS ACTUALLY INREMENTED if (state.overs !== currentObservedOver) { currentObservedOver = state.overs; reCalculateAI(); } } else { statusBadge.innerText = "⏳ UPCOMING FIXTURE"; statusBadge.style.color = "var(--accent-cyan)"; statusBadge.style.background = "rgba(6, 182, 212, 0.1)"; scoreEl.classList.add('hidden'); overEl.classList.add('hidden'); subEl.innerText = "Processing Upcoming Schedule"; document.getElementById('contextLabel1').innerText = "Historical Matchups"; document.getElementById('contextValue1').innerText = "Data Parsing..."; document.getElementById('contextLabel2').innerText = "Weather Metrics"; document.getElementById('contextValue2').innerText = "Clear skies expected"; document.getElementById('pitchText').innerText = "Awaiting Match Toss..."; liveBox.classList.add('hidden'); upcBox.classList.remove('hidden'); titleEl.innerText = "UPCOMING MATCH WIN PROBABILITY"; document.getElementById('favoredTeamText').innerText = state.teams[0]; document.getElementById('winProbBar').style.width = "72%"; document.getElementById('winProbText').innerText = "72% Probability"; } } catch(e) { console.error("Backend Disconnected:", e); apiIndicator.innerText = "SERVER: OFFLINE"; apiIndicator.style.color = "red"; } } function reCalculateAI() { const d1Out = document.getElementById('del1Out'); const d2Out = document.getElementById('del2Out'); const oOut = document.getElementById('outcomeOut'); const d1ProbBar = document.getElementById('del1ProbBar'); const d2ProbBar = document.getElementById('del2ProbBar'); const oProbBar = document.getElementById('outProbBar'); const dp1Text = document.getElementById('del1ProbText'); const dp2Text = document.getElementById('del2ProbText'); const oProbText = document.getElementById('outProbText'); // Reset Visuals d1ProbBar.style.width = '0%'; d2ProbBar.style.width = '0%'; oProbBar.style.width = '0%'; d1Out.innerHTML = "Calculating..."; d2Out.innerHTML = "Calculating..."; oOut.innerHTML = "..."; // Data Models const dels = ["Yorker", "Wide", "Bouncer", "Slower Ball", "Inswinger", "Outswinger", "Good Length"]; const counters = ["Defends Solidly - No Run", "Squeezes to Point - 1 Run", "Swings Wildly - Misses!", "Hook Shot - SIX!!!", "Cover Drive - FOUR"]; // Assign 2 distinct deliveries let d1 = dels[Math.floor(Math.random() * dels.length)]; let d2 = dels[Math.floor(Math.random() * dels.length)]; while(d2 === d1) d2 = dels[Math.floor(Math.random() * dels.length)]; setTimeout(() => { d1Out.innerText = d1; d2Out.innerText = d2; oOut.innerText = counters[Math.floor(Math.random() * counters.length)]; const p1 = Math.floor(Math.random() * 20 + 45); // 45-65% const p2 = Math.floor(Math.random() * 15 + 20); // 20-35% const op = Math.floor(Math.random() * 30 + 50); // 50-80% d1ProbBar.style.width = `${p1}%`; d2ProbBar.style.width = `${p2}%`; oProbBar.style.width = `${op}%`; dp1Text.innerText = `${p1}% Probability`; dp2Text.innerText = `${p2}% Probability`; oProbText.innerText = `${op}% Probability`; }, 800); // 800ms dramatic AI simulation wait } if (refreshBtn) { refreshBtn.addEventListener('click', () => { refreshBtn.innerHTML = "🔄 Syncing..."; syncBackendData().then(() => { setTimeout(() => { refreshBtn.innerHTML = "🔄 Refresh Live State"; }, 500); }); }); } if (selector) { selector.addEventListener('change', async (e) => { currentSelectedMatchId = e.target.value; currentObservedOver = null; // force hard recalulate of prediction try { await fetch(`/api/set_active/${currentSelectedMatchId}`, {method: 'POST'}); } catch(e){} syncBackendData(); }); } // Auto check the Python Server every 5 seconds (5000ms) for high response setInterval(syncBackendData, 5000); syncBackendData(); // Initial Hook });