mirror of
https://github.com/kuhyx/steam-backlog-enforcer.git
synced 2026-11-10 20:27:03 +01:00
_web_dataset.py 436 -> 178 + _web_models, _web_games, _web_pace The six dataclasses (WebGame, WebStateInfo, WebDefaults, DefaultSummary, PaceVsHLTB, WebDataset) are used by BOTH the parent and the helpers, so they go to their own leaf model module that both import. Leaving them in the parent is what created a circular import and broke ./run.sh on the previous attempt. All public names plus the seven private helpers tests reach for are re-exported from _web_dataset via __all__, so import paths are unchanged. Test patch targets split per class: TestBuildWebDataset, TestDatasetToPayload and TestDatasetEndpoint still patch load_snapshot on _web_dataset (that function did not move) while their cache patches move to _web_games. `bash scripts/check_file_length.sh --all` now exits 0 — no file in the repo is over 250 lines. 1344 tests, 100.00% coverage. Verified live: ./run.sh status works and build_web_dataset projects all 958 games with pace and summary sections intact; service at 0 restarts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016A1EYiv7e7HGhET84oa9M3
111 lines
2.9 KiB
Python
111 lines
2.9 KiB
Python
"""Dataclasses for the web UI's read-only dataset projection.
|
|
|
|
A leaf module: :mod:`steam_backlog_enforcer._web_dataset` and its helper
|
|
modules all import these types, so nothing here may import them back.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
|
|
# Mirrors ``_stats._HOURS_PER_DAY_PRESETS`` but mutable/JSON-friendly.
|
|
HOURS_PER_DAY_PRESETS = [2.0, 4.0, 6.0, 8.0]
|
|
|
|
|
|
@dataclass
|
|
class WebGame:
|
|
"""One incomplete candidate game, with raw filterable fields.
|
|
|
|
Hour fields use ``-1`` to mean "no data" (matching the cache convention),
|
|
so the client can choose to include or exclude unknown-length games.
|
|
"""
|
|
|
|
app_id: int
|
|
name: str
|
|
completion_pct: float
|
|
playtime_minutes: int
|
|
rush_hours: float
|
|
leisure_hours: float
|
|
worst_hours: float
|
|
count_comp: int
|
|
comp_100_count: int
|
|
hltb_game_id: int
|
|
protondb_tier: str
|
|
protondb_trending_tier: str
|
|
protondb_score: float
|
|
|
|
|
|
@dataclass
|
|
class WebStateInfo:
|
|
"""Pace inputs and current-assignment metadata for the UI."""
|
|
|
|
current_app_id: int | None
|
|
current_game_name: str
|
|
games_done: int
|
|
games_done_since_start: int
|
|
days_elapsed: int
|
|
enforcement_started_at: str
|
|
pace_games_per_day: float
|
|
|
|
|
|
@dataclass
|
|
class WebDefaults:
|
|
"""The CLI's hardcoded filter thresholds, surfaced as editable defaults."""
|
|
|
|
min_comp_100_polls: int
|
|
min_count_comp: int
|
|
min_confidence_sum: int
|
|
min_playable_tier: str
|
|
hours_per_day_presets: list[float]
|
|
|
|
|
|
@dataclass
|
|
class DefaultSummary:
|
|
"""Totals the CLI ``stats`` command would print at default thresholds.
|
|
|
|
Used as a parity oracle: the client's own default-filtered totals must
|
|
reproduce these numbers.
|
|
"""
|
|
|
|
qualifying: int
|
|
rush_total: float
|
|
leisure_total: float
|
|
worst_total: float
|
|
|
|
|
|
@dataclass
|
|
class PaceVsHLTB:
|
|
"""Player pace calibrated against HLTB rush/leisure averages.
|
|
|
|
Derived from completed games that have HLTB detail data. All ratio /
|
|
interpolation fields use ``-1`` to mean "insufficient data", matching the
|
|
cache convention used elsewhere.
|
|
|
|
Fields:
|
|
calibration_count: number of completed games used for calibration.
|
|
ratio_vs_rush: actual_hours / rush_hours across calibration games.
|
|
ratio_vs_leisure: actual_hours / leisure_hours (-1 if no leisure data).
|
|
interpolation_t: position between rush (0.0) and leisure (1.0) speed.
|
|
Negative means faster than rush; >1 means slower than leisure.
|
|
-1 means insufficient data.
|
|
player_style: human-readable style label.
|
|
"""
|
|
|
|
calibration_count: int
|
|
ratio_vs_rush: float
|
|
ratio_vs_leisure: float
|
|
interpolation_t: float
|
|
player_style: str
|
|
|
|
|
|
@dataclass
|
|
class WebDataset:
|
|
"""Full payload served to the browser."""
|
|
|
|
games: list[WebGame]
|
|
state: WebStateInfo
|
|
defaults: WebDefaults
|
|
default_summary: DefaultSummary
|
|
pace_vs_hltb: PaceVsHLTB | None
|
|
generated_at: str = field(default="")
|