# Pomiar: ile tokenów zajmuje ten sam tekst po polsku i po angielsku u dwóch dostawców.
# Uruchomiony 29.09.2026 na macOS: Claude Code 2.1.284 (claude -p) i Codex CLI 0.158 (codex exec).
# Metoda różnicowa: tokeny tekstu = wejście(wywołanie z tekstem) - wejście(to samo wywołanie bez tekstu).
# Każdy wariant dwa razy. Wynik: przebiegi.json; przeliczenie: tokeny-tekstu.json.
import json,subprocess,time,sys,os
KAT=os.path.dirname(os.path.abspath(__file__)); PUSTY=KAT+"/pusty"  # pusty katalog roboczy dla obu narzędzi (utwórz: mkdir pusty)
INSTR="Nie wykonuj żadnych działań i nie używaj narzędzi. Odpowiedz wyłącznie słowem OK."
WARIANTY={"baza":"", "prawo-PL":open(KAT+"/korpus/prawo-PL.txt").read(), "prawo-EN":open(KAT+"/korpus/prawo-EN.txt").read(), "biznes-PL":open(KAT+"/korpus/biznes-PL.txt").read()}
CODEX="codex"  # Codex CLI 0.158; w pomiarze: plik z aplikacji Codex na macOS
def claude(model,tekst):
    prompt=INSTR+("\n\n"+tekst if tekst else "")
    r=subprocess.run(["claude","-p",prompt,"--model",model,"--output-format","json","--tools","","--system-prompt","Jesteś licznikiem. Odpowiadasz jednym słowem."],capture_output=True,text=True,cwd=PUSTY)
    d=json.loads(r.stdout); u=d["usage"]
    return {"blad":d.get("is_error"),"wejscie":u["input_tokens"]+u.get("cache_creation_input_tokens",0)+u.get("cache_read_input_tokens",0),"wyjscie":u["output_tokens"],"surowe":u}
def codex(model,tekst):
    prompt=INSTR+("\n\n"+tekst if tekst else "")
    r=subprocess.run([CODEX,"exec","--json","--skip-git-repo-check","-s","read-only","-m",model,prompt],capture_output=True,text=True,cwd=PUSTY)
    for line in r.stdout.splitlines():
        if '"turn.completed"' in line:
            u=json.loads(line)["usage"]; return {"blad":False,"wejscie":u["input_tokens"],"wyjscie":u["output_tokens"],"surowe":u}
    return {"blad":True,"wejscie":None,"stderr":r.stderr[-300:]}
MODELE=[("claude-sonnet-5-5",claude),("claude-opus-5-5",claude),("gpt-6-sol",codex),("gpt-6-luna",codex),("claude-haiku-4-5-20251001",claude)]
# Haiku 4.5 (starszy tokenizer Anthropic) dołączono tego samego dnia osobną serią; pierwsza seria przy zimnej
# pamięci podręcznej jest w przebiegi-odrzucone.json, do wyniku weszła powtórzona seria.
wyniki=[]
for powt in (1,2):
    for model,fn in MODELE:
        for wariant,tekst in WARIANTY.items():
            t0=time.time(); w=fn(model,tekst); w.update(model=model,wariant=wariant,powtorzenie=powt,czas=round(time.time()-t0,1),data=time.strftime("%Y-%m-%d %H:%M:%S"))
            wyniki.append(w); print(json.dumps({k:w.get(k) for k in ("model","wariant","powtorzenie","blad","wejscie","wyjscie","czas")},ensure_ascii=False),flush=True)
            json.dump(wyniki,open(KAT+"/przebiegi.json","w"),ensure_ascii=False,indent=1)
