diff --git a/projects/radio-show/audio-processor/server/main.py b/projects/radio-show/audio-processor/server/main.py index bff4dbc..a5cd033 100644 --- a/projects/radio-show/audio-processor/server/main.py +++ b/projects/radio-show/audio-processor/server/main.py @@ -260,6 +260,18 @@ INDEX_HTML = """ mark { background: #ffec99; padding: 0 .15em; } .stats { font-size: 12px; color:#666; margin-top: 2em; } .empty { color:#999; padding: 1em 0; } + .controls select, .controls input[type=checkbox] { margin-right: .35em; } + .badge { display: inline-block; min-width: 1.6em; padding: 0 .35em; margin-right: .35em; + font-size: 11px; font-weight: 600; text-align: center; border-radius: 3px; + color: #fff; background: #999; vertical-align: 1px; } + .badge.s5 { background: #2a8f43; } + .badge.s4 { background: #5aa54b; } + .badge.s3 { background: #999; } + .badge.s2 { background: #c08a3a; } + .badge.s1 { background: #b85a4a; } + .topic { font-size: 11px; color: #888; padding: 0 .35em; border-radius: 3px; + background: #f0f0f0; } + .hit.dim { opacity: .55; }

Computer Guru Radio Archive

...
@@ -268,6 +280,18 @@ INDEX_HTML = """ + + + +
@@ -288,6 +312,8 @@ q.addEventListener('input', () => { timer = setTimeout(runSearch, 250); }); document.querySelectorAll('input[name=kind]').forEach(el => el.addEventListener('change', runSearch)); +document.getElementById('min_score').addEventListener('change', runSearch); +document.getElementById('exclude_banter').addEventListener('change', runSearch); function fmtTime(s) { if (s == null) return ''; @@ -295,20 +321,41 @@ function fmtTime(s) { return `${m}:${sec.toString().padStart(2,'0')}`; } +function escapeHtml(s) { + return (s ?? '').replace(/[&<>"']/g, c => ({ + '&':'&','<':'<','>':'>','"':'"',"'":''' + }[c])); +} + async function runSearch() { const term = q.value.trim(); if (term.length < 2) { results.innerHTML = ''; return; } const kind = document.querySelector('input[name=kind]:checked').value; - const r = await fetch(`/api/search?q=${encodeURIComponent(term)}&kind=${kind}&limit=40`); + const minScore = document.getElementById('min_score').value; + const excludeBanter = document.getElementById('exclude_banter').checked; + const params = new URLSearchParams({ q: term, kind, limit: '40' }); + if (minScore !== '0') params.set('min_score', minScore); + if (excludeBanter) params.set('exclude_banter', 'true'); + const r = await fetch(`/api/search?${params}`); const j = await r.json(); let html = ''; if (j.qa.length) { html += '

Q&A Pairs

'; for (const h of j.qa) { const ad = h.air_date ? ` (${h.air_date})` : ''; - const cn = h.caller_name ? ` — ${h.caller_name}` : ''; - html += `
-
${h.year} · ${h.title}${ad}${cn} · @ ${fmtTime(h.question_start_sec)}
+ const cn = h.caller_name ? ` — ${escapeHtml(h.caller_name)}` : ''; + const score = h.usefulness_score; + const topic = h.topic_class; + const banter = h.is_banter === 1; + const badge = score != null + ? `${score}` + : ''; + const topicTag = topic + ? `${escapeHtml(topic)} ` + : ''; + const dim = (score != null && score <= 2) || banter ? ' dim' : ''; + html += `
+
${badge}${topicTag}${h.year} · ${escapeHtml(h.title)}${ad}${cn} · @ ${fmtTime(h.question_start_sec)}
Q: ${h.q_snippet}
A: ${h.a_snippet}
`;