327 lines
9.1 KiB
Python
327 lines
9.1 KiB
Python
"""Comprehensive test of interaction_determinator.py"""
|
|
import sys
|
|
sys.path.insert(0, "/home/wall-o/projects/mtgonline/backend/scripts")
|
|
|
|
from interaction_determinator import (
|
|
InteractionDeterminator,
|
|
InteractionResult,
|
|
InteractionType,
|
|
)
|
|
|
|
det = InteractionDeterminator()
|
|
|
|
print("=" * 60)
|
|
print("TEST 1: extract_colors")
|
|
print("=" * 60)
|
|
|
|
# MTGJSON braced format
|
|
assert det.extract_colors("{1}{W}{U}") == ["W", "U"], f"Got: {det.extract_colors('{1}{W}{U}')}"
|
|
# Plain format
|
|
assert det.extract_colors("WWU") == ["W", "U"], f"Got: {det.extract_colors('WWU')}"
|
|
# Empty
|
|
assert det.extract_colors("") == []
|
|
# None
|
|
assert det.extract_colors(None) == []
|
|
# Single color
|
|
assert det.extract_colors("{R}") == ["R"]
|
|
# Multi-color
|
|
assert det.extract_colors("{W}{B}{R}") == ["W", "B", "R"]
|
|
print(" ✓ All color extraction tests passed")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 2: extract_archetypes")
|
|
print("=" * 60)
|
|
|
|
# List input (MTGJSON format)
|
|
assert sorted(det.extract_archetypes(["Goblin", "Warrior"])) == ["goblin", "warrior"], f"Got: {det.extract_archetypes(['Goblin', 'Warrior'])}"
|
|
# String input
|
|
assert sorted(det.extract_archetypes("Goblin Warrior")) == ["goblin", "warrior"]
|
|
# Empty
|
|
assert det.extract_archetypes([]) == []
|
|
assert det.extract_archetypes("") == []
|
|
# Multiple archetypes
|
|
result = det.extract_archetypes(["Elf", "Warrior", "Knight"])
|
|
assert "elf" in result and "warrior" in result and "knight" in result, f"Got: {result}"
|
|
print(" ✓ All archetype extraction tests passed")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 3: extract_mechanics")
|
|
print("=" * 60)
|
|
|
|
# Test that extracted mechanics work correctly
|
|
mechs = det.extract_mechanics("Creature — Elf", "Flying\nFirst strike")
|
|
assert "flying" in mechs, f"Got: {mechs}"
|
|
assert "first_strike" in mechs, f"Got: {mechs}"
|
|
# Empty
|
|
assert det.extract_mechanics("", "") == []
|
|
print(" ✓ All mechanic extraction tests passed")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 4: extract_targets")
|
|
print("=" * 60)
|
|
|
|
targets = det.extract_targets("Destroy target creature. Draw a card.")
|
|
assert "creature" in targets
|
|
assert "draws_card" in targets
|
|
assert det.extract_targets("") == []
|
|
print(" ✓ All target extraction tests passed")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 5: extract_triggers")
|
|
print("=" * 60)
|
|
|
|
triggers = det.extract_triggers("When this enters the battlefield, draw a card.")
|
|
assert "enters_battlefield" in triggers
|
|
assert "draws_card" in triggers
|
|
assert det.extract_triggers("") == []
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 6: extract_effects")
|
|
print("=" * 60)
|
|
|
|
effects = det.extract_effects("Target creature gains flying until end of turn.")
|
|
assert "gain_flying" in effects
|
|
assert "until_end_of_turn" in effects
|
|
assert det.extract_effects("") == []
|
|
print(" ✓ All effect extraction tests passed")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 7: extract_card_properties")
|
|
print("=" * 60)
|
|
|
|
card = {
|
|
"id": 1,
|
|
"name": "Test Card",
|
|
"types": ["Creature", "Elf"],
|
|
"subtypes": ["Elf", "Warrior"],
|
|
"mana_cost": "{1}{W}",
|
|
"oracle_text": "Flying\nWhen this enters the battlefield, draw a card.\nTarget creature gains deathtouch until end of turn.",
|
|
"power": "2",
|
|
"toughness": "2",
|
|
"card_faces": [],
|
|
}
|
|
profile = det.extract_card_properties(card)
|
|
assert profile["id"] == 1
|
|
assert profile["colors"] == ["W"]
|
|
assert "flying" in profile["mechanics"]
|
|
assert "elf" in profile["archetypes"]
|
|
assert "creature" in profile["targets"]
|
|
assert "enters_battlefield" in profile["triggers"]
|
|
assert "draws_card" in profile["triggers"]
|
|
assert profile["power"] == 2
|
|
assert profile["toughness"] == 2
|
|
print(" ✓ All card property extraction tests passed")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 8: determine_synergies")
|
|
print("=" * 60)
|
|
|
|
# Same archetype synergy
|
|
card_a = det.extract_card_properties({
|
|
"id": 10,
|
|
"name": "Goblin Warrior",
|
|
"types": ["Creature"],
|
|
"subtypes": ["Goblin", "Warrior"],
|
|
"mana_cost": "{R}",
|
|
"oracle_text": "Flying\nWhen this enters the battlefield, draw a card.",
|
|
"power": "1",
|
|
"toughness": "1",
|
|
"card_faces": [],
|
|
})
|
|
card_b = det.extract_card_properties({
|
|
"id": 11,
|
|
"name": "Goblin Hero",
|
|
"types": ["Creature"],
|
|
"subtypes": ["Goblin"],
|
|
"mana_cost": "{R}",
|
|
"oracle_text": "When this enters the battlefield, draw a card.",
|
|
"power": "2",
|
|
"toughness": "1",
|
|
"card_faces": [],
|
|
})
|
|
synergies = det.determine_synergies(card_a, card_b)
|
|
assert any(s.interaction_type == "archetype_support" for s in synergies), "Expected archetype_support"
|
|
print(f" ✓ Found {len(synergies)} synergies")
|
|
for s in synergies:
|
|
print(f" - {s.interaction_type}: {s.notes}")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 9: determine_counters")
|
|
print("=" * 60)
|
|
|
|
card_c = det.extract_card_properties({
|
|
"id": 12,
|
|
"name": "Indestructible Wall",
|
|
"types": ["Creature"],
|
|
"subtypes": ["Wall"],
|
|
"mana_cost": "{2}{W}",
|
|
"oracle_text": "Indestructible",
|
|
"power": "0",
|
|
"toughness": "5",
|
|
"card_faces": [],
|
|
})
|
|
card_d = det.extract_card_properties({
|
|
"id": 13,
|
|
"name": "Deathtouch Beast",
|
|
"types": ["Creature"],
|
|
"subtypes": ["Beast"],
|
|
"mana_cost": "{1}{B}",
|
|
"oracle_text": "Deathtouch",
|
|
"power": "1",
|
|
"toughness": "1",
|
|
"card_faces": [],
|
|
})
|
|
counters = det.determine_counters(card_c, card_d)
|
|
assert any("indestructible" in c.interaction_type.lower() or "deathtouch" in c.interaction_type.lower() for c in counters), "Expected indestructible/deathtouch counter"
|
|
print(f" ✓ Found {len(counters)} counters")
|
|
for c in counters:
|
|
print(f" - {c.interaction_type}: {c.notes}")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 10: determine_evolutions")
|
|
print("=" * 60)
|
|
|
|
card_e = det.extract_card_properties({
|
|
"id": 14,
|
|
"name": "Same Name Card",
|
|
"types": ["Creature"],
|
|
"subtypes": ["Elf"],
|
|
"mana_cost": "{G}",
|
|
"oracle_text": "Trample",
|
|
"power": "3",
|
|
"toughness": "3",
|
|
"card_faces": [],
|
|
})
|
|
card_f = det.extract_card_properties({
|
|
"id": 15,
|
|
"name": "Same Name Card",
|
|
"types": ["Creature"],
|
|
"subtypes": ["Elf"],
|
|
"mana_cost": "{G}",
|
|
"oracle_text": "Trample",
|
|
"power": "3",
|
|
"toughness": "3",
|
|
"card_faces": [],
|
|
})
|
|
evolutions = det.determine_evolutions(card_e, card_f)
|
|
assert any(e.interaction_type == "reprinted" for e in evolutions), "Expected reprint"
|
|
print(f" ✓ Found {len(evolutions)} evolutions")
|
|
for e in evolutions:
|
|
print(f" - {e.interaction_type}: {e.notes}")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 11: determine_all_interactions (batch)")
|
|
print("=" * 60)
|
|
|
|
all_cards = [card_a, card_b, card_c, card_d, card_e, card_f]
|
|
batch = det.determine_all_interactions(all_cards)
|
|
print(f" Synergies: {len(batch['synergies'])}")
|
|
print(f" Counters: {len(batch['counters'])}")
|
|
print(f" Evolutions: {len(batch['evolutions'])}")
|
|
assert len(batch["synergies"]) > 0
|
|
assert len(batch["counters"]) > 0
|
|
print(" ✓ Batch interaction determination passed")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 12: filter_by_confidence")
|
|
print("=" * 60)
|
|
|
|
high_conf = det.filter_by_confidence(batch["synergies"], 0.9)
|
|
assert all(s.confidence >= 0.9 for s in high_conf)
|
|
print(f" ✓ Filtered to {len(high_conf)} high-confidence synergies")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 13: group_by_card")
|
|
print("=" * 60)
|
|
|
|
grouped = det.group_by_card(batch["synergies"])
|
|
assert all(isinstance(v, list) for v in grouped.values())
|
|
print(f" ✓ Grouped into {len(grouped)} cards")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 14: get_interaction_summary")
|
|
print("=" * 60)
|
|
|
|
summary = det.get_interaction_summary(batch["synergies"])
|
|
assert isinstance(summary, dict)
|
|
print(f" ✓ Summary: {summary}")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("TEST 15: Pipeline integration (raw dicts)")
|
|
print("=" * 60)
|
|
|
|
# Test with raw MTGJSON-style dicts (as the pipeline passes them)
|
|
raw_cards = [
|
|
{
|
|
"id": 100,
|
|
"name": "Goblin Warrior",
|
|
"types": ["Creature"],
|
|
"subtypes": ["Goblin", "Warrior"],
|
|
"mana_cost": "{R}",
|
|
"oracle_text": "Flying\nWhen this enters the battlefield, draw a card.",
|
|
"power": "1",
|
|
"toughness": "1",
|
|
"card_faces": [],
|
|
},
|
|
{
|
|
"id": 101,
|
|
"name": "Goblin Hero",
|
|
"types": ["Creature"],
|
|
"subtypes": ["Goblin"],
|
|
"mana_cost": "{R}",
|
|
"oracle_text": "When this enters the battlefield, draw a card.",
|
|
"power": "2",
|
|
"toughness": "1",
|
|
"card_faces": [],
|
|
},
|
|
{
|
|
"id": 102,
|
|
"name": "Indestructible Wall",
|
|
"types": ["Creature"],
|
|
"subtypes": ["Wall"],
|
|
"mana_cost": "{2}{W}",
|
|
"oracle_text": "Indestructible",
|
|
"power": "0",
|
|
"toughness": "5",
|
|
"card_faces": [],
|
|
},
|
|
{
|
|
"id": 103,
|
|
"name": "Deathtouch Beast",
|
|
"types": ["Creature"],
|
|
"subtypes": ["Beast"],
|
|
"mana_cost": "{1}{B}",
|
|
"oracle_text": "Deathtouch",
|
|
"power": "1",
|
|
"toughness": "1",
|
|
"card_faces": [],
|
|
},
|
|
]
|
|
|
|
batch = det.determine_all_interactions(raw_cards)
|
|
print(f" Synergies: {len(batch['synergies'])}")
|
|
print(f" Counters: {len(batch['counters'])}")
|
|
print(f" Evolutions: {len(batch['evolutions'])}")
|
|
assert len(batch["synergies"]) > 0
|
|
assert len(batch["counters"]) > 0
|
|
print(" ✓ Pipeline integration test passed")
|
|
|
|
print()
|
|
print("=" * 60)
|
|
print("ALL TESTS PASSED ✓")
|
|
print("=" * 60)
|