loop-benchmarking

Controlled experiments across agentic coding configurations. Same task, one variable, what actually works.
git clone https://git.shiptheloop.com/loop-benchmarking.git
Log | Files | Refs | README

Heatmap.tsx (5303B)


      1 import type { InteractionResult } from "../lib/analysis";
      2 
      3 interface HeatmapProps {
      4   data: InteractionResult;
      5   metric: string;
      6   totalRuns?: number;
      7   totalCells?: number;
      8 }
      9 
     10 export default function Heatmap({ data, metric, totalRuns, totalCells }: HeatmapProps) {
     11   const { axisA, axisB, table } = data;
     12 
     13   const aValues = Object.keys(table).sort();
     14   const bValues = Array.from(
     15     new Set(aValues.flatMap((a) => Object.keys(table[a])))
     16   ).sort();
     17 
     18   if (aValues.length === 0 || bValues.length === 0) {
     19     return (
     20       <div
     21         className="card"
     22         style={{
     23           textAlign: "center",
     24           padding: "40px",
     25           color: "var(--text-muted)",
     26         }}
     27       >
     28         Not enough data for this interaction.
     29       </div>
     30     );
     31   }
     32 
     33   // Find min/max for color scale
     34   const allMeans = aValues.flatMap((a) =>
     35     bValues.filter((b) => table[a]?.[b]).map((b) => table[a][b].mean)
     36   );
     37   const minVal = Math.min(...allMeans);
     38   const maxVal = Math.max(...allMeans);
     39   const range = maxVal - minVal || 1;
     40 
     41   function cellColor(value: number): string {
     42     const ratio = (value - minVal) / range;
     43     if (ratio > 0.66)
     44       return `rgba(34, 197, 94, ${0.3 + ratio * 0.5})`;
     45     if (ratio > 0.33)
     46       return `rgba(234, 179, 8, ${0.3 + ratio * 0.4})`;
     47     return `rgba(239, 68, 68, ${0.3 + (1 - ratio) * 0.4})`;
     48   }
     49 
     50   return (
     51     <div className="card">
     52       <h3 style={{ marginBottom: "4px" }}>
     53         {axisA} x {axisB}
     54       </h3>
     55       {totalRuns != null && totalCells != null && (
     56         <div style={{ fontSize: "10px", fontFamily: "'JetBrains Mono', monospace", color: "var(--text-muted, hsl(213 14% 65%))", marginBottom: "4px" }}>
     57           (n={totalRuns} runs across {totalCells} cells)
     58         </div>
     59       )}
     60       <p
     61         style={{
     62           color: "var(--text-muted)",
     63           fontSize: "0.75rem",
     64           marginBottom: "16px",
     65         }}
     66       >
     67         Mean {metric} for each combination. Interaction strength:{" "}
     68         <span
     69           style={{
     70             fontFamily: "var(--font-mono)",
     71             color:
     72               data.maxInteraction > 0.05
     73                 ? "var(--yellow)"
     74                 : "var(--text-muted)",
     75           }}
     76         >
     77           {(data.maxInteraction * 100).toFixed(1)}%
     78         </span>
     79       </p>
     80 
     81       <div style={{ overflowX: "auto" }}>
     82         <table style={{ borderCollapse: "collapse" }}>
     83           <thead>
     84             <tr>
     85               <th
     86                 style={{
     87                   padding: "8px 12px",
     88                   fontSize: "0.7rem",
     89                   textAlign: "center",
     90                 }}
     91               >
     92                 {axisA} \ {axisB}
     93               </th>
     94               {bValues.map((b) => (
     95                 <th
     96                   key={b}
     97                   style={{
     98                     padding: "8px 12px",
     99                     fontSize: "0.75rem",
    100                     textAlign: "center",
    101                     fontFamily: "var(--font-mono)",
    102                   }}
    103                 >
    104                   {b}
    105                 </th>
    106               ))}
    107             </tr>
    108           </thead>
    109           <tbody>
    110             {aValues.map((a) => (
    111               <tr key={a}>
    112                 <td
    113                   style={{
    114                     padding: "8px 12px",
    115                     fontSize: "0.75rem",
    116                     fontFamily: "var(--font-mono)",
    117                     fontWeight: 600,
    118                   }}
    119                 >
    120                   {a}
    121                 </td>
    122                 {bValues.map((b) => {
    123                   const cell = table[a]?.[b];
    124                   if (!cell) {
    125                     return (
    126                       <td
    127                         key={b}
    128                         style={{
    129                           padding: "8px 12px",
    130                           textAlign: "center",
    131                           color: "var(--text-muted)",
    132                         }}
    133                       >
    134                         -
    135                       </td>
    136                     );
    137                   }
    138                   const isLowN = cell.n < 3;
    139                   return (
    140                     <td
    141                       key={b}
    142                       style={{
    143                         padding: "8px 12px",
    144                         textAlign: "center",
    145                         background: cellColor(cell.mean),
    146                         fontFamily: "var(--font-mono)",
    147                         fontSize: "0.8rem",
    148                         fontWeight: 600,
    149                         borderRadius: "2px",
    150                         opacity: isLowN ? 0.4 : 1,
    151                         ...(isLowN ? { borderStyle: "dashed", borderWidth: "1px", borderColor: "var(--text-muted)" } : {}),
    152                       }}
    153                     >
    154                       {(cell.mean * 100).toFixed(0)}%
    155                       <div
    156                         style={{
    157                           fontSize: "0.6rem",
    158                           color: isLowN ? "var(--yellow, hsl(40 95% 64%))" : "var(--text-muted)",
    159                           fontWeight: isLowN ? 600 : 400,
    160                         }}
    161                       >
    162                         n={cell.n}
    163                       </div>
    164                     </td>
    165                   );
    166                 })}
    167               </tr>
    168             ))}
    169           </tbody>
    170         </table>
    171       </div>
    172     </div>
    173   );
    174 }

Impressum · Datenschutz