File size: 3,144 Bytes
dec56a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
91
import { useState, useMemo } from 'react';
import {
  ResponsiveContainer,
  LineChart,
  Line,
  XAxis,
  YAxis,
  Tooltip,
  ReferenceLine,
  CartesianGrid,
} from 'recharts';

const SERIES = {
  treasury: { label: 'Treasury', accessor: r => r.treasury_after, color: '#7c5cff' },
  total_revenue: { label: 'Revenue', accessor: r => r.total_revenue, color: '#2dd4bf' },
  productivity: { label: 'Productivity', accessor: r => r.productivity, color: '#f6c177' },
  prosperity: { label: 'Prosperity ×1e3', accessor: r => r.prosperity * 1000, color: '#60a5fa' },
  population: { label: 'Population', accessor: r => r.population, color: '#fb923c' },
  reward_total: { label: 'Reward (step)', accessor: r => r.reward.total, color: '#4ade80' },
  cumulative_reward: { label: 'Cumulative reward', accessor: r => r.cumulative_reward, color: '#f472b6' },
  total_allocation: { label: 'Total allocation', accessor: r => r.total_allocation, color: '#a78bfa' },
};

export default function TimeSeries({ rounds, currentRound }) {
  const [active, setActive] = useState(['treasury', 'total_revenue', 'cumulative_reward']);

  const data = useMemo(() => rounds.map(r => {
    const row = { round: r.round_num };
    for (const [k, s] of Object.entries(SERIES)) {
      row[k] = s.accessor(r);
    }
    return row;
  }), [rounds]);

  const toggle = key => {
    setActive(prev => (prev.includes(key) ? prev.filter(k => k !== key) : [...prev, key]));
  };

  return (
    <div className="card">
      <h3>
        Time series
        <span className="meta">{rounds.length} rounds</span>
      </h3>
      <div className="chart-tabs">
        {Object.entries(SERIES).map(([k, s]) => (
          <button
            key={k}
            type="button"
            className={active.includes(k) ? 'active' : ''}
            onClick={() => toggle(k)}
            style={{ color: active.includes(k) ? s.color : undefined }}
          >
            {s.label}
          </button>
        ))}
      </div>
      <div className="chart-wrap">
        <ResponsiveContainer width="100%" height="100%">
          <LineChart data={data} margin={{ top: 8, right: 12, bottom: 4, left: 0 }}>
            <CartesianGrid stroke="#1d2230" strokeDasharray="3 3" />
            <XAxis dataKey="round" stroke="#5a6480" tick={{ fontSize: 11 }} />
            <YAxis stroke="#5a6480" tick={{ fontSize: 11 }} width={50} />
            <Tooltip
              contentStyle={{
                background: '#11141c',
                border: '1px solid #232838',
                borderRadius: 8,
                fontSize: 12,
              }}
              labelStyle={{ color: '#cbd2e0' }}
            />
            <ReferenceLine x={currentRound} stroke="#7c5cff" strokeDasharray="2 4" />
            {active.map(k => (
              <Line
                key={k}
                type="monotone"
                dataKey={k}
                stroke={SERIES[k].color}
                dot={false}
                strokeWidth={1.6}
                isAnimationActive={false}
              />
            ))}
          </LineChart>
        </ResponsiveContainer>
      </div>
    </div>
  );
}