Predicted lineups, predicted-vs-actual goals, and goals on upcoming cards
- Scheduler now captures FotMob details for fixtures inside 48h, so the projected XIs exist before kickoff; the Lineups tab shows the pitch pre-match under a 'Predicted lineups' header with an honest note (official lineups ~1h before kickoff), switching to the confirmed view at kickoff - Finished matches get their forecast back: the preview falls back to the prediction frozen <=15min before kickoff (the scoreboard's no-hindsight snapshot), with the most-likely-score chip rebuilt from the frozen expected goals; the model card now reads 'Model's pre-match expected goals: 1.60 - 1.02 · final score 2-1', and the market-movement chart returns to finished matches too - Upcoming match cards append the model's expected goals to the hint: 'Model: Brazil 64% · 1.3-0.9 goals' Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -213,7 +213,16 @@ export function MatchPreviewPage() {
|
||||
<CardHeader><span className="font-display font-bold text-ink">{hasScore ? t.match.preMatchModel : t.match.modelExpectation}</span></CardHeader>
|
||||
<CardBody className="space-y-2">
|
||||
<WinProbBar home={preview.prediction.home} away={preview.prediction.away} probs={preview.prediction.probs} topScore={preview.prediction.topScore} />
|
||||
<p className="text-xs text-faint">{fmt(t.match.expectedGoalsLine, { home: preview.prediction.lambdaHome.toFixed(2), away: preview.prediction.lambdaAway.toFixed(2) })}</p>
|
||||
<p className="text-xs text-faint">
|
||||
{finished && f.homeScore != null && f.awayScore != null
|
||||
? fmt(t.match.predictedVsActual, {
|
||||
ph: preview.prediction.lambdaHome.toFixed(2),
|
||||
pa: preview.prediction.lambdaAway.toFixed(2),
|
||||
ah: f.homeScore,
|
||||
aa: f.awayScore,
|
||||
})
|
||||
: fmt(t.match.expectedGoalsLine, { home: preview.prediction.lambdaHome.toFixed(2), away: preview.prediction.lambdaAway.toFixed(2) })}
|
||||
</p>
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
@@ -419,14 +428,14 @@ export function MatchPreviewPage() {
|
||||
{/* ── Lineups ── */}
|
||||
{tab === 'lineups' && (
|
||||
<div className="space-y-4">
|
||||
{/* FotMob serves predicted XIs before kickoff — only draw the pitch
|
||||
once the match has started or ESPN confirms the lineups. */}
|
||||
{rich?.lineup && (hasScore || preview.lineups) ? (
|
||||
{/* Before kickoff the pitch shows FotMob's projected XIs, clearly
|
||||
labeled as predicted; from kickoff it's the confirmed lineup. */}
|
||||
{rich?.lineup ? (
|
||||
<Card>
|
||||
<CardHeader className="flex items-center gap-2"><Shirt size={16} className="text-accent" /><span className="font-display font-bold text-ink">{t.match.lineups}</span></CardHeader>
|
||||
<CardHeader className="flex items-center gap-2"><Shirt size={16} className="text-accent" /><span className="font-display font-bold text-ink">{hasScore ? t.match.lineups : t.match.predictedLineups}</span></CardHeader>
|
||||
<CardBody>
|
||||
<LineupPitch lineup={rich.lineup} home={homeName} away={awayName} events={preview.events} />
|
||||
<p className="mt-2 text-xs text-faint">{t.match.xgAttribution}</p>
|
||||
<p className="mt-2 text-xs text-faint">{hasScore ? t.match.xgAttribution : t.match.predictedLineupsNote}</p>
|
||||
</CardBody>
|
||||
</Card>
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user