{"spec_id":"qq-basic","library":"echarts","language":"javascript","code":"// anyplot.ai\n// qq-basic: Basic Q-Q Plot\n// Library: echarts 6.1.0 | JavaScript 22.23.1\n// Quality: 90/100 | Created: 2026-07-24\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Reaction-time trial data (ms), right-skewed like typical human reaction\n// times, compared against a standard normal reference distribution.\nfunction makeLcg(seed) {\n  let state = seed;\n  return function lcg() {\n    state = (state * 1103515245 + 12345) & 0x7fffffff;\n    return state / 0x7fffffff;\n  };\n}\n\nfunction standardNormal(rand) {\n  const u1 = Math.max(rand(), 1e-12);\n  const u2 = rand();\n  return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);\n}\n\n// Rational approximation of the inverse standard normal CDF (Acklam's algorithm).\nfunction invNormCdf(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 rand = makeLcg(42);\nconst n = 120;\nconst baseMs = 230;\nconst skewSigma = 0.28;\nconst reactionTimes = [];\nfor (let i = 0; i < n; i++) {\n  const z = standardNormal(rand);\n  reactionTimes.push(baseMs * Math.exp(skewSigma * z));\n}\nreactionTimes.sort((a, b) => a - b);\n\nconst mean = reactionTimes.reduce((s, v) => s + v, 0) / n;\nconst variance = reactionTimes.reduce((s, v) => s + (v - mean) ** 2, 0) / (n - 1);\nconst std = Math.sqrt(variance);\nconst standardizedSample = reactionTimes.map((v) => (v - mean) / std);\n\n// Blom's plotting positions matched to sorted standardized sample quantiles.\nconst points = standardizedSample.map((sq, i) => {\n  const p = (i + 1 - 0.5) / n;\n  return [invNormCdf(p), sq];\n});\nconst tMin = points[0][0];\nconst tMax = points[points.length - 1][0];\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: \"qq-basic · javascript · echarts · anyplot.ai\",\n    left: \"center\",\n    textStyle: { color: t.ink, fontSize: 22, fontWeight: 500 },\n  },\n  legend: {\n    top: 56,\n    right: 70,\n    textStyle: { color: t.ink, fontSize: 15 },\n    itemWidth: 20,\n    itemHeight: 12,\n  },\n  grid: { left: 100, right: 70, top: 130, bottom: 90 },\n  xAxis: {\n    type: \"value\",\n    name: \"Theoretical Quantiles\",\n    nameLocation: \"middle\",\n    nameGap: 44,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    axisLabel: { color: t.inkSoft, fontSize: 14 },\n    axisLine: { lineStyle: { color: t.inkSoft } },\n    splitLine: { lineStyle: { color: t.grid } },\n  },\n  yAxis: {\n    type: \"value\",\n    name: \"Sample Quantiles (z-score)\",\n    nameLocation: \"middle\",\n    nameGap: 60,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    axisLabel: { color: t.inkSoft, fontSize: 14 },\n    axisLine: { lineStyle: { color: t.inkSoft } },\n    splitLine: { lineStyle: { color: t.grid } },\n  },\n  series: [\n    {\n      name: \"Reaction times\",\n      type: \"scatter\",\n      data: points,\n      symbolSize: 12,\n      itemStyle: { color: t.palette[0], opacity: 0.8 },\n    },\n    {\n      name: \"Reference (y = x)\",\n      type: \"line\",\n      data: [[tMin, tMin], [tMax, tMax]],\n      showSymbol: false,\n      lineStyle: { color: t.ink, width: 2, type: \"dashed\" },\n      z: 1,\n    },\n  ],\n});\n"}