from mtga_assistant.history import GameSummary from mtga_assistant.history_stats import WEEK_MS, Filter, apply_filters, compute_stats NOW = 1_800_000_000_000 DAY = 24 * 3600 * 1000 def game(n: int, result: str, *, deck="Deck A", on_play="me", days_ago=0, turns=8, length_s=300, event="Ladder", best_of=1, game_number=1) -> GameSummary: start = NOW - days_ago * DAY - n * 1000 return GameSummary(match_id=f"m{n}", game_number=game_number, started_ms=start, ended_ms=start + length_s * 1000, event_id=event, opponent=f"opp{n}", deck_name=deck, on_play=on_play, result=result, my_colors="UB", opp_colors="R", turns=turns, best_of=best_of) def test_filters_only_and_hide_combine(): games = [game(1, "Won", deck="A"), game(2, "Lost", deck="B"), game(3, "Won", deck="A", on_play="opp")] assert [g.match_id for g in apply_filters(games, [Filter("deck", "A")])] == ["m1", "m3"] assert [g.match_id for g in apply_filters(games, [Filter("deck", "A"), Filter("on_play", "opp")])] == ["m3"] assert [g.match_id for g in apply_filters(games, [Filter("deck", "A", exclude=True)])] == ["m2"] def test_filter_labels_are_readable(): assert Filter("on_play", "opp").label == "On the play = you on the draw" assert Filter("event", "Play_Brawl_Historic", exclude=True).label == "Event ≠ Play Brawl Historic" assert Filter("game", "Bo1").label == "Game = Bo1" def test_stats_windows_and_averages(): # 12 recent games (newest first: n=0 is newest): W W L W W L W W L W | L L results = ["Won", "Won", "Lost", "Won", "Won", "Lost", "Won", "Won", "Lost", "Won", "Lost", "Lost"] games = [game(n, r, days_ago=0 if n < 6 else 10, turns=6 + n % 3, length_s=240 + 60 * (n % 2), on_play="me" if n % 2 == 0 else "opp") for n, r in enumerate(results)] games.append(game(99, "", days_ago=1)) # no result: counted as a game, not in win rates s = compute_stats(games, NOW) assert s.games == 13 assert (s.overall.wins, s.overall.losses) == (7, 5) assert (s.last_10.wins, s.last_10.losses) == (7, 3) assert s.last_10.rate == 0.7 assert s.last_100.games == 12 assert s.week_games == 7 and (s.week.wins, s.week.losses) == (4, 2) assert (s.on_play.wins, s.on_play.losses) == (3, 3) assert (s.on_draw.wins, s.on_draw.losses) == (4, 2) assert s.avg_turns is not None and 6 <= s.avg_turns <= 8 assert s.avg_length_s is not None and 240 <= s.avg_length_s <= 300 def test_stats_follow_filters(): games = [game(1, "Won", deck="A"), game(2, "Lost", deck="A"), game(3, "Lost", deck="B"), game(4, "Lost", deck="B")] assert compute_stats(apply_filters(games, [Filter("deck", "A")]), NOW).overall.rate == 0.5 assert compute_stats(apply_filters(games, [Filter("deck", "B")]), NOW).overall.rate == 0.0 def test_empty_history(): s = compute_stats([], NOW) assert s.games == 0 and s.overall.rate is None and s.avg_length_s is None and s.week_games == 0 assert WEEK_MS == 7 * DAY