LovecaSim / engine /tests /framework /ability_test_generator.py
trioskosmos's picture
Upload folder using huggingface_hub
bb3fbf9 verified
"""
Auto-generates test cases for all cards with abilities.
"""
import json
from pathlib import Path
from typing import Any, Dict, List
def load_card_database() -> Dict[str, Any]:
"""Load compiled card database."""
# Try multiple paths
paths = [
Path("data/cards_compiled.json"),
Path("engine/data/cards_compiled.json"),
]
for p in paths:
if p.exists():
with open(p, "r", encoding="utf-8") as f:
return json.load(f)
raise FileNotFoundError("Could not find cards_compiled.json")
def generate_ability_test_cases() -> List[Dict[str, Any]]:
"""
Generate parametrized test cases for all cards with abilities.
Returns list of dicts with:
- card_id: int
- card_name: str
- card_type: 'member' or 'live'
- ability_idx: int
- trigger: str (e.g., 'ON_PLAY', 'LIVE_START')
- effects: List[str] (e.g., ['DRAW_CARDS', 'DISCARD'])
- has_cost: bool
- is_optional: bool
"""
data = load_card_database()
test_cases = []
# Process members
from engine.models.ability import TriggerType
for cid_str, card in data.get("member_db", {}).items():
cid = int(cid_str)
abilities = card.get("abilities", [])
for idx, ability in enumerate(abilities):
raw_trigger = ability.get("trigger", "NONE")
# Map int to Enum name if possible
try:
if isinstance(raw_trigger, int):
trigger = TriggerType(raw_trigger).name
else:
trigger = raw_trigger
except Exception:
trigger = str(raw_trigger)
effects = [e.get("effect_type", "UNKNOWN") for e in ability.get("effects", [])]
costs = ability.get("costs", [])
# Map condition enums
from engine.models.ability import ConditionType, TriggerType
conditions = []
for c in ability.get("conditions", []):
# Compiled JSON uses 'type' for ConditionType
ctype = c.get("type", c.get("condition_type", "NONE"))
try:
if isinstance(ctype, int):
cname = ConditionType(ctype).name
else:
cname = ctype
except Exception:
cname = str(ctype)
cond_copy = c.copy()
cond_copy["condition_type"] = cname
conditions.append(cond_copy)
test_cases.append(
{
"card_id": cid,
"card_name": card.get("name", f"Unknown_{cid}"),
"card_type": "member",
"ability_idx": idx,
"trigger": trigger,
"effects": effects,
"conditions": conditions,
"has_cost": len(costs) > 0,
"is_optional": any(c.get("is_optional", False) for c in costs),
"raw_text": ability.get("raw_text", "")[:50],
}
)
# Process lives
for cid_str, card in data.get("live_db", {}).items():
cid = int(cid_str)
abilities = card.get("abilities", [])
for idx, ability in enumerate(abilities):
trigger = ability.get("trigger", "NONE")
effects = [e.get("effect_type", "UNKNOWN") for e in ability.get("effects", [])]
test_cases.append(
{
"card_id": cid,
"card_name": card.get("name", f"Unknown_{cid}"),
"card_type": "live",
"ability_idx": idx,
"trigger": trigger,
"effects": effects,
"has_cost": False,
"is_optional": False,
"raw_text": ability.get("raw_text", "")[:50],
}
)
return test_cases
def get_cards_by_trigger(trigger: str) -> List[Dict[str, Any]]:
"""Get all test cases with a specific trigger type."""
return [tc for tc in generate_ability_test_cases() if tc["trigger"] == trigger]
def get_cards_by_effect(effect: str) -> List[Dict[str, Any]]:
"""Get all test cases that include a specific effect type."""
return [tc for tc in generate_ability_test_cases() if effect in tc["effects"]]
def get_complex_cards(min_effects: int = 3) -> List[Dict[str, Any]]:
"""Get cards with complex abilities (multiple effects)."""
return [tc for tc in generate_ability_test_cases() if len(tc["effects"]) >= min_effects]
def get_cards_with_condition(condition_type: str) -> List[Dict[str, Any]]:
"""Get all test cases that have a specific condition type."""
cases = []
for tc in generate_ability_test_cases():
for cond in tc.get("conditions", []):
if cond.get("condition_type") == condition_type:
cases.append(tc)
break
return cases
# Summary statistics
def print_ability_summary():
"""Print summary of ability coverage."""
cases = generate_ability_test_cases()
# Count by trigger
triggers = {}
for tc in cases:
triggers[tc["trigger"]] = triggers.get(tc["trigger"], 0) + 1
# Count by effect
effects = {}
for tc in cases:
for e in tc["effects"]:
effects[e] = effects.get(e, 0) + 1
print(f"Total abilities: {len(cases)}")
print("\nBy Trigger:")
for t, c in sorted(triggers.items(), key=lambda x: -x[1]):
print(f" {t}: {c}")
print("\nBy Effect (top 15):")
for e, c in sorted(effects.items(), key=lambda x: -x[1])[:15]:
print(f" {e}: {c}")
if __name__ == "__main__":
print_ability_summary()