{"spec_id":"histogram-capability","library":"highcharts","language":"javascript","code":"// anyplot.ai\n// histogram-capability: Process Capability Plot with Specification Limits\n// Library: highcharts 12.6.0 | JavaScript 22.22.3\n// Quality: 88/100 | Created: 2026-06-20\n\n//# anyplot-orientation: landscape\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Deterministic data generation (LCG + Box-Muller) ----------------------\nlet seed = 42;\nfunction lcgNext() {\n    seed = (Math.imul(1664525, seed) + 1013904223) >>> 0;\n    return seed / 4294967296;\n}\nfunction randn() {\n    const u1 = Math.max(lcgNext(), 1e-15);\n    const u2 = lcgNext();\n    return Math.sqrt(-2.0 * Math.log(u1)) * Math.cos(2.0 * Math.PI * u2);\n}\n\n// Process parameters — shaft diameter (mm) quality control\nconst LSL = 9.95;\nconst USL = 10.05;\nconst TARGET = 10.00;\nconst TRUE_MEAN = 10.003;\nconst TRUE_SIGMA = 0.013;\nconst N = 200;\n\nconst measurements = Array.from({ length: N }, () => TRUE_MEAN + TRUE_SIGMA * randn());\n\n// Sample statistics\nconst sampleMean = measurements.reduce((a, b) => a + b, 0) / N;\nconst sampleVariance = measurements.reduce((s, x) => s + (x - sampleMean) ** 2, 0) / (N - 1);\nconst sampleSigma = Math.sqrt(sampleVariance);\n\n// Process capability indices\nconst cp = (USL - LSL) / (6 * sampleSigma);\nconst cpk = Math.min(\n    (USL - sampleMean) / (3 * sampleSigma),\n    (sampleMean - LSL) / (3 * sampleSigma)\n);\n\n// --- Histogram bins --------------------------------------------------------\nconst BIN_MIN = 9.92;\nconst BIN_MAX = 10.08;\nconst N_BINS = 20;\nconst BIN_WIDTH = (BIN_MAX - BIN_MIN) / N_BINS;\n\nconst binCounts = new Array(N_BINS).fill(0);\nmeasurements.forEach(m => {\n    const i = Math.floor((m - BIN_MIN) / BIN_WIDTH);\n    if (i >= 0 && i < N_BINS) binCounts[i]++;\n});\n\nconst histData = binCounts.map((count, i) => ({\n    x: BIN_MIN + (i + 0.5) * BIN_WIDTH,\n    y: count\n}));\n\n// --- Normal distribution curve (scaled to count space) ---------------------\nfunction normalPDF(x, mu, sigma) {\n    return Math.exp(-0.5 * ((x - mu) / sigma) ** 2) / (sigma * Math.sqrt(2 * Math.PI));\n}\n\nconst CURVE_POINTS = 120;\nconst normalCurveData = Array.from({ length: CURVE_POINTS }, (_, i) => {\n    const x = BIN_MIN + (i / (CURVE_POINTS - 1)) * (BIN_MAX - BIN_MIN);\n    const y = N * BIN_WIDTH * normalPDF(x, sampleMean, sampleSigma);\n    return [x, y];\n});\n\n// --- Chart -----------------------------------------------------------------\nconst chart = Highcharts.chart(\"container\", {\n    chart: {\n        type: \"column\",\n        backgroundColor: \"transparent\",\n        animation: false,\n        style: { fontFamily: \"inherit\" }\n    },\n    credits: { enabled: false },\n    colors: t.palette,\n    title: {\n        text: \"histogram-capability · javascript · highcharts · anyplot.ai\",\n        style: { color: t.ink, fontSize: \"22px\", fontWeight: \"600\" }\n    },\n    subtitle: {\n        text: `Shaft Diameter Measurements  ·  n = ${N}  ·  Mean = ${sampleMean.toFixed(4)} mm  ·  σ = ${sampleSigma.toFixed(4)} mm`,\n        style: { color: t.inkSoft, fontSize: \"14px\" }\n    },\n    xAxis: {\n        title: {\n            text: \"Shaft Diameter (mm)\",\n            style: { color: t.inkSoft, fontSize: \"16px\" }\n        },\n        lineColor: t.inkSoft,\n        tickColor: t.inkSoft,\n        tickInterval: 0.02,\n        startOnTick: false,\n        endOnTick: false,\n        min: BIN_MIN,\n        max: BIN_MAX,\n        labels: {\n            formatter: function () { return this.value.toFixed(2); },\n            style: { color: t.inkSoft, fontSize: \"14px\" }\n        },\n        gridLineWidth: 0,\n        plotBands: [\n            {\n                from: BIN_MIN,\n                to: LSL,\n                color: \"rgba(174, 48, 48, 0.08)\",\n                zIndex: 0\n            },\n            {\n                from: USL,\n                to: BIN_MAX,\n                color: \"rgba(174, 48, 48, 0.08)\",\n                zIndex: 0\n            }\n        ],\n        plotLines: [\n            {\n                color: \"#AE3030\",\n                width: 3,\n                value: LSL,\n                dashStyle: \"Dash\",\n                zIndex: 5,\n                label: {\n                    text: \"LSL\",\n                    align: \"left\",\n                    rotation: 0,\n                    x: 5,\n                    y: 20,\n                    style: { color: \"#AE3030\", fontSize: \"13px\", fontWeight: \"bold\" }\n                }\n            },\n            {\n                color: \"#AE3030\",\n                width: 3,\n                value: USL,\n                dashStyle: \"Dash\",\n                zIndex: 5,\n                label: {\n                    text: \"USL\",\n                    align: \"right\",\n                    rotation: 0,\n                    x: -5,\n                    y: 20,\n                    style: { color: \"#AE3030\", fontSize: \"13px\", fontWeight: \"bold\" }\n                }\n            },\n            {\n                color: \"#BD8233\",\n                width: 2.5,\n                value: TARGET,\n                dashStyle: \"ShortDot\",\n                zIndex: 4,\n                label: {\n                    text: \"Target\",\n                    align: \"left\",\n                    rotation: 0,\n                    x: 5,\n                    y: 50,\n                    style: { color: \"#BD8233\", fontSize: \"13px\", fontWeight: \"bold\" }\n                }\n            }\n        ]\n    },\n    yAxis: {\n        title: {\n            text: \"Count\",\n            style: { color: t.inkSoft, fontSize: \"16px\" }\n        },\n        gridLineColor: t.grid,\n        labels: { style: { color: t.inkSoft, fontSize: \"14px\" } },\n        min: 0\n    },\n    legend: {\n        enabled: true,\n        itemStyle: { color: t.inkSoft, fontSize: \"14px\" },\n        itemHoverStyle: { color: t.ink }\n    },\n    tooltip: { enabled: false },\n    plotOptions: {\n        series: { animation: false },\n        column: {\n            pointRange: BIN_WIDTH,\n            groupPadding: 0,\n            pointPadding: 0,\n            borderWidth: 0\n        }\n    },\n    series: [\n        {\n            name: \"Measurements\",\n            type: \"column\",\n            data: histData,\n            color: t.palette[0]\n        },\n        {\n            name: \"Normal Fit\",\n            type: \"line\",\n            data: normalCurveData,\n            color: t.palette[1],\n            lineWidth: 3,\n            marker: { enabled: false }\n        }\n    ]\n});\n\n// --- Cp / Cpk annotation box in plot area ----------------------------------\nconst BOX_W = 190, BOX_H = 70, BOX_PAD = 12, BOX_R = 5;\nconst boxX = chart.plotLeft + chart.plotWidth - BOX_W - BOX_PAD;\nconst boxY = chart.plotTop + BOX_PAD;\n\nchart.renderer.rect(boxX, boxY, BOX_W, BOX_H, BOX_R).attr({\n    fill: t.elevatedBg,\n    stroke: t.inkSoft,\n    \"stroke-width\": 1,\n    zIndex: 7\n}).add();\n\nchart.renderer.text(`Cp = ${cp.toFixed(2)}`, boxX + BOX_W / 2, boxY + 28)\n    .attr({ align: \"center\", zIndex: 8 })\n    .css({ color: t.ink, fontSize: \"15px\", fontWeight: \"600\" })\n    .add();\n\nchart.renderer.text(`Cpk = ${cpk.toFixed(2)}`, boxX + BOX_W / 2, boxY + 56)\n    .attr({ align: \"center\", zIndex: 8 })\n    .css({ color: t.ink, fontSize: \"15px\", fontWeight: \"600\" })\n    .add();\n"}