"""Solution for latency_practice.py."""


def percentile(times: list[float], pct: float) -> float:
    """The lab's nearest-rank percentile: sort the times, then take the one at rank
    round(pct / 100 * n), counting from 1 (at least 1, at most n). p50 is the middle,
    p95 the answer only 1 in 20 is slower than."""
    ordered = sorted(times)
    rank = max(1, round(pct / 100 * len(ordered)))
    return ordered[min(rank, len(ordered)) - 1]


def slower_than_average(times: list[float]) -> int:
    """How many answers took longer than the average of all of them?"""
    avg = sum(times) / len(times)
    return sum(t > avg for t in times)


def cut_off(times: list[float], timeout: float) -> int:
    """With the app giving up after `timeout` seconds, how many of these answers would it cut off?
    An answer that took exactly the timeout still arrives."""
    return sum(t > timeout for t in times)


def total_time(first_token: float, output_tokens: int, tokens_per_s: float) -> float:
    """Roughly how long a whole answer takes: the wait for the first token, plus the time to
    write every token at a steady speed."""
    return first_token + output_tokens / tokens_per_s


def slow_end(times: list[float]) -> float:
    """How far the slow end sits past the typical answer: p95 minus p50, in seconds,
    rounded to 2 decimals."""
    return round(percentile(times, 95) - percentile(times, 50), 2)
