durgexh commited on
Commit
d316651
·
verified ·
1 Parent(s): 1b77c77

Upload 9 files

Browse files
Files changed (4) hide show
  1. app.js +35 -3
  2. index.html +5 -0
  3. main.py +70 -68
  4. style.css +21 -0
app.js CHANGED
@@ -15,16 +15,40 @@ document.addEventListener('DOMContentLoaded', () => {
15
  const upcBox = document.getElementById('upcomingPredictorBox');
16
  const titleEl = document.getElementById('predictionTitle');
17
  const refreshBtn = document.getElementById('refreshBtn');
 
18
 
19
  let currentObservedOver = null;
 
20
 
21
  async function syncBackendData() {
22
  try {
23
  apiIndicator.style.color = "yellow";
24
 
25
- // Fetch exactly from Python Server memory state
26
- const res = await fetch('/api/state');
27
- const state = await res.json();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
  apiIndicator.innerText = "SERVER: CONNECTED";
30
  apiIndicator.style.color = "var(--accent-green)";
@@ -152,6 +176,14 @@ document.addEventListener('DOMContentLoaded', () => {
152
  });
153
  }
154
 
 
 
 
 
 
 
 
 
155
  // Auto check the Python Server every 5 seconds (5000ms) for high response
156
  setInterval(syncBackendData, 5000);
157
  syncBackendData(); // Initial Hook
 
15
  const upcBox = document.getElementById('upcomingPredictorBox');
16
  const titleEl = document.getElementById('predictionTitle');
17
  const refreshBtn = document.getElementById('refreshBtn');
18
+ const selector = document.getElementById('matchSelector');
19
 
20
  let currentObservedOver = null;
21
+ let currentSelectedMatchId = null;
22
 
23
  async function syncBackendData() {
24
  try {
25
  apiIndicator.style.color = "yellow";
26
 
27
+ // Fetch list of ALL ESPNcricinfo matches globally
28
+ const res = await fetch('/api/matches');
29
+ const matches = await res.json();
30
+
31
+ if (!matches || matches.length === 0) return;
32
+
33
+ // Populate Check dropdown
34
+ if (selector && selector.options.length <= 1) {
35
+ selector.innerHTML = '';
36
+ matches.forEach(m => {
37
+ const opt = document.createElement('option');
38
+ opt.value = m.id;
39
+ opt.innerText = `${m.is_ipl ? '🏏 PRIORITY: IPL' : (m.live ? '🔴 LIVE' : '⏳ UPCOMING')} - ${m.title}`;
40
+ selector.appendChild(opt);
41
+ });
42
+ if(!currentSelectedMatchId) {
43
+ currentSelectedMatchId = matches[0].id;
44
+ selector.value = currentSelectedMatchId;
45
+ }
46
+ }
47
+
48
+ if(!currentSelectedMatchId) currentSelectedMatchId = matches[0].id;
49
+
50
+ const state = matches.find(m => m.id === currentSelectedMatchId);
51
+ if(!state) return;
52
 
53
  apiIndicator.innerText = "SERVER: CONNECTED";
54
  apiIndicator.style.color = "var(--accent-green)";
 
176
  });
177
  }
178
 
179
+ if (selector) {
180
+ selector.addEventListener('change', (e) => {
181
+ currentSelectedMatchId = e.target.value;
182
+ currentObservedOver = null; // force hard recalulate of prediction
183
+ syncBackendData();
184
+ });
185
+ }
186
+
187
  // Auto check the Python Server every 5 seconds (5000ms) for high response
188
  setInterval(syncBackendData, 5000);
189
  syncBackendData(); // Initial Hook
index.html CHANGED
@@ -12,6 +12,11 @@
12
  <div class="logo">
13
  <span class="ai-glow">Predict</span>IPL
14
  </div>
 
 
 
 
 
15
  <ul class="nav-links">
16
  <li><button id="refreshBtn" class="refresh-btn">🔄 Refresh Live State</button></li>
17
  <li><a href="index.html" class="active">Live Prediction</a></li>
 
12
  <div class="logo">
13
  <span class="ai-glow">Predict</span>IPL
14
  </div>
15
+ <div class="nav-center">
16
+ <select id="matchSelector" class="match-dropdown">
17
+ <option value="">Fetching Live Global Feeds...</option>
18
+ </select>
19
+ </div>
20
  <ul class="nav-links">
21
  <li><button id="refreshBtn" class="refresh-btn">🔄 Refresh Live State</button></li>
22
  <li><a href="index.html" class="active">Live Prediction</a></li>
main.py CHANGED
@@ -10,24 +10,19 @@ from datetime import datetime
10
 
11
  app = FastAPI()
12
 
13
- # Central Python Brain State Memory
14
- system_state = {
15
- "live": False, "status": "UPCOMING", "teams": ["Initializing", "Data"],
16
- "score": "0/0", "overs": "0.0", "venue": "Loading Stadium..."
17
- }
18
  prediction_history = []
19
- last_over = ""
20
 
21
  LIVE_MATCH_URL = "https://www.espncricinfo.com/live-cricket-score"
22
 
23
  def autonomous_backend_scraper():
24
- global system_state, prediction_history, last_over
25
- print("ESPN Network Hack Engaged. Stealth fetching active...")
26
 
27
  while True:
28
  try:
29
- # Reverting back to our core hacker mechanic instead of the blocked free API
30
- # We natively rip the Next.js database bypassing Cloudflare
31
  r = requests.get(LIVE_MATCH_URL, impersonate='chrome120', timeout=15)
32
  soup = BeautifulSoup(r.text, 'html.parser')
33
  next_data = soup.find('script', id='__NEXT_DATA__')
@@ -36,82 +31,89 @@ def autonomous_backend_scraper():
36
  data = json.loads(next_data.string)
37
  matches_data = data.get('props', {}).get('appPageProps', {}).get('data', {}).get('content', {}).get('matches', [])
38
 
39
- # Filter for LIVE matches dynamically
40
- live_matches = [m for m in matches_data if m.get('state') == 'LIVE']
41
-
42
- if len(live_matches) > 0:
43
- live_match = live_matches[0]
44
-
45
- system_state["live"] = True
46
- system_state["status"] = "LIVE"
47
-
48
- # Extract Teams
49
- teams = live_match.get('teams', [])
50
- team1_name = teams[0].get('team', {}).get('shortName', teams[0].get('team', {}).get('name', 'Team A')) if len(teams) > 0 else "Team A"
51
- team2_name = teams[1].get('team', {}).get('shortName', teams[1].get('team', {}).get('name', 'Team B')) if len(teams) > 1 else "Team B"
52
 
53
- system_state["teams"] = [team1_name, team2_name]
54
- system_state["venue"] = live_match.get('ground', {}).get('name', 'Live Stadium')
55
 
56
- # Extract Score & Overs natively from ESPN database
57
- new_over = str(live_match.get('liveOvers', '0.0'))
58
 
59
- # Find which team is currently batting
60
- btm_team = next((t for t in teams if t.get('isLive')), teams[0] if len(teams)>0 else {})
61
- new_score = btm_team.get('score', "0/0")
62
 
63
- system_state["score"] = new_score
64
- system_state["overs"] = new_over
 
 
 
 
 
 
 
 
65
 
66
- # History Logic: Save records when ball increments!
67
- if new_over != last_over and last_over != "":
68
- prediction_history.append({
69
- "time": datetime.now().strftime("%H:%M:%S"),
70
- "match": f"{team1_name} vs {team2_name}",
71
- "over": new_over,
72
- "score": new_score,
73
- "prediction": "Vanguard Assessment Complete"
74
- })
75
- if len(prediction_history) > 50:
76
- prediction_history.pop(0)
77
-
78
- last_over = new_over
79
 
80
- else:
81
- # No live match found, default to upcoming
82
- upc_matches = [m for m in matches_data if m.get('state') != 'LIVE']
83
- if len(upc_matches) > 0:
84
- upc = upc_matches[0]
85
- system_state["live"] = False
86
- system_state["status"] = "UPCOMING"
87
 
88
- teams = upc.get('teams', [])
89
- team1_name = teams[0].get('team', {}).get('name', 'Team A') if len(teams) > 0 else "Team A"
90
- team2_name = teams[1].get('team', {}).get('name', 'Team B') if len(teams) > 1 else "Team B"
91
- system_state["teams"] = [team1_name, team2_name]
92
 
93
- system_state["venue"] = upc.get('ground', {}).get('name', 'Upcoming Stadium')
94
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  except Exception as e:
96
- print("Python Server Network Error:", e)
97
 
98
- # Cooldown timer
99
  time.sleep(5)
100
 
101
- # Start the Ghost Thread
102
  threading.Thread(target=autonomous_backend_scraper, daemon=True).start()
103
 
104
- # API Endpoints
105
- @app.get("/api/state")
106
- def get_state():
107
- return system_state
108
 
109
  @app.get("/api/history")
110
  def get_history():
111
- return prediction_history
 
112
 
113
- # Serve the beautiful frontend GUI
114
  app.mount("/", StaticFiles(directory=".", html=True), name="frontend")
115
 
116
  if __name__ == "__main__":
117
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
 
 
10
 
11
  app = FastAPI()
12
 
13
+ # Global Match Tracking Memory Map
14
+ all_matches_memory = []
 
 
 
15
  prediction_history = []
16
+ last_overs = {}
17
 
18
  LIVE_MATCH_URL = "https://www.espncricinfo.com/live-cricket-score"
19
 
20
  def autonomous_backend_scraper():
21
+ global all_matches_memory, prediction_history, last_overs
22
+ print("ESPN Network Hack Engaged. Multi-Match Scanner Active...")
23
 
24
  while True:
25
  try:
 
 
26
  r = requests.get(LIVE_MATCH_URL, impersonate='chrome120', timeout=15)
27
  soup = BeautifulSoup(r.text, 'html.parser')
28
  next_data = soup.find('script', id='__NEXT_DATA__')
 
31
  data = json.loads(next_data.string)
32
  matches_data = data.get('props', {}).get('appPageProps', {}).get('data', {}).get('content', {}).get('matches', [])
33
 
34
+ parsed_matches = []
35
+ for m in matches_data:
36
+ m_id = str(m.get('objectId', m.get('id', 'unknown')))
37
+ state_raw = str(m.get('state')) # LIVE, PRE, POST
38
+ teams = m.get('teams', [])
 
 
 
 
 
 
 
 
39
 
40
+ team1_name = teams[0].get('team', {}).get('name', 'Team A') if len(teams) > 0 else "Team A"
41
+ team2_name = teams[1].get('team', {}).get('name', 'Team B') if len(teams) > 1 else "Team B"
42
 
43
+ series_name = m.get('series', {}).get('longName', m.get('slug', ''))
 
44
 
45
+ # Mathmatically prioritize IPL
46
+ is_ipl = "indian-premier-league" in str(series_name).lower() or "ipl" in str(series_name).lower()
 
47
 
48
+ match_obj = {
49
+ "id": m_id,
50
+ "title": f"{team1_name} vs {team2_name}",
51
+ "series": series_name,
52
+ "live": state_raw == 'LIVE',
53
+ "status": state_raw,
54
+ "teams": [team1_name, team2_name],
55
+ "venue": m.get('ground', {}).get('name', 'Stadium'),
56
+ "is_ipl": is_ipl
57
+ }
58
 
59
+ if state_raw == 'LIVE':
60
+ new_over = str(m.get('liveOvers', '0.0'))
61
+ btm_team = next((t for t in teams if t.get('isLive')), teams[0] if len(teams)>0 else {})
62
+ new_score = btm_team.get('score', "0/0")
 
 
 
 
 
 
 
 
 
63
 
64
+ match_obj["score"] = new_score
65
+ match_obj["overs"] = new_over
 
 
 
 
 
66
 
67
+ # History Tracker
68
+ if m_id not in last_overs: last_overs[m_id] = ""
 
 
69
 
70
+ if new_over != last_overs[m_id] and last_overs[m_id] != "":
71
+ prediction_history.append({
72
+ "time": datetime.now().strftime("%H:%M:%S"),
73
+ "match": f"{team1_name} vs {team2_name}",
74
+ "over": new_over,
75
+ "score": new_score,
76
+ "prediction": "Vanguard Complete"
77
+ })
78
+ if len(prediction_history) > 100: prediction_history.pop(0)
79
+
80
+ last_overs[m_id] = new_over
81
+ else:
82
+ match_obj["score"] = "0/0"
83
+ match_obj["overs"] = "0.0"
84
+
85
+ parsed_matches.append(match_obj)
86
+
87
+ # Sort algorithm: IPL first, then LIVE matches
88
+ def sort_priority(x):
89
+ score = 0
90
+ if x["is_ipl"]: score += 100
91
+ if x["live"]: score += 50
92
+ return -score
93
+
94
+ parsed_matches.sort(key=sort_priority)
95
+ all_matches_memory = parsed_matches
96
+
97
  except Exception as e:
98
+ print("Server Network Intercept Error:", e)
99
 
 
100
  time.sleep(5)
101
 
102
+ # Ghost Threading
103
  threading.Thread(target=autonomous_backend_scraper, daemon=True).start()
104
 
105
+ @app.get("/api/matches")
106
+ def get_matches():
107
+ return all_matches_memory
 
108
 
109
  @app.get("/api/history")
110
  def get_history():
111
+ # Return last 50 processed balls from all matches
112
+ return prediction_history[-50:]
113
 
 
114
  app.mount("/", StaticFiles(directory=".", html=True), name="frontend")
115
 
116
  if __name__ == "__main__":
117
+ import os
118
+ port = int(os.environ.get("PORT", 7860))
119
+ uvicorn.run(app, host="0.0.0.0", port=port)
style.css CHANGED
@@ -53,6 +53,27 @@ body {
53
  gap: 2rem;
54
  }
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  .nav-links a {
57
  color: var(--text-muted);
58
  text-decoration: none;
 
53
  gap: 2rem;
54
  }
55
 
56
+ .nav-center {
57
+ flex-grow: 1;
58
+ display: flex;
59
+ justify-content: center;
60
+ padding: 0 1rem;
61
+ }
62
+
63
+ .match-dropdown {
64
+ background: var(--bg-dark);
65
+ color: var(--accent-cyan);
66
+ border: 1px solid var(--accent-cyan);
67
+ padding: 0.5rem 1rem;
68
+ border-radius: 8px;
69
+ font-family: 'Outfit', sans-serif;
70
+ font-size: 0.95rem;
71
+ width: 100%;
72
+ max-width: 400px;
73
+ outline: none;
74
+ cursor: pointer;
75
+ }
76
+
77
  .nav-links a {
78
  color: var(--text-muted);
79
  text-decoration: none;