/* comparison-view.js — Renderização visual (tabelas + gráficos) de uma comparação de benchmarks. Não sabe nada sobre como a comparação foi montada nem sobre relatórios — recebe só { tables, charts, summary } e devolve HTML. Reaproveitado pela pré-visualização (Benchmarks) e pelo detalhe de um relatório salvo (Relatórios). */ const ComparisonView = (() => { const esc = UI.escapeHtml; const dash = (v, suf) => (v === null || v === undefined ? "indisponível" : `${v}${suf || ""}`); function renderGeneralTable(rows) { return ` ${rows.map((r) => ``).join("")}
PerfilModeloTipoDataStatusDuração total
${esc(r.profile)} ${esc(r.model)} ${esc(r.type)} ${esc(UI.dt(r.date))} ${UI.benchBadge(r.status)} ${UI.duration(r.durationS)}
`; } function renderPerformanceTable(rows) { return ` ${rows.map((r) => ``).join("")}
PerfilTokens/sTempo totalLatência média CPU médioRAM máxGPU médioVRAM máx
${esc(r.profile)} ${dash(r.tokensPerSecond, " tok/s")} ${UI.duration(r.totalS)} ${dash(r.avgLatencyS, " s")} ${dash(r.avgCpuPct, "%")} ${dash(r.maxRamGb, " GB")} ${dash(r.avgGpuPct, "%")} ${dash(r.maxVramMib, " MiB")}
`; } function renderConfigTable(rows) { return ` ${rows.map((r) => ``).join("")}
PerfilModeloQuantizaçãoCamadas GPU ContextoThreadsBatch sizeComando
${esc(r.profile)} ${esc(r.model)} ${dash(r.quantization)} ${dash(r.nGpuLayers)} ${dash(r.ctxSize)} ${dash(r.threads)} ${dash(r.batchSize)} ${esc(r.command)}
`; } function renderTables(tables) { return `

Tabela geral

${renderGeneralTable(tables.general || [])}

Tabela de desempenho

${renderPerformanceTable(tables.performance || [])}

Tabela de configuração

${renderConfigTable(tables.config || [])}
`; } // Gráfico de barras simples (sem dependências externas). function renderBarChart(title, series, unit) { if (!series || !series.available) { return `

${esc(title)}

Métrica indisponível para os benchmarks selecionados.
`; } const points = series.points || []; const max = Math.max(1, ...points.map((p) => (p.value != null ? p.value : 0))); return `

${esc(title)}

${points.map((p) => { const pct = p.value != null ? Math.round((p.value / max) * 100) : 0; const label = p.value != null ? `${p.value}${unit || ""}` : "indisponível"; return `
${esc(p.label)}
${esc(label)}
`; }).join("") || `
Sem dados.
`}
`; } function renderCharts(charts) { if (!charts) return ""; return `

Gráficos comparativos

${renderBarChart("Tokens/s", charts.tokensPerSecond, " tok/s")} ${renderBarChart("Tempo total", charts.totalTimeS, " s")} ${renderBarChart("RAM máxima", charts.maxRamGb, " GB")} ${renderBarChart("VRAM máxima", charts.maxVramMib, " MiB")} ${renderBarChart("CPU médio", charts.avgCpuPct, "%")} ${renderBarChart("GPU médio", charts.avgGpuPct, "%")}
`; } function renderSummary(summary) { return `

Resumo automático

${esc(summary || "Sem resumo disponível.")}

`; } // Monta a comparação completa (tabelas + gráficos + resumo) em um bloco. function render(data) { return `${renderSummary(data.summary)}${renderTables(data.tables || {})}${renderCharts(data.charts)}`; } return { render, renderTables, renderCharts, renderSummary }; })();