"""
Practice: signals that flag a bad transcript without a reference.

In production there's no human transcript to compute WER against. These signals use only
the audio (how many seconds of speech a VAD found) and the model's output.

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

WORDS_PER_SECOND = 2.7  # a typical speaking rate


def length_ratio(n_words: int, speech_seconds: float) -> float:
    """Words written / words expected from the speech in the audio.

        ratio = n_words / (2.7 * speech_seconds + 0.2)

    About 1.0 is normal. Far above 1: invented text. Far below: truncation.
    The +0.2 keeps it finite on silence, while one invented word still stands out.

    TODO 1
    """
    return 0.0


def compression_ratio(text: str) -> float:
    """Size of the text in bytes / size after zlib compression. 0.0 for empty text.
    Repetitive text compresses well, so loops get a high ratio. Whisper's own rule is > 2.4.

    TODO 2 (hint: text.encode(), zlib.compress)
    """
    return 0.0


def repeated_ngrams(text: str, n: int = 4) -> float:
    """Share of n-word sequences that already appeared earlier: 1 - unique / total.
    Lowercase and split on whitespace. 0.0 when the text has fewer than n words.

    TODO 3
    """
    return 0.0


def wilson(k: int, n: int, z: float = 1.96) -> tuple[float, float]:
    """95% Wilson interval for a rate of k failures in n tries. Stays sensible at k = 0.

        p      = k / n
        centre = (p + z²/2n) / (1 + z²/n)
        half   = z * sqrt(p(1-p)/n + z²/4n²) / (1 + z²/n)

    Return (max(0, centre - half), min(1, centre + half)). For n == 0, return (0.0, 1.0).

    TODO 4
    """
    return 0.0, 1.0
