Spaces:
Running
Running
processing speed enhancements x 2
Browse files- frontend/js/vehicles.js +56 -8
- frontend/vehicles.html +1 -1
frontend/js/vehicles.js
CHANGED
|
@@ -1011,12 +1011,46 @@ window.switchTab = switchTab;
|
|
| 1011 |
let liveCongestion = [];
|
| 1012 |
let liveFlowTimes = [];
|
| 1013 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1014 |
ws.onmessage = e => {
|
| 1015 |
const d = JSON.parse(e.data);
|
| 1016 |
|
| 1017 |
if (!firstMessageReceived) {
|
| 1018 |
firstMessageReceived = true;
|
| 1019 |
document.getElementById('proc-label').innerText = 'Processing';
|
|
|
|
| 1020 |
}
|
| 1021 |
|
| 1022 |
// Hide empty state on first data
|
|
@@ -1024,6 +1058,7 @@ window.switchTab = switchTab;
|
|
| 1024 |
if (emptyState) emptyState.style.display = 'none';
|
| 1025 |
if (d.error) {
|
| 1026 |
processingDone = true;
|
|
|
|
| 1027 |
document.getElementById('proc-label').innerText = 'Engine Error';
|
| 1028 |
console.error('[UrbanFlow] Engine error:', d.detail || d.error);
|
| 1029 |
document.getElementById('run-results-content').innerHTML = `
|
|
@@ -1040,6 +1075,7 @@ window.switchTab = switchTab;
|
|
| 1040 |
|
| 1041 |
if (d.done) {
|
| 1042 |
processingDone = true;
|
|
|
|
| 1043 |
|
| 1044 |
// Stats Tracking (Scoped by email)
|
| 1045 |
const session = (typeof getAuthSession === 'function') ? getAuthSession() : null;
|
|
@@ -1131,14 +1167,27 @@ window.switchTab = switchTab;
|
|
| 1131 |
return;
|
| 1132 |
}
|
| 1133 |
|
| 1134 |
-
|
| 1135 |
-
|
| 1136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1137 |
document.getElementById('proc-frames').innerText = `${d.frame_index} / ${d.total_iters} Frames`;
|
| 1138 |
-
|
| 1139 |
-
const procPctEl = document.getElementById('proc-pct');
|
| 1140 |
-
const currPct = parseFloat(procPctEl.innerText) || 0;
|
| 1141 |
-
animateValue(procPctEl, currPct, pct + '%', 300);
|
| 1142 |
|
| 1143 |
const totalIn = sumValues(d.class_in);
|
| 1144 |
const totalOut = sumValues(d.class_out);
|
|
@@ -1168,7 +1217,6 @@ window.switchTab = switchTab;
|
|
| 1168 |
}
|
| 1169 |
}
|
| 1170 |
|
| 1171 |
-
const now = performance.now();
|
| 1172 |
if (now - lastUIUpdate < 150) return;
|
| 1173 |
lastUIUpdate = now;
|
| 1174 |
|
|
|
|
| 1011 |
let liveCongestion = [];
|
| 1012 |
let liveFlowTimes = [];
|
| 1013 |
|
| 1014 |
+
// ---- Smooth progress interpolation ----
|
| 1015 |
+
// Predicts progress between real frame updates so the bar never "freezes"
|
| 1016 |
+
let lastRealPct = 0;
|
| 1017 |
+
let lastRealTime = 0;
|
| 1018 |
+
let pctPerMs = 0; // observed speed: % gained per ms
|
| 1019 |
+
let interpPct = 0; // current interpolated display %
|
| 1020 |
+
let interpRAF = null;
|
| 1021 |
+
|
| 1022 |
+
function startProgressInterpolation() {
|
| 1023 |
+
const bar = document.getElementById('proc-bar');
|
| 1024 |
+
const pctEl = document.getElementById('proc-pct');
|
| 1025 |
+
|
| 1026 |
+
function tick() {
|
| 1027 |
+
if (processingDone) return;
|
| 1028 |
+
const now = performance.now();
|
| 1029 |
+
const elapsed = now - lastRealTime;
|
| 1030 |
+
|
| 1031 |
+
if (pctPerMs > 0 && lastRealPct < 99.5) {
|
| 1032 |
+
// Predict forward, but cap at ~halfway to the next expected frame
|
| 1033 |
+
// to avoid overshoot before the next real update arrives
|
| 1034 |
+
const predicted = lastRealPct + (elapsed * pctPerMs * 0.85);
|
| 1035 |
+
const cap = Math.min(predicted, lastRealPct + (pctPerMs * 3000), 99.5);
|
| 1036 |
+
if (cap > interpPct) {
|
| 1037 |
+
interpPct = cap;
|
| 1038 |
+
bar.style.width = interpPct.toFixed(1) + '%';
|
| 1039 |
+
pctEl.innerText = Math.floor(interpPct) + '%';
|
| 1040 |
+
}
|
| 1041 |
+
}
|
| 1042 |
+
interpRAF = requestAnimationFrame(tick);
|
| 1043 |
+
}
|
| 1044 |
+
interpRAF = requestAnimationFrame(tick);
|
| 1045 |
+
}
|
| 1046 |
+
|
| 1047 |
ws.onmessage = e => {
|
| 1048 |
const d = JSON.parse(e.data);
|
| 1049 |
|
| 1050 |
if (!firstMessageReceived) {
|
| 1051 |
firstMessageReceived = true;
|
| 1052 |
document.getElementById('proc-label').innerText = 'Processing';
|
| 1053 |
+
startProgressInterpolation();
|
| 1054 |
}
|
| 1055 |
|
| 1056 |
// Hide empty state on first data
|
|
|
|
| 1058 |
if (emptyState) emptyState.style.display = 'none';
|
| 1059 |
if (d.error) {
|
| 1060 |
processingDone = true;
|
| 1061 |
+
if (interpRAF) cancelAnimationFrame(interpRAF);
|
| 1062 |
document.getElementById('proc-label').innerText = 'Engine Error';
|
| 1063 |
console.error('[UrbanFlow] Engine error:', d.detail || d.error);
|
| 1064 |
document.getElementById('run-results-content').innerHTML = `
|
|
|
|
| 1075 |
|
| 1076 |
if (d.done) {
|
| 1077 |
processingDone = true;
|
| 1078 |
+
if (interpRAF) cancelAnimationFrame(interpRAF);
|
| 1079 |
|
| 1080 |
// Stats Tracking (Scoped by email)
|
| 1081 |
const session = (typeof getAuthSession === 'function') ? getAuthSession() : null;
|
|
|
|
| 1167 |
return;
|
| 1168 |
}
|
| 1169 |
|
| 1170 |
+
// ---- Real frame update: recalibrate interpolation ----
|
| 1171 |
+
let pct = ((d.frame_index / d.total_iters) * 100);
|
| 1172 |
+
if (d.frame_index >= d.total_iters - 1) pct = 100;
|
| 1173 |
+
|
| 1174 |
+
const now = performance.now();
|
| 1175 |
+
if (lastRealTime > 0 && pct > lastRealPct) {
|
| 1176 |
+
const dt = now - lastRealTime;
|
| 1177 |
+
const dp = pct - lastRealPct;
|
| 1178 |
+
// Exponential moving average of speed for stability
|
| 1179 |
+
const newRate = dp / dt;
|
| 1180 |
+
pctPerMs = pctPerMs > 0 ? (pctPerMs * 0.6 + newRate * 0.4) : newRate;
|
| 1181 |
+
}
|
| 1182 |
+
lastRealPct = pct;
|
| 1183 |
+
lastRealTime = now;
|
| 1184 |
+
|
| 1185 |
+
// Snap bar + percentage to real value (interpolation was just a prediction)
|
| 1186 |
+
interpPct = pct;
|
| 1187 |
+
const pctStr = pct.toFixed(1);
|
| 1188 |
+
document.getElementById('proc-bar').style.width = pctStr + '%';
|
| 1189 |
document.getElementById('proc-frames').innerText = `${d.frame_index} / ${d.total_iters} Frames`;
|
| 1190 |
+
document.getElementById('proc-pct').innerText = Math.floor(pct) + '%';
|
|
|
|
|
|
|
|
|
|
| 1191 |
|
| 1192 |
const totalIn = sumValues(d.class_in);
|
| 1193 |
const totalOut = sumValues(d.class_out);
|
|
|
|
| 1217 |
}
|
| 1218 |
}
|
| 1219 |
|
|
|
|
| 1220 |
if (now - lastUIUpdate < 150) return;
|
| 1221 |
lastUIUpdate = now;
|
| 1222 |
|
frontend/vehicles.html
CHANGED
|
@@ -149,7 +149,7 @@
|
|
| 149 |
<span class="text-[11px] font-black text-white uppercase tracking-wider whitespace-nowrap"
|
| 150 |
id="proc-label">Waiting</span>
|
| 151 |
<div class="flex-1 h-2 bg-[#111111] rounded-full overflow-hidden relative border border-[#1a1a1a]">
|
| 152 |
-
<div id="proc-bar" class="h-full bg-[#444444] rounded-full
|
| 153 |
style="width: 0%"></div>
|
| 154 |
</div>
|
| 155 |
</div>
|
|
|
|
| 149 |
<span class="text-[11px] font-black text-white uppercase tracking-wider whitespace-nowrap"
|
| 150 |
id="proc-label">Waiting</span>
|
| 151 |
<div class="flex-1 h-2 bg-[#111111] rounded-full overflow-hidden relative border border-[#1a1a1a]">
|
| 152 |
+
<div id="proc-bar" class="h-full bg-[#444444] rounded-full"
|
| 153 |
style="width: 0%"></div>
|
| 154 |
</div>
|
| 155 |
</div>
|