/* BT episode grade v1: 20-80 listener grades under the podcast player */ (function () { var W = 'https://bt-grades.jason-a-churchill.workers.dev/'; var LABELS = { 20: 'Poor', 25: 'Poor', 30: 'Well below average', 35: 'Well below average', 40: 'Below average', 45: 'Fringe average', 50: 'Average', 55: 'Above average', 60: 'Plus', 65: 'Plus', 70: 'Plus-plus', 75: 'Plus-plus', 80: 'Elite' }; var GRADES = [20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80]; function run() { if (!document.body.classList.contains('tag-podcast')) return; var player = document.querySelector('.gh-content iframe[src*="transistor.fm"]'); if (!player || document.getElementById('bt-grade')) return; var ep; try { ep = 'tr:' + new URL(player.src).pathname.replace(/\/+$/, ''); } catch (e) { return; } fetch('/members/api/session', { credentials: 'same-origin' }) .then(function (r) { return r.ok ? r.text() : ''; }) .then(function (tok) { if (!tok || tok.split('.').length !== 3) return; var auth = { Authorization: 'Bearer ' + tok }; fetch(W + '?ep=' + encodeURIComponent(ep), { headers: auth }) .then(function (r) { return r.ok ? r.json() : null; }) .then(function (d) { if (d) build(player, ep, auth, d); }) .catch(function () {}); }) .catch(function () {}); } function css() { if (document.getElementById('bt-grade-css')) return; var s = document.createElement('style'); s.id = 'bt-grade-css'; s.textContent = '#bt-grade{margin:16px 0 32px;padding:20px;border:1px solid rgba(255,255,255,.14);border-radius:12px;background:rgba(255,255,255,.04);font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;color:#fff}' + '#bt-grade .btg-h{display:flex;justify-content:space-between;align-items:baseline;gap:12px;flex-wrap:wrap;margin:0 0 14px}' + '#bt-grade .btg-t{font-size:17px;font-weight:700;letter-spacing:.01em}' + '#bt-grade .btg-s{font-size:13px;opacity:.65}' + '#bt-grade .btg-g{display:grid;grid-template-columns:repeat(13,1fr);gap:6px}' + '#bt-grade .btg-b{appearance:none;border:1px solid rgba(255,255,255,.2);background:transparent;color:#fff;border-radius:8px;padding:10px 0;font:600 16px Inter,sans-serif;cursor:pointer;transition:background .12s,border-color .12s}' + '#bt-grade .btg-b:hover{border-color:#3b82f6}' + '#bt-grade .btg-b.on{background:#3b82f6;border-color:#3b82f6}' + '#bt-grade .btg-f{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-top:14px}' + '#bt-grade .btg-l{font-size:15px;opacity:.8;min-height:1.2em}' + '#bt-grade .btg-go{appearance:none;border:0;background:#3b82f6;color:#fff;border-radius:8px;padding:10px 18px;font:700 15px Inter,sans-serif;cursor:pointer}' + '#bt-grade .btg-go[disabled]{opacity:.4;cursor:default}' + '#bt-grade .btg-n{font-size:12px;opacity:.55;margin-top:8px}' + '#bt-grade .btg-r{display:flex;gap:28px;flex-wrap:wrap;align-items:flex-end}' + '#bt-grade .btg-k{font-size:12px;text-transform:uppercase;letter-spacing:.08em;opacity:.6;margin-bottom:4px}' + '#bt-grade .btg-v{font-size:40px;font-weight:800;line-height:1}' + '#bt-grade .btg-v.mine{font-size:28px;opacity:.85}' + '#bt-grade .btg-c{font-size:14px;opacity:.65;margin-top:6px}' + '#bt-grade .btg-e{color:#fca5a5;font-size:14px}' + '@media (max-width:640px){#bt-grade .btg-g{grid-template-columns:repeat(7,1fr)}}'; document.head.appendChild(s); } function el(tag, cls, text) { var e = document.createElement(tag); if (cls) e.className = cls; if (text != null) e.textContent = text; return e; } function build(player, ep, auth, d) { css(); var box = el('div'); box.id = 'bt-grade'; var anchor = player; while (anchor.parentElement && !anchor.parentElement.classList.contains('gh-content')) anchor = anchor.parentElement; anchor.insertAdjacentElement('afterend', box); if (d.mine != null) results(box, d); else form(box, ep, auth); } function form(box, ep, auth) { box.innerHTML = ''; var h = el('div', 'btg-h'); h.appendChild(el('div', 'btg-t', 'Grade this episode')); h.appendChild(el('div', 'btg-s', '20–80 scouting scale')); box.appendChild(h); var grid = el('div', 'btg-g'); var pick = null, label = el('div', 'btg-l', 'Pick a grade to see the listener average.'); var go = el('button', 'btg-go', 'Lock in grade'); go.disabled = true; GRADES.forEach(function (g) { var b = el('button', 'btg-b', String(g)); b.type = 'button'; b.title = g + ' – ' + LABELS[g]; b.onclick = function () { pick = g; Array.prototype.forEach.call(grid.children, function (x) { x.classList.toggle('on', x === b); }); label.textContent = g + ' – ' + LABELS[g]; go.disabled = false; }; grid.appendChild(b); }); box.appendChild(grid); var f = el('div', 'btg-f'); f.appendChild(label); f.appendChild(go); box.appendChild(f); box.appendChild(el('div', 'btg-n', 'Grades are final once submitted.')); go.onclick = function () { if (pick == null) return; go.disabled = true; go.textContent = 'Saving…'; fetch(W, { method: 'POST', headers: Object.assign({ 'Content-Type': 'application/json' }, auth), body: JSON.stringify({ ep: ep, grade: pick }) }) .then(function (r) { if (!r.ok) throw new Error(r.status); return r.json(); }) .then(function (d) { results(box, d); }) .catch(function () { go.disabled = false; go.textContent = 'Lock in grade'; label.className = 'btg-e'; label.textContent = 'Something went wrong saving your grade. Try again.'; }); }; } function results(box, d) { box.innerHTML = ''; var h = el('div', 'btg-h'); h.appendChild(el('div', 'btg-t', 'Listener grade')); h.appendChild(el('div', 'btg-s', '20–80 scouting scale')); box.appendChild(h); var r = el('div', 'btg-r'); var a = el('div'); a.appendChild(el('div', 'btg-k', 'Average')); a.appendChild(el('div', 'btg-v', Number(d.avg).toFixed(1))); var n = Number(d.n) || 0; a.appendChild(el('div', 'btg-c', 'from ' + n + (n === 1 ? ' listener' : ' listeners'))); r.appendChild(a); var m = el('div'); m.appendChild(el('div', 'btg-k', 'Your grade')); m.appendChild(el('div', 'btg-v mine', String(d.mine))); m.appendChild(el('div', 'btg-c', LABELS[d.mine] || '')); r.appendChild(m); box.appendChild(r); } if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', run); else run(); })();