// ------------------------------------------------------------------------ // activity-profile.js - Estimates the % chance of a good viewing on a given // day for a multi-day cosmic event (meteor shower, conjunction), based on // how far that day sits from the event's peak. // // The calendar data only has start/end/peak dates, not real activity // curves, so this is a simplified heuristic (not live forecast data): // chance falls off exponentially from 100% at peak, halving every // `riseTau`/`decayTau` days on the approach/departure side. Values below // are rough approximations of each shower's real-world activity profile // (sharp showers like the Quadrantids get small tau, broad ones like the // Eta Aquariids get larger tau) - good enough to gate "is this worth // looking up for" without pretending to be precise astronomy. // // Single-day events (start === end) are always 100% - they only ever // appear in COSMIC_CALENDAR on their one active day anyway. // ------------------------------------------------------------------------ const ACTIVITY_PROFILES = { quadrantids: { riseTau: 0.3, decayTau: 0.4 }, lyrids: { riseTau: 0.6, decayTau: 0.7 }, 'eta-aquariids': { riseTau: 3.5, decayTau: 3.0 }, perseids: { riseTau: 2.2, decayTau: 1.8 }, orionids: { riseTau: 1.5, decayTau: 1.5 }, leonids: { riseTau: 0.5, decayTau: 0.6 }, geminids: { riseTau: 1.0, decayTau: 1.0 }, ursids: { riseTau: 0.4, decayTau: 0.4 }, 'mars-conjunction': { riseTau: 1.0, decayTau: 1.0 }, 'venus-jupiter-conjunction': { riseTau: 1.0, decayTau: 1.0 }, }; const DEFAULT_PROFILE = { riseTau: 1.0, decayTau: 1.0 }; function baseKey(id) { return String(id).replace(/-\d{4}$/, ''); } export function getActivityProfile(id) { return ACTIVITY_PROFILES[baseKey(id)] || DEFAULT_PROFILE; } // Returns an integer 0-100. export function activityChance(ev, dateStr) { if (!ev.peak || ev.start === ev.end) return 100; const today = new Date(dateStr + 'T00:00Z'); const peak = new Date(ev.peak + 'T00:00Z'); const diffDays = (today - peak) / 86400000; const { riseTau, decayTau } = getActivityProfile(ev.id); const tau = diffDays <= 0 ? riseTau : decayTau; const pct = 100 * Math.pow(0.5, Math.abs(diffDays) / tau); return Math.round(pct); }