#!/usr/bin/env python3
"""
Analyse the three-arm token measurement. Prints the tables that go in the post.

  A  no system prompt
  B  org block, LENGTH line removed
  C  org block, LENGTH line present

B vs C isolates the one line. A vs C is the honest end-to-end effect.
"""

import csv
import statistics as st
import sys
from collections import defaultdict

# Published per-million rates, verified against platform.claude.com/docs/en/about-claude/pricing
# on 2026-08-06.
#
# Claude Sonnet 5 is $2 / $10 through 2026-08-31 (introductory), then $3 / $15 from
# 2026-09-01. The run below happened inside the introductory window, but the tables use
# the STANDARD rate because that is what will be in force when anyone reads this.
#
# The thing that actually drives the result is the RATIO, and the ratio is 5:1 output to
# input on every current Claude model: Fable 5 $10/$50, Opus 5 $5/$25, Sonnet $3/$15,
# Haiku 4.5 $1/$5. So the conclusion does not depend on which model or which rate card.
IN_RATE = 3.00
OUT_RATE = 15.00
RATE_NOTE = "standard Sonnet: $3 in / $15 out per MTok (5:1)"

path = sys.argv[1] if len(sys.argv) > 1 else "token-measure-results.csv"
rows = [r for r in csv.DictReader(open(path)) if r["output_tokens"]]

out = defaultdict(list)
inp = defaultdict(list)
lat = defaultdict(list)
for r in rows:
    out[r["arm"]].append(int(r["output_tokens"]))
    inp[r["arm"]].append(int(r["input_tokens"]))
    lat[r["arm"]].append(float(r["latency_s"]))

LABEL = {
    "A": "A  no system prompt",
    "B": "B  org block, no LENGTH line",
    "C": "C  org block, with LENGTH line",
}

print("=" * 78)
print("THREE-ARM RESULT".center(78))
print("=" * 78)
print(f"{'arm':<32}{'n':>4}{'in':>8}{'out mean':>10}{'out med':>9}{'sd':>8}{'sec':>7}")
print("-" * 78)
for a in "ABC":
    if not out[a]:
        continue
    print(f"{LABEL[a]:<32}{len(out[a]):>4}{st.mean(inp[a]):>8.0f}"
          f"{st.mean(out[a]):>10.1f}{st.median(out[a]):>9.0f}"
          f"{st.pstdev(out[a]):>8.1f}{st.mean(lat[a]):>7.1f}")

mA, mB, mC = (st.mean(out[a]) for a in "ABC")
iA, iB, iC = (st.mean(inp[a]) for a in "ABC")
line_cost = iC - iB
block_cost = iB - iA

print()
print("=" * 78)
print("WHAT THE LENGTH LINE ALONE DID  (B vs C, everything else identical)")
print("=" * 78)
print(f"  output tokens        {mB:.1f}  ->  {mC:.1f}     ({(mC-mB)/mB*100:+.1f}%)")
print(f"  saved per request    {mB-mC:.1f} output tokens")
print(f"  the line itself cost {line_cost:.1f} input tokens on every request")
print(f"  cost of the line     ${line_cost/1e6*IN_RATE:.6f}")
print(f"  value of the saving  ${(mB-mC)/1e6*OUT_RATE:.6f}")
print(f"  NET per request      ${((mB-mC)/1e6*OUT_RATE) - (line_cost/1e6*IN_RATE):+.6f}")
if line_cost:
    ratio = ((mB - mC) * OUT_RATE) / (line_cost * IN_RATE)
    print(f"  the line returns     {ratio:.1f}x what it costs")

print()
print("=" * 78)
print("THE WHOLE BLOCK, END TO END  (A vs C) -- this is the number that answers")
print("the objection 'it adds tokens to every single prompt'")
print("=" * 78)
print(f"  output tokens        {mA:.1f}  ->  {mC:.1f}     ({(mC-mA)/mA*100:+.1f}%)")
print(f"  block adds           {iC-iA:.1f} input tokens per request")
print(f"  input cost added     ${(iC-iA)/1e6*IN_RATE:+.6f}")
print(f"  output cost saved    ${(mA-mC)/1e6*OUT_RATE:+.6f}")
net = ((mA - mC) / 1e6 * OUT_RATE) - ((iC - iA) / 1e6 * IN_RATE)
print(f"  NET per request      ${net:+.6f}   ({'saving' if net > 0 else 'COST'})")
print()
print(f"  and without the LENGTH line (A vs B), the same block would be:")
netB = ((mA - mB) / 1e6 * OUT_RATE) - ((iB - iA) / 1e6 * IN_RATE)
print(f"  NET per request      ${netB:+.6f}   ({'saving' if netB > 0 else 'COST'})")

