{"spec_id":"line-win-probability","library":"echarts","language":"javascript","code":"// anyplot.ai\n// line-win-probability: Win Probability Chart\n// Library: echarts 5.5.1 | JavaScript 22.22.3\n// Quality: 90/100 | Created: 2026-06-21\n\nconst t = window.ANYPLOT_TOKENS;\n\n// NFL comeback — Atlanta Falcons (home) vs Baltimore Ravens (away)\n// Home-team win probability by game minute, derived from in-game model\nconst keyPoints = [\n  [0, 50], [8, 65], [18, 50], [23, 35],\n  [30, 32], [37, 18], [43, 38], [49, 55], [54, 72], [60, 85],\n];\n\n// Linear interpolation between key turning points (~2 pts per minute)\nconst times = [], probs = [];\nfor (let i = 0; i < keyPoints.length - 1; i++) {\n  const [x0, y0] = keyPoints[i], [x1, y1] = keyPoints[i + 1];\n  const steps = Math.max(4, Math.round((x1 - x0) * 2));\n  for (let s = 0; s < steps; s++) {\n    const f = s / steps;\n    times.push(+(x0 + (x1 - x0) * f).toFixed(2));\n    probs.push(+(y0 + (y1 - y0) * f).toFixed(1));\n  }\n}\ntimes.push(60); probs.push(85);\n\n// Clamped arrays: area above 50% (home) and below 50% (away)\nconst lineData     = times.map((m, i) => [m, probs[i]]);\nconst homeAreaData = times.map((m, i) => [m, Math.max(probs[i], 50)]);\nconst awayAreaData = times.map((m, i) => [m, Math.min(probs[i], 50)]);\n\n// Title with proportional font scaling\nconst titleText = \"Win Probability · line-win-probability · javascript · echarts · anyplot.ai\";\nconst titleFs = Math.max(14, Math.round(22 * Math.min(1, 67 / titleText.length)));\n\nconst chart = echarts.init(document.getElementById(\"container\"));\n\nchart.setOption({\n  animation: false,\n  backgroundColor: \"transparent\",\n  color: t.palette,\n\n  title: {\n    text: titleText,\n    left: \"center\",\n    top: 24,\n    textStyle: { color: t.ink, fontSize: titleFs, fontWeight: \"600\" },\n  },\n\n  legend: {\n    data: [\n      { name: \"Falcons (Home)\", icon: \"roundRect\" },\n      { name: \"Ravens (Away)\",  icon: \"roundRect\" },\n    ],\n    right: 40,\n    bottom: 20,\n    textStyle: { color: t.ink, fontSize: 14 },\n    itemWidth: 22,\n    itemHeight: 12,\n    itemGap: 28,\n  },\n\n  grid: { left: 92, right: 40, top: 90, bottom: 80 },\n\n  xAxis: {\n    type: \"value\",\n    name: \"Game Time (minutes)\",\n    nameLocation: \"middle\",\n    nameGap: 48,\n    nameTextStyle: { color: t.inkSoft, fontSize: 14 },\n    min: 0, max: 60,\n    interval: 15,\n    axisLabel: {\n      color: t.inkSoft, fontSize: 13,\n      formatter: v => ({ 0: \"Kickoff\", 15: \"Q2\", 30: \"Half\", 45: \"Q4\", 60: \"Final\" }[v] ?? \"\"),\n    },\n    axisLine: { lineStyle: { color: t.inkSoft } },\n    axisTick: { show: false },\n    splitLine: { show: false },\n  },\n\n  yAxis: {\n    type: \"value\",\n    name: \"Home Win Probability\",\n    nameLocation: \"middle\",\n    nameGap: 58,\n    nameTextStyle: { color: t.inkSoft, fontSize: 14 },\n    min: 0, max: 100,\n    interval: 25,\n    axisLabel: { color: t.inkSoft, fontSize: 13, formatter: \"{value}%\" },\n    axisLine: { show: false },\n    axisTick: { show: false },\n    splitLine: { show: false },\n  },\n\n  series: [\n    // Away team fill — below 50% (Ravens)\n    {\n      name: \"Ravens (Away)\",\n      type: \"line\",\n      data: awayAreaData,\n      symbol: \"none\",\n      lineStyle: { width: 0 },\n      itemStyle: { color: t.palette[4] },\n      areaStyle: { color: t.palette[4], opacity: 0.28, origin: 50 },\n      z: 1, silent: true,\n    },\n    // Home team fill — above 50% (Falcons)\n    {\n      name: \"Falcons (Home)\",\n      type: \"line\",\n      data: homeAreaData,\n      symbol: \"none\",\n      lineStyle: { width: 0 },\n      itemStyle: { color: t.palette[0] },\n      areaStyle: { color: t.palette[0], opacity: 0.28, origin: 50 },\n      z: 1, silent: true,\n    },\n    // Main win-probability line with annotations\n    {\n      type: \"line\",\n      data: lineData,\n      symbol: \"none\",\n      lineStyle: { width: 2.5, color: t.ink },\n      z: 3,\n      markLine: {\n        silent: true,\n        symbol: \"none\",\n        data: [\n          // 50% reference\n          {\n            yAxis: 50,\n            lineStyle: { color: t.inkSoft, type: \"dashed\", width: 1.5 },\n            label: {\n              show: true, position: \"insideStartTop\",\n              formatter: \"Even\", color: t.inkSoft, fontSize: 11,\n            },\n          },\n          // Quarter dividers\n          { xAxis: 15, lineStyle: { color: t.grid, type: \"solid\", width: 1 }, label: { show: false } },\n          { xAxis: 30, lineStyle: { color: t.grid, type: \"solid\", width: 1 }, label: { show: false } },\n          { xAxis: 45, lineStyle: { color: t.grid, type: \"solid\", width: 1 }, label: { show: false } },\n        ],\n      },\n      markPoint: {\n        silent: true,\n        symbolSize: 10,\n        data: [\n          {\n            coord: [8, 65],\n            itemStyle: { color: t.palette[0] },\n            label: { show: true, formatter: \"TD 7–0\",   color: t.palette[0], fontSize: 11, fontWeight: \"700\", position: \"top\" },\n          },\n          {\n            coord: [23, 35],\n            itemStyle: { color: t.palette[4] },\n            label: { show: true, formatter: \"TD 7–14\",  color: t.palette[4], fontSize: 11, fontWeight: \"700\", position: \"bottom\" },\n          },\n          {\n            coord: [37, 18],\n            itemStyle: { color: t.palette[4] },\n            label: { show: true, formatter: \"TD 7–21\",  color: t.palette[4], fontSize: 11, fontWeight: \"700\", position: \"bottom\" },\n          },\n          {\n            coord: [49, 55],\n            itemStyle: { color: t.palette[0] },\n            label: { show: true, formatter: \"TD 21–21\", color: t.palette[0], fontSize: 11, fontWeight: \"700\", position: \"top\" },\n          },\n          {\n            coord: [54, 72],\n            itemStyle: { color: t.palette[0] },\n            label: { show: true, formatter: \"FG 24–21\", color: t.palette[0], fontSize: 11, fontWeight: \"700\", position: \"top\" },\n          },\n        ],\n      },\n    },\n  ],\n\n  graphic: [\n    {\n      type: \"text\",\n      z: 5,\n      style: {\n        text: \"Final: Falcons 24 – Ravens 21\",\n        fill: t.ink,\n        fontSize: 13,\n        fontWeight: \"600\",\n        x: 1200,\n        y: 106,\n        textAlign: \"right\",\n      },\n    },\n  ],\n});\n"}