diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7e971dc..d87ad31 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -110,7 +110,7 @@ repos: - --disable-error-code=list-item additional_dependencies: - types-requests - - earned-time @ git+https://github.com/kuhyx/utils@earned-time-v0.2.0#subdirectory=earned_time + - earned-time @ git+https://github.com/kuhyx/utils@earned-time-v0.3.0#subdirectory=earned_time # =========================================================================== # PYLINT @@ -130,7 +130,7 @@ repos: # (steam_backlog_enforcer._mcp_server). additional_dependencies: - aiohttp==3.14.3 - - earned-time @ git+https://github.com/kuhyx/utils@earned-time-v0.2.0#subdirectory=earned_time + - earned-time @ git+https://github.com/kuhyx/utils@earned-time-v0.3.0#subdirectory=earned_time - howlongtobeatpy==1.0.23 - mcp==2.3.0 - pytest diff --git a/pyproject.toml b/pyproject.toml index 10b4300..6d9c83c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ dependencies = [ "websockets==17.2", # The earner registry (gaming budget terms); stdlib-only, so the root # daemon imports it from the desktop user's site-packages. - "earned-time @ git+https://github.com/kuhyx/utils@earned-time-v0.2.0#subdirectory=earned_time", + "earned-time @ git+https://github.com/kuhyx/utils@earned-time-v0.3.0#subdirectory=earned_time", ] # Optional extras. The `mcp` group is ONLY needed by the MCP server diff --git a/requirements.txt b/requirements.txt index 789fd69..e8a434f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ aiohttp==3.14.3 bandit==1.9.4 codespell==2.4.3 coverage==7.16.2 -earned-time @ git+https://github.com/kuhyx/utils@earned-time-v0.2.0#subdirectory=earned_time +earned-time @ git+https://github.com/kuhyx/utils@earned-time-v0.3.0#subdirectory=earned_time howlongtobeatpy==1.0.24 mcp==2.3.0 mypy==2.4.0 diff --git a/steam_backlog_enforcer/tests/test_budget_resolve.py b/steam_backlog_enforcer/tests/test_budget_resolve.py index c498253..8fa0d92 100644 --- a/steam_backlog_enforcer/tests/test_budget_resolve.py +++ b/steam_backlog_enforcer/tests/test_budget_resolve.py @@ -12,6 +12,7 @@ import logging from typing import TYPE_CHECKING from unittest.mock import patch +import earned_time import pytest from steam_backlog_enforcer import _leetcode_bonus, _workout_budget @@ -116,11 +117,13 @@ class TestTheEightDays: patch(_READING, return_value=True), ): resolved = resolve_budget(Config()) + # Every other registered earner has no ledger here, so earns nothing. + others = {e.name: 0.0 for e in earned_time.EARNERS} assert resolved.earned_seconds == { + **others, "workout": 2 * _HOUR, "leetcode": 0.0, "reading": _HOUR, - "anki": 0.0, } diff --git a/steam_backlog_enforcer/tests/test_budget_resolve_reading.py b/steam_backlog_enforcer/tests/test_budget_resolve_reading.py index c8679e0..9a24aab 100644 --- a/steam_backlog_enforcer/tests/test_budget_resolve_reading.py +++ b/steam_backlog_enforcer/tests/test_budget_resolve_reading.py @@ -38,6 +38,17 @@ _READING = "steam_backlog_enforcer._budget_resolve.read_today" _HOUR = 3600.0 +def _later_penalised() -> list[earned_time.Earner]: + """Earners whose penalty starts after reading's 2026-10-01 cut.""" + cut = earned_time.READING.penalty_from + assert cut is not None + return [ + e + for e in earned_time.EARNERS + if e.penalty_from is not None and e.penalty_from > cut + ] + + @pytest.fixture(autouse=True) def _clear_caches() -> Iterator[None]: """Keep both module memos from leaking answers between tests. @@ -88,11 +99,12 @@ class TestTheBase: def test_every_later_day_uses_the_lower_floor(self) -> None: """No drift back to 5h once the cut has happened. - A year on, later earners' cuts (Anki from 2026-10-06) are in force too. + A year on, every later earner's cut (Anki, Automation, ...) is in force + too -- summed from the registry, so a new earner needs no edit here. """ with pin_today(AFTER_CUT + timedelta(days=400)): resolved = _resolve(earners=(False, False, False)) - later_cuts = earned_time.ANKI.gaming_minutes * 60 + later_cuts = 60 * sum(e.gaming_minutes for e in _later_penalised()) assert resolved.base_seconds == 4 * _HOUR - later_cuts diff --git a/steam_backlog_enforcer/tests/test_ledger_earners.py b/steam_backlog_enforcer/tests/test_ledger_earners.py index cde0203..d308d38 100644 --- a/steam_backlog_enforcer/tests/test_ledger_earners.py +++ b/steam_backlog_enforcer/tests/test_ledger_earners.py @@ -187,5 +187,7 @@ class TestAGenericEarnerInTheBudget: patch(_ANSWER, return_value=False) as asked, ): resolved = resolve_budget(Config()) - assert asked.call_args_list == [call(earned_time.ANKI)] + dedicated = (earned_time.WORKOUT, earned_time.LEETCODE, earned_time.READING) + generic = [e for e in earned_time.EARNERS if e not in dedicated] + assert asked.call_args_list == [call(e) for e in generic] assert set(resolved.earned_seconds) == {e.name for e in earned_time.EARNERS}