"""Render the Monte-Carlo / exact-probability tables for the notes from results/*.json.
Run from the case folder: python3 code/render_tables.py  -> results/gillogly_pvalues.md
"""
import os, json
from beale_common import RESULTS

d = json.load(open(os.path.join(RESULTS, 'gillogly_strings.json')))
try:
    m = json.load(open(os.path.join(RESULTS, 'gillogly_multi_runs.json')))
except FileNotFoundError:
    m = None

def fmt(r):
    if r['count'] == 0:
        return '0/%s (<%.1e)' % (format(r['N'], ','), r['upper95_if_zero'])
    return '%.2e ± %.1e (%d/%s)' % (r['p'], r['se'], r['count'], format(r['N'], ','))

lines = ['## Task 4 probability tables (generated by code/render_tables.py)', '',
         'Simulations: %s exact-letter shuffles/draws, %s for the substitution statistics; seed %d.' % (format(d['nsim'], ','), format(d['nsim_sub'], ','), d['seed']), '']
# exact DP
lines += ['### (i) i.i.d. letters drawn from the DOI-initial distribution: exact probabilities (n = 520)', '',
          '| key (letter distribution) | statistic | L=10 | L=12 | L=14 | L=17 | L=20 |', '|---|---|---|---|---|---|---|']
for k, e in d['null_i_iid_letters_exact'].items():
    for rel in ('nondecreasing', 'step01'):
        for suffix, label in (('_run_ge_L_n520', 'no breaks'), ('_run_ge_L_with_B1_breaks', 'with B1 break fraction %.3f' % e['break_fraction_in_B1'])):
            v = e['exact_P_' + rel + suffix]
            lines.append('| %s | %s, %s | %s |' % (k, rel, label, ' | '.join('%.2e' % v[str(L)] for L in (10, 12, 14, 17, 20))))
e = d['null_i_iid_letters_exact']['gillogly_table1']
lines += ['', 'Uniform-26-letter model (Gillogly\'s arithmetic): P(+0/+1 run >= 14 in 520) = %.2e, >= 17: %.2e, >= 20: %.2e; ' % tuple(e['uniform26_P_step01_run_ge_L_n520'][str(L)] for L in (14, 17, 20)) +
          'non-decreasing >= 14: %.2e; Gillogly\'s 495/13^13 = %.2e.' % (e['uniform26_P_nondecreasing_run_ge_L_n520']['14'], e['gillogly_arithmetic_495_over_13^13']), '']
lines += ['Expected number of maximal non-decreasing runs of length >= L (i.i.d. DOI letters, Gillogly distribution): ' +
          ', '.join('L>=%s: %.3g' % (L, v) for L, v in e['expected_number_of_nondecreasing_runs_ge_L_(approx)'].items()), '']
# MC tables
lines += ['### Monte-Carlo p-values for B1 (P of a run at least as long as observed; MC standard error; count/N)', '',
          '| null model | key | statistic | observed | P(>= observed) | P(>= 14) | P(>= 17) | P(>= 20) |', '|---|---|---|---|---|---|---|---|']
for label, nm in (('(i) i.i.d. letters (B1 breaks)', 'null_i_iid_letters_mc'), ('(ii) permutation of B1 numbers', 'null_ii_permutation_of_B1_numbers'),
                  ('(iii) uniform numbers 1..key', 'null_iii_uniform_numbers')):
    for k, e in d[nm].items():
        for sname, v in e.items():
            if not (isinstance(v, dict) and 'P_ge' in v):
                continue
            obs = v.get('observed_B1', d['observed']['B1/' + k]['S1_longest_nondecreasing_exact' if sname == 'nondecreasing' else 'S2_longest_step01_exact'])
            P = v['P_ge']
            def g(L):
                return fmt(P[str(L)]) if str(L) in P else '-'
            lines.append('| %s | %s | %s | %d | %s | %s | %s | %s |' % (label, k, sname, obs, g(obs), g(14), g(17), g(20)))
if m:
    lines += ['', '### Number of long runs in B1 (supplement, code/gillogly_multi_runs.py; %s simulations)' % format(m['nsim'], ','), '',
              '| key | relation | L | observed # runs >= L | P(>= observed), permutation | P(>= observed), uniform numbers |', '|---|---|---|---|---|---|']
    for k, ent in m.items():
        if k == 'nsim':
            continue
        for rel, res in ent.items():
            for L, r in res.items():
                lines.append('| %s | %s | %s | %d | %s | %s |' % (k, rel, L, r['observed_count'], fmt(r['permutation']['P_ge_observed']), fmt(r['uniform_numbers']['P_ge_observed'])))
open(os.path.join(RESULTS, 'gillogly_pvalues.md'), 'w').write('\n'.join(lines) + '\n')
if __name__ == '__main__':
    print('\n'.join(lines))
