///////////////////////////// // Get totals in the last year of the map (2082) as a way to check total capacity. This can be combined with the yearly data. (async () => { /********************** * Utility functions * **********************/ const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); const visible = (el) => !!el && !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length); const norm = (s) => (s || "").replace(/\u00A0/g, " ").replace(/\s+/g, " ").trim(); const labelKey = (s) => norm(s).replace(/:$/, "").toLowerCase(); // CSV helpers const csvEscape = (val) => { const s = (val === null || val === undefined) ? "" : String(val); if (/[",\n]/.test(s)) return `"${s.replace(/"/g, '""')}"`; return s; }; const saveCSV = (rows, filename = "Curie_Spent_Fuel_Site_Totals.csv") => { const csv = rows.map(r => r.map(csvEscape).join(",")).join("\n"); const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 1000); }; /******************************************** * ISO-only date extraction & min/max * ********************************************/ const isValidISO = (yyyy, mm, dd) => { const y = Number(yyyy), m = Number(mm), d = Number(dd); if (!(y >= 1800 && y <= 2200)) return false; if (!(m >= 1 && m <= 12)) return false; if (!(d >= 1 && d <= 31)) return false; // light bounds return true; }; // Extract ISO date strings YYYY-MM-DD only, validated const extractISODates = (str) => { const s = norm(str); const re = /\b(\d{4})-(\d{2})-(\d{2})\b/g; const out = []; let m; while ((m = re.exec(s)) !== null) { if (isValidISO(m[1], m[2], m[3])) out.push(`${m[1]}-${m[2]}-${m[3]}`); } return Array.from(new Set(out)); // dedupe }; // Compute min/max via lexicographic compare (correct for ISO) const isoMinMax = (valOrArr) => { const arr = Array.isArray(valOrArr) ? valOrArr : [valOrArr]; const all = []; for (const v of arr) { if (!v) continue; all.push(...extractISODates(v)); } if (!all.length) return { min: "", max: "" }; all.sort(); return { min: all[0], max: all[all.length - 1] }; }; /**************************************** * Locate the "Locate Site" UI control * ****************************************/ const findLocateSiteControl = () => { // 1) Prefer labeled