[object Object]

← back to Wallco Ai

drunk-animals: generator status pill + auto-recap mode on /live

50ea14f3ae4e07bcdba3714c6f82bd687bca353a · 2026-05-13 05:20:17 -0700 · SteveStudio2

Stats endpoint now returns status='live' during 18:00→05:59 PT window,
status='complete' outside it. Live page status pill shows 'live'
(pulsing green) during the run, 'complete · 10.7h run' after 6am cutoff.
'Next in N:NN' countdown hides automatically when complete.

Effect: same /drunk-animals/live URL works as live stream during the
overnight run AND as a morning recap after 6am PT. No separate /recap
page needed.

Smoke-tested: status=live, hours_elapsed=10.7, total=164, per_hr=15.4.

Files touched

Diff

commit 50ea14f3ae4e07bcdba3714c6f82bd687bca353a
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Wed May 13 05:20:17 2026 -0700

    drunk-animals: generator status pill + auto-recap mode on /live
    
    Stats endpoint now returns status='live' during 18:00→05:59 PT window,
    status='complete' outside it. Live page status pill shows 'live'
    (pulsing green) during the run, 'complete · 10.7h run' after 6am cutoff.
    'Next in N:NN' countdown hides automatically when complete.
    
    Effect: same /drunk-animals/live URL works as live stream during the
    overnight run AND as a morning recap after 6am PT. No separate /recap
    page needed.
    
    Smoke-tested: status=live, hours_elapsed=10.7, total=164, per_hr=15.4.
---
 server.js | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/server.js b/server.js
index 19ae4eb..c5aaa28 100644
--- a/server.js
+++ b/server.js
@@ -2257,13 +2257,21 @@ app.get('/api/drunk-animals/stats', (_req, res) => {
   const elapsedMs = (earliest && latest) ? (latest - earliest) : 0;
   const hoursElapsed = elapsedMs / 3_600_000;
   const designsPerHour = hoursElapsed > 0.1 ? (total / hoursElapsed) : null;
+  // Is the generator currently in its active window? Tick script runs only
+  // 18:00→05:59 PT (STOP_HOUR=6). Outside that window, show 'complete'.
+  const STOP_HOUR = 6;
+  const nowPT = new Date(new Date().toLocaleString('en-US', { timeZone: 'America/Los_Angeles' }));
+  const h = nowPT.getHours();
+  const inWindow = (h >= 18) || (h < STOP_HOUR);
   res.json({
     total,
-    animals,                                    // [['frog',18],['orangutan',14],...]
+    animals,
     avg_saturation: satCount ? +(satSum/satCount).toFixed(3) : null,
     earliest_at: earliest ? new Date(earliest).toISOString() : null,
     latest_at:   latest   ? new Date(latest).toISOString()   : null,
-    designs_per_hour: designsPerHour ? +designsPerHour.toFixed(1) : null
+    designs_per_hour: designsPerHour ? +designsPerHour.toFixed(1) : null,
+    status: inWindow ? 'live' : 'complete',
+    hours_elapsed: +hoursElapsed.toFixed(1),
   });
 });
 
@@ -2323,7 +2331,7 @@ main { padding:20px; max-width:1500px; margin:0 auto }
 </head><body>
 <header>
   <h1>The Drunk Animals Collection</h1>
-  <span class="meta pulse">live</span>
+  <span class="meta pulse" id="status-pill">live</span>
   <span class="pill" id="count">0 designs</span>
   <span class="pill green" id="next">next in —</span>
   <a href="/drunk-animals">Grid view</a>
@@ -2369,7 +2377,7 @@ async function poll() {
   try {
     const r = await fetch('/api/drunk-animals/feed?since_id=' + maxId);
     const j = await r.json();
-    countEl.textContent = j.total + ' design' + (j.total === 1 ? '' : 's') + ' · 1 every 4 min';
+    countEl.textContent = j.total + ' design' + (j.total === 1 ? '' : 's');
     if (j.designs.length === 0 && maxId === 0) {
       empty.textContent = 'No designs yet — generator just started';
       return;
@@ -2421,6 +2429,20 @@ async function pollStats() {
     const ani = document.getElementById('s-animals');
     ani.innerHTML = (j.animals || []).slice(0, 8)
       .map(([name, n]) => '<span class="animal-pill">' + name + '<strong>' + n + '</strong></span>').join('');
+    // Status pill: live (overnight window) vs complete (daylight quiet hours).
+    const pill = document.getElementById('status-pill');
+    const next = document.getElementById('next');
+    if (j.status === 'complete') {
+      pill.textContent = 'complete · ' + (j.hours_elapsed||0).toFixed(1) + 'h run';
+      pill.classList.remove('pulse');
+      pill.style.color = '#50fa7b';
+      next.style.display = 'none';
+    } else {
+      pill.textContent = 'live';
+      pill.classList.add('pulse');
+      pill.style.color = '';
+      next.style.display = '';
+    }
   } catch (e) { console.warn('stats poll failed', e); }
 }
 

← 768a775 drunk-animals: 'Best of the night' rail on /live  ·  back to Wallco Ai  ·  drunk-animals: salvage 6 orphan PNGs + fix spoon_all_designs 2edefae →