51 lines
1.5 KiB
JavaScript
51 lines
1.5 KiB
JavaScript
// door ranges
|
||
const doors = [
|
||
...Array.from({length: 138 - 124 + 1}, (_, i) => 124 + i),
|
||
...Array.from({length: 201 - 142 + 1}, (_, i) => 142 + i),
|
||
...Array.from({length: 209 - 202 + 1}, (_, i) => 202 + i),
|
||
];
|
||
|
||
// NOAA heat‐index formula
|
||
function getColorFromHI(H) {
|
||
const pct = Math.min(Math.max((H - 70) / 30, 0), 1);
|
||
const r = 255;
|
||
const g = Math.round(255 * (1 - pct));
|
||
return `rgba(${r},${g},0,0.8)`;
|
||
}
|
||
|
||
function createGrid() {
|
||
const row = document.getElementById('dock-row');
|
||
doors.forEach(d => {
|
||
const sq = document.createElement('div');
|
||
sq.className = 'dock-square';
|
||
sq.dataset.door = d;
|
||
row.appendChild(sq);
|
||
});
|
||
}
|
||
|
||
// apply a new reading to its square
|
||
function colorize(door, hi) {
|
||
const sq = document.querySelector(`.dock-square[data-door="${door}"]`);
|
||
if (!sq) return;
|
||
sq.style.background = getColorFromHI(hi);
|
||
}
|
||
|
||
async function init() {
|
||
createGrid();
|
||
// initial fill
|
||
const all = await fetch('/api/readings').then(r=>r.json());
|
||
// pick latest per door
|
||
const latest = {};
|
||
all.forEach(r => { latest[r.dockDoor] = r.heatIndex; });
|
||
Object.entries(latest).forEach(([door, hi]) => colorize(door, hi));
|
||
|
||
// subscribe SSE
|
||
const es = new EventSource('/api/stream');
|
||
es.addEventListener('new-reading', e => {
|
||
const { dockDoor, heatIndex } = JSON.parse(e.data);
|
||
colorize(dockDoor, heatIndex);
|
||
});
|
||
}
|
||
|
||
document.addEventListener('DOMContentLoaded', init);
|
||
|