{"spec_id":"curve-oc","library":"muix","language":"javascript","code":"// anyplot.ai\n// curve-oc: Operating Characteristic (OC) Curve\n// Library: muix 7.29.1 | JavaScript 22.22.3\n// Quality: 85/100 | Created: 2026-06-20\n\nimport { LineChart } from \"@mui/x-charts/LineChart\";\nimport { ChartsReferenceLine } from \"@mui/x-charts/ChartsReferenceLine\";\nimport Box from \"@mui/material/Box\";\nimport Typography from \"@mui/material/Typography\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data -------------------------------------------------------------------\n\n// Binomial coefficient (n choose k)\nfunction binomCoeff(n: number, k: number): number {\n  if (k < 0 || k > n) return 0;\n  if (k === 0 || k === n) return 1;\n  let r = 1;\n  for (let i = 0; i < k; i++) r = (r * (n - i)) / (i + 1);\n  return r;\n}\n\n// P(accept | n, c, p) = P(X ≤ c) where X ~ Binomial(n, p)\nfunction pAccept(n: number, c: number, p: number): number {\n  let prob = 0;\n  for (let k = 0; k <= c; k++) {\n    prob += binomCoeff(n, k) * Math.pow(p, k) * Math.pow(1 - p, n - k);\n  }\n  return Math.min(1, Math.max(0, prob));\n}\n\n// x-axis: fraction defective 0–15%, 200 points for a smooth S-curve\nconst N_POINTS = 200;\nconst P_MAX = 0.15;\nconst pValues = Array.from({ length: N_POINTS }, (_, i) => (i * P_MAX) / (N_POINTS - 1));\n\n// Three sampling plans to show discrimination power with increasing n\nconst plans: [number, number, string][] = [\n  [50,  1, \"n=50 c=1\"],\n  [100, 2, \"n=100 c=2\"],\n  [200, 4, \"n=200 c=4\"],\n];\n\nconst series = plans.map(([n, c, label]) => ({\n  data: pValues.map((p) => pAccept(n, c, p)),\n  label,\n  showMark: false,\n  curve: \"catmullRom\" as const,\n}));\n\n// Quality thresholds\nconst AQL  = 0.02;  // Acceptable Quality Level — producer's risk reference (α = 5%)\nconst LTPD = 0.10;  // Lot Tolerance Percent Defective — consumer's risk reference (β = 10%)\n\nconst TITLE_HEIGHT = 60;\n\n// --- Chart ------------------------------------------------------------------\n\nexport default function Chart() {\n  const { width, height } = window.ANYPLOT_SIZE;\n\n  return (\n    <Box\n      sx={{\n        width,\n        height,\n        display: \"flex\",\n        flexDirection: \"column\",\n        paddingTop: \"20px\",\n      }}\n    >\n      <Typography\n        sx={{\n          color: t.ink,\n          fontSize: 22,\n          fontWeight: 500,\n          textAlign: \"center\",\n          lineHeight: 1.2,\n        }}\n      >\n        curve-oc · javascript · muix · anyplot.ai\n      </Typography>\n      <LineChart\n        width={width}\n        height={height - TITLE_HEIGHT}\n        skipAnimation\n        colors={t.palette}\n        xAxis={[{\n          data: pValues,\n          scaleType: \"linear\",\n          valueFormatter: (v: number) => `${(v * 100).toFixed(0)}%`,\n          label: \"Fraction Defective (p)\",\n          min: 0,\n          max: P_MAX,\n          tickInterval: [0, 0.02, 0.04, 0.06, 0.08, 0.10, 0.12, 0.14],\n        }]}\n        yAxis={[{\n          label: \"Probability of Acceptance\",\n          min: 0,\n          max: 1,\n          valueFormatter: (v: number) => `${(v * 100).toFixed(0)}%`,\n        }]}\n        series={series}\n        margin={{ left: 90, right: 60, top: 20, bottom: 80 }}\n        sx={{\n          \"& .MuiChartsAxis-tickLabel\": { fontSize: \"14px\" },\n          \"& .MuiChartsAxis-label\": { fontSize: \"16px\" },\n          \"& .MuiChartsLegend-label\": { fontSize: \"14px\" },\n          \"& .MuiLineElement-root\": { strokeWidth: 3 },\n        }}\n      >\n        <ChartsReferenceLine\n          x={AQL}\n          label=\"AQL (2%)\"\n          labelAlign=\"end\"\n          lineStyle={{ stroke: t.inkSoft, strokeDasharray: \"6 4\", strokeWidth: 1.5 }}\n          labelStyle={{ fill: t.inkSoft, fontSize: 13 }}\n        />\n        <ChartsReferenceLine\n          x={LTPD}\n          label=\"LTPD (10%)\"\n          labelAlign=\"end\"\n          lineStyle={{ stroke: t.inkSoft, strokeDasharray: \"6 4\", strokeWidth: 1.5 }}\n          labelStyle={{ fill: t.inkSoft, fontSize: 13 }}\n        />\n        <ChartsReferenceLine\n          y={0.95}\n          label=\"1−α = 0.95\"\n          labelAlign=\"end\"\n          lineStyle={{ stroke: t.inkSoft, strokeDasharray: \"3 3\", strokeWidth: 1 }}\n          labelStyle={{ fill: t.inkSoft, fontSize: 12 }}\n        />\n        <ChartsReferenceLine\n          y={0.10}\n          label=\"β = 0.10\"\n          labelAlign=\"end\"\n          lineStyle={{ stroke: t.inkSoft, strokeDasharray: \"3 3\", strokeWidth: 1 }}\n          labelStyle={{ fill: t.inkSoft, fontSize: 12 }}\n        />\n      </LineChart>\n    </Box>\n  );\n}\n"}