"""Solution for the Capstone B practice: release pipeline decisions."""


def signal_alarm(stable: float, canary: float, z: float, margin: float,
                 z_line: float = 3.5, relative: bool = False, both_ways: bool = False) -> bool:
    if relative:
        if stable == 0:
            return False
        change = canary / stable - 1
    else:
        change = canary - stable
    if both_ways:
        return abs(change) > margin and abs(z) > z_line
    return change > margin and z > z_line


def probe_alarms(stable_wer: float, canary_wer: float, must_pass_failures: list[str],
                 margin: float = 2.0) -> list[str]:
    out = []
    if canary_wer > stable_wer + margin:
        out.append("probe WER")
    if must_pass_failures:
        out.append("must-pass")
    return out


def canary_decision(alarms: list[str], per_segment: dict[str, int], requests: int,
                    min_per_segment: int = 40, max_requests: int = 900) -> str:
    if alarms:
        return "rollback"
    if per_segment and all(n >= min_per_segment for n in per_segment.values()):
        return "promote"
    if requests >= max_requests:
        return "rollback"
    return "continue"


def smallest_detectable(half_width: float) -> float:
    return 2.8 * half_width / 1.96


def clips_needed(clips: int, detectable: float, tolerance: float) -> float:
    return clips * (detectable / tolerance) ** 2
