{"spec_id":"histogram-stepwise","library":"echarts","language":"javascript","code":"// anyplot.ai\n// histogram-stepwise: Step Histogram\n// Library: echarts 6.1.0 | JavaScript 22.23.2\n// Quality: 90/100 | Created: 2026-09-05\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic LCG) -----------------------------------\n// Reaction times (ms) from a simulated cognitive test, n=1500. Modeled as an\n// ex-Gaussian (normal + exponential tail) — the standard shape for human\n// reaction-time data: a sharp rise near the mode and a long right tail.\nfunction lcg(seed) {\n  let state = seed;\n  return () => {\n    state = (state * 1664525 + 1013904223) % 4294967296;\n    return state / 4294967296;\n  };\n}\nconst rand = lcg(42);\n\nfunction randNormal(mean, std) {\n  const u1 = rand() || 1e-9;\n  const u2 = rand();\n  const z = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);\n  return mean + z * std;\n}\n\nfunction randExponential(mean) {\n  return -mean * Math.log(1 - rand());\n}\n\nconst reactionTimes = [];\nfor (let i = 0; i < 1500; i++) {\n  reactionTimes.push(randNormal(230, 28) + randExponential(55));\n}\n\n// --- Binning ----------------------------------------------------------------\nconst binCount = 24;\nconst minVal = Math.min(...reactionTimes);\nconst maxVal = Math.max(...reactionTimes);\nconst binWidth = (maxVal - minVal) / binCount;\n\nconst counts = new Array(binCount).fill(0);\nfor (const v of reactionTimes) {\n  let idx = Math.floor((v - minVal) / binWidth);\n  if (idx >= binCount) idx = binCount - 1;\n  counts[idx]++;\n}\n\nconst binLeftEdges = Array.from({ length: binCount }, (_, i) => minVal + i * binWidth);\n\nlet peakIdx = 0;\nfor (let i = 1; i < binCount; i++) {\n  if (counts[i] > counts[peakIdx]) peakIdx = i;\n}\nconst peakCenter = binLeftEdges[peakIdx] + binWidth / 2;\n\n// Step-line points: ECharts' native `step: \"end\"` draws the horizontal\n// segment across each bin and the vertical segment between bins; closing the\n// ends to zero makes the outline read as a step function.\nconst stepData = [\n  [minVal, 0],\n  ...binLeftEdges.map((x, i) => [x, counts[i]]),\n  [maxVal, 0],\n];\n\n// --- Init ---------------------------------------------------------------\nconst chart = echarts.init(document.getElementById(\"container\"));\n\n// --- Option -----------------------------------------------------------------\nchart.setOption({\n  animation: false,\n  color: t.palette,\n  backgroundColor: \"transparent\",\n  title: {\n    text: \"histogram-stepwise · javascript · echarts · anyplot.ai\",\n    left: \"center\",\n    textStyle: { color: t.ink, fontSize: 22, fontWeight: 500 },\n  },\n  grid: { left: 90, right: 60, top: 90, bottom: 90 },\n  xAxis: {\n    type: \"value\",\n    name: \"Reaction Time (ms)\",\n    nameLocation: \"middle\",\n    nameGap: 40,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    min: Math.floor(minVal / 10) * 10,\n    max: Math.ceil(maxVal / 10) * 10,\n    axisLabel: { color: t.inkSoft, fontSize: 14 },\n    axisLine: { lineStyle: { color: t.inkSoft } },\n    axisTick: { show: false },\n    splitLine: { show: false },\n  },\n  yAxis: {\n    type: \"value\",\n    name: \"Count\",\n    nameLocation: \"middle\",\n    nameGap: 60,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    min: 0,\n    axisLabel: { color: t.inkSoft, fontSize: 14 },\n    axisLine: { show: false },\n    axisTick: { show: false },\n    splitLine: { lineStyle: { color: t.grid } },\n  },\n  series: [\n    {\n      type: \"line\",\n      step: \"end\",\n      data: stepData,\n      showSymbol: false,\n      lineStyle: { color: t.palette[0], width: 3 },\n      emphasis: { disabled: true },\n      markLine: {\n        symbol: \"none\",\n        silent: true,\n        lineStyle: { color: t.inkSoft, type: \"dashed\", width: 1.5 },\n        label: {\n          formatter: `Peak: ${Math.round(peakCenter)} ms`,\n          color: t.ink,\n          fontSize: 13,\n          position: \"insideEndTop\",\n        },\n        data: [{ xAxis: peakCenter }],\n      },\n    },\n  ],\n});\n"}