'use strict'; const { Router } = require('express'); const { getAllTests, getConfig } = require('../db'); const router = Router(); router.get('/', (req, res) => { const tests = getAllTests(); // ── Overall ─────────────────────────────────────────────────────────────── const totalCompleted = tests.filter(t => t.completed).length; const overall = { total: tests.length, completed: totalCompleted, completionRate: tests.length > 0 ? totalCompleted / tests.length : 0, }; // ── Per device ──────────────────────────────────────────────────────────── const deviceMap = new Map(); for (const t of tests) { if (!t.device) continue; if (!deviceMap.has(t.device)) deviceMap.set(t.device, { total: 0, completed: 0 }); const d = deviceMap.get(t.device); d.total++; if (t.completed) d.completed++; } const devices = Array.from(deviceMap.entries()) .sort(([a], [b]) => a.localeCompare(b)) .map(([name, d]) => ({ name, total: d.total, completed: d.completed, completionRate: d.total > 0 ? d.completed / d.total : 0, })); // ── Elapsed = sum of individual test durations ──────────────────────────── const elapsedSeconds = tests.reduce((sum, t) => { return t.completed && t.duration_seconds != null ? sum + t.duration_seconds : sum; }, 0); // ── Per-type averages and remaining counts ──────────────────────────────── const TYPES = ['COE', 'P2P', 'P3P']; const byType = {}; let estimatedRemainingSeconds = 0; let estimatePossible = true; for (const type of TYPES) { const typeTests = tests.filter(t => t.interference === type); const completed = typeTests.filter(t => t.completed); const withDuration = completed.filter(t => t.duration_seconds != null); const remaining = typeTests.length - completed.length; const calcAvg = withDuration.length > 0 ? withDuration.reduce((s, t) => s + t.duration_seconds, 0) / withDuration.length : null; const manualValue = getConfig(`avg_time_${type.toLowerCase()}`); let avgSeconds = null; let avgSource = null; if (manualValue !== null) { avgSeconds = parseFloat(manualValue); avgSource = calcAvg !== null ? 'manual_override' : 'manual'; } else if (calcAvg !== null) { avgSeconds = calcAvg; avgSource = 'calculated'; } byType[type] = { total: typeTests.length, completed: completed.length, remaining, avgSeconds, avgSource, }; if (remaining > 0) { if (avgSeconds !== null) { estimatedRemainingSeconds += avgSeconds * remaining; } else { estimatePossible = false; } } } res.json({ overall, devices, timing: { elapsedSeconds, estimatedRemainingSeconds: estimatePossible ? estimatedRemainingSeconds : null, byType, }, }); }); module.exports = router;