File size: 2,900 Bytes
a2bbd94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fb23187
a2bbd94
 
 
 
 
 
 
fb23187
a2bbd94
 
 
fb23187
a2bbd94
 
 
 
fb23187
a2bbd94
fb23187
 
 
a2bbd94
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
 * Live progress card for an in-flight (non-published) evaluation run.
 * Fed by the SSE stream when available, otherwise by 1.5s polling.
 */
import Box from '@mui/material/Box';
import LinearProgress from '@mui/material/LinearProgress';
import Typography from '@mui/material/Typography';
import type { RunProgress } from '../../types/megaeval';
import { fmtCompact } from '../../services/megaeval';
import { SectionCard } from '../labeleval/shared';
import { CompactStat, RunStatusChip } from './shared';

function fmtEta(s: number | null): string {
  if (s === null || Number.isNaN(s)) return '—';
  if (s < 60) return `${Math.max(0, Math.round(s))}s`;
  return `${Math.floor(s / 60)}m ${Math.round(s % 60)}s`;
}

export default function RunProgressCard({ progress }: { progress: RunProgress }) {
  // Tolerate either 0..1 or 0..100 percent encodings from the backend.
  const pct = Math.max(0, Math.min(100, progress.percent <= 1 ? progress.percent * 100 : progress.percent));
  return (
    <SectionCard
      title={
        <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
          <span>
            Evaluation run {progress.run_id.slice(0, 8)} · {progress.model_version}
          </span>
          <RunStatusChip status={progress.status} />
        </Box>
      }
      helpTerm="sse"
    >
      <LinearProgress
        variant="determinate"
        value={pct}
        sx={{ height: 10, borderRadius: 1, mb: 1.5, bgcolor: '#232a31' }}
      />
      <Box sx={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>
        <CompactStat label="Progress" value={`${pct.toFixed(1)}%`} info="Share of population partitions fully evaluated." />
        <CompactStat
          label="Objects"
          value={`${fmtCompact(progress.objects_processed)} / ${fmtCompact(progress.objects_total)}`}
          info="Objects scored so far vs total in the population."
        />
        <CompactStat
          label="Partitions"
          value={`${progress.partitions_done} / ${progress.partitions_total}`}
          term="partition"
        />
        <CompactStat label="Workers" value={progress.workers} info="Parallel evaluation workers consuming the partition queue." />
        <CompactStat label="Throughput" value={`${fmtCompact(progress.throughput_objs_per_s)} objs/s`} term="throughput" />
        <CompactStat label="ETA" value={fmtEta(progress.eta_s)} info="Remaining objects divided by current throughput." />
      </Box>
      {progress.error ? (
        <Typography variant="body2" sx={{ color: '#ef5350', mt: 1.5, fontFamily: 'monospace' }}>
          {progress.error}
        </Typography>
      ) : (
        <Typography variant="caption" sx={{ color: '#8a949e', display: 'block', mt: 1.5 }}>
          Map partitions across workers → reduce partial aggregates → materialize cube &amp; indexes → publish.
        </Typography>
      )}
    </SectionCard>
  );
}