From 83f21a9ca27724f3b593834c1fd247d66d12d079 Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Mon, 16 Mar 2026 19:49:52 +0100 Subject: [PATCH] feat: puzzle solver algorithm --- steam_backlog_enforcer/main.py | 13 ++++++++++--- steam_backlog_enforcer/protondb.py | 9 ++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/steam_backlog_enforcer/main.py b/steam_backlog_enforcer/main.py index 33a7f7d..5093a4b 100644 --- a/steam_backlog_enforcer/main.py +++ b/steam_backlog_enforcer/main.py @@ -91,6 +91,8 @@ PROTECTED_APP_IDS = { 1493710, # Proton Experimental 1161040, # Proton BattlEye Runtime 1007020, # Proton EasyAntiCheat Runtime + # Games allowed to be installed anytime + 3949040, # RV There Yet? } STEAMAPPS_PATH = Path("~/.local/share/Steam/steamapps").expanduser() @@ -1088,10 +1090,15 @@ def _try_reassign_shorter_game( candidates.sort(key=lambda g: g.completionist_hours) if not candidates or candidates[0].app_id == app_id: return False - shortest = candidates[0] + # Filter out Linux-incompatible games before deciding to reassign. + playable = _pick_playable_candidate( + [c for c in candidates if c.app_id != app_id], + ) + if playable is None or playable.completionist_hours >= hours: + return False _echo( - f"\n Reassigning: {shortest.name} is shorter" - f" (~{shortest.completionist_hours:.1f}h vs ~{hours:.1f}h)" + f"\n Reassigning: {playable.name} is shorter" + f" (~{playable.completionist_hours:.1f}h vs ~{hours:.1f}h)" ) pick_next_game(all_games, state, config) return True diff --git a/steam_backlog_enforcer/protondb.py b/steam_backlog_enforcer/protondb.py index d9ebbe6..52f0c19 100644 --- a/steam_backlog_enforcer/protondb.py +++ b/steam_backlog_enforcer/protondb.py @@ -62,8 +62,8 @@ class ProtonDBRating: - Its tier is gold but trending to silver or worse. - No data exists (unknown compatibility). """ - if not self.tier: - return True # No data → don't block; user can skip manually. + if not self.tier or self.tier == "pending": + return True # No data / pending → don't block; user can skip manually. tier_rank = TIER_ORDER.get(self.tier, 99) min_rank = TIER_ORDER[MIN_PLAYABLE_TIER] @@ -83,7 +83,10 @@ class ProtonDBRating: def _load_cache() -> dict[str, Any]: """Load the on-disk ProtonDB cache.""" if PROTONDB_CACHE_FILE.exists(): - return json.loads(PROTONDB_CACHE_FILE.read_text(encoding="utf-8")) # type: ignore[no-any-return] + data: dict[str, Any] = json.loads( + PROTONDB_CACHE_FILE.read_text(encoding="utf-8"), + ) + return data return {}