From a931b24bd4f8906dec762d326ea4862f4d9227a6 Mon Sep 17 00:00:00 2001 From: Florent Tapponnier <160007691+Flotapponnier@users.noreply.github.com> Date: Wed, 29 Jul 2026 19:53:24 +0200 Subject: [PATCH] feat(data-api): add chain sub-scores to By Provider pivot cells --- src/components/data-api-providers-pivot.tsx | 61 ++++++++++++++++++--- src/lib/data-api-stats.ts | 36 ++++++++++++ 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/components/data-api-providers-pivot.tsx b/src/components/data-api-providers-pivot.tsx index ad75450c..8db603a6 100644 --- a/src/components/data-api-providers-pivot.tsx +++ b/src/components/data-api-providers-pivot.tsx @@ -9,6 +9,7 @@ import { fmtDataValue, type DataApiProviderPivotRow, type DataApiRegionScore, + type DataApiChainScore, type DataApiGroup, } from "@/lib/data-api-stats"; @@ -217,6 +218,8 @@ function GroupCell({ const { bestRank, bestCell } = cell; const accent = GROUP_META[group].accent; const hasRegions = bestCell.regions && bestCell.regions.length > 0; + const hasChains = bestCell.chains && bestCell.chains.length > 0; + const hasSub = hasRegions || hasChains; const bg = bestRank === 1 @@ -250,13 +253,20 @@ function GroupCell({ {bestCell.benchShortTitle.replace("coverage", "cov.").replace("freshness", "fresh.")} - {/* Regional sub-scores */} - {hasRegions && ( - + {/* Region + chain sub-scores merged in one row */} + {hasSub && ( +
+ {hasRegions && ( + + )} + {hasChains && ( + + )} +
)} ); @@ -272,7 +282,7 @@ function RegionSubScores({ accent: string; }) { return ( -
+ <> {regions.map((r) => (
))} -
+ + ); +} + +function ChainSubScores({ + chains, + accent, +}: { + chains: DataApiChainScore[]; + accent: string; +}) { + const MAX = 4; + const visible = chains.slice(0, MAX); + const overflow = chains.length - MAX; + return ( + <> + {visible.map((c) => ( + + {c.label} + + ))} + {overflow > 0 && ( + +{overflow} + )} + ); } diff --git a/src/lib/data-api-stats.ts b/src/lib/data-api-stats.ts index 9f0d7b97..7283a310 100644 --- a/src/lib/data-api-stats.ts +++ b/src/lib/data-api-stats.ts @@ -150,6 +150,12 @@ export type DataApiRegionScore = { p50: number; }; +export type DataApiChainScore = { + chain: string; + label: string; + p50: number; +}; + export type DataApiProviderCell = { benchSlug: string; benchShortTitle: string; @@ -160,6 +166,8 @@ export type DataApiProviderCell = { higherIsBetter: boolean; /** Per-region ranks for benches that have extras.regions populated. */ regions?: DataApiRegionScore[]; + /** Chains this provider leads on in this bench (rank 1 per chain). */ + chains?: DataApiChainScore[]; }; export type DataApiProviderPivotRow = { @@ -321,6 +329,32 @@ function computeProviderRegionScores( return result; } +/** + * Returns the chains where providerSlug is the winner (rank 1) in this bench. + */ +function computeProviderChainScores( + bench: Benchmark, + providerSlug: string, +): DataApiChainScore[] { + if (!bench.bestPerChain) return []; + const scores: DataApiChainScore[] = []; + for (const [chain, r] of Object.entries(bench.bestPerChain)) { + if ( + r.slug === providerSlug && + r.availability !== "unavailable" && + !r.unresponsive && + r.ms.p50 > 0 + ) { + scores.push({ + chain, + label: CHAIN_LABELS[chain] ?? chain, + p50: r.ms.p50, + }); + } + } + return scores.sort((a, b) => a.label.localeCompare(b.label)); +} + function toBenchRow(slug: string, bench: Benchmark): DataApiBenchRow { const live = sortedResults(liveResults(bench), bench.higherIsBetter); return { @@ -420,6 +454,7 @@ async function buildSnapshot(): Promise { providerMap.set(r.slug, { name: r.name, cells: [] }); } const regions = regionScores.get(r.slug); + const chains = computeProviderChainScores(bench, r.slug); providerMap.get(r.slug)!.cells.push({ benchSlug: slug, benchShortTitle: BENCH_SHORT_TITLE[slug] ?? slug, @@ -429,6 +464,7 @@ async function buildSnapshot(): Promise { unit: bench.unit, higherIsBetter: bench.higherIsBetter, regions: regions && regions.length > 0 ? regions : undefined, + chains: chains.length > 0 ? chains : undefined, }); } }