Spaces:
Running
Running
Fill in Health Score, Fault Probabilities, Energy ledger, Latency and Cost and Recent Alerts with template data
Browse files- index.html +53 -68
index.html
CHANGED
|
@@ -170,73 +170,56 @@ setTheme(dark);
|
|
| 170 |
document.getElementById('themeBtn').onclick = ()=>setTheme(!body.classList.contains('theme-dark'));
|
| 171 |
/* DEMO DATA GENERATION */
|
| 172 |
let lastHealth=0.94, lastEta=180;
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
const
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
return {x, y: Math.max(0.7, base + failure + noise)};
|
| 194 |
-
});
|
| 195 |
|
| 196 |
-
//
|
| 197 |
-
const
|
| 198 |
-
for(let i=0;i<
|
| 199 |
-
const
|
| 200 |
-
|
| 201 |
-
const
|
| 202 |
-
|
| 203 |
-
// Voltage Sag (most common during peak hours)
|
| 204 |
-
let sagProb = isPeak ? 0.25 : 0.15;
|
| 205 |
-
sagProb += Math.sin(i/180) * 0.1; // cyclic pattern every 3 hours
|
| 206 |
-
if(i % (7*60) === 0 && Math.random() > 0.7) sagProb += 0.3; // random spikes
|
| 207 |
-
dataSag.unshift({x, y: Math.min(0.9, Math.max(0, sagProb + Math.random()*0.05))});
|
| 208 |
-
|
| 209 |
-
// Voltage Swell (less common)
|
| 210 |
-
let swellProb = isPeak ? 0.18 : 0.1;
|
| 211 |
-
swellProb += Math.sin(i/240) * 0.08;
|
| 212 |
-
if(i % (10*60) === 0 && Math.random() > 0.8) swellProb += 0.2;
|
| 213 |
-
dataSwell.unshift({x, y: Math.min(0.8, Math.max(0, swellProb + Math.random()*0.03))});
|
| 214 |
-
|
| 215 |
-
// Frequency Oscillation (rare but important)
|
| 216 |
-
let oscProb = isPeak ? 0.12 : 0.08;
|
| 217 |
-
oscProb += Math.sin(i/300) * 0.05;
|
| 218 |
-
if(i % (15*60) === 0 && Math.random() > 0.9) oscProb += 0.25;
|
| 219 |
-
dataOsc.unshift({x, y: Math.min(0.7, Math.max(0, oscProb + Math.random()*0.02))});
|
| 220 |
-
|
| 221 |
-
// Latency & Cost (better at night)
|
| 222 |
-
const latency = isPeak ? 0.18 + Math.random()*0.04 : 0.12 + Math.random()*0.03;
|
| 223 |
-
dataLatency.unshift({x, y: latency});
|
| 224 |
-
dataCost.unshift({x, y: latency / 1500}); // cost proportional to latency
|
| 225 |
-
|
| 226 |
-
// Energy consumption
|
| 227 |
-
const energy = isPeak ? 0.0095 + Math.random()*0.002 : 0.006 + Math.random()*0.0015;
|
| 228 |
-
dataEnergy.unshift({x, y: energy});
|
| 229 |
}
|
| 230 |
|
| 231 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 232 |
const alerts = [
|
| 233 |
-
{time:new Date(
|
| 234 |
-
{time:new Date(
|
| 235 |
-
{time:new Date(
|
| 236 |
-
{time:new Date(
|
| 237 |
-
{time:new Date(
|
| 238 |
-
{time:new Date(
|
| 239 |
-
{time:new Date(
|
| 240 |
];
|
| 241 |
/* CHARTS */
|
| 242 |
function lineConfig(data,label,color,fill=false){
|
|
@@ -281,7 +264,6 @@ function refresh(){
|
|
| 281 |
const gauge = document.getElementById('gauge');
|
| 282 |
let c = lastHealth>=0.8? '#22c55e':lastHealth>=0.5? '#f59e0b': '#ef4444';
|
| 283 |
gauge.style.borderColor = c;
|
| 284 |
-
|
| 285 |
lastEta = Math.max(0,lastEta-1+Math.random()*2);
|
| 286 |
const eta = lastEta<60?Math.round(lastEta)+' s':`${Math.floor(lastEta/60)} m`;
|
| 287 |
document.getElementById('etaVal').textContent=eta;
|
|
@@ -289,10 +271,13 @@ function refresh(){
|
|
| 289 |
kpiEta.classList.toggle('blink', lastEta<60);
|
| 290 |
const hour = new Date().getHours();
|
| 291 |
const isPeak = hour > 8 && hour < 20;
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
|
|
|
|
|
|
|
|
|
| 296 |
const tbody = document.querySelector('#alertsTable tbody');
|
| 297 |
tbody.innerHTML='';
|
| 298 |
alerts.forEach(a=>{
|
|
|
|
| 170 |
document.getElementById('themeBtn').onclick = ()=>setTheme(!body.classList.contains('theme-dark'));
|
| 171 |
/* DEMO DATA GENERATION */
|
| 172 |
let lastHealth=0.94, lastEta=180;
|
| 173 |
+
// Template data for Health Score (15 minutes, updated every second)
|
| 174 |
+
const dataHealth = [];
|
| 175 |
+
const now = Date.now();
|
| 176 |
+
for (let i = 0; i < 15 * 60; i++) {
|
| 177 |
+
const time = now - (15 * 60 - i) * 1000;
|
| 178 |
+
// Use template values that vary realistically
|
| 179 |
+
const values = [0.95, 0.94, 0.93, 0.92, 0.91, 0.90, 0.89, 0.88, 0.87, 0.86];
|
| 180 |
+
const value = values[i % values.length] + (Math.random() * 0.02 - 0.01);
|
| 181 |
+
dataHealth.push({ x: time, y: Math.max(0.85, Math.min(0.96, value)) });
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
// Template data for Fault Probabilities (24 hours, updated every minute)
|
| 185 |
+
const dataSag = [], dataSwell = [], dataOsc = [];
|
| 186 |
+
for (let i = 0; i < 24 * 60; i++) {
|
| 187 |
+
const time = now - (24 * 60 - i) * 60000;
|
| 188 |
+
// Use template patterns for each fault type
|
| 189 |
+
dataSag.push({ x: time, y: 0.1 + 0.1 * Math.sin(i / 30) + Math.random() * 0.05 });
|
| 190 |
+
dataSwell.push({ x: time, y: 0.05 + 0.08 * Math.sin(i / 45 + 1) + Math.random() * 0.03 });
|
| 191 |
+
dataOsc.push({ x: time, y: 0.02 + 0.06 * Math.sin(i / 60 + 2) + Math.random() * 0.02 });
|
| 192 |
+
}
|
|
|
|
|
|
|
| 193 |
|
| 194 |
+
// Template data for Energy Ledger (24 hours, hourly data)
|
| 195 |
+
const dataEnergy = [];
|
| 196 |
+
for (let i = 0; i < 24; i++) {
|
| 197 |
+
const time = now - (23 - i) * 3600000;
|
| 198 |
+
// Template energy consumption pattern
|
| 199 |
+
const base = 0.005 + 0.003 * Math.sin(i / 4);
|
| 200 |
+
dataEnergy.push({ x: time, y: base + Math.random() * 0.002 });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 201 |
}
|
| 202 |
|
| 203 |
+
// Template data for Latency & Cost (24 hours, hourly data)
|
| 204 |
+
const dataLatency = [], dataCost = [];
|
| 205 |
+
for (let i = 0; i < 24; i++) {
|
| 206 |
+
const time = now - (23 - i) * 3600000;
|
| 207 |
+
// Template latency pattern
|
| 208 |
+
const latency = 0.1 + 0.05 * Math.sin(i / 3) + Math.random() * 0.02;
|
| 209 |
+
dataLatency.push({ x: time, y: latency });
|
| 210 |
+
// Cost derived from latency
|
| 211 |
+
dataCost.push({ x: time, y: latency * 0.0005 });
|
| 212 |
+
}
|
| 213 |
+
|
| 214 |
+
// Template data for Recent Alerts
|
| 215 |
const alerts = [
|
| 216 |
+
{time:new Date(now-2*60000), feeder:"F01", fault:"Voltage Sag 0.85", eta:"32 s", action:"Adjust tap changer"},
|
| 217 |
+
{time:new Date(now-5*60000), feeder:"F02", fault:"Current Swell 0.78", eta:"1:45", action:"Notify maintenance"},
|
| 218 |
+
{time:new Date(now-10*60000), feeder:"F03", fault:"Frequency Osc 0.65", eta:"2:10", action:"Monitor"},
|
| 219 |
+
{time:new Date(now-30*60000), feeder:"F04", fault:"Harmonic Dist 0.72", eta:"4:30", action:"Schedule filter check"},
|
| 220 |
+
{time:new Date(now-60*60000), feeder:"F05", fault:"Voltage Dip 0.88", eta:"12:30", action:"Reroute load"},
|
| 221 |
+
{time:new Date(now-90*60000), feeder:"F06", fault:"Phase Unbalance 0.81", eta:"6:15", action:"Balance load"},
|
| 222 |
+
{time:new Date(now-120*60000), feeder:"F07", fault:"Capacitor Bank Fail", eta:"8:20", action:"Dispatch crew"}
|
| 223 |
];
|
| 224 |
/* CHARTS */
|
| 225 |
function lineConfig(data,label,color,fill=false){
|
|
|
|
| 264 |
const gauge = document.getElementById('gauge');
|
| 265 |
let c = lastHealth>=0.8? '#22c55e':lastHealth>=0.5? '#f59e0b': '#ef4444';
|
| 266 |
gauge.style.borderColor = c;
|
|
|
|
| 267 |
lastEta = Math.max(0,lastEta-1+Math.random()*2);
|
| 268 |
const eta = lastEta<60?Math.round(lastEta)+' s':`${Math.floor(lastEta/60)} m`;
|
| 269 |
document.getElementById('etaVal').textContent=eta;
|
|
|
|
| 271 |
kpiEta.classList.toggle('blink', lastEta<60);
|
| 272 |
const hour = new Date().getHours();
|
| 273 |
const isPeak = hour > 8 && hour < 20;
|
| 274 |
+
// Use template values for latency and energy
|
| 275 |
+
const latencyVal = isPeak ? 0.15 + Math.random() * 0.03 : 0.12 + Math.random() * 0.02;
|
| 276 |
+
const energyVal = isPeak ? 0.008 + Math.random() * 0.0015 : 0.006 + Math.random() * 0.0012;
|
| 277 |
+
document.getElementById('latencyVal').textContent = latencyVal.toFixed(2) + ' ms';
|
| 278 |
+
document.getElementById('energyVal').textContent = energyVal.toFixed(3) + ' Wh';
|
| 279 |
+
document.getElementById('co2Val').textContent = (2.1 + Math.random() * 0.2).toFixed(1) + ' kg';
|
| 280 |
+
// alerts
|
| 281 |
const tbody = document.querySelector('#alertsTable tbody');
|
| 282 |
tbody.innerHTML='';
|
| 283 |
alerts.forEach(a=>{
|