"""
Practice: alerts, scored. Lab 14's script 04 (04_alerts.py) and alerts.py: a threshold rule, a
baseline rule (a binomial test against the normal rate), the bar a baseline sets for each hour's
size, and both rules scored against the planted week: when they caught the broken search, and how
many times they fired for nothing.

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

MIN_N = 5  # don't judge an hour with fewer requests


def over_threshold(k, n, threshold=0.30, min_n=MIN_N):
    """The threshold rule: True when more than `threshold` of the hour's n answers were
    "I don't know" (k of them). An hour with fewer than min_n requests is never judged."""
    # TODO
    return False


def binom_sf(k, n, p):
    """P(X >= k) for X ~ Binomial(n, p): if each answer says "I don't know" with chance p, the
    chance that k or more of n do. P(X >= 0) is 1."""
    # TODO
    return 0.0


def above_baseline(k, n, base, alpha=0.001, min_n=MIN_N):
    """The baseline rule: True when k or more "I don't know"s out of n would happen by chance less
    than `alpha` of the time, if the rate were still the normal `base`. Skip hours under min_n."""
    # TODO
    return False


def bar(n, base, alpha=0.001):
    """The smallest k out of n that the baseline rule alerts on (n >= MIN_N): the bar it sets for an
    hour of this size. Return n + 1 if even n of n wouldn't alert."""
    # TODO
    return 0


def fired(hours, rule):
    """`hours` is a list of (hour, n, k). Return the hours where rule(k, n) is True, in order."""
    # TODO
    return []


def score(alerts, incident, size=1):
    """Score a rule's alerts against one incident. Each alert is a window number; window w covers
    hours w*size up to (w+1)*size (size=1: hourly checks, size=24: daily). `incident` is
    (first_hour, end_hour), end not included. A window is inside the incident if they overlap, and
    an alert speaks at the END of its window. Return (delay, false_alarms):
      delay: minutes from the incident's start to the first alert inside it (None if never),
      false_alarms: alerts whose window doesn't overlap the incident."""
    # TODO
    return (None, 0)


def by_day(hours, per_day=24):
    """Add up hourly (hour, n, k) into days: [(day, n, k)], day = hour // per_day, in order."""
    # TODO
    return []
