Add experiment_results_visualization/js/ui.js
This commit is contained in:
parent
0e33154c45
commit
0a3b8c027a
1 changed files with 161 additions and 0 deletions
161
experiment_results_visualization/js/ui.js
Normal file
161
experiment_results_visualization/js/ui.js
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
/**
|
||||
* UI Update Module for Experiment Results Visualization
|
||||
* Handles summary cards, charts, and table rendering.
|
||||
* @module ui
|
||||
*/
|
||||
|
||||
/**
|
||||
* Renders statistical summary cards.
|
||||
* @param {Object} experiment_data - Contains pinned and unpinned experiment results.
|
||||
*/
|
||||
export function renderSummary(experiment_data) {
|
||||
const container = document.querySelector('.summary-section');
|
||||
if (!container) return;
|
||||
container.innerHTML = '';
|
||||
|
||||
const createCard = (title, value) => {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'summary-card';
|
||||
const heading = document.createElement('h3');
|
||||
heading.textContent = title;
|
||||
const valElem = document.createElement('p');
|
||||
valElem.textContent = value;
|
||||
card.appendChild(heading);
|
||||
card.appendChild(valElem);
|
||||
return card;
|
||||
};
|
||||
|
||||
const pinned = experiment_data?.pinned ?? [];
|
||||
const unpinned = experiment_data?.unpinned ?? [];
|
||||
|
||||
const pinnedLatencies = pinned.map(r => r.latency_ms ?? 0);
|
||||
const unpinnedLatencies = unpinned.map(r => r.latency_ms ?? 0);
|
||||
const percentiles = (arr, p) => {
|
||||
if (!arr.length) return 0;
|
||||
const sorted = [...arr].sort((a, b) => a - b);
|
||||
const idx = Math.floor((p / 100) * sorted.length);
|
||||
return sorted[idx] ?? 0;
|
||||
};
|
||||
|
||||
const pinnedP95 = percentiles(pinnedLatencies, 95).toFixed(2);
|
||||
const pinnedP99 = percentiles(pinnedLatencies, 99).toFixed(2);
|
||||
const unpinnedP95 = percentiles(unpinnedLatencies, 95).toFixed(2);
|
||||
const unpinnedP99 = percentiles(unpinnedLatencies, 99).toFixed(2);
|
||||
|
||||
const correlation = (() => {
|
||||
if (pinnedLatencies.length !== unpinnedLatencies.length || !pinnedLatencies.length) return 0;
|
||||
const avgPinned = pinnedLatencies.reduce((a,b)=>a+b,0)/pinnedLatencies.length;
|
||||
const avgUnpinned = unpinnedLatencies.reduce((a,b)=>a+b,0)/unpinnedLatencies.length;
|
||||
let num=0,den1=0,den2=0;
|
||||
for(let i=0;i<pinnedLatencies.length;i++){
|
||||
const x = pinnedLatencies[i] - avgPinned;
|
||||
const y = unpinnedLatencies[i] - avgUnpinned;
|
||||
num += x*y;
|
||||
den1 += x*x;
|
||||
den2 += y*y;
|
||||
}
|
||||
return (num / Math.sqrt(den1 * den2)).toFixed(3);
|
||||
})();
|
||||
|
||||
container.appendChild(createCard('Pinned p95', `${pinnedP95} ms`));
|
||||
container.appendChild(createCard('Pinned p99', `${pinnedP99} ms`));
|
||||
container.appendChild(createCard('Unpinned p95', `${unpinnedP95} ms`));
|
||||
container.appendChild(createCard('Unpinned p99', `${unpinnedP99} ms`));
|
||||
container.appendChild(createCard('Correlation (latency)', correlation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders comparative charts for pinned vs unpinned runs.
|
||||
* Expects charting library available in global scope (e.g., Chart.js or similar).
|
||||
* @param {Object} experiment_data - Experiment dataset
|
||||
*/
|
||||
export function renderCharts(experiment_data) {
|
||||
const pinned = experiment_data?.pinned ?? [];
|
||||
const unpinned = experiment_data?.unpinned ?? [];
|
||||
const pinnedCanvas = document.getElementById('chart-pinned');
|
||||
const unpinnedCanvas = document.getElementById('chart-unpinned');
|
||||
if (!pinnedCanvas || !unpinnedCanvas) return;
|
||||
|
||||
const pinnedData = pinned.map(r => r.latency_ms ?? 0);
|
||||
const unpinnedData = unpinned.map(r => r.latency_ms ?? 0);
|
||||
const labels = pinned.map((_, i) => `Run ${i+1}`);
|
||||
|
||||
const createChart = (ctx, label, data, color) => {
|
||||
if (!window.Chart) return;
|
||||
if (ctx.__chartInstance) ctx.__chartInstance.destroy();
|
||||
ctx.__chartInstance = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels,
|
||||
datasets: [{
|
||||
label,
|
||||
data,
|
||||
borderColor: color,
|
||||
backgroundColor: 'transparent',
|
||||
borderWidth: 2
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
y: { beginAtZero: false }
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
createChart(pinnedCanvas.getContext('2d'), 'Pinned Latency (ms)', pinnedData, '#4caf50');
|
||||
createChart(unpinnedCanvas.getContext('2d'), 'Unpinned Latency (ms)', unpinnedData, '#f44336');
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a table view of runs data.
|
||||
* @param {Object} experiment_data - Dataset from API including pinned and unpinned.
|
||||
*/
|
||||
export function renderTable(experiment_data) {
|
||||
const container = document.querySelector('.runs-table');
|
||||
if (!container) return;
|
||||
|
||||
const pinned = experiment_data?.pinned ?? [];
|
||||
const unpinned = experiment_data?.unpinned ?? [];
|
||||
|
||||
const table = document.createElement('table');
|
||||
table.className = 'runs-table__inner';
|
||||
|
||||
const thead = document.createElement('thead');
|
||||
thead.innerHTML = `
|
||||
<tr>
|
||||
<th>Run ID</th>
|
||||
<th>Type</th>
|
||||
<th>Latency (ms)</th>
|
||||
<th>Timestamp</th>
|
||||
</tr>
|
||||
`;
|
||||
table.appendChild(thead);
|
||||
|
||||
const tbody = document.createElement('tbody');
|
||||
|
||||
const makeRow = (run, type) => {
|
||||
const tr = document.createElement('tr');
|
||||
const tdId = document.createElement('td');
|
||||
const tdType = document.createElement('td');
|
||||
const tdLatency = document.createElement('td');
|
||||
const tdTime = document.createElement('td');
|
||||
|
||||
tdId.textContent = run.id ?? '-';
|
||||
tdType.textContent = type;
|
||||
tdLatency.textContent = run.latency_ms?.toFixed(2) ?? '-';
|
||||
tdTime.textContent = new Date(run.timestamp ?? Date.now()).toLocaleString();
|
||||
|
||||
tr.append(tdId, tdType, tdLatency, tdTime);
|
||||
return tr;
|
||||
};
|
||||
|
||||
pinned.forEach(run => tbody.appendChild(makeRow(run, 'pinned')));
|
||||
unpinned.forEach(run => tbody.appendChild(makeRow(run, 'unpinned')));
|
||||
|
||||
table.appendChild(tbody);
|
||||
container.innerHTML = '';
|
||||
container.appendChild(table);
|
||||
}
|
||||
Loading…
Reference in a new issue