File size: 2,495 Bytes
d091b77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19abe39
 
d091b77
 
19abe39
 
 
 
 
 
d091b77
19abe39
 
 
d091b77
19abe39
 
 
 
 
d091b77
19abe39
 
d091b77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19abe39
 
 
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
const METRIC_FIELDS = [
  {
    key: 'compactness',
    label: 'compactness',
    color: 'var(--progress)',
    normalize: (v) => Math.min(Math.max(v || 0, 0), 1),
    format: (v) => (v != null ? v.toFixed(3) : 'β€”'),
  },
  {
    key: 'max_strain',
    label: 'max strain',
    color: 'var(--validity)',
    // Show as inverted bar: low strain = small bar (good)
    normalize: (v) => Math.min((v || 0) / 0.2, 1),
    format: (v) => (v != null ? v.toFixed(4) : 'β€”'),
    inverted: true,
  },
  {
    key: 'kawasaki_violations',
    label: 'kawasaki',
    color: 'var(--validity)',
    normalize: (v) => Math.min((v || 0) / 5, 1),
    format: (v) => (v != null ? String(v) : 'β€”'),
    inverted: true,
  },
  {
    key: 'maekawa_violations',
    label: 'maekawa',
    color: 'var(--validity)',
    normalize: (v) => Math.min((v || 0) / 5, 1),
    format: (v) => (v != null ? String(v) : 'β€”'),
    inverted: true,
  },
  {
    key: 'fits_target_box',
    label: 'fits box',
    color: 'var(--progress)',
    normalize: (v) => (v ? 1 : 0),
    format: (v) => (v == null ? 'β€”' : v ? 'YES' : 'NO'),
  },
  {
    key: 'is_deployable',
    label: 'deployable',
    color: 'var(--progress)',
    normalize: (v) => (v ? 1 : 0),
    format: (v) => (v == null ? 'β€”' : v ? 'YES' : 'NO'),
  },
];

function RewardRow({ label, color, pct, formattedValue, isDash, inverted }) {
  const barColor = inverted && pct > 0 ? 'var(--validity)' : color;
  return (
    <div className="reward-row">
      <span className="reward-label">{label}</span>
      <div className="reward-track">
        <div
          className="reward-bar"
          style={{ width: `${isDash ? 0 : pct}%`, background: barColor }}
        />
      </div>
      <span className={`reward-value${isDash ? ' dim' : ''}`}>
        {formattedValue}
      </span>
    </div>
  );
}

export default function RewardPanel({ metrics }) {
  return (
    <div className="reward-panel">
      {METRIC_FIELDS.map(({ key, label, color, normalize, format, inverted }) => {
        const raw = metrics ? metrics[key] : undefined;
        const isDash = raw === null || raw === undefined;
        const pct = isDash ? 0 : normalize(raw) * 100;
        return (
          <RewardRow
            key={key}
            label={label}
            color={color}
            pct={pct}
            formattedValue={isDash ? 'β€”' : format(raw)}
            isDash={isDash}
            inverted={!!inverted}
          />
        );
      })}
    </div>
  );
}