{"spec_id":"qq-basic","library":"highcharts","language":"javascript","code":"// anyplot.ai\n// qq-basic: Basic Q-Q Plot\n// Library: highcharts 12.6.0 | JavaScript 22.23.1\n// Quality: 92/100 | Created: 2026-07-24\n\n//# anyplot-orientation: square\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Website page-load times: right-skewed (lognormal-ish), a classic case where\n// a normality assumption needs checking before applying parametric tests.\nfunction lcg(seed) {\n  let state = seed;\n  return function () {\n    state = (state * 1664525 + 1013904223) % 4294967296;\n    return state / 4294967296;\n  };\n}\nconst rand = lcg(42);\n\nfunction randNormal() {\n  const u1 = Math.max(rand(), 1e-9);\n  const u2 = rand();\n  return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);\n}\n\n// Inverse standard normal CDF (Acklam's rational approximation).\nfunction invNorm(p) {\n  const a = [-3.969683028665376e1, 2.209460984245205e2, -2.759285104469687e2,\n             1.383577518672690e2, -3.066479806614716e1, 2.506628277459239e0];\n  const b = [-5.447609879822406e1, 1.615858368580409e2, -1.556989798598866e2,\n             6.680131188771972e1, -1.328068155288572e1];\n  const c = [-7.784894002430293e-3, -3.223964580411365e-1, -2.400758277161838e0,\n             -2.549732539343734e0, 4.374664141464968e0, 2.938163982698783e0];\n  const d = [7.784695709041462e-3, 3.224671290700398e-1, 2.445134137142996e0,\n             3.754408661907416e0];\n  const pLow = 0.02425;\n  const pHigh = 1 - pLow;\n  if (p < pLow) {\n    const q = Math.sqrt(-2 * Math.log(p));\n    return (((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) /\n           ((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1);\n  }\n  if (p <= pHigh) {\n    const q = p - 0.5;\n    const r = q * q;\n    return (((((a[0] * r + a[1]) * r + a[2]) * r + a[3]) * r + a[4]) * r + a[5]) * q /\n           (((((b[0] * r + b[1]) * r + b[2]) * r + b[3]) * r + b[4]) * r + 1);\n  }\n  const q = Math.sqrt(-2 * Math.log(1 - p));\n  return -(((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) /\n          ((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1);\n}\n\nconst n = 150;\nconst muLog = -0.35;\nconst sigmaLog = 0.45;\nconst loadTimes = [];\nfor (let i = 0; i < n; i++) {\n  loadTimes.push(Math.exp(muLog + sigmaLog * randNormal()));\n}\nloadTimes.sort((a, b) => a - b);\n\nconst mean = loadTimes.reduce((s, v) => s + v, 0) / n;\nconst variance = loadTimes.reduce((s, v) => s + (v - mean) ** 2, 0) / (n - 1);\nconst std = Math.sqrt(variance);\n\n// Standardized sample quantiles vs. theoretical normal quantiles — under a\n// perfect normal fit, points fall on the y = x diagonal.\nconst points = loadTimes.map((value, i) => {\n  const p = (i + 0.5) / n;\n  const theoreticalQ = invNorm(p);\n  const sampleQ = (value - mean) / std;\n  return [theoreticalQ, sampleQ];\n});\n\nconst allValues = points.flat();\nconst lo = Math.min(...allValues);\nconst hi = Math.max(...allValues);\nconst pad = (hi - lo) * 0.08;\nconst axisMin = lo - pad;\nconst axisMax = hi + pad;\n\n// Points beyond this theoretical quantile are the \"tail\" where the sample\n// visibly bows away from the reference line. They get a larger, fully-opaque\n// marker; the tightly-packed mid-section gets a smaller, translucent one so\n// the S-curve deviation reads clearly instead of the middle overlapping.\nconst tailThreshold = 1.15;\nfunction withAlpha(hex, alpha) {\n  const r = parseInt(hex.slice(1, 3), 16);\n  const g = parseInt(hex.slice(3, 5), 16);\n  const b = parseInt(hex.slice(5, 7), 16);\n  return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\nconst sampleColor = t.palette[0];\nconst midColor = withAlpha(sampleColor, 0.55);\nconst scatterData = points.map(([x, y]) => ({\n  x,\n  y,\n  marker: Math.abs(x) > tailThreshold\n    ? { radius: 5.5, fillColor: sampleColor }\n    : { radius: 3.5, fillColor: midColor },\n}));\n\n// --- Chart -------------------------------------------------------------------\nHighcharts.chart(\"container\", {\n  chart: { type: \"scatter\", backgroundColor: \"transparent\", animation: false,\n           style: { fontFamily: \"inherit\" } },\n  credits: { enabled: false },\n  colors: t.palette,\n  title: { text: \"qq-basic · javascript · highcharts · anyplot.ai\",\n           style: { color: t.ink, fontSize: \"22px\", fontWeight: \"600\" } },\n  subtitle: { text: \"Page load times vs. normal distribution\",\n              style: { color: t.inkSoft, fontSize: \"14px\" } },\n  xAxis: { title: { text: \"Theoretical Quantiles\",\n                     style: { color: t.inkSoft, fontSize: \"16px\" } },\n           min: axisMin, max: axisMax,\n           lineColor: t.inkSoft, tickColor: t.inkSoft, gridLineColor: t.grid,\n           gridLineWidth: 1,\n           labels: { style: { color: t.inkSoft, fontSize: \"14px\" } },\n           plotBands: [\n             { from: axisMin, to: -tailThreshold, color: withAlpha(sampleColor, 0.06),\n               label: { text: \"Deviating tail\", align: \"left\", x: 6, y: 14,\n                        style: { color: t.inkSoft, fontSize: \"11px\", fontStyle: \"italic\" } } },\n             { from: tailThreshold, to: axisMax, color: withAlpha(sampleColor, 0.06),\n               label: { text: \"Deviating tail\", align: \"right\", x: -6, y: 14,\n                        style: { color: t.inkSoft, fontSize: \"11px\", fontStyle: \"italic\" } } },\n           ] },\n  yAxis: { title: { text: \"Sample Quantiles (z-score)\",\n                     style: { color: t.inkSoft, fontSize: \"16px\" } },\n           min: axisMin, max: axisMax,\n           lineColor: t.inkSoft, tickColor: t.inkSoft, gridLineColor: t.grid,\n           labels: { style: { color: t.inkSoft, fontSize: \"14px\" } } },\n  legend: { itemStyle: { color: t.inkSoft, fontSize: \"14px\" },\n            itemHoverStyle: { color: t.ink } },\n  plotOptions: { series: { animation: false } },\n  series: [\n    {\n      name: \"Reference (y = x)\",\n      type: \"line\",\n      data: [[axisMin, axisMin], [axisMax, axisMax]],\n      color: t.ink,\n      dashStyle: \"Dash\",\n      lineWidth: 2,\n      marker: { enabled: false },\n      enableMouseTracking: false,\n    },\n    {\n      name: \"Sample\",\n      type: \"scatter\",\n      data: scatterData,\n      color: sampleColor,\n      marker: { radius: 3.5, fillColor: midColor },\n    },\n  ],\n});\n"}