{"spec_id":"bifurcation-basic","library":"chartjs","language":"javascript","code":"// anyplot.ai\n// bifurcation-basic: Bifurcation Diagram for Dynamical Systems\n// Library: chartjs 4.4.7 | JavaScript 22.22.3\n// Quality: 89/100 | Created: 2026-06-17\n\nconst t = window.ANYPLOT_TOKENS;\nconst rgba = (hex, a) => { const [r,g,b] = [1,3,5].map(o=>parseInt(hex.slice(o,o+2),16)); return `rgba(${r},${g},${b},${a})`; };\n\n// --- Data: Logistic map x(n+1) = r * x(n) * (1 - x(n)) ---\nconst R_MIN = 2.5, R_MAX = 4.0;\nconst N_R = 1000;\nconst N_SKIP = 200;\nconst N_PLOT = 100;\n\nconst points = [];\nfor (let i = 0; i <= N_R; i++) {\n  const r = R_MIN + (R_MAX - R_MIN) * i / N_R;\n  let x = 0.5;\n  for (let j = 0; j < N_SKIP; j++) x = r * x * (1 - x);\n  for (let j = 0; j < N_PLOT; j++) {\n    x = r * x * (1 - x);\n    points.push({ x: r, y: x });\n  }\n}\n\n// --- Bifurcation points: dashed vertical lines via Chart.js line datasets ---\n// r=3.449 and r=3.544 are very close (~89 px apart); labels staggered in dy.\nconst BIFURC = [\n  { r: 3.0,   text: \"r≈3.0 (period-2)\",  dy: 14 },\n  { r: 3.449, text: \"r≈3.449 (period-4)\", dy: 14 },\n  { r: 3.544, text: \"r≈3.544 (period-8)\", dy: 34 },\n];\n\nconst refColor = rgba(t.ink, 0.28);\nconst refDatasets = BIFURC.map(({ r }) => ({\n  type: \"line\",\n  data: [{ x: r, y: 0 }, { x: r, y: 1 }],\n  borderColor: refColor,\n  borderWidth: 1.5,\n  borderDash: [7, 5],\n  pointRadius: 0,\n  fill: false,\n  tension: 0,\n}));\n\n// Plugin for annotation text labels only (lines handled by datasets above)\nconst labelPlugin = {\n  id: \"bifurcLabels\",\n  afterDraw({ ctx, chartArea: { top }, scales }) {\n    ctx.save();\n    ctx.fillStyle = t.inkSoft;\n    ctx.font = \"14px system-ui, sans-serif\";\n    ctx.textAlign = \"center\";\n    BIFURC.forEach(({ r, text, dy }) => ctx.fillText(text, scales.x.getPixelForValue(r), top + dy));\n    ctx.restore();\n  },\n};\n\n// --- Mount ---\nconst canvas = document.createElement(\"canvas\");\ndocument.getElementById(\"container\").appendChild(canvas);\n\n// Per-theme alpha: slightly higher in light for better chaos-region visibility\nconst dotAlpha = window.ANYPLOT_THEME === \"light\" ? 0.13 : 0.10;\n\n// --- Chart ---\nnew Chart(canvas, {\n  type: \"scatter\",\n  data: {\n    datasets: [\n      ...refDatasets,\n      {\n        label: \"Logistic map\",\n        data: points,\n        backgroundColor: rgba(t.palette[0], dotAlpha),\n        borderColor: \"transparent\",\n        borderWidth: 0,\n        pointRadius: 0.8,\n        pointHoverRadius: 0,\n      },\n    ],\n  },\n  options: {\n    responsive: true,\n    maintainAspectRatio: false,\n    animation: false,\n    plugins: {\n      title: {\n        display: true,\n        text: \"bifurcation-basic · javascript · chartjs · anyplot.ai\",\n        color: t.ink,\n        font: { size: 22, weight: \"500\", family: \"system-ui, sans-serif\" },\n        padding: { top: 12, bottom: 18 },\n      },\n      legend: { display: false },\n      tooltip: { enabled: false },\n    },\n    scales: {\n      x: {\n        type: \"linear\",\n        min: R_MIN,\n        max: R_MAX,\n        border: { display: false },\n        title: {\n          display: true,\n          text: \"Growth Rate Parameter (r)\",\n          color: t.ink,\n          font: { size: 16 },\n        },\n        ticks: { color: t.inkSoft, font: { size: 14 } },\n        grid: { color: t.grid },\n      },\n      y: {\n        type: \"linear\",\n        min: 0,\n        max: 1,\n        border: { display: false },\n        title: {\n          display: true,\n          text: \"Population Value (x)\",\n          color: t.ink,\n          font: { size: 16 },\n        },\n        ticks: { color: t.inkSoft, font: { size: 14 } },\n        grid: { color: t.grid },\n      },\n    },\n  },\n  plugins: [labelPlugin],\n});\n"}