feat(web): Core Refactor Phase A — extract sampling and cache modules; add adaptive TTL + eviction heuristics, Redis PoC, and metrics wiring. Tests added for TTL, eviction, exports, splash-adaptive, card index, and service worker. Docs+roadmap updated.

This commit is contained in:
matt 2025-09-24 13:57:23 -07:00
parent c4a7fc48ea
commit a029d430c5
49 changed files with 3889 additions and 701 deletions

View file

@ -0,0 +1,41 @@
from code.web.services import sampling
def test_role_saturation_penalty_applies(monkeypatch):
# Construct a minimal fake pool via monkeypatching card_index.get_tag_pool
# We'll generate many payoff-tagged cards to trigger saturation.
cards = []
for i in range(30):
cards.append({
"name": f"Payoff{i}",
"color_identity": "G",
"tags": ["testtheme"], # ensures payoff
"mana_cost": "1G",
"rarity": "common",
"color_identity_list": ["G"],
"pip_colors": ["G"],
})
def fake_pool(tag: str):
assert tag == "testtheme"
return cards
# Patch symbols where they are used (imported into sampling module)
monkeypatch.setattr("code.web.services.sampling.get_tag_pool", lambda tag: fake_pool(tag))
monkeypatch.setattr("code.web.services.sampling.maybe_build_index", lambda: None)
monkeypatch.setattr("code.web.services.sampling.lookup_commander", lambda name: None)
chosen = sampling.sample_real_cards_for_theme(
theme="testtheme",
limit=12,
colors_filter=None,
synergies=["testtheme"],
commander=None,
)
# Ensure we have more than half flagged as payoff in initial classification
payoff_scores = [c["score"] for c in chosen if c["roles"][0] == "payoff"]
assert payoff_scores, "Expected payoff cards present"
# Saturation penalty should have been applied to at least one (score reduced by 0.4 increments) once cap exceeded.
# We detect presence by existence of reason substring.
penalized = [c for c in chosen if any(r.startswith("role_saturation_penalty") for r in c.get("reasons", []))]
assert penalized, "Expected at least one card to receive role_saturation_penalty"