"use client"; import { useMemo, useState } from "react"; import { COLORS, VizFrame } from "./common"; function genPoints(n: number, slope: number, intercept: number, noise: number) { let seed = 42; const rng = () => { seed = (seed * 1664525 + 1013904223) % 4294967296; return seed / 4294967296; }; return Array.from({ length: n }, () => { const x = rng() * 8 + 1; const y = slope * x + intercept + (rng() - 0.5) * noise; return { x, y }; }); } export function ScatterFit({ width = 720, height = 460, }: { width?: number; height?: number; }) { const padX = 60; const padY = 40; const points = useMemo(() => genPoints(40, 0.6, 1.2, 1.4), []); const [w, setW] = useState(0.6); const [b, setB] = useState(1.2); const xMin = 0; const xMax = 10; const yMin = 0; const yMax = 9; const sx = (x: number) => padX + ((x - xMin) / (xMax - xMin)) * (width - padX * 2); const sy = (y: number) => height - padY - ((y - yMin) / (yMax - yMin)) * (height - padY * 2); const yhat = (x: number) => w * x + b; const mse = points.reduce((acc, p) => acc + (p.y - yhat(p.x)) ** 2, 0) / points.length; return (