/* ============================================================ FIFA EDGE — H2H Match Detail view ============================================================ */ const { useState: useSh, useMemo: useMh, useEffect: useEh } = React; function pickPlayer(id) { return PLAYERS.find(p => p.id === id) || PLAYERS[0]; } const H2H_EMPTY = { h2h: { games: 0, aWins: 0, draws: 0, bWins: 0, avgGoals: 0, overRate: 0, bttsRate: 0 }, recent: [], overLines: [ { line: 0.5, a: 0, b: 0 }, { line: 1.5, a: 0, b: 0 }, { line: 2.5, a: 0, b: 0 }, { line: 3.5, a: 0, b: 0 }, { line: 4.5, a: 0, b: 0 }, { line: 5.5, a: 0, b: 0 }, ], underLines: [ { line: 1.5, a: 0, b: 0 }, { line: 2.5, a: 0, b: 0 }, { line: 3.5, a: 0, b: 0 }, { line: 4.5, a: 0, b: 0 }, ], goalsByMin: [], dailyDist: Array.from({length: 24}, (_, i) => ({ h: String(i).padStart(2,'0'), a: 0, b: 0 })), mostFrequent: [], bothScore: [ ['Ambos marcaram 1T', 0], ['Ambos marcaram 2T', 0], ['Nenhum marcou 1T', 0], ['Nenhum marcou 2T', 0], ], }; const H2HDetail = ({ matchId, onBack }) => { const m = MATCHES.find(x => x.id === matchId) || MATCHES[0]; if (!m) return
Jogo não encontrado.
; const A = m.home, B = m.away; const [data, setData] = useSh(H2H_EMPTY); useEh(() => { if (!A?.handle || !B?.handle) return; const url = `/api/h2h?home=${encodeURIComponent(A.handle)}&away=${encodeURIComponent(B.handle)}`; fetch(url, { cache: 'no-store' }) .then(r => r.ok ? r.json() : null) .then(d => { if (d) setData({ ...H2H_EMPTY, ...d }); }) .catch(err => console.warn('[h2h] fetch failed', err)); }, [A?.handle, B?.handle]); const { h2h, recent, overLines, underLines, goalsByMin, dailyDist, mostFrequent, bothScore } = data; const ap = A.wr, bp = B.wr, dp = 1 - ap - bp + 0.15; const total = ap + bp + dp; const pctA = Math.round((ap/total)*100), pctB = Math.round((bp/total)*100), pctD = 100 - pctA - pctB; const overBar = (v) => (
{v.line}
{v.a.toFixed(1)}%
); const underBar = (v) => (
{v.line}
{v.a.toFixed(1)}%
); return ( <>

Confronto direto · {A.handle} vs {B.handle}

Kickoff {window.fmtHM(m.kickoff)} (SP) · {m.league} · T-{m.minuteToKO}m
{/* ===== Hero head-to-head ===== */}
{A.handle.slice(0,2).toUpperCase()}
{A.handle}
{A.team}
ÚLTIMOS 10 PARTIDAS
{h2h.aWins}
{A.handle}
{h2h.draws}
EMPATE
{h2h.bWins}
{B.handle}
BTTS {(h2h.bttsRate*100).toFixed(0)}% O2.5 {(h2h.overRate*100).toFixed(0)}% AVG {h2h.avgGoals}
{B.handle.slice(0,2).toUpperCase()}
{B.handle}
{B.team}
{/* Pro notice */}
Visão parcial · dados de 6 partidas recentes
Para o histórico completo e mercados consolidados, ative PRO + LIVE + BOT no plano operador.
{/* Top KPIs */}
{/* ===== Over/Under grids ===== */}
Over/Under (Partida) — {A.handle}
{overLines.map(v => overBar(v))}
Handicap Asiático — LIVE
{[[-2, 12.4, 47.8], [-1.5, 21.3, 36.2], [-1, 32.4, 28.1], [-0.5, 42.8, 22.4], [0, 52.6, 18.7], [+0.5, 64.1, 13.2], [+1, 72.4, 9.8]].map((r,i) => ( ))}
Linha {A.handle} {B.handle}
{r[0] > 0 ? '+' : ''}{r[0]} 50?'var(--win)':'var(--loss)'}}>{r[1].toFixed(1)}% 50?'var(--win)':'var(--loss)'}}>{r[2].toFixed(1)}%
Over (1º tempo) — {A.handle}
{[{line:0.5,a:72.4},{line:1.5,a:41.8},{line:2.5,a:18.9}].map(v => overBar(v))}
Over (1º tempo) — {B.handle}
{[{line:0.5,a:68.1},{line:1.5,a:37.4},{line:2.5,a:15.2}].map(v => overBar(v))}
Under — {A.handle}
{underLines.map(v => underBar(v))}
Under — {B.handle}
{underLines.map(v => underBar({...v, a: v.a*0.9}))}
{/* Média gols / Estatísticas da partida */}
Média de gols por tempo
{A.handle} Tempo {B.handle}
1.42 1º T 1.18
1.87 2º T 1.64
Estatísticas da partida
{[ ['Posse média', 54.2, 45.8], ['Finalizações', 62.1, 37.9], ['Finalizações ao gol', 58.7, 41.3], ['xG médio', 55.4, 44.6], ['Escanteios', 51.8, 48.2], ].map((r,i)=>(
{r[1]}% {r[0]} {r[2]}%
))}
{/* Ambos equipes marcam / Resultado mais frequente */}
Ambos equipes marcam
{bothScore.map((r,i) => (
{r[0]} {r[1]}%
))}
Resultados mais frequentes
{mostFrequent.map((r,i) => (
{r[0]}
{r[1]}%
))}
{/* Análise de time por equipe */}
{[A,B].map((P, ix) => (
Análise de time · {P.handle}
{['Man City','Bayern','Liverpool','Real Madrid','PSG'].map((t,i)=>{ const pj = 3+i, v = pj-i, e = (i%2), d = pj-v-e; return ( ); })}
TimePVEDGPGC
{t} {pj} {v} {e} {d} {pj*2} {pj}
))}
{/* Média de pontos linha tempo */}
Média de pontos (média móvel · 12 jogos)
{[1,2,3,4,5].map(y => )} {[0,1,2,3,4,5,6].map(y => {y})}
{A.handle} {B.handle}
{/* Distribuição diária */}
Distribuição diária de partidas (por hora UTC)
{dailyDist.map((d,i) => (
{d.h}
))}
{/* Histórico de partidas */}
Histórico de partidas
ÚLTIMAS 6
{recent.map((r,i) => (
r.scB?'var(--text-0)':'var(--text-2)', fontWeight:r.scA>r.scB?600:400}}>{A.handle} {A.team}
{r.scA} : {r.scB}
r.scA?'var(--text-0)':'var(--text-2)', fontWeight:r.scB>r.scA?600:400}}>{B.team} {B.handle}
{r.date}
))}
{/* Últimas partidas por player */}
{[A,B].map(P => (
Últimas partidas · {P.handle}
{P.form.slice(0,5).map((r,i) => (
{P.handle} {r==='w'?'2 : 1':r==='d'?'1 : 1':'0 : 2'} Opponent_{i+1}
))}
))}
{/* Insights text */}
Histórico de confrontos · análise
ÚLT. ATUALIZAÇÃO: 19/04 18:00 UTC

● Visão Geral

Em {h2h.games} confrontos entre {A.handle} e {B.handle}, {A.handle} venceu {h2h.aWins} vezes, {B.handle} venceu {h2h.bWins}, com {h2h.draws} empates. ELO atual {A.elo} vs {B.elo} favorece {A.elo>B.elo?A.handle:B.handle} por {Math.abs(A.elo-B.elo)} pontos.

● Performance

Nos últimos confrontos diretos, {A.handle} acumulou {(A.wr*100).toFixed(0)}% de vitórias, enquanto {B.handle} manteve {(B.wr*100).toFixed(0)}% aproveitamento. Over 2.5 bateu em {(h2h.overRate*100).toFixed(0)}% das partidas.

); }; Object.assign(window, { H2HDetail });