document.addEventListener('DOMContentLoaded', () => { fetchAvailableConfigs().then(() => { fetchConfig(); fetchTasks(); }); // Bind filter functionality document.getElementById('total-tasks').parentElement.addEventListener('click', () => setTaskFilter('all')); document.getElementById('active-tasks').parentElement.addEventListener('click', () => setTaskFilter('active')); document.getElementById('completed-tasks').parentElement.addEventListener('click', () => setTaskFilter('completed')); document.getElementById('error-tasks').parentElement.addEventListener('click', () => setTaskFilter('error')); }); let allTaskData = null; let currentFilter = 'all'; let availableConfigs = []; let currentConfig = null; let categoryStats = {}; // Get configuration from URL parameters function getConfigFromURL() { const urlParams = new URLSearchParams(window.location.search); return { action_space: urlParams.get('action_space'), observation_type: urlParams.get('observation_type'), model_name: urlParams.get('model_name') }; } // Update URL parameters with current configuration function updateURLWithConfig(config) { const url = new URL(window.location); if (config.action_space) url.searchParams.set('action_space', config.action_space); else url.searchParams.delete('action_space'); if (config.observation_type) url.searchParams.set('observation_type', config.observation_type); else url.searchParams.delete('observation_type'); if (config.model_name) url.searchParams.set('model_name', config.model_name); else url.searchParams.delete('model_name'); window.history.replaceState({}, '', url); } // Build API URL with config parameters function buildAPIURL(endpoint, config = null) { const params = new URLSearchParams(); const configToUse = config || getConfigFromURL(); if (configToUse.action_space) params.set('action_space', configToUse.action_space); if (configToUse.observation_type) params.set('observation_type', configToUse.observation_type); if (configToUse.model_name) params.set('model_name', configToUse.model_name); return params.toString() ? `${endpoint}?${params.toString()}` : endpoint; } function refreshPage() { // Save expanded state before refresh const expandedTaskTypes = []; document.querySelectorAll('.task-type').forEach(section => { if (!section.classList.contains('collapsed')) { const typeName = section.querySelector('.task-type-name').textContent.trim(); expandedTaskTypes.push(typeName); } }); // Store in sessionStorage sessionStorage.setItem('expandedTaskTypes', JSON.stringify(expandedTaskTypes)); // Full page refresh window.location.reload(); } function fetchTasks() { fetch(buildAPIURL('/api/tasks/brief')) .then(response => response.json()) .then(data => { allTaskData = data; categoryStats = calculateCategoryStats(data); renderTasks(data); updateStatistics(data); }) .catch(error => console.error('Error fetching tasks:', error)); } function setTaskFilter(filter) { currentFilter = filter; if (!allTaskData) return; renderTasks(allTaskData); // Highlight selected card document.querySelectorAll('.stat-card').forEach(card => card.classList.remove('selected')); if (filter === 'all') { document.getElementById('total-tasks').parentElement.classList.add('selected'); } else if (filter === 'active') { document.getElementById('active-tasks').parentElement.classList.add('selected'); } else if (filter === 'completed') { document.getElementById('completed-tasks').parentElement.classList.add('selected'); } else if (filter === 'error') { document.getElementById('error-tasks').parentElement.classList.add('selected'); } } // Update statistics info function updateStatistics(data) { let totalTasks = 0; let activeTasks = 0; let completedTasks = 0; let errorTasks = 0; let totalScore = 0; Object.entries(data).forEach(([taskType, tasks]) => { totalTasks += tasks.length; tasks.forEach(task => { if (task.status.status === 'Running' || task.status.status === 'Preparing' || task.status.status === 'Initializing') { activeTasks++; } else if (task.status.status === 'Done' || task.status.status === 'Done (Message Exit)' || task.status.status === 'Done (Max Steps)' || task.status.status === 'Done (Thought Exit)') { completedTasks++; // Calculate score if task is completed if (task.status.result) { try { const score = parseFloat(task.status.result); if (!isNaN(score) && score >= 0 && score <= 1) { totalScore += score; } } catch (e) { console.log(`Could not parse score for task: ${task.id}`); } } } else if (task.status.status === 'Error') { errorTasks++; } }); }); document.getElementById('total-tasks').textContent = totalTasks; document.getElementById('active-tasks').textContent = activeTasks; document.getElementById('completed-tasks').textContent = completedTasks; document.getElementById('error-tasks').textContent = errorTasks; // Update score display with formatted score and accuracy percentage const scoreDisplay = document.getElementById('score-display'); if (completedTasks > 0) { const scoreFormatted = totalScore.toFixed(2); const averageScore = totalScore / completedTasks; const accuracyPercentage = (averageScore * 100).toFixed(1); scoreDisplay.innerHTML = `${scoreFormatted} / ${completedTasks} (${accuracyPercentage}%)`; } else { scoreDisplay.innerHTML = '0.00 / 0 (0.0%)'; } // Highlight the currently selected statistics card document.querySelectorAll('.stat-card').forEach(card => card.classList.remove('selected')); if (currentFilter === 'all') { document.getElementById('total-tasks').parentElement.classList.add('selected'); } else if (currentFilter === 'active') { document.getElementById('active-tasks').parentElement.classList.add('selected'); } else if (currentFilter === 'completed') { document.getElementById('completed-tasks').parentElement.classList.add('selected'); } else if (currentFilter === 'error') { document.getElementById('error-tasks').parentElement.classList.add('selected'); } } function renderTasks(data) { const container = document.getElementById('task-container'); container.innerHTML = ''; let filteredData = {}; if (currentFilter === 'all') { filteredData = data; } else { Object.entries(data).forEach(([taskType, tasks]) => { let filteredTasks = []; if (currentFilter === 'active') { filteredTasks = tasks.filter(task => ['Running', 'Preparing', 'Initializing'].includes(task.status.status)); } else if (currentFilter === 'completed') { filteredTasks = tasks.filter(task => task.status.status === 'Done' || task.status.status === 'Done (Message Exit)' || task.status.status === 'Done (Max Steps)'|| task.status.status === 'Done (Thought Exit)'); } else if (currentFilter === 'error') { filteredTasks = tasks.filter(task => task.status.status === 'Error'); } if (filteredTasks.length > 0) { filteredData[taskType] = filteredTasks; } }); } if (Object.keys(filteredData).length === 0) { container.innerHTML = '