"""
Practice: self-hosting vs. an API, measured. Lab 12's comparison (12_self_host_vs_api.py): Lab 11's
fine-tuned 0.6B, 4-bit, on the laptop vs. gpt-5.4-nano and gpt-5.4-mini through OpenAI's API, on the
same 100 made-up test emails. Describe the speed honestly, check whether 99 vs. 97 right is a real
difference, and work out what one email costs each way.

Fill in the TODOs, then run the tests:
    pytest test_selfhost_practice.py        (locally)
or press "Run tests" on the chapter page.
"""
import math

# USD per 1M tokens when the lab was written (the lab's inference_utils.PRICES).
PRICES = {
    "gpt-5.4-nano": {"input": 0.20, "cached_input": 0.02, "output": 1.25},
    "gpt-5.4-mini": {"input": 0.75, "cached_input": 0.075, "output": 4.50},
}


def percentile(values, pct):
    """The lab's nearest-rank percentile: sort the values, take rank = round(pct / 100 * n), at
    least 1, and return the value at that rank (1-based). Return 0.0 for an empty list."""
    # TODO
    return 0.0


def paired_p(a, b):
    """Exact two-sided McNemar test for two models scored on the same items (lists of True/False).
    Only the items where they disagree count: a_only = A right and B wrong, b_only = the reverse.
    If there's no real difference, each disagreement is a coin flip, so the p-value is twice the
    binomial tail: 2 * sum(comb(n, i) for i in 0..k) / 2**n, with n = a_only + b_only and
    k = min(a_only, b_only). Cap it at 1.0, and return 1.0 when they never disagree."""
    # TODO
    return 0.0


def api_per_1000(model, in_tokens, out_tokens, cached=0):
    """What 1,000 calls cost through the API, in dollars, for calls with `in_tokens` input and
    `out_tokens` output tokens each. `cached` of the input tokens are billed at the cached price,
    the rest at the full input price."""
    # TODO
    return 0.0


def self_host_per_1000(hourly, per_hour, busy=1.0):
    """The lab's formula for a self-hosted email: the machine's hourly cost divided by the emails
    it actually handles in that hour (`per_hour` at full use, times `busy`), times 1,000."""
    # TODO
    return 0.0


def always_on_per_1000(hourly, per_day):
    """A machine kept on all day (24 hours at `hourly`) that handles `per_day` emails: dollars per
    1,000 emails."""
    # TODO
    return 0.0
