"use client"; import { motion } from "framer-motion"; import { COLORS, VizFrame } from "./common"; function genCurve(ap: number) { const N = 80; const pts: [number, number][] = []; for (let i = 0; i < N; i++) { const r = i / (N - 1); const p = Math.max(0, Math.min(1, 1 - (1 - ap) * Math.pow(r, 1.6) - r * 0.05)); pts.push([r, p]); } return pts; } export function PRCurve({ width = 720, height = 460, classes = [ { name: "gate", ap: 0.92, color: COLORS.accent }, { name: "drone", ap: 0.78, color: COLORS.honey }, { name: "post", ap: 0.65, color: COLORS.green }, ], }: { width?: number; height?: number; classes?: { name: string; ap: number; color: string }[]; }) { const padX = 60; const padY = 50; const sx = (x: number) => padX + x * (width - padX * 2); const sy = (y: number) => height - padY - y * (height - padY * 2); return ( {[0, 0.25, 0.5, 0.75, 1].map((g) => ( {g.toFixed(2)} {g.toFixed(2)} ))} recall precision {classes.map((c, i) => { const pts = genCurve(c.ap); const path = `M ${pts.map((p) => `${sx(p[0])},${sy(p[1])}`).join(" L ")}`; return ( ); })} {/* Legend */} {classes.map((c, i) => ( {c.name} AP {c.ap.toFixed(2)} ))} ); }