// ------------------------------------------------------------------------ // almanac-calendar.js - Extended event calendar for the "What's Coming" // panel and getUpcomingEvents() export. // // The per-year data now lives in ./calendar/.js — each of those files // exports an `almanac` array. This module concatenates them (chronological // order) and provides the visibility-note and upcoming-events helpers. // // Each entry has a 'latHint': // null = global / no hint // 'north' = better from northern latitudes // 'south' = better from southern latitudes // 'path:...' = specific eclipse path note // // To add a new year: create ./calendar/.js (copy an existing one), // then import it below and add its `almanac` spread to ALMANAC_CALENDAR. // ------------------------------------------------------------------------ import { almanac as almanac2026 } from './calendar/2026.js'; import { almanac as almanac2027 } from './calendar/2027.js'; import { almanac as almanac2028 } from './calendar/2028.js'; import { almanac as almanac2029 } from './calendar/2029.js'; import { almanac as almanac2030 } from './calendar/2030.js'; export const ALMANAC_CALENDAR = [ ...almanac2026, ...almanac2027, ...almanac2028, ...almanac2029, ...almanac2030, ]; // Returns a location-aware visibility note for an almanac entry. // lat = user's latitude. export function getVisibilityNote(entry, lat) { if (!entry.latHint) return null; if (entry.latHint.startsWith('path:')) { return entry.latHint.replace('path:', '').trim(); } if (entry.latHint === 'north') { if (lat >= 45) return 'Well placed for your latitude'; if (lat >= 20) return 'Visible from your location'; return 'Better from northern latitudes'; } if (entry.latHint === 'south') { if (lat <= 10) return 'Well placed for your latitude'; if (lat <= 40) return 'Visible from your location'; return 'Better from southern latitudes'; } return null; } // --- MAIN ALMANAC EXPORT ------------------------------------------------- // Returns events with peak dates in the next 'days' days (default 90), // sorted by peak date, with a visibility note added. export function getUpcomingEvents(location, days = 90) { const today = new Date(); today.setHours(0, 0, 0, 0); const cutoff = new Date(today); cutoff.setDate(cutoff.getDate() + days); const todayStr = today.toISOString().slice(0, 10); const cutoffStr = cutoff.toISOString().slice(0, 10); return ALMANAC_CALENDAR .filter(ev => ev.peak >= todayStr && ev.peak <= cutoffStr) .sort((a, b) => a.peak.localeCompare(b.peak)) .map(ev => ({ ...ev, visibilityNote: getVisibilityNote(ev, location?.lat ?? 51), daysUntil: Math.round((new Date(ev.peak + 'T00:00Z') - today) / 86400000), })); }