{"spec_id":"histogram-cumulative","library":"highcharts","language":"javascript","code":"// anyplot.ai\n// histogram-cumulative: Cumulative Histogram\n// Library: highcharts 12.6.0 | JavaScript 22.23.2\n// Quality: 84/100 | Created: 2026-09-05\n\n//# anyplot-orientation: landscape\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ---------------------------------------\n// Fixed-seed LCG — the browser has no seeded RNG, so this stands in for\n// np.random.seed(42) to keep the sample reproducible across renders.\nlet seed = 42;\nfunction lcgRandom() {\n  seed = (seed * 1664525 + 1013904223) % 4294967296;\n  return seed / 4294967296;\n}\nfunction randomNormal(mean, std) {\n  const u1 = lcgRandom() || 1e-9;\n  const u2 = lcgRandom();\n  const z = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);\n  return mean + z * std;\n}\n\nconst sampleSize = 600;\nconst deliveryTimes = Array.from({ length: sampleSize }, () =>\n  Math.max(5, randomNormal(38, 11))\n);\n\nconst binCount = 18;\nconst minValue = Math.min(...deliveryTimes);\nconst maxValue = Math.max(...deliveryTimes);\nconst binWidth = (maxValue - minValue) / binCount;\n\nconst binCounts = new Array(binCount).fill(0);\ndeliveryTimes.forEach((value) => {\n  const index = Math.min(binCount - 1, Math.floor((value - minValue) / binWidth));\n  binCounts[index] += 1;\n});\n\nlet running = 0;\nconst cumulativeData = binCounts.map((count, i) => {\n  running += count;\n  const binEdge = minValue + (i + 1) * binWidth;\n  return [Math.round(binEdge * 10) / 10, running];\n});\n// Anchor the curve at the first bin's lower edge so the ogive starts at zero.\ncumulativeData.unshift([Math.round(minValue * 10) / 10, 0]);\n\nconst firstX = cumulativeData[0][0];\nconst lastX = cumulativeData[cumulativeData.length - 1][0];\n\n// 90th percentile delivery time — the spec's VaR/quantile use case, called\n// out as a distinctive plotLines marker.\nconst sortedTimes = [...deliveryTimes].sort((a, b) => a - b);\nconst p90 = sortedTimes[Math.floor(0.9 * (sortedTimes.length - 1))];\n\n// --- Chart -----------------------------------------------------------------\nHighcharts.chart(\"container\", {\n  chart: {\n    type: \"area\",\n    backgroundColor: \"transparent\",\n    animation: false,\n    style: { fontFamily: \"inherit\" },\n  },\n  credits: { enabled: false },\n  colors: t.palette,\n  title: {\n    text: \"histogram-cumulative · javascript · highcharts · anyplot.ai\",\n    style: { color: t.ink, fontSize: \"22px\", fontWeight: \"600\" },\n  },\n  xAxis: {\n    title: { text: \"Delivery Time (minutes)\", style: { color: t.inkSoft, fontSize: \"16px\" } },\n    lineColor: t.inkSoft,\n    tickColor: t.inkSoft,\n    gridLineColor: t.grid,\n    labels: { style: { color: t.inkSoft, fontSize: \"14px\" } },\n    min: firstX,\n    max: lastX,\n    plotLines: [\n      {\n        value: p90,\n        color: t.amber,\n        width: 2,\n        dashStyle: \"Dash\",\n        zIndex: 5,\n        label: {\n          text: `P90: ${p90.toFixed(1)} min`,\n          style: { color: t.amber, fontSize: \"13px\", fontWeight: \"600\" },\n          align: \"left\",\n          x: 6,\n          y: 16,\n        },\n      },\n    ],\n  },\n  yAxis: {\n    title: { text: \"Cumulative Deliveries\", style: { color: t.inkSoft, fontSize: \"16px\" } },\n    gridLineColor: t.grid,\n    min: 0,\n    max: sampleSize,\n    labels: { style: { color: t.inkSoft, fontSize: \"14px\" } },\n  },\n  legend: { enabled: false },\n  tooltip: {\n    backgroundColor: t.elevatedBg,\n    borderColor: t.inkSoft,\n    style: { color: t.ink, fontSize: \"14px\" },\n    formatter() {\n      const pct = ((this.y / sampleSize) * 100).toFixed(1);\n      return `<b>&le; ${this.x} min</b><br/>Cumulative: ${this.y} deliveries (${pct}%)`;\n    },\n  },\n  plotOptions: {\n    series: { animation: false },\n    area: {\n      step: \"left\",\n      lineWidth: 2.5,\n      fillOpacity: 0.25,\n      marker: { enabled: false },\n    },\n  },\n  series: [\n    {\n      name: \"Cumulative deliveries\",\n      data: cumulativeData,\n      color: t.palette[0],\n    },\n  ],\n});\n"}