Spaces:
Running
Running
Careful, i'm saying fill in the Health Score, Fault Problem, Energy Ledger, Latency & Cost, and Recent Alerts with template data
Browse files- index.html +41 -34
index.html
CHANGED
|
@@ -168,34 +168,40 @@ function setTheme(darkMode){
|
|
| 168 |
}
|
| 169 |
setTheme(dark);
|
| 170 |
document.getElementById('themeBtn').onclick = ()=>setTheme(!body.classList.contains('theme-dark'));
|
| 171 |
-
|
| 172 |
/* DEMO DATA GENERATION */
|
| 173 |
-
let lastHealth=0.
|
| 174 |
-
const dataHealth = Array(15*60).fill().map((_,i)=>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 175 |
const dataSag = [], dataSwell=[], dataOsc=[], dataLatency=[], dataCost=[], dataEnergy=[];
|
| 176 |
for(let i=0;i<60*24;i++){
|
| 177 |
-
const
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
}
|
| 185 |
|
| 186 |
-
const
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
feeder: feeders[Math.floor(Math.random() * feeders.length)],
|
| 194 |
-
fault: `${faultTypes[Math.floor(Math.random() * faultTypes.length)]} ${(0.7 + Math.random()*0.3).toFixed(2)}`,
|
| 195 |
-
eta: timeOffset < 60000 ? `${Math.floor(timeOffset/1000)} s` : `${Math.floor(timeOffset/60000)} m`,
|
| 196 |
-
action: actions[Math.floor(Math.random() * actions.length)]
|
| 197 |
-
};
|
| 198 |
-
}).sort((a,b) => b.time - a.time);
|
| 199 |
/* CHARTS */
|
| 200 |
function lineConfig(data,label,color,fill=false){
|
| 201 |
return {
|
|
@@ -234,19 +240,22 @@ window.onload = ()=>{
|
|
| 234 |
|
| 235 |
/* REFRESH UI */
|
| 236 |
function refresh(){
|
| 237 |
-
lastHealth = Math.max(0
|
| 238 |
-
document.getElementById('healthText').textContent = lastHealth.toFixed(2);
|
| 239 |
const gauge = document.getElementById('gauge');
|
| 240 |
let c = lastHealth>=0.8? '#22c55e':lastHealth>=0.5? '#f59e0b': '#ef4444';
|
| 241 |
gauge.style.borderColor = c;
|
| 242 |
-
|
| 243 |
-
|
|
|
|
| 244 |
document.getElementById('etaVal').textContent=eta;
|
| 245 |
const kpiEta = document.getElementById('kpiEta');
|
| 246 |
kpiEta.classList.toggle('blink', lastEta<60);
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
document.getElementById('
|
|
|
|
|
|
|
| 250 |
// alerts
|
| 251 |
const tbody = document.querySelector('#alertsTable tbody');
|
| 252 |
tbody.innerHTML='';
|
|
@@ -260,10 +269,8 @@ const eta = lastEta<60?Math.round(lastEta)+' s':`${Math.floor(lastEta/60)} m`;
|
|
| 260 |
<td class="italic">${a.action}</td>`;
|
| 261 |
tbody.append(tr);
|
| 262 |
});
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
showToast(`${fault} detected on ${feeders[Math.floor(Math.random() * feeders.length)]}`, {type:'warning'});
|
| 266 |
-
}
|
| 267 |
}
|
| 268 |
const format = dateFns.format;
|
| 269 |
setInterval(refresh,1000);
|
|
|
|
| 168 |
}
|
| 169 |
setTheme(dark);
|
| 170 |
document.getElementById('themeBtn').onclick = ()=>setTheme(!body.classList.contains('theme-dark'));
|
|
|
|
| 171 |
/* DEMO DATA GENERATION */
|
| 172 |
+
let lastHealth=0.92, lastEta=120;
|
| 173 |
+
const dataHealth = Array(15*60).fill().map((_,i)=>{
|
| 174 |
+
const x = Date.now()-i*1000;
|
| 175 |
+
// Simulate normal fluctuations with occasional dips
|
| 176 |
+
const base = 0.9 + Math.sin(i/300)*0.02;
|
| 177 |
+
const anomaly = i%500 < 10 ? -0.15 : 0; // Simulate brief anomalies
|
| 178 |
+
const noise = Math.random()*0.005;
|
| 179 |
+
return {x, y: Math.max(0.6, base + anomaly + noise)};
|
| 180 |
+
});
|
| 181 |
+
|
| 182 |
const dataSag = [], dataSwell=[], dataOsc=[], dataLatency=[], dataCost=[], dataEnergy=[];
|
| 183 |
for(let i=0;i<60*24;i++){
|
| 184 |
+
const x = Date.now()-i*60000;
|
| 185 |
+
// Fault probabilities with realistic patterns
|
| 186 |
+
dataSag.unshift({x, y: Math.max(0, 0.3 + Math.sin(i/120)*0.2 + (i%300<10?0.4:0) + Math.random()*0.1)});
|
| 187 |
+
dataSwell.unshift({x, y: Math.max(0, 0.2 + Math.sin(i/180)*0.15 + Math.random()*0.08)});
|
| 188 |
+
dataOsc.unshift({x, y: Math.max(0, 0.1 + Math.sin(i/240)*0.1 + (i%400<15?0.3:0) + Math.random()*0.05)});
|
| 189 |
+
|
| 190 |
+
// Energy and latency with daily patterns
|
| 191 |
+
const hour = (i/60)%24;
|
| 192 |
+
const isDay = hour > 6 && hour < 20;
|
| 193 |
+
dataLatency.unshift({x, y: (isDay ? 0.15 : 0.1) + Math.random()*0.03});
|
| 194 |
+
dataCost.unshift({x, y: ((isDay ? 0.15 : 0.1) + Math.random()*0.03)/1000});
|
| 195 |
+
dataEnergy.unshift({x, y: (isDay ? 0.008 : 0.005) + Math.random()*0.0015});
|
| 196 |
}
|
| 197 |
|
| 198 |
+
const alerts = [
|
| 199 |
+
{time:new Date(Date.now()-120000), feeder:"F03", fault:"Voltage Sag 0.82", eta:"45 s", action:"Notify crew"},
|
| 200 |
+
{time:new Date(Date.now()-300000), feeder:"F01", fault:"Frequency Osc 0.78", eta:"02:10", action:"Adjust set-point"},
|
| 201 |
+
{time:new Date(Date.now()-1800000), feeder:"F02", fault:"Current Swell 0.91", eta:"05:45", action:"Dispatch team"},
|
| 202 |
+
{time:new Date(Date.now()-3600000), feeder:"F04", fault:"Harmonic Dist 0.67", eta:"12:30", action:"Monitor"},
|
| 203 |
+
{time:new Date(Date.now()-7200000), feeder:"F01", fault:"Voltage Sag 0.88", eta:"08:15", action:"Reroute power"}
|
| 204 |
+
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 205 |
/* CHARTS */
|
| 206 |
function lineConfig(data,label,color,fill=false){
|
| 207 |
return {
|
|
|
|
| 240 |
|
| 241 |
/* REFRESH UI */
|
| 242 |
function refresh(){
|
| 243 |
+
lastHealth = Math.max(0,lastHealth-0.001+Math.random()*0.002);
|
| 244 |
+
document.getElementById('healthText').textContent = lastHealth.toFixed(2);
|
| 245 |
const gauge = document.getElementById('gauge');
|
| 246 |
let c = lastHealth>=0.8? '#22c55e':lastHealth>=0.5? '#f59e0b': '#ef4444';
|
| 247 |
gauge.style.borderColor = c;
|
| 248 |
+
|
| 249 |
+
lastEta = Math.max(0,lastEta-1+Math.random()*2);
|
| 250 |
+
const eta = lastEta<60?Math.round(lastEta)+' s':`${Math.floor(lastEta/60)} m`;
|
| 251 |
document.getElementById('etaVal').textContent=eta;
|
| 252 |
const kpiEta = document.getElementById('kpiEta');
|
| 253 |
kpiEta.classList.toggle('blink', lastEta<60);
|
| 254 |
+
const hour = new Date().getHours();
|
| 255 |
+
const isPeak = hour > 8 && hour < 20;
|
| 256 |
+
document.getElementById('latencyVal').textContent = (isPeak ? 0.15 : 0.1 + Math.random()*0.02).toFixed(2)+' ms';
|
| 257 |
+
document.getElementById('energyVal').textContent = (isPeak ? 0.008 : 0.005 + Math.random()*0.001).toFixed(3)+' Wh';
|
| 258 |
+
document.getElementById('co2Val').textContent = (2.4 + Math.sin(Date.now()/86400000)*0.3).toFixed(2)+' kg';
|
| 259 |
// alerts
|
| 260 |
const tbody = document.querySelector('#alertsTable tbody');
|
| 261 |
tbody.innerHTML='';
|
|
|
|
| 269 |
<td class="italic">${a.action}</td>`;
|
| 270 |
tbody.append(tr);
|
| 271 |
});
|
| 272 |
+
|
| 273 |
+
if(Math.random()>0.998) showToast('Fault probability threshold reached',{type:'warning'});
|
|
|
|
|
|
|
| 274 |
}
|
| 275 |
const format = dateFns.format;
|
| 276 |
setInterval(refresh,1000);
|