{"spec_id":"ecdf-basic","library":"muix","language":"javascript","code":"// anyplot.ai\n// ecdf-basic: Basic ECDF Plot\n// Library: muix 7.29.1 | JavaScript 22.22.3\n// Quality: 88/100 | Created: 2026-06-25\n//# anyplot-orientation: landscape\n// anyplot.ai\n// ecdf-basic: Basic ECDF Plot\n// Library: MUI X Charts | React | Node 22\n// License: @mui/x-charts — MIT (community). Pro/Premium are out of scope.\n// Quality: pending | Created: 2026-06-25\n\nimport { LineChart } from \"@mui/x-charts/LineChart\";\nimport { ChartsReferenceLine } from \"@mui/x-charts/ChartsReferenceLine\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// Seeded LCG for deterministic data generation (no seeded RNG in browser)\nlet seed = 42;\nfunction rand() {\n  seed = (Math.imul(1664525, seed) + 1013904223) | 0;\n  return (seed >>> 0) / 4294967296;\n}\nfunction randn() {\n  const u = Math.max(rand(), 1e-10);\n  return Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * rand());\n}\nfunction normalSorted(mean, std, n) {\n  return Array.from({ length: n }, () => mean + std * randn()).sort((a, b) => a - b);\n}\n\n// Exam scores from two teaching methods, 80 students each\nconst N = 80;\nconst traditional = normalSorted(72, 12, N);   // Traditional instruction: μ=72, σ=12\nconst projectBased = normalSorted(78, 10, N);  // Project-based learning:  μ=78, σ=10\n\n// Merge and sort all x-values to build a shared axis for both ECDF curves\nconst allX = [...traditional, ...projectBased].sort((a, b) => a - b);\n\n// ECDF: fraction of observations ≤ x evaluated at every merged x-value\nfunction computeEcdf(sorted, xValues) {\n  let j = 0;\n  return xValues.map((x) => {\n    while (j < sorted.length && sorted[j] <= x) j++;\n    return j / sorted.length;\n  });\n}\n\nconst ecdfTrad = computeEcdf(traditional, allX);\nconst ecdfProj = computeEcdf(projectBased, allX);\n\nconst TITLE_H = 52;\n\nexport default function Chart() {\n  const W = window.ANYPLOT_SIZE.width;\n  const H = window.ANYPLOT_SIZE.height;\n\n  return (\n    <div\n      style={{\n        width: W,\n        height: H,\n        display: \"flex\",\n        flexDirection: \"column\",\n        backgroundColor: t.pageBg,\n      }}\n    >\n      <div\n        style={{\n          padding: \"18px 36px 0\",\n          fontSize: 22,\n          fontWeight: 600,\n          color: t.ink,\n          height: TITLE_H,\n          boxSizing: \"border-box\",\n          fontFamily: \"sans-serif\",\n          letterSpacing: \"-0.3px\",\n        }}\n      >\n        ecdf-basic · javascript · muix · anyplot.ai\n      </div>\n      <LineChart\n        width={W}\n        height={H - TITLE_H}\n        skipAnimation\n        series={[\n          {\n            data: ecdfTrad,\n            curve: \"stepAfter\",\n            label: \"Traditional Teaching\",\n            showMark: false,\n            color: t.palette[0],\n          },\n          {\n            data: ecdfProj,\n            curve: \"stepAfter\",\n            label: \"Project-based Learning\",\n            showMark: false,\n            color: t.palette[1],\n          },\n        ]}\n        xAxis={[\n          {\n            data: allX,\n            label: \"Exam Score\",\n            tickMinStep: 10,\n            valueFormatter: (v) => String(Math.round(v)),\n            tickLabelStyle: { fontSize: 14 },\n            labelStyle: { fontSize: 16 },\n          },\n        ]}\n        yAxis={[\n          {\n            min: 0,\n            max: 1,\n            label: \"Cumulative Proportion\",\n            tickMinStep: 0.25,\n            valueFormatter: (v) => `${Math.round(v * 100)}%`,\n            tickLabelStyle: { fontSize: 14 },\n            labelStyle: { fontSize: 16 },\n          },\n        ]}\n        grid={{ horizontal: true }}\n        sx={{\n          \"& .MuiLineElement-root\": { strokeWidth: 2.5 },\n          \"& .MuiChartsGrid-line\": { strokeOpacity: 0.15 },\n          \"& .MuiChartsAxis-line\": { strokeOpacity: 0.3 },\n          \"& .MuiChartsAxis-tick\": { strokeOpacity: 0.3 },\n        }}\n        margin={{ left: 90, right: 36, top: 20, bottom: 100 }}\n      >\n        <ChartsReferenceLine\n          y={0.5}\n          label=\"Median (50th)\"\n          labelAlign=\"end\"\n          lineStyle={{\n            stroke: t.inkSoft,\n            strokeDasharray: \"6 3\",\n            strokeWidth: 1.5,\n          }}\n          labelStyle={{ fontSize: 13, fill: t.inkSoft }}\n        />\n      </LineChart>\n    </div>\n  );\n}\n"}