// The day page (Marty, 2026-09-23): everything that happened across the WHOLE contract on one
// Central calendar day, at a dated address that keeps working forever.
//
// Why it exists: the daily Telegram snapshot outgrew Telegram. Past 1,000 members the post hit
// the 4,096-character limit and was rejected outright for two mornings, and capping the lists to
// fit meant deciding what to throw away. Manson caught the cost of that: the level-up list was
// ordered by time, so the cap hid 2 Culmen and 13 Fabrica behind 24 routine Ascensus upgrades.
// Now the post carries the headline and the climbs, and everything else lives here with no cap.
//
// Today is computed live from the chain index. A past day is read from a file written once when
// that day closed, because the index only keeps the most recent few hundred payouts (about four
// days at current volume) and an older day could never be rebuilt from it.
'use strict';
const fs = require('fs');
const path = require('path');
let DATA_DIR = null;
const LEVELS = ['Scintilla', 'Ascensus', 'Fabrica', 'Culmen', 'Apex', 'Fastigium', 'Vertex', 'Corona'];
const lname = n => (n >= 1 && n <= 8) ? LEVELS[n - 1] : 'L' + n;
function init(opts) { DATA_DIR = opts.dataDir; try { fs.mkdirSync(path.join(DATA_DIR, 'days'), { recursive: true }); } catch (e) {} }
const indexFile = () => path.join(DATA_DIR, 'chain-index.json');
const dayFile = key => path.join(DATA_DIR, 'days', key + '.json');
// Central calendar day, the same key the rest of the estate uses
const dayKey = ts => new Date(ts === undefined ? Date.now() : ts).toLocaleDateString('en-CA', { timeZone: 'America/Chicago' });
const isKey = k => /^\d{4}-\d{2}-\d{2}$/.test(String(k || ''));
// midnight-to-midnight in Central, found by bisection so it is right on both clock-change days
function bounds(key) {
const probe = Date.parse(key + 'T12:00:00Z');
let lo = probe - 36 * 3600000, hi = probe;
while (hi - lo > 1000) { const mid = Math.floor((lo + hi) / 2); if (dayKey(mid) < key) lo = mid; else hi = mid; }
const start = hi;
lo = start; hi = start + 36 * 3600000;
while (hi - lo > 1000) { const mid = Math.floor((lo + hi) / 2); if (dayKey(mid) <= key) lo = mid; else hi = mid; }
return { start, end: hi };
}
function readIndex() { try { return JSON.parse(fs.readFileSync(indexFile(), 'utf8')); } catch (e) { return null; } }
// everything that happened on one Central day, company-wide: no team or org filter anywhere
function compute(key) {
const idx = readIndex();
if (!idx) return null;
const { start, end } = bounds(key);
const s = Math.floor(start / 1000), e = Math.floor(end / 1000);
const members = idx.members || {};
const all = idx.payouts || [];
const joins = Object.keys(members)
.map(i => ({ id: Number(i), m: members[i] }))
.filter(x => { const t = Number(x.m.joinedAt || 0); return t >= s && t < e; })
.sort((a, b) => Number(a.m.joinedAt) - Number(b.m.joinedAt))
.map(x => ({ id: x.id, referrerId: Number(x.m.referrerId || 0) || null, tier: x.m.tier || null, level: Number(x.m.level || 0) || null }));
const pays = all.filter(p => { const t = Number(p.ts || 0); return t >= s && t < e; })
.map(p => ({ toId: Number(p.toId || 0), fromId: Number(p.fromId || 0), kind: p.kind || null, level: Number(p.level || 0) || null,
pol: Number(p.pol || 0), tx: p.tx || null, ts: Number(p.ts || 0), upgrade: p.upgrade || null }))
.sort((a, b) => b.pol - a.pol);
const climbSeen = new Map();
for (const p of pays) if (p.upgrade) climbSeen.set(p.upgrade.id + ':' + p.upgrade.newLevel, { id: Number(p.upgrade.id), lvl: Number(p.upgrade.newLevel), ts: p.ts });
const climbs = [...climbSeen.values()].sort((a, b) => b.lvl - a.lvl || a.ts - b.ts);
const recruited = {};
for (const j of joins) if (j.referrerId) (recruited[j.referrerId] = recruited[j.referrerId] || []).push(j.id);
const recruiters = Object.keys(recruited).map(r => ({
id: Number(r), brought: recruited[r], directs: Number((members[r] || {}).directCount || 0),
})).sort((a, b) => b.brought.length - a.brought.length || a.id - b.id);
const polMoved = pays.reduce((n, p) => n + p.pol, 0);
// the index keeps a rolling payout window; if a day fills it the totals are a floor, not the whole day
const clipped = pays.length >= all.length && all.length > 0;
return {
key, computedAt: Date.now(), clipped,
totals: { joins: joins.length, climbs: climbs.length, payouts: pays.length, polMoved: Math.round(polMoved * 1e6) / 1e6 },
contract: { members: Object.keys(members).length, lifetimePol: Number((idx.totals || {}).pol || 0), lifetimePayouts: Number((idx.totals || {}).count || 0) },
climbs, joins, recruiters, payouts: pays,
biggest: pays[0] || null,
};
}
// a finished day is written once and read from disk forever after
function get(key) {
if (!isKey(key)) return null;
const today = dayKey();
if (key !== today) {
try { return JSON.parse(fs.readFileSync(dayFile(key), 'utf8')); } catch (e) {}
if (key > today) return null;
}
const d = compute(key);
if (!d) return null;
if (key !== today) {
// a past day with nothing in it is either before the contract or beyond the index's reach:
// say not found rather than serving an empty page, and never write a file for it
if (d.totals.payouts + d.totals.joins === 0) return null;
save(d);
}
return d;
}
function save(d) { try { fs.writeFileSync(dayFile(d.key), JSON.stringify(d)); } catch (e) {} }
function stored() { try { return fs.readdirSync(path.join(DATA_DIR, 'days')).filter(f => f.endsWith('.json')).map(f => f.slice(0, -5)).sort().reverse(); } catch (e) { return []; } }
// hourly: close out any finished day that has not been written yet, so the archive never depends
// on someone opening the page before the payout window rolls past it
function tick() {
const today = dayKey();
for (let back = 1; back <= 3; back++) {
const k = dayKey(Date.now() - back * 86400000);
if (k === today) continue;
if (fs.existsSync(dayFile(k))) continue;
const d = compute(k);
if (d && d.totals.payouts + d.totals.joins > 0) { save(d); console.log('daysnap: stored ' + k); }
}
}
// ---- the page ---------------------------------------------------------------------------------
const esc = s => String(s == null ? '' : s).replace(/[&<>"]/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"' }[c]));
const n0 = v => Number(v || 0).toLocaleString('en-US', { maximumFractionDigits: 0 });
const n2 = v => Number(v || 0).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
const SCAN = 'https://polygonscan.com/tx/';
const pretty = key => { const [y, m, d] = key.split('-').map(Number); return new Date(Date.UTC(y, m - 1, d)).toLocaleDateString('en-US', { timeZone: 'UTC', weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' }); };
function render(key, opts) {
const o = opts || {};
const d = get(key);
const today = dayKey();
const prev = dayKey(bounds(key).start - 3600000);
const nextKey = dayKey(bounds(key).end + 3600000);
const title = 'The Circle on ' + pretty(key);
if (!d) return { status: 404, html: shell(title, '
No figures for that date yet.
', key, prev, null) };
const usd = Number(o.polUsd) || 0;
const dol = p => usd ? ' (~$' + n0(p * usd) + ')' : '';
const high = d.climbs.filter(c => c.lvl >= 3);
const routine = d.climbs.length - high.length;
const head = ''
+ tile(n0(d.totals.joins), 'new members')
+ tile(n0(d.totals.climbs), 'upgrades')
+ tile(n0(d.totals.polMoved) + ' POL', 'moved on chain' + (usd ? ' · ~$' + n0(d.totals.polMoved * usd) : ''))
+ tile(n0(d.contract.members), 'on the contract')
+ '
';
// grouped by rung, highest first: the ladder is the story, and a two-column table of the same
// thing wastes half the page and buries a Culmen among two dozen Ascensus rows
const byLevel = new Map();
for (const c of d.climbs) { if (!byLevel.has(c.lvl)) byLevel.set(c.lvl, []); byLevel.get(c.lvl).push(c.id); }
const climbRows = d.climbs.length
? [...byLevel.keys()].sort((a, b) => b - a).map(lv => ''
+ '
' + esc(lname(lv)) + ' ' + byLevel.get(lv).length + '
'
+ '
' + byLevel.get(lv).map(i => '#' + i + '').join('') + '
').join('')
: 'No upgrades on this day.
';
const joinRows = d.joins.length
? '| Position | Invited by | Entry |
'
+ d.joins.map(j => '| #' + j.id + ' | ' + (j.referrerId ? '#' + j.referrerId : '—') + ' | ' + esc(j.tier === 2 || j.tier === 'Premium' ? 'Premium' : 'Standard') + ' |
').join('')
+ '
'
: 'No new members on this day.
';
const recRows = d.recruiters.length
? '| Position | Brought in | Who | Directs |
'
+ d.recruiters.map(r => '| #' + r.id + ' | ' + r.brought.length + ' | '
+ r.brought.map(x => '#' + x).join(' ') + ' | ' + (r.directs >= 2 ? 'qualified' : r.directs + '/2') + ' |
').join('')
+ '
'
: 'Nobody added a personal referral on this day.
';
const payRows = d.payouts.length
? '| POL | To | From | Why | Proof |
'
+ d.payouts.map(p => '| ' + n2(p.pol) + '' + dol(p.pol) + ' | #' + p.toId + ' | '
+ (p.fromId ? '#' + p.fromId : '—') + ' | ' + esc(p.upgrade ? 'upgrade to ' + lname(p.upgrade.newLevel) : (p.kind || 'payment'))
+ ' | ' + (p.tx ? 'Polygonscan ↗' : '—') + ' |
').join('')
+ '
'
: 'No payments on this day.
';
const body = head
+ (high.length ? 'Highest climb of the day: ' + esc(lname(high[0].lvl)) + ', reached by '
+ high.filter(c => c.lvl === high[0].lvl).map(c => '#' + c.id).join(', ') + '.
' : '')
+ (d.biggest ? 'Biggest single payment: ' + n2(d.biggest.pol) + ' POL' + dol(d.biggest.pol)
+ ', caught by #' + d.biggest.toId + ''
+ (d.biggest.tx ? ' · Polygonscan ↗' : '') + '.
' : '')
+ (d.clipped ? 'These payment totals are a floor: the index window filled for this day.
' : '')
+ sec('Every climb', (high.length ? high.length + ' above Ascensus' : '') + (routine ? (high.length ? ' · ' : '') + routine + ' reached Ascensus' : ''), climbRows)
+ sec('Every payment', d.totals.payouts + ' on chain, each one verifiable', payRows)
+ sec('Every new member', d.totals.joins + ' joined', joinRows)
+ sec('Recruiters', d.recruiters.length + ' added someone', recRows);
return { status: 200, html: shell(title, body, key, prev, nextKey <= today && nextKey !== key ? nextKey : null) };
}
const tile = (v, l) => '';
const sec = (h, sub, inner) => '' + esc(h) + (sub ? ' ' + esc(sub) + '' : '') + '
'
+ (/^