# Copyright (c) 2026 Krzysztof Rudnicki. MIT licence. """The crown: who holds it, for how long, and what a tie does to a run.""" from __future__ import annotations from typing import TYPE_CHECKING from signal_bot.stats.streaks import ( current_streaks, daily_winners, held_days, longest_ever, names_of, ) from tests.stats_seed import ALA, BASIA, GROUP, KUHY, wrote if TYPE_CHECKING: from signal_bot.store import Store def test_no_history_has_no_crown(store: Store) -> None: winners = daily_winners(store.events, GROUP) assert winners == {} assert current_streaks(winners) == [] assert longest_ever(winners) is None assert held_days(winners, "u-kuhy") == 0 def test_the_busiest_person_holds_the_day(store: Store) -> None: wrote(store, "2026-09-01", ALA, 10) wrote(store, "2026-09-01", KUHY, 5) winners = daily_winners(store.events, GROUP) assert names_of(winners["2026-09-01"]) == ["Ala"] def test_a_tie_shares_the_crown(store: Store) -> None: """kuhy's call: shared, because the alternative starts arguments.""" wrote(store, "2026-09-01", ALA, 4) wrote(store, "2026-09-01", KUHY, 4) wrote(store, "2026-09-01", BASIA, 1) winners = daily_winners(store.events, GROUP) assert names_of(winners["2026-09-01"]) == ["Ala", "kuhy"] def test_a_tie_keeps_every_tied_run_alive(store: Store) -> None: """Three days, both tied throughout: both hold a three-day streak.""" for day in ("2026-09-01", "2026-09-02", "2026-09-03"): wrote(store, day, ALA, 3) wrote(store, day, KUHY, 3) streaks = current_streaks(daily_winners(store.events, GROUP)) assert [(s.display_name, s.length) for s in streaks] == [("Ala", 3), ("kuhy", 3)] def test_a_run_survives_a_day_nobody_spoke(store: Store) -> None: """There was no crown to lose on a silent day, so the run continues.""" wrote(store, "2026-09-01", KUHY, 5) # 09-02 and 09-03 silent. wrote(store, "2026-09-04", KUHY, 5) streaks = current_streaks(daily_winners(store.events, GROUP)) assert [(s.display_name, s.length) for s in streaks] == [("kuhy", 2)] def test_losing_a_day_ends_a_run_but_keeps_what_it_reached(store: Store) -> None: """The bug this test exists for reported every streak as zero.""" wrote(store, "2026-09-01", ALA, 10) wrote(store, "2026-09-02", ALA, 10) wrote(store, "2026-09-03", ALA, 4) wrote(store, "2026-09-03", KUHY, 4) wrote(store, "2026-09-06", KUHY, 9) streaks = current_streaks(daily_winners(store.events, GROUP)) assert [(s.display_name, s.length) for s in streaks] == [("kuhy", 2)] assert streaks[0].last_day == "2026-09-06" def test_longest_ever_survives_the_run_that_set_it_ending(store: Store) -> None: wrote(store, "2026-09-01", ALA, 10) wrote(store, "2026-09-02", ALA, 10) wrote(store, "2026-09-03", ALA, 10) wrote(store, "2026-09-04", KUHY, 10) best = longest_ever(daily_winners(store.events, GROUP)) assert (best.display_name, best.length, best.last_day) == ("Ala", 3, "2026-09-03") def test_held_days_counts_shared_days_for_everyone_tied(store: Store) -> None: wrote(store, "2026-09-01", ALA, 10) wrote(store, "2026-09-02", ALA, 4) wrote(store, "2026-09-02", KUHY, 4) winners = daily_winners(store.events, GROUP) assert held_days(winners, "u-ala") == 2 assert held_days(winners, "u-kuhy") == 1 assert held_days(winners, "u-basia") == 0 def test_somebody_who_merely_took_part_holds_nothing(store: Store) -> None: """Neither leader nor tied: the common case, and the one worth pinning.""" wrote(store, "2026-09-01", ALA, 10) wrote(store, "2026-09-01", KUHY, 4) wrote(store, "2026-09-01", BASIA, 1) winners = daily_winners(store.events, GROUP) assert names_of(winners["2026-09-01"]) == ["Ala"] assert held_days(winners, "u-basia") == 0 def test_streak_order_is_stable(store: Store) -> None: """Longest first, then by name -- not whichever the dict happened to yield.""" wrote(store, "2026-09-01", ALA, 3) wrote(store, "2026-09-01", KUHY, 3) wrote(store, "2026-09-01", BASIA, 3) streaks = current_streaks(daily_winners(store.events, GROUP)) assert [s.display_name for s in streaks] == ["Ala", "Basia", "kuhy"] def test_the_backfilled_day_can_be_left_out(store: Store) -> None: wrote(store, "2026-08-30", ALA, 98) wrote(store, "2026-09-01", KUHY, 5) winners = daily_winners(store.events, GROUP, exclude="2026-08-30") assert "2026-08-30" not in winners assert [s.display_name for s in current_streaks(winners)] == ["kuhy"]