print()
print("=" * 78)
print("BREAK-EVEN, which is the part that does not depend on the rate card")
print("=" * 78)
ratio = OUT_RATE / IN_RATE
print(f"  output costs {ratio:.0f}x input on every current Claude model.")
print(f"  so 1 output token saved pays for {ratio:.0f} input tokens carried.")
print(f"  a block of {iC-iA:.0f} input tokens breaks even at {(iC-iA)/ratio:.0f} output tokens saved.")
print(f"  it actually saved {mA-mC:.0f}.")
print(f"  break-even margin: {(mA-mC)/((iC-iA)/ratio):.1f}x")

print()
print("=" * 78)
print("THE SAME BLOCK, READ FROM CACHE  (cache hits bill at 0.1x input)")
print("=" * 78)
cached_in = (iC - iA) * IN_RATE * 0.1 / 1e6
print(f"  block adds           {iC-iA:.1f} input tokens, billed at 0.1x")
print(f"  input cost added     ${cached_in:+.6f}")
print(f"  output cost saved    ${(mA-mC)/1e6*OUT_RATE:+.6f}")
print(f"  NET per request      ${(mA-mC)/1e6*OUT_RATE - cached_in:+.6f}   "
      f"({'saving' if (mA-mC)/1e6*OUT_RATE - cached_in > 0 else 'COST'})")
print(f"  break-even shifts to {(iC-iA)/ratio*0.1:.0f} output tokens saved. It saved {mA-mC:.0f}.")

print()
print("=" * 78)
print("BY QUESTION TYPE  (mean output tokens)")
print("=" * 78)
cat = defaultdict(lambda: defaultdict(list))
for r in rows:
    cat[r["category"]][r["arm"]].append(int(r["output_tokens"]))
print("B->C is the column that matters: it is the LENGTH line acting alone.")
print()
print(f"{'category':<12}{'A':>8}{'B':>8}{'C':>8}{'B->C':>10}{'A->C':>10}")
print("-" * 56)
bc = []
for c in sorted(cat, key=lambda k: st.mean(cat[k]["C"]) / st.mean(cat[k]["B"])):
    a = st.mean(cat[c]["A"]) if cat[c]["A"] else 0
    b = st.mean(cat[c]["B"]) if cat[c]["B"] else 0
    cc = st.mean(cat[c]["C"]) if cat[c]["C"] else 0
    print(f"{c:<12}{a:>8.0f}{b:>8.0f}{cc:>8.0f}"
          f"{(cc-b)/b*100:>9.1f}%{(cc-a)/a*100:>9.1f}%")
    bc.append(((cc - b) / b * 100, c))
print()
print(f"  hardest hit: {bc[0][1]} at {bc[0][0]:.1f}%")
print(f"  least hit:   {bc[-1][1]} at {bc[-1][0]:.1f}%   <- the release valve working")

print()
print("=" * 78)
print("SCALED -- the LENGTH LINE only (B vs C net), projected, NOT an invoice")
print("=" * 78)
line_net = ((mB - mC) / 1e6 * OUT_RATE) - (line_cost / 1e6 * IN_RATE)
print(f"  per-request net of the line: ${line_net:.6f}")
print()
print(f"{'seats':>7}{'req/user/day':>14}{'per day':>12}{'per year':>12}")
print("-" * 46)
for seats in (150, 500, 2000):
    for rpd in (5, 20):
        day = line_net * seats * rpd
        print(f"{seats:>7}{rpd:>14}{day:>11.2f}${day*250:>11,.0f}")
print()
print("250 working days. Substitute your own numbers. The per-request net is the")
print("only thing measured here; everything right of it is arithmetic.")
print()
print("This scales the LINE, not the block, because the line is the part that pays")
print("for itself. The block's own overhead is a separate decision, priced above.")
