v1.42 - Fix Cosmic Events + Popups
This commit is contained in:
+41
-6
@@ -331,23 +331,54 @@ function checkStargazing(rows) {
|
||||
}
|
||||
|
||||
function checkSunset(rows, location) {
|
||||
// Perfect sunset: clear low cloud near sunset hour, good visibility
|
||||
const sunsetRows = rows.filter(r => r.elev > -3 && r.elev < 8);
|
||||
if (sunsetRows.length === 0) return null;
|
||||
// Find the actual sunset window: the LAST contiguous run of rows where
|
||||
// solar elevation is in the golden/civil-twilight band (-3° to 8°).
|
||||
// This distinguishes sunset from sunrise (which is the first such run).
|
||||
const twilightIndices = rows
|
||||
.map((r, i) => ({ r, i }))
|
||||
.filter(({ r }) => r.elev > -3 && r.elev < 8);
|
||||
if (twilightIndices.length === 0) return null;
|
||||
|
||||
// Split into runs separated by gaps (midday gap separates sunrise from sunset)
|
||||
const runs = [];
|
||||
let run = [twilightIndices[0]];
|
||||
for (let k = 1; k < twilightIndices.length; k++) {
|
||||
if (twilightIndices[k].i === twilightIndices[k - 1].i + 1) {
|
||||
run.push(twilightIndices[k]);
|
||||
} else {
|
||||
runs.push(run);
|
||||
run = [twilightIndices[k]];
|
||||
}
|
||||
}
|
||||
runs.push(run);
|
||||
|
||||
// Use the LAST run (sunset). If only one run exists it's either sunrise-only
|
||||
// or a single dusk window — use it but we'll label generically.
|
||||
const sunsetRun = runs[runs.length - 1];
|
||||
const sunsetRows = sunsetRun.map(({ r }) => r);
|
||||
const isSunrise = runs.length === 1 && sunsetRows[0].elev < sunsetRows[sunsetRows.length - 1].elev;
|
||||
// If sun is rising through the band this is a sunrise window, not sunset — skip.
|
||||
if (isSunrise) return null;
|
||||
|
||||
const avgCloud = sunsetRows.reduce((s, r) => s + r.cc, 0) / sunsetRows.length;
|
||||
// We want some high cloud (colour) but not low cloud (obstruction)
|
||||
const avgLowCloud = sunsetRows.reduce((s, r) => s + (r.ccLow || 0), 0) / sunsetRows.length;
|
||||
if (avgLowCloud > 25) return null;
|
||||
if (avgCloud < 5 || avgCloud > 75) return null; // pure clear = less dramatic
|
||||
if (avgCloud < 5 || avgCloud > 75) return null;
|
||||
|
||||
// Store the ISO time range so getCellTagEvents can limit the icon to those hours
|
||||
const firstISO = sunsetRun[0].r.iso;
|
||||
const lastISO = sunsetRun[sunsetRun.length - 1].r.iso;
|
||||
|
||||
return {
|
||||
id: 'perfect-sunset',
|
||||
emoji: '🌅',
|
||||
title: 'Spectacular Sunset Conditions',
|
||||
message: `Low cloud is clear near the horizon but high cloud will scatter the light — conditions are ideal for a vivid sunset near ${location.name}.`,
|
||||
message: `Low cloud is clear near the horizon but high cloud will scatter the light — conditions look ideal for a vivid sunset near ${location.name}.`,
|
||||
color: '#3a1a00',
|
||||
textColor: '#ffe0b0',
|
||||
type: 'weather',
|
||||
nightOnly: false,
|
||||
isoRange: [firstISO, lastISO], // only show cell icon during these hours
|
||||
};
|
||||
}
|
||||
|
||||
@@ -709,6 +740,10 @@ export function getCellTagEvents(events, row) {
|
||||
if (ev.type === 'promo') return false;
|
||||
if (ev.nightOnly && row.elev >= -5) return false;
|
||||
if (ev.id === 'heat-spike' && row.elev < 0) return false;
|
||||
// Sunset/sunrise events: only show icon during the actual twilight window
|
||||
if (ev.isoRange) {
|
||||
if (row.iso < ev.isoRange[0] || row.iso > ev.isoRange[1]) return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user