# retoor from datetime import datetime, timedelta, timezone from devplacepy.services.opinionwar import rules def test_damage_bounds_and_monotonicity(): previous = None for level in range(1, 200): damage = rules.damage_for(level) assert isinstance(damage, int) assert rules.BASE_DAMAGE + rules.LEVEL_DAMAGE_STEP <= damage <= 300 if previous is not None: assert damage >= previous previous = damage def test_damage_caps_at_level_cap(): capped = rules.damage_for(rules.LEVEL_DAMAGE_CAP) assert rules.damage_for(rules.LEVEL_DAMAGE_CAP + 1) == capped assert rules.damage_for(1000) == capped assert capped == rules.BASE_DAMAGE + rules.LEVEL_DAMAGE_STEP * rules.LEVEL_DAMAGE_CAP def test_damage_tolerates_junk_levels(): floor = rules.damage_for(1) assert rules.damage_for(None) == floor assert rules.damage_for(0) == floor assert rules.damage_for(-3) == floor assert rules.damage_for("junk") == floor assert rules.damage_for("7") == rules.damage_for(7) def test_leader_and_winner_agree(): for hp_a in range(0, 40, 3): for hp_b in range(0, 40, 5): leader = rules.leader_of(hp_a, hp_b) winner = rules.winner_of(hp_a, hp_b) if hp_a == hp_b: assert leader == "" assert winner == "draw" else: assert leader in ("a", "b") assert winner == leader def test_pct_split_sums_to_hundred(): for hp_a in range(0, 50, 7): for hp_b in range(0, 50, 9): pct_a, pct_b = rules.pct_split(hp_a, hp_b) assert pct_a + pct_b == 100 assert rules.pct_split(0, 0) == (50, 50) assert rules.pct_split(10, 0) == (100, 0) assert rules.pct_split(0, 10) == (0, 100) def test_ends_at_round_trip(): now = datetime.now(timezone.utc) ends = rules.ends_at_for(now.isoformat()) assert not rules.is_ended(ends, now) assert not rules.is_ended(ends, now + timedelta(days=6, hours=23)) assert rules.is_ended(ends, now + timedelta(days=7, seconds=1)) assert rules.is_ended("", now) is False assert rules.is_ended("garbage", now) is False def test_cooldown_math(): now = datetime.now(timezone.utc) stamp = now.isoformat() assert rules.can_fight_at("", now) assert not rules.can_fight_at(stamp, now + timedelta(hours=23, minutes=59)) assert rules.can_fight_at(stamp, now + timedelta(hours=24, seconds=1)) ready = rules.cooldown_ready_at(stamp) assert ready > stamp assert rules.cooldown_ready_at("") == "" def test_ends_in_label_shapes(): now = datetime.now(timezone.utc) long_label = rules.ends_in_label( (now + timedelta(days=2, hours=14, minutes=32, seconds=30)).isoformat(), now ) assert long_label == "2d 14h 32m" hours_label = rules.ends_in_label( (now + timedelta(hours=3, minutes=5, seconds=30)).isoformat(), now ) assert hours_label == "3h 5m" minutes_label = rules.ends_in_label( (now + timedelta(minutes=9, seconds=30)).isoformat(), now ) assert minutes_label == "9m" assert rules.ends_in_label((now - timedelta(minutes=1)).isoformat(), now) == "" assert rules.ends_in_label("", now) == ""