# Bytes each tool needs to reach the same SSIMULACRA2 score, ImageOptim head-to-head (9 October 2026).
# Same method as match2.py: per image, interpolate in log-bytes between the two nearest measured settings; sum over images.
import json, math
IO = json.load(open('/tmp/smol-bench/io-results.json'))
R5 = json.load(open('/tmp/smol-bench/results24.json'))   # 5 October rows: Smol from the PNG originals
rows = IO + [dict(r, source='png') for r in R5 if r['tool'] == 'Smol']
ALL = [f"kodim{i:02d}" for i in range(1, 25)]
def curve(img, tool, source, fmt, lossy_only=True):
    c = [r for r in rows if r['image']==img and r['tool']==tool and r['source']==source and r['format']==fmt and str(r['setting'])!='lossless']
    return sorted(c, key=lambda r: r['bytes'])
def at(img, tool, source, fmt, target, metric='ssimulacra2'):
    c = curve(img, tool, source, fmt)
    for a, b in zip(c, c[1:]):
        if a[metric] <= target <= b[metric] and b[metric] > a[metric]:
            t = (target - a[metric]) / (b[metric] - a[metric])
            return math.exp(math.log(a['bytes']) + t * (math.log(b['bytes']) - math.log(a['bytes'])))
    return None
def table(title, series, targets, metric='ssimulacra2'):
    print(f"\n#### {title}")
    res = {}
    for target in targets:
        print(f"== total bytes to reach {metric} = {target}")
        per = {s: [at(i, *s, target, metric) for i in ALL] for s in series}
        ok = [k for k in range(24) if all(per[s][k] is not None for s in series)]
        for s in series:
            miss = sum(v is None for v in per[s])
            tot = sum(per[s][k] for k in ok)
            res[(target, s)] = tot
            print(f"  {s[0]:10} {s[1]:4}->{s[2]:4}  reachable on {24-miss:2}/24   total over the {len(ok)} images all series reach: {round(tot):>10,}")
        base = res[(target, series[0])]
        for s in series[1:]:
            print(f"     {s[0]} {s[2]} vs {series[0][0]} {series[0][2]}: {100*(res[(target,s)]/base-1):+.1f}%")
    return res
table("JPEG photos in (sips quality 90 sources)", [('ImageOptim','jpeg','jpeg'),('Smol','jpeg','jpeg'),('Smol','jpeg','webp'),('Smol','jpeg','avif')], (65, 70, 75, 80))
table("PNG photos in", [('ImageOptim','png','png'),('Smol','png','png'),('Smol','png','jpeg'),('Smol','png','webp'),('Smol','png','avif')], (75, 80))
table("PNG photos in, without Smol PNG (wider overlap)", [('ImageOptim','png','png'),('Smol','png','jpeg'),('Smol','png','webp'),('Smol','png','avif')], (75, 80, 85))
table("PNG photos in, SSIM", [('ImageOptim','png','png'),('Smol','png','png'),('Smol','png','avif')], (0.96, 0.97), 'ssim')
table("JPEG photos in, SSIM", [('ImageOptim','jpeg','jpeg'),('Smol','jpeg','jpeg'),('Smol','jpeg','avif')], (0.91, 0.93, 0.95), 'ssim')
