From 9540ff9d2e01cc223d55ab162d98857280fc8275 Mon Sep 17 00:00:00 2001 From: Fahri Can Date: Mon, 1 Jun 2026 01:09:04 +0300 Subject: [PATCH] gg --- .../dashboard/dashboard-content.tsx | 3 +- src/components/matches/prediction-card.tsx | 50 ++++++++++++++----- .../predictions/predictions-content.tsx | 3 +- src/lib/api/predictions/types.ts | 6 +++ 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/components/dashboard/dashboard-content.tsx b/src/components/dashboard/dashboard-content.tsx index 36dbe33..185a262 100644 --- a/src/components/dashboard/dashboard-content.tsx +++ b/src/components/dashboard/dashboard-content.tsx @@ -373,7 +373,8 @@ export default function DashboardContent() { borderRadius="full" > {Math.round( - pred.main_pick.calibrated_confidence ?? + pred.main_pick.unified_score ?? + pred.main_pick.calibrated_confidence ?? pred.main_pick.confidence, )} % diff --git a/src/components/matches/prediction-card.tsx b/src/components/matches/prediction-card.tsx index 550f115..07b797a 100644 --- a/src/components/matches/prediction-card.tsx +++ b/src/components/matches/prediction-card.tsx @@ -643,7 +643,7 @@ function PickCard({ ( {formatOdds(item.odds)} + + {formatPercent( + (item.model_probability ?? 0) * 100, + 0, + )}{" "} + {getUiText(ui, "probability-short", "olasılık")} + - {formatPercent(item.calibrated_confidence, 0)} + {formatPercent(item.unified_score ?? item.calibrated_confidence, 0)} [item.market, item]), + (betSummary || []).map((item) => [`${item.market}:${item.pick}`, item]), ); + // Fallback: first row of a market, for cards whose pick has no exact row. + for (const item of betSummary || []) { + if (!summaryByMarket.has(item.market)) { + summaryByMarket.set(item.market, item); + } + } const orderedEntries = Object.entries(marketBoard).sort(([left], [right]) => { const leftIndex = MARKET_ORDER.indexOf(left); const rightIndex = MARKET_ORDER.indexOf(right); @@ -899,9 +915,18 @@ function MarketBoardSection({ {orderedEntries.map(([market, entry]) => { if (!entry?.probs) return null; - const summary = summaryByMarket.get(market); + const summary = + summaryByMarket.get(`${market}:${entry.pick}`) ?? + summaryByMarket.get(market); const interval = summary?.confidence_interval || entry.confidence_interval; + // Hit probability == the dominant (green) bar in the graph below, + // so the headline never contradicts the distribution it sits on. + const pickProbPct = + Math.max( + 0, + ...Object.values(entry.probs).map((p) => Number(p) || 0), + ) * 100; return ( - {entry.pick} ({formatPercent(entry.confidence, 0)}) + {entry.pick} ({formatPercent(pickProbPct, 0)}) ) : null} = pickProbPct - 1e-6 ? "green.400" : "blue.400" } @@ -1349,7 +1373,7 @@ export default function PredictionCard({ prediction }: PredictionCardProps) { diff --git a/src/components/predictions/predictions-content.tsx b/src/components/predictions/predictions-content.tsx index c93b8fd..dcfab1a 100644 --- a/src/components/predictions/predictions-content.tsx +++ b/src/components/predictions/predictions-content.tsx @@ -193,7 +193,8 @@ export default function PredictionsContent() { color="primary.fg" > {Math.round( - pred.main_pick.calibrated_confidence ?? + pred.main_pick.unified_score ?? + pred.main_pick.calibrated_confidence ?? pred.main_pick.confidence, )} % diff --git a/src/lib/api/predictions/types.ts b/src/lib/api/predictions/types.ts index 4c6210b..e9942c5 100644 --- a/src/lib/api/predictions/types.ts +++ b/src/lib/api/predictions/types.ts @@ -90,6 +90,8 @@ export interface EngineBreakdownDto { export type BetGrade = "A" | "B" | "C" | "PASS"; export type SignalTier = "CORE" | "VALUE" | "LEAN" | "LONGSHOT" | "PASS"; +export type UnifiedScoreLabel = "very_reliable" | "reliable" | "moderate" | "low"; + export interface MatchPickDto { market: string; pick: string; @@ -98,6 +100,8 @@ export interface MatchPickDto { odds: number; raw_confidence: number; calibrated_confidence: number; + unified_score?: number; + unified_score_label?: UnifiedScoreLabel; min_required_confidence: number; edge: number; ev_edge: number; @@ -158,6 +162,8 @@ export interface MatchBetSummaryItemDto { pick: string; raw_confidence: number; calibrated_confidence: number; + unified_score?: number; + unified_score_label?: UnifiedScoreLabel; bet_grade: BetGrade; playable: boolean; stake_units: number;