Small tweaks

This commit is contained in:
fraxle
2026-06-11 23:31:24 +01:00
parent 2608f93483
commit 5a95b875c2
7 changed files with 49 additions and 106 deletions
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File
File diff suppressed because one or more lines are too long
+33 -5
View File
@@ -12,20 +12,48 @@
// ------------------------------------------------------------------------
export function checkStargazing(rows) {
// Great stargazing: mostly clear night hours with low cloud
// Great stargazing: mostly clear night hours with low cloud.
// Split night into contiguous runs (pre-dawn vs post-dusk) and evaluate
// each independently so a cloudy evening doesn't suppress a clear morning
// (or vice versa), and so the icon is pinned to only the clear hours.
const nightRows = rows.filter(r => r.elev < -5);
if (nightRows.length < 3) return null;
const avgCloud = nightRows.reduce((s, r) => s + r.cc, 0) / nightRows.length;
if (avgCloud > 30) return null;
// Build contiguous runs — a gap > 2 h means we've crossed daytime.
const runs = [];
let cur = [nightRows[0]];
for (let i = 1; i < nightRows.length; i++) {
const dtDiff = (new Date(nightRows[i].iso) - new Date(nightRows[i - 1].iso)) / 3600000;
if (dtDiff <= 2) { cur.push(nightRows[i]); }
else { runs.push(cur); cur = [nightRows[i]]; }
}
runs.push(cur);
// Evaluate each run; among those passing ≤30% avg cloud prefer the evening
// run (actionable for tonight) then fall back to whichever is clearest.
let bestRun = null, bestAvg = Infinity;
for (const run of runs) {
if (run.length < 2) continue;
const avg = run.reduce((s, r) => s + r.cc, 0) / run.length;
if (avg > 30) continue;
const isEvening = parseInt(run[0].iso.slice(11, 13), 10) >= 12;
if (!bestRun || (isEvening && parseInt(bestRun[0].iso.slice(11, 13), 10) < 12) || avg < bestAvg) {
bestRun = run; bestAvg = avg;
}
}
if (!bestRun) return null;
const isPreDawn = parseInt(bestRun[0].iso.slice(11, 13), 10) < 12;
return {
id: 'stargazing',
emoji: '⭐',
title: 'Great Stargazing Tonight',
message: `Clear skies expected overnight at ${nightRows.length} hours with average ${Math.round(avgCloud)}% cloud — ideal conditions for stargazing.`,
title: isPreDawn ? 'Great Stargazing Overnight' : 'Great Stargazing Tonight',
message: `Clear skies expected for ${bestRun.length} hours overnight with average ${Math.round(bestAvg)}% cloud — ideal conditions for stargazing.`,
color: '#080e1a',
textColor: '#c8dcff',
type: 'weather',
nightOnly: true,
isoRange: [bestRun[0].iso, bestRun[bestRun.length - 1].iso],
};
}
+15 -2
View File
@@ -18,9 +18,22 @@
}
},
"2026-06-11": {
"visits": 28,
"visits": 31,
"profiles": {
"showall": 1
"showall": 11,
"custom": 9,
"alltemps": 1,
"vehicle": 3,
"home": 4,
"basic": 5,
"farming": 1
}
},
"2026-06-12": {
"visits": 1,
"profiles": {
"showall": 1,
"basic": 1
}
}
}
-38
View File
@@ -1,38 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>scope cell</title>
<link rel="stylesheet" href="./assets/css/header.css" />
<style>
html,body { margin:0; height:100%; background: transparent; overflow: hidden; }
#cell { display:flex; align-items:center; justify-content:center; height:100%; }
.scope-ring { width: 200px; height: 200px; }
</style>
</head>
<body>
<div id="cell"></div>
<script type="module">
import { h, render } from './assets/vendor/preact.js';
const { ScopeReticle } = await import('./assets/js/components.js?v=' + Date.now());
const q = new URLSearchParams(location.search);
const n = (k, d) => { const v = q.get(k); return v == null ? d : Number(v); };
// hour drives the rising/setting palette (UTC hour < 12 => sunrise tints).
const dt = new Date(Date.UTC(2026, 5, 6, n('hour', 12), 0, 0));
const cat = { label: 'Comfortable', bg: '#90d090', fg: '#157a15' };
const storm = q.get('storm') === '1';
render(h(ScopeReticle, {
value: 12.4, cat, loading: false,
elev: n('elev', 30), dt, glob: n('glob', 400),
activeEvent: storm ? { id: 'storm' } : null,
cc: n('cc', 0), ccLow: n('ccLow', 0), ccMid: n('ccMid', 0), ccHigh: n('ccHigh', 0),
precip: n('precip', 0), snow: n('snow', 0), visKm: n('vis', 30),
env: q.get('env') || 'open',
wind: n('wind', 0), gust: n('gust', 0), wd: q.get('wd') != null ? n('wd', 0) : null,
}), document.getElementById('cell'));
</script>
</body>
</html>
-61
View File
@@ -1,61 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>SunScope — Ground Lab (dev)</title>
<style>
body { margin: 0; background: #1a140c; font-family: Manrope, system-ui, sans-serif; color: #f5edd6; }
h1 { text-align: center; font-weight: 700; font-size: 18px; padding: 14px 0 2px; opacity: 0.8; }
p.note { text-align:center; opacity:0.45; font-size:12px; margin:0 0 10px; }
.row-label { text-align:center; font-size:12px; font-weight:700; opacity:0.6; margin:14px 0 2px; letter-spacing:1px; text-transform:uppercase; }
.grid { display: grid; grid-template-columns: repeat(8, 150px); gap: 6px 8px; justify-content: center; padding: 0 12px; }
.cell { display: flex; flex-direction: column; align-items: center; }
.label { font-size: 11px; font-weight: 700; opacity: 0.85; }
iframe { width: 150px; height: 150px; border: 0; background: transparent; }
</style>
</head>
<body>
<h1>SunScope — Ground Lab</h1>
<p class="note">dev preview · per-environment grounds across the cycle</p>
<div id="lab"></div>
<script>
const envs = ['open','forest','alpine','urban','beach','openwater','desert','river'];
const envName = { open:'Grass', forest:'Forest', alpine:'Alpine', urban:'City', beach:'Beach', openwater:'Open Water', desert:'Desert', river:'River' };
// [rowLabel, base query]
const rows = [
['Midday · clear', 'elev=45&hour=12&glob=800&cc=0&vis=30'],
['Sunset · clear', 'elev=2&hour=19&glob=110&cc=10&vis=30'],
['Night · clear', 'elev=-15&hour=23&glob=0&cc=10&vis=30'],
['Midday · overcast','elev=45&hour=12&glob=300&cc=95&ccLow=90&ccMid=70&vis=18'],
['Day · rain', 'elev=40&hour=12&glob=220&cc=98&ccLow=92&ccMid=75&precip=5&vis=6'],
['Day · snow', 'elev=30&hour=12&glob=200&cc=95&ccLow=90&snow=1.2&vis=4'],
];
const lab = document.getElementById('lab');
for (const [rowLabel, q] of rows) {
const rl = document.createElement('div');
rl.className = 'row-label';
rl.textContent = rowLabel;
lab.appendChild(rl);
const grid = document.createElement('div');
grid.className = 'grid';
for (const env of envs) {
const cell = document.createElement('div');
cell.className = 'cell';
const lbl = document.createElement('span');
lbl.className = 'label';
lbl.textContent = envName[env];
const ifr = document.createElement('iframe');
ifr.src = `./scope-cell?${q}&env=${env}&_=${Date.now()}`;
ifr.loading = 'eager';
cell.append(lbl, ifr);
grid.append(cell);
}
lab.appendChild(grid);
}
</script>
</body>
</html>