"""Descriptive diagnostics for CrashMath's public synthetic CSV, not live games.

Usage: python prediction_diagnostics.py crashmath_10000_rounds_dataset.csv
No third-party dependencies. Runs-test normal approximation uses no continuity correction.
"""
import csv
import hashlib
import json
import logging
import math
from decimal import Decimal
from pathlib import Path
import sys


def diagnose(path):
    expected_hash = '0f3341c5dc53667e4e7b36c80998461ad0d215ce8608dded2d72c27d9bf7ab10'
    actual_hash = hashlib.sha256(path.read_bytes()).hexdigest()
    if actual_hash != expected_hash:
        raise ValueError('File differs from the documented synthetic corpus')
    with path.open(encoding='utf-8', newline='') as stream:
        rows = list(csv.DictReader(stream))
    values = [Decimal(row['multiplier']) for row in rows]
    n = len(values)
    mean = sum(values) / n
    denominator = sum((value-mean)**2 for value in values)
    correlations = {
        str(lag): float(sum((values[i]-mean)*(values[i+lag]-mean) for i in range(n-lag))/denominator)
        for lag in [1,2,5,10]
    }
    cutoff = Decimal('1.88')
    states = [value >= cutoff for value in values]
    above = sum(states)
    below = n-above
    runs = 1+sum(a != b for a,b in zip(states,states[1:]))
    expected_runs = Decimal(2*above*below)/n+1
    variance = Decimal(2*above*below*(2*above*below-n))/(n*n*(n-1))
    deviation = variance.sqrt()
    z = float((runs-expected_runs)/deviation)
    return dict(scope='One fixed public synthetic corpus; no operator or predictor certification',
        csvSha256=actual_hash,rows=n,timestampColumns=[key for key in rows[0] if 'time' in key or 'date' in key],
        displayed1x=sum(value==1 for value in values),maximum=float(max(values)),acf=correlations,
        runsTest=dict(cutoff=float(cutoff),highRule='multiplier >= cutoff, ties included',
            high=above,low=below,observedRuns=runs,expectedRuns=float(expected_runs),
            standardDeviation=float(deviation),zWithoutContinuityCorrection=z,
            approximateTwoSidedNormalP=math.erfc(abs(z)/math.sqrt(2))))


if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO,format='%(message)s')
    source = Path(sys.argv[1]) if len(sys.argv)>1 else Path(__file__).with_name('crashmath_10000_rounds_dataset.csv')
    logging.info(json.dumps(diagnose(source),indent=2))
