Download backend/static/pro.html from zeroday01/ipl_prediction_engine: direct link, hf CLI and curl.
- Browser
- Download file 13.6 kB
-
https://huggingface.co/zeroday01/ipl_prediction_engine/resolve/main/backend/static/pro.html
- Command line
-
hf download hf://zeroday01/ipl_prediction_engine/backend/static/pro.html
-
curl -L -o pro.html https://huggingface.co/zeroday01/ipl_prediction_engine/resolve/main/backend/static/pro.html
13.6 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>IPL Pro Analytics Dashboard</title> | |
| <style> | |
| :root { | |
| --bg-dark: #0f172a; | |
| --panel-bg: rgba(255, 255, 255, 0.05); | |
| --text-main: #f8fafc; | |
| --text-muted: #94a3b8; | |
| --accent: #3b82f6; | |
| --accent-hover: #2563eb; | |
| --border: rgba(255, 255, 255, 0.1); | |
| --win: #10b981; | |
| --loss: #ef4444; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| body { | |
| font-family: 'Inter', -apple-system, sans-serif; | |
| background-color: var(--bg-dark); | |
| color: var(--text-main); | |
| line-height: 1.6; | |
| } | |
| .container { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 2rem; | |
| } | |
| /* Tabs */ | |
| .tabs { | |
| display: flex; | |
| gap: 1rem; | |
| margin-bottom: 2rem; | |
| border-bottom: 1px solid var(--border); | |
| padding-bottom: 1rem; | |
| } | |
| .tablink { | |
| background: transparent; | |
| color: var(--text-muted); | |
| border: none; | |
| padding: 0.75rem 1.5rem; | |
| font-size: 1rem; | |
| font-weight: 600; | |
| cursor: pointer; | |
| border-radius: 6px; | |
| transition: all 0.2s; | |
| } | |
| .tablink:hover { | |
| color: var(--text-main); | |
| background: var(--panel-bg); | |
| } | |
| .tablink.active { | |
| color: #fff; | |
| background: var(--accent); | |
| } | |
| .tabcontent { | |
| display: none; | |
| animation: fadeIn 0.3s ease-in-out; | |
| } | |
| .tabcontent.active { | |
| display: block; | |
| } | |
| /* Panels */ | |
| .panel { | |
| background: var(--panel-bg); | |
| border: 1px solid var(--border); | |
| border-radius: 12px; | |
| padding: 1.5rem; | |
| margin-bottom: 1.5rem; | |
| backdrop-filter: blur(10px); | |
| } | |
| /* Forms & Inputs */ | |
| input[type="text"] { | |
| width: 100%; | |
| padding: 1rem; | |
| background: rgba(0, 0, 0, 0.2); | |
| border: 1px solid var(--border); | |
| color: white; | |
| border-radius: 8px; | |
| font-size: 1rem; | |
| margin-bottom: 1rem; | |
| } | |
| input[type="text"]:focus { | |
| outline: none; | |
| border-color: var(--accent); | |
| } | |
| /* Tables & Lists */ | |
| table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| margin-top: 1rem; | |
| } | |
| th, td { | |
| padding: 1rem; | |
| text-align: left; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| th { | |
| color: var(--text-muted); | |
| font-weight: 600; | |
| } | |
| /* Utilities */ | |
| h2, h3 { margin-bottom: 1rem; } | |
| .text-accent { color: var(--accent); } | |
| .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(5px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| #autocomplete-results { | |
| max-height: 200px; | |
| overflow-y: auto; | |
| background: #1e293b; | |
| border: 1px solid var(--border); | |
| border-radius: 8px; | |
| margin-top: -0.5rem; | |
| margin-bottom: 1rem; | |
| position: absolute; | |
| width: calc(100% - 3rem); | |
| z-index: 10; | |
| display: none; | |
| } | |
| .autocomplete-item { | |
| padding: 0.75rem 1rem; | |
| cursor: pointer; | |
| } | |
| .autocomplete-item:hover { | |
| background: var(--accent); | |
| } | |
| .stats-card { | |
| background: rgba(0,0,0,0.2); | |
| padding: 1rem; | |
| border-radius: 8px; | |
| text-align: center; | |
| } | |
| .stats-val { | |
| font-size: 1.5rem; | |
| font-weight: bold; | |
| color: var(--accent); | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <header style="margin-bottom: 2rem;"> | |
| <h1><span class="text-accent">IPL</span> Pro Analytics</h1> | |
| <p style="color: var(--text-muted);">Real-time Insights & Historical Intelligence</p> | |
| </header> | |
| <div class="tabs"> | |
| <button class="tablink active" onclick="openTab(event, 'live')">Live Betting</button> | |
| <button class="tablink" onclick="openTab(event, 'schedule')">Schedule & Points</button> | |
| <button class="tablink" onclick="openTab(event, 'analysis')">Player Analysis</button> | |
| </div> | |
| <!-- Live Tab --> | |
| <div id="live" class="tabcontent active"> | |
| <div class="panel"> | |
| <h2>Live Match Intelligence</h2> | |
| <p style="color: var(--text-muted); margin-bottom: 1rem;">Waiting for active match data...</p> | |
| <div id="live-odds-container" class="grid-2"> | |
| <!-- Data will be injected here via websocket in future updates --> | |
| </div> | |
| <a href="/" style="color: var(--accent); text-decoration: none;">← Back to Classic Dashboard</a> | |
| </div> | |
| </div> | |
| <!-- Schedule Tab --> | |
| <div id="schedule" class="tabcontent"> | |
| <div class="grid-2"> | |
| <div class="panel"> | |
| <h3>Upcoming Matches (2024/2025)</h3> | |
| <div id="upcoming-container">Loading schedule...</div> | |
| </div> | |
| <div class="panel"> | |
| <h3>Points Table</h3> | |
| <div id="points-container">Loading points...</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Analysis Tab --> | |
| <div id="analysis" class="tabcontent"> | |
| <div class="panel" style="position: relative;"> | |
| <h3>Search Player Database</h3> | |
| <input type="text" id="player-search" placeholder="Type player name (e.g., Virat Kohli)" onkeyup="autocompletePlayer()" autocomplete="off"> | |
| <div id="autocomplete-results"></div> | |
| <div id="player-stats-container" style="display: none; margin-top: 2rem;"> | |
| <h2 id="ps-name" class="text-accent" style="font-size: 2rem; margin-bottom: 1.5rem;"></h2> | |
| <div class="grid-2"> | |
| <div> | |
| <h4 style="margin-bottom: 1rem; color: var(--text-muted);">BATTING</h4> | |
| <div class="grid-2" style="gap: 1rem;"> | |
| <div class="stats-card"><div>Runs</div><div class="stats-val" id="ps-runs">0</div></div> | |
| <div class="stats-card"><div>Strike Rate</div><div class="stats-val" id="ps-sr">0</div></div> | |
| <div class="stats-card"><div>Fours</div><div class="stats-val" id="ps-4s">0</div></div> | |
| <div class="stats-card"><div>Sixes</div><div class="stats-val" id="ps-6s">0</div></div> | |
| </div> | |
| </div> | |
| <div> | |
| <h4 style="margin-bottom: 1rem; color: var(--text-muted);">BOWLING</h4> | |
| <div class="grid-2" style="gap: 1rem;"> | |
| <div class="stats-card"><div>Wickets</div><div class="stats-val" id="ps-wkts">0</div></div> | |
| <div class="stats-card"><div>Economy</div><div class="stats-val" id="ps-econ">0</div></div> | |
| <div class="stats-card"><div>Matches</div><div class="stats-val" id="ps-bmat">0</div></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Tab Logic | |
| function openTab(evt, tabName) { | |
| var i, tabcontent, tablinks; | |
| tabcontent = document.getElementsByClassName("tabcontent"); | |
| for (i = 0; i < tabcontent.length; i++) { | |
| tabcontent[i].style.display = "none"; | |
| tabcontent[i].classList.remove("active"); | |
| } | |
| tablinks = document.getElementsByClassName("tablink"); | |
| for (i = 0; i < tablinks.length; i++) { | |
| tablinks[i].classList.remove("active"); | |
| } | |
| document.getElementById(tabName).style.display = "block"; | |
| document.getElementById(tabName).classList.add("active"); | |
| evt.currentTarget.classList.add("active"); | |
| // Load data if switching to specific tabs | |
| if(tabName === 'schedule') loadSchedule(2024); // Fallback to 2024 as 2025 feed might not be live yet | |
| } | |
| // Schedule & Points Logic | |
| async function loadSchedule(season) { | |
| try { | |
| const upContainer = document.getElementById('upcoming-container'); | |
| const ptContainer = document.getElementById('points-container'); | |
| const [upcomingRes, pointsRes] = await Promise.all([ | |
| fetch(`/upcoming/${season}`), | |
| fetch(`/points/${season}`) | |
| ]); | |
| if (upcomingRes.ok) { | |
| const upcoming = await upcomingRes.json(); | |
| if(upcoming && upcoming.matchschedule) { | |
| let html = '<table><tr><th>Date</th><th>Match</th><th>Venue</th></tr>'; | |
| upcoming.matchschedule.slice(0, 10).forEach(m => { // Show next 10 | |
| html += `<tr><td>${m.matchdate}</td><td>${m.teama} vs ${m.teamb}</td><td>${m.venue}</td></tr>`; | |
| }); | |
| html += '</table>'; | |
| upContainer.innerHTML = html; | |
| } else { | |
| upContainer.innerHTML = 'No schedule data available.'; | |
| } | |
| } | |
| if(pointsRes.ok) { | |
| const points = await pointsRes.json(); | |
| if(points && points.points) { | |
| let html = '<table><tr><th>Team</th><th>M</th><th>W</th><th>L</th><th>Pts</th><th>NRR</th></tr>'; | |
| points.points.forEach(p => { | |
| html += `<tr><td><b>${p.teamshortname}</b></td><td>${p.matchesplayed}</td><td>${p.matcheswon}</td><td>${p.matcheslost}</td><td class="text-accent"><b>${p.points}</b></td><td>${p.nrr}</td></tr>`; | |
| }); | |
| html += '</table>'; | |
| ptContainer.innerHTML = html; | |
| } else { | |
| ptContainer.innerHTML = 'No points table data available.'; | |
| } | |
| } | |
| } catch (e) { | |
| console.error("Error loading schedule data:", e); | |
| } | |
| } | |
| // Player Analysis Autocomplete | |
| let searchTimeout; | |
| async function autocompletePlayer() { | |
| const input = document.getElementById('player-search').value; | |
| const resultsDiv = document.getElementById('autocomplete-results'); | |
| if (input.length < 3) { | |
| resultsDiv.style.display = 'none'; | |
| return; | |
| } | |
| clearTimeout(searchTimeout); | |
| searchTimeout = setTimeout(async () => { | |
| try { | |
| const response = await fetch(`/ipl/players?search=${encodeURIComponent(input)}`); | |
| const data = await response.json(); | |
| if (data.players && data.players.length > 0) { | |
| let html = ''; | |
| data.players.slice(0, 10).forEach(p => { | |
| html += `<div class="autocomplete-item" onclick="selectPlayer('${p.replace(/'/g, "\\'")}')">${p}</div>`; | |
| }); | |
| resultsDiv.innerHTML = html; | |
| resultsDiv.style.display = 'block'; | |
| } else { | |
| resultsDiv.style.display = 'none'; | |
| } | |
| } catch (e) { | |
| console.error("Search error", e); | |
| } | |
| }, 300); | |
| } | |
| async function selectPlayer(name) { | |
| document.getElementById('player-search').value = name; | |
| document.getElementById('autocomplete-results').style.display = 'none'; | |
| try { | |
| const response = await fetch(`/ipl/player/${encodeURIComponent(name)}`); | |
| if (response.ok) { | |
| const data = await response.json(); | |
| document.getElementById('ps-name').innerText = data.player; | |
| document.getElementById('ps-runs').innerText = data.batting.runs; | |
| document.getElementById('ps-sr').innerText = data.batting.strike_rate; | |
| document.getElementById('ps-4s').innerText = data.batting.fours; | |
| document.getElementById('ps-6s').innerText = data.batting.sixes; | |
| document.getElementById('ps-wkts').innerText = data.bowling.wickets; | |
| document.getElementById('ps-econ').innerText = data.bowling.economy; | |
| document.getElementById('ps-bmat').innerText = data.bowling.matches; | |
| document.getElementById('player-stats-container').style.display = 'block'; | |
| } | |
| } catch (e) { | |
| console.error("Error loading player stats", e); | |
| } | |
| } | |
| // Close autocomplete when clicking outside | |
| document.addEventListener('click', function(e) { | |
| if (e.target.id !== 'player-search') { | |
| document.getElementById('autocomplete-results').style.display = 'none'; | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> | |