diff --git a/assets/insights.js b/assets/insights.js index 9edc35c6..f6af42c6 100644 --- a/assets/insights.js +++ b/assets/insights.js @@ -42,7 +42,7 @@ } function load() { - return fetch('assets/insights.json?v=a6a894c6').then(function (r) { + return fetch('assets/insights.json?v=19b59a90').then(function (r) { if (!r.ok) throw new Error('insights.json ' + r.status); return r.json(); }); @@ -226,7 +226,43 @@ return s + ''; } - var VIZ = { bars: barsSVG, shares: sharesSVG, timeline: timelineSVG, line: lineSVG }; + var VIZ = { bars: barsSVG, shares: sharesSVG, timeline: timelineSVG, line: lineSVG, seasons: seasonsSVG }; + + /* Multi-season cheapest-vs-priciest comparison: one group per season, two + bars each (gold = cheapest wins, terra = priciest). Rows carry + {s, cheap:{label,v,note}, pricey:{label,v,note}}. */ + function seasonsSVG(ins) { + var rows = (ins.rows || []).filter(function (r) { + return r && typeof r.s === 'string' && + r.cheap && typeof r.cheap.label === 'string' && typeof r.cheap.v === 'number' && isFinite(r.cheap.v) && + r.pricey && typeof r.pricey.label === 'string' && typeof r.pricey.v === 'number' && isFinite(r.pricey.v); + }); + if (!rows.length) return ''; + var W = 620, headH = 34, groupH = 96, barH = 13, barGap = 28; + var H = headH + rows.length * groupH + 6; + var maxV = Math.max.apply(null, rows.map(function (r) { return r.pricey.v; })) * 1.06 || 1; + function X(v) { return (v / maxV) * W; } + var s = ''; + } /* ---------- card + spotlight rendering ---------- */ @@ -523,6 +559,28 @@ c.fillText(rows4[0].s, X(0), y + h + 34); var ls = rows4[rows4.length - 1].s; c.fillText(ls, X(rows4.length - 1) - c.measureText(ls).width, y + h + 34); + } else if (ins.viz === 'seasons') { + /* Multi-season cheapest-vs-priciest: season label, then a gold + (cheapest) and terra (priciest) bar per season. */ + var rows5 = (ins.rows || []).filter(function (r) { return r && r.cheap && r.pricey; }); + var rh5 = rows5.length ? h / rows5.length : h; + var max5 = rows5.length ? + Math.max.apply(null, rows5.map(function (r) { return r.pricey.v; })) * 1.06 : 1; + rows5.forEach(function (r, i) { + var ry = y + i * rh5; + c.font = '700 26px ' + F; c.fillStyle = '#F9F6F0'; + c.fillText(r.s, x, ry + 32); + [['cheap', GOLD], ['pricey', TERRA]].forEach(function (t, j) { + var d = r[t[0]]; + var bwy = ry + 46 + j * 46; + c.font = '400 22px ' + F; c.fillStyle = '#F9F6F0'; + fitLabel(d.label + ' \u00b7 $' + d.v + 'M/win', x, bwy + 19, 300); + c.fillStyle = t[1]; + c.beginPath(); + c.roundRect(x + 320, bwy, Math.max(4, (d.v / max5) * (w - 320)), 24, 6); + c.fill(); + }); + }); } c.restore(); return y + h; diff --git a/assets/insights.json b/assets/insights.json index 837cb208..f7250f61 100644 --- a/assets/insights.json +++ b/assets/insights.json @@ -1232,65 +1232,72 @@ "series": "ledger" }, { - "foot": "Payrolls: Basketball Insiders 2024-25 season snapshot (total cap). Wins: 2024-25 regular season. Cross-checked against Spotrac cap tracker.", + "foot": "Payrolls: Spotrac NBA Team Salary Cap Tracker, 'Total Cap Allocations' (includes dead money and mid-season moves), one table per season. Wins: final regular-season records — 2023-24 wins cross-checked against landofbasketball.com, whose tracker record column was stale that year. League-average cost per win rose $3.84M → $4.83M over the window. The earlier single-season card used a Basketball Insiders snapshot, so 2024-25 figures differ slightly.", "kicker": "Money layer", - "lede": "Revenue efficiency, team-level: 2024-25 total payroll (Basketball Insiders season snapshot) divided by regular-season wins. A 5.4x spread separates the most efficient checkbook from the least.", - "og_desc": "Oklahoma City spent $159M and won 68 games. Washington spent $228M and won 18. Payroll per win, 2024-25.", - "og_title": "The cheapest NBA wins cost $2.34M — the priciest $12.67M", + "lede": "Revenue efficiency, team-level: Spotrac Total Cap Allocations divided by regular-season wins, 2022-23 through 2025-26. One consistent source across all four seasons.", + "og_desc": "Oklahoma City bought the cheapest wins three of the last four seasons. Washington paid the most three straight — $13.65M per win in 2025-26.", + "og_title": "The cheapest NBA wins cost $2.28M — the priciest $13.65M", "rows": [ { - "label": "Oklahoma City", - "tag": "68 wins, best", - "value": 2.34 - }, - { - "label": "Detroit", - "tag": null, - "value": 2.98 - }, - { - "label": "Cleveland", - "tag": null, - "value": 2.99 - }, - { - "label": "Boston", - "tag": null, - "value": 3.36 - }, - { - "label": "Phoenix", - "tag": "$237M for 36 wins", - "value": 6.58 - }, - { - "label": "Philadelphia", - "tag": null, - "value": 7.43 + "s": "2022-23", + "cheap": { + "label": "Memphis", + "v": 2.28, + "note": "56 wins" + }, + "pricey": { + "label": "Houston", + "v": 6.91, + "note": "20 wins" + } }, { - "label": "Utah", - "tag": null, - "value": 8.73 + "s": "2023-24", + "cheap": { + "label": "Oklahoma City", + "v": 2.82, + "note": "57 wins" + }, + "pricey": { + "label": "Washington", + "v": 12.66, + "note": "15 wins" + } }, { - "label": "New Orleans", - "tag": null, - "value": 8.84 + "s": "2024-25", + "cheap": { + "label": "Oklahoma City", + "v": 2.44, + "note": "68 wins" + }, + "pricey": { + "label": "Washington", + "v": 11.76, + "note": "18 wins" + } }, { - "label": "Washington", - "tag": "18 wins, worst", - "value": 12.67 + "s": "2025-26", + "cheap": { + "label": "Oklahoma City", + "v": 2.94, + "note": "64 wins" + }, + "pricey": { + "label": "Washington", + "v": 13.65, + "note": "17 wins" + } } ], "slug": "payroll-per-win", - "stat": "2.34", - "stat_label": "$M per win — Oklahoma City, best payroll efficiency", - "title": "The cheapest wins in the NBA cost $2.34M — the priciest cost $12.67M", - "tldr": "Team payroll divided by 2024-25 wins: Oklahoma City bought the league's best record for $2.34M per win, while Washington spent $12.67M per win on 18 wins.", - "viz": "bars", - "viz_label": "Payroll $M per regular-season win, 2024-25 (lower = cheaper wins)", + "stat": "6.0x", + "stat_label": "cheapest-to-priciest win across the four-season window", + "title": "The cheapest wins in the NBA cost $2.28M — the priciest cost $13.65M", + "tldr": "Payroll divided by wins, four seasons running: Oklahoma City bought the cheapest wins three of the last four years; Washington paid the most three straight, $13.65M per win last season.", + "viz": "seasons", + "viz_label": "Payroll $M per regular-season win — cheapest vs priciest, by season (lower = cheaper wins)", "series": "ledger" }, { @@ -1658,4 +1665,4 @@ "series": "ledger" } ] -} \ No newline at end of file +} diff --git a/assets/og/insight-payroll-per-win.png b/assets/og/insight-payroll-per-win.png index f97ea3d5..8c26f9c3 100644 Binary files a/assets/og/insight-payroll-per-win.png and b/assets/og/insight-payroll-per-win.png differ diff --git a/insights.html b/insights.html index e61c0e87..c5bfb24f 100644 --- a/insights.html +++ b/insights.html @@ -104,6 +104,6 @@