"""Standalone synthetic teaching example. Run locally with Python, not in the HTML."""
import json
import numpy as np
import pandas as pd
from scipy.special import expit

def clean(value):
    if isinstance(value, dict): return {str(k):clean(v) for k,v in value.items()}
    if isinstance(value,(list,tuple,np.ndarray)): return [clean(v) for v in value]
    if isinstance(value,(np.integer,)): return int(value)
    if isinstance(value,(float,np.floating)): return float(value) if np.isfinite(value) else None
    if isinstance(value,(np.bool_,)): return bool(value)
    return value

def print_result(result):
    print(json.dumps(clean(result),ensure_ascii=False,allow_nan=False))


def ols_fit(X, y):
    """X excludes intercept. Return intercept, slopes, rank of centered X."""
    X, y = np.asarray(X, float), np.asarray(y, float)
    if X.ndim != 2 or y.shape != (len(X),) or len(X) == 0:
        raise ValueError("Expected nonempty X(n,p) and y(n)")
    if not np.isfinite(X).all() or not np.isfinite(y).all():
        raise ValueError("Resolve nonfinite data first")
    mean = X.mean(axis=0)
    coef, _, rank, _ = np.linalg.lstsq(X-mean, y-y.mean(), rcond=None)
    return float(y.mean()-mean@coef), coef, int(rank)

def ridge_fit(X, y, lam):
    """SSE/(2n) + lam*||beta||^2/2; do not penalize intercept."""
    if not np.isfinite(lam) or lam < 0:
        raise ValueError("lam must be nonnegative and finite")
    if lam == 0:
        b, coef, _ = ols_fit(X, y)
        return b, coef
    X, y = np.asarray(X, float), np.asarray(y, float)
    ols_fit(X, y)  # Validate the input; not used as the regularized solution.
    mean = X.mean(0)
    xc, yc = X-mean, y-y.mean()
    coef = np.linalg.solve(xc.T@xc + len(X)*lam*np.eye(X.shape[1]), xc.T@yc)
    return float(y.mean()-mean@coef), coef

def best_split(x, y, min_leaf=1):
    """One-feature squared-error stump. None means no positive valid gain."""
    x, y = np.asarray(x,float), np.asarray(y,float)
    if x.ndim != 1 or y.shape != x.shape or min_leaf < 1:
        raise ValueError("Expected matching 1D arrays and min_leaf>=1")
    if len(x)==0 or not np.isfinite(x).all() or not np.isfinite(y).all():
        raise ValueError("Expected nonempty finite data")
    order = np.argsort(x,kind="stable"); xs, ys = x[order], y[order]
    parent = np.sum((ys-ys.mean())**2)
    best = None; best_sse = parent
    for i in range(min_leaf, len(x)-min_leaf+1):
        if xs[i-1] == xs[i]:
            continue
        left, right = ys[:i].mean(), ys[i:].mean()
        sse = np.sum((ys[:i]-left)**2)+np.sum((ys[i:]-right)**2)
        if sse < best_sse-1e-12:
            best_sse = sse
            best = (float((xs[i-1]+xs[i])/2), float(left), float(right), float(sse))
    return best

if __name__ == "__main__":
    X=np.array([[-1.],[0.],[1.]])
    y=2*X[:,0]
    b,w=ridge_fit(X,y,1.)
    np.testing.assert_allclose(w,[.8])
    split=best_split(np.arange(1,7),np.array([0.,0.,1.,4.,5.,5.]))
    GL,HL,GR,HR,lam,gamma=-2.,2.,2.,2.,1.,.1
    gain=.5*(GL**2/(HL+lam)+GR**2/(HR+lam)-(GL+GR)**2/(HL+HR+lam))-gamma
    print_result({"ridge_hand_fixture":w[0],"split_hand_fixture":split,
        "xgboost_gain_hand_fixture":gain,"scope":"numerical fixtures, not a mastery score"})
