diff --git a/analyze_results.py b/analyze_results.py
index 6ff4941..1088c6f 100644
--- a/analyze_results.py
+++ b/analyze_results.py
@@ -704,7 +704,7 @@ class WebInterface:
.scale-toggle {
position: absolute;
top: 30px;
- right: 140px;
+ right: 180px;
background: var(--border-color);
border: none;
padding: 10px 20px;
diff --git a/templates/dashboard.html b/templates/dashboard.html
index fe36bb3..6b587b9 100644
--- a/templates/dashboard.html
+++ b/templates/dashboard.html
@@ -81,7 +81,7 @@
.scale-toggle {
position: absolute;
top: 30px;
- right: 140px;
+ right: 180px;
background: var(--border-color);
border: none;
padding: 10px 20px;
@@ -408,6 +408,92 @@
.tooltiptext strong {
color: #667eea;
}
+
+ .chart-type-toggle {
+ display: flex;
+ gap: 5px;
+ background: var(--border-color);
+ border-radius: 8px;
+ padding: 4px;
+ }
+
+ .chart-type-btn {
+ padding: 8px 16px;
+ border: none;
+ border-radius: 6px;
+ cursor: pointer;
+ font-size: 0.9em;
+ transition: all 0.3s;
+ background: transparent;
+ color: var(--text-primary);
+ }
+
+ .chart-type-btn:hover {
+ background: rgba(102, 126, 234, 0.2);
+ }
+
+ .chart-type-btn.active {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ }
+
+ .model-toggles {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ margin-top: 15px;
+ padding: 15px;
+ background: var(--stat-card-bg);
+ border-radius: 10px;
+ }
+
+ .model-toggle-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 6px 12px;
+ background: var(--card-bg);
+ border-radius: 20px;
+ cursor: pointer;
+ transition: all 0.3s;
+ border: 2px solid transparent;
+ }
+
+ .model-toggle-item:hover {
+ border-color: var(--text-secondary);
+ }
+
+ .model-toggle-item.active {
+ border-color: currentColor;
+ }
+
+ .model-toggle-checkbox {
+ width: 18px;
+ height: 18px;
+ cursor: pointer;
+ accent-color: #667eea;
+ }
+
+ .model-toggle-label {
+ font-size: 0.9em;
+ cursor: pointer;
+ user-select: none;
+ }
+
+ .model-color-indicator {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ flex-shrink: 0;
+ }
+
+ .radar-controls {
+ display: none;
+ }
+
+ .radar-controls.visible {
+ display: block;
+ }
@@ -473,6 +559,16 @@
+
+
+
+
+
+
+
Toggle models to show/hide on the spider web chart:
+
+
+
@@ -924,13 +1020,91 @@
});
if (comparisonData.categories.length > 0) {
+ initializeModelToggles();
updateCategoryChart();
}
}
+ // Category chart type state
+ let categoryChartType = 'bar';
+ let selectedModelsForRadar = {};
+
+ // Model colors for radar chart
+ const modelColors = [
+ { bg: 'rgba(102, 126, 234, 0.3)', border: 'rgba(102, 126, 234, 1)' },
+ { bg: 'rgba(118, 75, 162, 0.3)', border: 'rgba(118, 75, 162, 1)' },
+ { bg: 'rgba(16, 185, 129, 0.3)', border: 'rgba(16, 185, 129, 1)' },
+ { bg: 'rgba(245, 158, 11, 0.3)', border: 'rgba(245, 158, 11, 1)' },
+ { bg: 'rgba(239, 68, 68, 0.3)', border: 'rgba(239, 68, 68, 1)' },
+ { bg: 'rgba(59, 130, 246, 0.3)', border: 'rgba(59, 130, 246, 1)' },
+ { bg: 'rgba(236, 72, 153, 0.3)', border: 'rgba(236, 72, 153, 1)' },
+ { bg: 'rgba(34, 197, 94, 0.3)', border: 'rgba(34, 197, 94, 1)' },
+ { bg: 'rgba(168, 85, 247, 0.3)', border: 'rgba(168, 85, 247, 1)' },
+ { bg: 'rgba(251, 146, 60, 0.3)', border: 'rgba(251, 146, 60, 1)' }
+ ];
+
+ function initializeModelToggles() {
+ if (!comparisonData) return;
+
+ const models = Object.keys(comparisonData.models);
+ const container = document.getElementById('modelToggleContainer');
+ container.innerHTML = '';
+
+ models.forEach((model, index) => {
+ const colorIndex = index % modelColors.length;
+ selectedModelsForRadar[model] = true; // All selected by default
+
+ const item = document.createElement('label');
+ item.className = 'model-toggle-item active';
+ item.style.color = modelColors[colorIndex].border;
+ item.innerHTML = `
+
+
+ ${model}
+ `;
+ container.appendChild(item);
+ });
+ }
+
+ function toggleModelVisibility(model, isVisible, element) {
+ selectedModelsForRadar[model] = isVisible;
+ element.classList.toggle('active', isVisible);
+ updateCategoryChart();
+ }
+
+ function setCategoryChartType(type) {
+ categoryChartType = type;
+
+ // Update button states
+ document.getElementById('barChartBtn').classList.toggle('active', type === 'bar');
+ document.getElementById('radarChartBtn').classList.toggle('active', type === 'radar');
+
+ // Show/hide radar controls
+ document.getElementById('radarModelToggles').classList.toggle('visible', type === 'radar');
+
+ // Show/hide category selector (hide for radar since it shows all categories)
+ document.getElementById('categorySelect').style.display = type === 'radar' ? 'none' : 'block';
+
+ updateCategoryChart();
+ }
+
function updateCategoryChart() {
if (!comparisonData) return;
+ const ctx = document.getElementById('categoryChart');
+ if (window.categoryChartInstance) {
+ window.categoryChartInstance.destroy();
+ }
+
+ if (categoryChartType === 'radar') {
+ updateRadarChart(ctx);
+ } else {
+ updateBarChart(ctx);
+ }
+ }
+
+ function updateBarChart(ctx) {
const category = document.getElementById('categorySelect').value;
const models = Object.keys(comparisonData.models);
@@ -939,11 +1113,6 @@
return stats ? stats.average : 0;
});
- const ctx = document.getElementById('categoryChart');
- if (window.categoryChartInstance) {
- window.categoryChartInstance.destroy();
- }
-
window.categoryChartInstance = new Chart(ctx, {
type: 'bar',
data: {
@@ -964,6 +1133,92 @@
});
}
+ function updateRadarChart(ctx) {
+ const categories = comparisonData.categories;
+ const models = Object.keys(comparisonData.models);
+
+ // Create datasets for each selected model
+ const datasets = [];
+ let allData = [];
+
+ models.forEach((model, index) => {
+ if (!selectedModelsForRadar[model]) return;
+
+ const colorIndex = index % modelColors.length;
+ const data = categories.map(category => {
+ const stats = comparisonData.models[model].category_stats[category];
+ return stats ? stats.average : 0;
+ });
+
+ allData = allData.concat(data);
+
+ datasets.push({
+ label: model,
+ data: data,
+ backgroundColor: modelColors[colorIndex].bg,
+ borderColor: modelColors[colorIndex].border,
+ borderWidth: 2,
+ pointBackgroundColor: modelColors[colorIndex].border,
+ pointBorderColor: '#fff',
+ pointHoverBackgroundColor: '#fff',
+ pointHoverBorderColor: modelColors[colorIndex].border,
+ pointRadius: 4,
+ pointHoverRadius: 6
+ });
+ });
+
+ window.categoryChartInstance = new Chart(ctx, {
+ type: 'radar',
+ data: {
+ labels: categories,
+ datasets: datasets
+ },
+ options: {
+ responsive: true,
+ maintainAspectRatio: false,
+ plugins: {
+ legend: {
+ position: 'top',
+ labels: {
+ padding: 20,
+ usePointStyle: true,
+ pointStyle: 'circle'
+ }
+ },
+ tooltip: {
+ callbacks: {
+ label: function(context) {
+ return `${context.dataset.label}: ${context.raw.toFixed(2)}`;
+ }
+ }
+ }
+ },
+ scales: {
+ r: {
+ beginAtZero: !zoomedScale,
+ min: zoomedScale ? Math.max(0, Math.min(...allData) - 0.5) : 0,
+ max: zoomedScale ? Math.min(5, Math.max(...allData) + 0.5) : 5,
+ ticks: {
+ stepSize: zoomedScale ? 0.5 : 1,
+ backdropColor: 'transparent'
+ },
+ grid: {
+ color: 'rgba(102, 126, 234, 0.2)'
+ },
+ angleLines: {
+ color: 'rgba(102, 126, 234, 0.2)'
+ },
+ pointLabels: {
+ font: {
+ size: 11
+ }
+ }
+ }
+ }
+ }
+ });
+ }
+
async function loadModelDetails() {
const modelName = document.getElementById('modelSelect').value;
if (!modelName || !comparisonData) return;