"""Lab 03 practice: separate ranking from the decision to serve a result, then score
the top k the way Lab 03's 05_evaluation.py does.

Each row is (top_score, labelled_article_was_first). The recorded customer-wording
scores below come from the final help-center video, not the lab's AI-article set.
"""

CUSTOMER = [
    (0.5199, True), (0.4840, True), (0.3874, False), (0.5046, True),
    (0.1848, True), (0.5249, True), (0.3968, True), (0.4770, True),
]
OFF_TOPIC = [0.0834, 0.0846]


def score_run(rows: list[tuple[float, bool]], cutoff: float) -> dict[str, int]:
    """TODO 1: Return counts: ranked_right, answered, correct_answer, handed_off.

    A score equal to the cutoff is answered. A correct answer needs BOTH an
    answered decision and the labelled article first.
    """
    return {"ranked_right": 0, "answered": 0, "correct_answer": 0, "handed_off": 0}


def rejected_off_topic(scores: list[float], cutoff: float) -> int:
    """TODO 2: Count off-topic questions below the cutoff."""
    return 0


def precision_at_k(results: list[str], relevant: set[str], k: int) -> float:
    """Share of the top k results whose article is in `relevant`.

    TODO 3
    """
    return 0.0


def recall_at_k(results: list[str], relevant: set[str], k: int) -> float:
    """Share of the `relevant` articles that appear anywhere in the top k.

    TODO 4
    """
    return 0.0
