#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
#define lli long long int
#define fop(i,m,n) for (int i=(m);i<(n);i++)
#define FOP(i,m,n) for (int i=(m)-1;i>=(n);--i)
#define test(x) cout << #x << ' ' << x << endl;
#define printv(a) {\
    for (auto i : a) cout << i << ' ';\
    cout << '\n';\
}
#define eb emplace_back
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define pii pair<int,int>
#define pdd pair<ld,ld>
typedef long double ld;
#define pll pair<lli,lli>
#define tiii tuple<int,int,int>
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define X first
#define Y second
#define oset tree<lli,null_type,less<lli>,rb_tree_tag,tree_order_statistics_node_update>
#define readfile freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
auto SEED = chrono::steady_clock::now().time_since_epoch().count();
mt19937 rng(SEED);

// AC automaton will help me get AC!
struct AC {
    vector <vector <int>> ch;
    vector <int> cnt, f;
    AC () {extend();}
    void extend() {
        ch.pb(vector <int>(26, 0));
        cnt.pb(0);
    }
    int next(int u, int v) {
        if (!ch[u][v]) {
            ch[u][v] = ch.size();
            extend();
        }
        return ch[u][v];
    }
    void insert(string &s) {
        int now = 0;
        for (char c : s) {
            now = next(now, c - 'a');
        }
        cnt[now]++;
    }
    void build_fail() {
        f.assign(ch.size(), 0);
        queue <int> q;
        for (int i = 0; i < 26; ++i) if (ch[0][i]) q.push(ch[0][i]);
        while (q.size()) {
            int v = q.front(); q.pop();
            for (int i = 0; i < 26; ++i) if (ch[v][i]) {
                    int k = f[v];
                    while (k && !ch[k][i]) k = f[k];
                    if (ch[k][i]) k = ch[k][i];
                    f[ch[v][i]] = k;
                    cnt[ch[v][i]] += cnt[k];
                    q.push(ch[v][i]);
                }
        }
    }
    int match(string &s) {
        int k = 0, ans = 0;
        for (char c : s) {
            while (k && !ch[k][c - 'a']) k = f[k];
            if (ch[k][c - 'a']) k = ch[k][c - 'a'];
            ans += cnt[k];
        }
        return ans;
    }
};

const int mod = 1e9 + 7, x = 864197532, N = 300087, logN = 17;

int main () {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, sz;
    lli m, d;
    cin >> n;
    vector <lli> dp(10, -1ll << 60);
    dp[0] = 0;
    fop (i,0,n) {
        cin >> sz;
        lli a1 = -1 << 30, a2 = -1 << 30, a3 = -1 << 30, b1 = -1 << 30, c1 = -1 << 30;
        fop (i,0,sz) {
            cin >> m >> d;
            if (m == 1) {
                if (a1 <= d) a3 = a2, a2 = a1, a1 = d;
                else if (a2 <= d) a3 = a2, a2 = d;
                else if (a3 <= d) a3 = d;
            } else if (m == 2) {
                b1 = max(b1, d);
            } else {
                c1 = max(c1, d);
            }
        }
        vector <lli> pre(10, -1ll << 60);
        // 1
        fop (i,1,10) {
            pre[i] = max(pre[i], dp[i - 1] + max({a1, b1, c1}));
        }
        pre[0] = max(pre[0], dp[9] + max({a1, b1, c1}) * 2);
        // 2
        fop (i,0,10) {
            if (i >= 2) pre[i] = max(pre[i], dp[i - 2] + max(a1 + a2, a1 + b1));
            else {
                lli mx = max(a2, b1), aa = max(mx, a1), bb = min(mx, a1);
                pre[i] = max(pre[i], dp[i + 8] + aa * 2 + bb);
            }
        }
        // 3
        fop (i,0,10) {
            if (i >= 3) pre[i] = max(pre[i], dp[i - 3] + a1 + a2 + a3);
            else pre[i] = max(pre[i], dp[i + 7] + a1 * 2 + a2 + a3);
        }
        swap(dp, pre);
    }
    cout << *max_element(all(dp));
}