"""Shared pace math for usage-window tracking.

`server.py::_compute_pace` and `simulate_display.py::draw_gauge` both need to
turn "how far into the window are we, and how much has been used" into a pace
ratio, but they apply *different* guard/clamp policy on top of that ratio:

- `server.py` returns the raw, unclamped ratio (or `None` on a few edge
  conditions) because it feeds the `/status` API's `"pace"` field, a real
  consumer surface.
- `simulate_display.py` clamps the ratio to `[0.0, 2.0]` for the gauge's
  visual arc and has its own branch behavior at the edges.

Only the genuinely-shared arithmetic lives here. Each caller keeps its own
guards, clamps, and edge-case handling exactly as before — this module does
not decide policy.
"""

from __future__ import annotations


def elapsed_fraction(resets_in_sec: int, duration_sec: int) -> float:
    """Fraction of the window elapsed so far: (duration - remaining) / duration.

    Caller is responsible for guarding `duration_sec` (e.g. against zero or
    negative values) and for clamping/interpreting the result — this is pure
    arithmetic, no policy.
    """
    return (duration_sec - resets_in_sec) / duration_sec


def pace_ratio(pct: float, elapsed_frac: float) -> float:
    """Usage pace ratio: pct used vs. pct expected at this point in the window.

    `elapsed_frac * 100.0` is the expected usage percent if usage were
    perfectly linear; `pct / expected_pct` is 1.0 exactly on pace, >1.0 ahead
    of pace (overpace), <1.0 behind pace (underpace). Caller is responsible
    for guarding `elapsed_frac` (e.g. against zero/negative) and for any
    clamping of the result.
    """
    return pct / (elapsed_frac * 100.0)
