{"spec_id":"line-load-duration","library":"muix","language":"javascript","code":"// anyplot.ai\n// line-load-duration: Load Duration Curve for Energy Systems\n// Library: muix 7.29.1 | JavaScript 22.22.3\n// Quality: 88/100 | Created: 2026-06-10\nimport { LineChart } from \"@mui/x-charts/LineChart\";\nimport { ChartsReferenceLine } from \"@mui/x-charts/ChartsReferenceLine\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (deterministic, no RNG) -------------------------------------------\n// 8,760 hours sorted descending: peak ≈ 1200 MW → base ≈ 400 MW\nconst N_HOURS = 8760;\nconst hours = Array.from({ length: N_HOURS }, (_, i) => i);\n\n// Power-law decay gives realistic LDC shape (steep peak drop, flat base tail)\nconst loadMW = hours.map(h => 400 + 800 * Math.pow(1 - h / (N_HOURS - 1), 0.65));\n\n// Decompose into three stacked bands\nconst baseData  = hours.map(() => 400);\nconst interData = hours.map(h => Math.min(Math.max(loadMW[h] - 400, 0), 400));\nconst peakData  = hours.map(h => Math.max(loadMW[h] - 800, 0));\n\nconst totalEnergyTWh = (loadMW.reduce((s, v) => s + v, 0) / 1e6).toFixed(2);\n\nconst TITLE = \"line-load-duration · javascript · muix · anyplot.ai\";\n\n// Chart margins — declared once, shared by LineChart and the annotation overlay\nconst MARGIN = { top: 20, right: 130, bottom: 72, left: 80 };\nconst Y_MAX = 1280;\nconst X_MAX = N_HOURS - 1;\n\n// Convert data-space coordinates to CSS px within the chart container\nfunction toPixel(x, y, cW, cH) {\n  const dw = cW - MARGIN.left - MARGIN.right;\n  const dh = cH - MARGIN.top - MARGIN.bottom;\n  return {\n    left: MARGIN.left + (x / X_MAX) * dw,\n    top:  MARGIN.top  + (1 - y / Y_MAX) * dh,\n  };\n}\n\n// --- Component (default-exported; harness mounts it with no props) -----------\nexport default function Chart() {\n  const W = window.ANYPLOT_SIZE.width;\n  const H = window.ANYPLOT_SIZE.height;\n\n  const HEADER_H = 50;\n  const FOOTER_H = 28;\n  const PAD_TOP  = 20;\n  const PAD_BOT  = 12;\n  const PAD_H    = 48;\n  const chartW   = W - PAD_H;\n  const chartH   = H - PAD_TOP - HEADER_H - FOOTER_H - PAD_BOT;\n\n  // Labels placed at representative (x, y) data coords inside each band\n  // Base band: 0–400 MW (y=200 at x=7000 → far-right flat region)\n  // Intermediate band: 400–800 MW (y=600 at x=5000 → saturated mid-band)\n  // Peak band: >800 MW (y=950 at x=1500 → steep left portion)\n  const bandLabels = [\n    { x: 7000, y: 200, text: \"Base Load\"    },\n    { x: 5000, y: 600, text: \"Intermediate\" },\n    { x: 1500, y: 950, text: \"Peak Load\"    },\n  ];\n\n  return (\n    <div style={{\n      width: W,\n      height: H,\n      backgroundColor: t.pageBg,\n      display: \"flex\",\n      flexDirection: \"column\",\n      padding: `${PAD_TOP}px 24px ${PAD_BOT}px`,\n      boxSizing: \"border-box\",\n      fontFamily: \"sans-serif\",\n    }}>\n      {/* Chart title */}\n      <div style={{\n        color: t.ink,\n        fontSize: 22,\n        fontWeight: 600,\n        lineHeight: \"30px\",\n        marginBottom: 8,\n        flexShrink: 0,\n      }}>\n        {TITLE}\n      </div>\n\n      {/* Stacked-area chart with region-label overlay */}\n      <div style={{ position: \"relative\", width: chartW, height: chartH, flexShrink: 0 }}>\n        <LineChart\n          width={chartW}\n          height={chartH}\n          margin={MARGIN}\n          skipAnimation\n          grid={{ horizontal: true }}\n          colors={[t.palette[0], t.palette[1], t.palette[2]]}\n          xAxis={[{\n            data: hours,\n            label: \"Hours in a Year (sorted by descending load)\",\n            min: 0,\n            max: X_MAX,\n            tickInterval: [0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000],\n            tickLabelStyle: { fontSize: 13 },\n          }]}\n          yAxis={[{\n            label: \"Power Demand (MW)\",\n            min: 0,\n            max: Y_MAX,\n            tickLabelStyle: { fontSize: 13 },\n          }]}\n          series={[\n            {\n              data: baseData,\n              area: true,\n              stack: \"load\",\n              label: \"Base Load (< 400 MW)\",\n              showMark: false,\n              curve: \"linear\",\n            },\n            {\n              data: interData,\n              area: true,\n              stack: \"load\",\n              label: \"Intermediate Load (400–800 MW)\",\n              showMark: false,\n              curve: \"linear\",\n            },\n            {\n              data: peakData,\n              area: true,\n              stack: \"load\",\n              label: \"Peak Load (> 800 MW)\",\n              showMark: false,\n              curve: \"linear\",\n            },\n          ]}\n          sx={{\n            \"& .MuiLineElement-root\":  { strokeWidth: 0 },\n            \"& .MuiAreaElement-root\":  { fillOpacity: 0.82 },\n            \"& .MuiChartsGrid-line\":   { stroke: t.grid, strokeOpacity: 0.5, strokeDasharray: \"4 3\" },\n            \"& .MuiChartsAxis-line\":   { stroke: t.inkSoft, strokeOpacity: 0.3 },\n            \"& .MuiChartsAxis-tick\":   { stroke: t.inkSoft, strokeOpacity: 0.3 },\n          }}\n          slotProps={{\n            legend: {\n              position: { vertical: \"top\", horizontal: \"right\" },\n              itemMarkWidth: 14,\n              itemMarkHeight: 14,\n              markGap: 6,\n              itemGap: 12,\n            },\n          }}\n        >\n          {/* Horizontal dashed lines at capacity tier boundaries */}\n          <ChartsReferenceLine\n            y={400}\n            label=\"Base capacity: 400 MW\"\n            lineStyle={{ stroke: t.inkSoft, strokeDasharray: \"8 4\", strokeWidth: 1.5 }}\n            labelStyle={{ fontSize: 12, fill: t.inkSoft }}\n            labelAlign=\"end\"\n          />\n          <ChartsReferenceLine\n            y={800}\n            label=\"Intermediate capacity: 800 MW\"\n            lineStyle={{ stroke: t.inkSoft, strokeDasharray: \"8 4\", strokeWidth: 1.5 }}\n            labelStyle={{ fontSize: 12, fill: t.inkSoft }}\n            labelAlign=\"end\"\n          />\n        </LineChart>\n\n        {/* Direct in-band region labels — spec requires labeling each band on the plot */}\n        {bandLabels.map(({ x, y, text }) => {\n          const pos = toPixel(x, y, chartW, chartH);\n          return (\n            <div\n              key={text}\n              style={{\n                position: \"absolute\",\n                left: pos.left,\n                top: pos.top,\n                transform: \"translate(-50%, -50%)\",\n                color: t.ink,\n                fontSize: 15,\n                fontWeight: 700,\n                fontFamily: \"sans-serif\",\n                pointerEvents: \"none\",\n                textShadow: `0 0 8px ${t.pageBg}, 0 0 8px ${t.pageBg}`,\n                letterSpacing: \"0.04em\",\n                whiteSpace: \"nowrap\",\n              }}\n            >\n              {text}\n            </div>\n          );\n        })}\n      </div>\n\n      {/* Total energy annotation */}\n      <div style={{\n        color: t.inkSoft,\n        fontSize: 14,\n        textAlign: \"center\",\n        marginTop: 4,\n        flexShrink: 0,\n        fontFamily: \"sans-serif\",\n      }}>\n        Total annual energy consumption: {totalEnergyTWh} TWh\n      </div>\n    </div>\n  );\n}\n"}