"""Illustrative rates and one observation window; not actual cloud prices or savings."""
import json
from decimal import Decimal
rows=[]
for label,attempts in [('baseline',120),('retries',240)]:
 compute=Decimal(attempts)*Decimal('.04');logs=Decimal(attempts)*Decimal('.01');storage=Decimal('2.00');total=compute+logs+storage
 rows.append({'case':label,'attempts':attempts,'completedUsefulJobs':120,'computeGBP':str(compute),'logsGBP':str(logs),'retainedStorageAllocationGBP':str(storage),'totalGBP':str(total),'costPerCompletedJobGBP':str(total/120),'attemptsPerCompletion':attempts/120})
assert Decimal(rows[0]['totalGBP'])==8 and Decimal(rows[1]['totalGBP'])==14
assert Decimal(rows[1]['totalGBP'])/Decimal(rows[0]['totalGBP'])==Decimal('1.75')
report={'status':'All rates, amounts and times illustrative; no2025 or current vendor pricing used','window':'one defined batch observation window','rates':{'computeGBPPerAttempt':'0.04','logsGBPPerAttempt':'0.01','storageAllocationGBPPerWindow':'2.00'},'cases':rows,'timeline':[{'time':'08:00–09:00','event':'240attempts produce120useful completions; illustrative allocated cost£14'},{'time':'12:00','event':'Example billing view reflects the usage window'},{'time':'12:30','event':'Example£10threshold notification arrives'},{'time':'12:35','event':'Owner inspects attempt/completion counts and cost components'}],'scope':'Arithmetic and attribution only; no billing API, alert latency measurement or automatic shutdown'}
if __name__=='__main__':print(json.dumps(report,indent=2))
