"""Solution for the chapter 8 search-evaluation exercise."""

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]:
    answered = sum(score >= cutoff for score, _ in rows)
    return {
        "ranked_right": sum(right for _, right in rows),
        "answered": answered,
        "correct_answer": sum(score >= cutoff and right for score, right in rows),
        "handed_off": len(rows) - answered,
    }


def rejected_off_topic(scores: list[float], cutoff: float) -> int:
    return sum(score < cutoff for score in scores)


def precision_at_k(results: list[str], relevant: set[str], k: int) -> float:
    top = results[:k]
    return sum(r in relevant for r in top) / k if k else 0.0


def recall_at_k(results: list[str], relevant: set[str], k: int) -> float:
    return len(relevant & set(results[:k])) / len(relevant) if relevant else 0.0
