/* ============================================================ FIFA EDGE — real-data bootstrap Fetches from /api/bootstrap (SQLite-backed) and publishes to window.{LEAGUES,PLAYERS,MATCHES,LIVE,SIGNALS,ROI_14D,HEATMAP} Keeps the exact same shape the React views expect. ============================================================ */ const FALLBACK = { LEAGUES: [{ id: 22614, name: 'Battle 8', code: 'BATTLE-8', active: true }], PLAYERS: [], MATCHES: [], LIVE: [], SIGNALS: [], ROI_14D: Array(14).fill(0), HEATMAP: Array(70).fill(2), OVERVIEW: { bankroll: null, roi_14d: null, roi_delta: 0, winrate: null, ev_plus_avg: null, signals_14d: 0, signals_total: 0, wins: 0, losses: 0, market_odds_available: false, }, }; function toDate(x) { if (!x) return new Date(); const d = new Date(x); return isNaN(d.getTime()) ? new Date() : d; } // Fuso São Paulo (UTC-3). Usar em todo horário exibido. const SP_TZ = 'America/Sao_Paulo'; window.fmtHM = (d) => d instanceof Date ? d.toLocaleTimeString('pt-BR', { timeZone: SP_TZ, hour: '2-digit', minute: '2-digit', hour12: false }) : '--:--'; window.fmtDate = (d) => d instanceof Date ? d.toLocaleDateString('pt-BR', { timeZone: SP_TZ, day: '2-digit', month: '2-digit' }) : '--/--'; function reshape(api) { const PLAYERS = (api.players || []).map(p => ({ id: p.id, handle: p.handle, team: p.team, elo: p.elo, delta: p.delta, games: p.games, wr: p.wr, form: p.form && p.form.length ? p.form : ['-','-','-','-','-','-','-','-','-','-'], })); const side = s => ({ handle: s?.handle ?? '?', team: s?.team ?? '—', elo: s?.elo ?? 0, wr: s?.wr ?? 0, games: s?.games ?? 0, form: (s?.form && s.form.length) ? s.form : ['-','-','-','-','-'], }); const MATCHES = (api.matches || []).map(m => ({ id: m.id, kickoff: toDate(m.kickoff), league: m.league, home: side(m.home), away: side(m.away), odds: { h: m.odds.h ?? null, d: m.odds.d ?? null, a: m.odds.a ?? null, }, ev: { pick: m.ev.pick, market: m.ev.market, value: m.ev.value ?? 0, conf: m.ev.conf ?? 0, }, minuteToKO: m.minuteToKO ?? 0, status: m.status, })); const LIVE = (api.live || []).map(l => ({ id: l.id, minute: l.minute, home: side(l.home), away: side(l.away), score: l.score, odds: l.odds, })); const SIGNALS = (api.signals || []).map(s => ({ id: s.id, ts: toDate(s.ts), match: s.match, pick: s.pick, market: s.market, odd: s.odd ?? 0, stake: s.stake ?? 1, result: s.result, pnl: s.pnl ?? 0, ev: s.ev ?? 0, conf: s.conf ?? 0, })); return { LEAGUES: api.leagues || FALLBACK.LEAGUES, PLAYERS, MATCHES, LIVE, SIGNALS, ROI_14D: api.roi14d || FALLBACK.ROI_14D, HEATMAP: api.heatmap || FALLBACK.HEATMAP, OVERVIEW: api.overview || FALLBACK.OVERVIEW, }; } async function loadBootstrap() { try { const res = await fetch('/api/bootstrap', { cache: 'no-store' }); if (!res.ok) throw new Error('api ' + res.status); return reshape(await res.json()); } catch (err) { console.warn('[fifa-edge] bootstrap failed, using fallbacks:', err); return FALLBACK; } } // seed fallbacks so any early read doesn't crash — real data overwrites below Object.assign(window, FALLBACK); window.__FIFA_READY__ = loadBootstrap().then(data => { Object.assign(window, data); window.__FIFA_DATA__ = data; window.dispatchEvent(new CustomEvent('fifa:data')); });