Final project commit: MTGJSON data integration and backend API
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
# MTG Card Interaction Pipeline - Code Review
|
||||
|
||||
## Overview
|
||||
|
||||
The interaction pipeline consists of four main modules:
|
||||
1. `card_profile_extractor.py` - Extracts structured profiles from MTGJSON data
|
||||
2. `interaction_determinator.py` - Determines interactions between card pairs
|
||||
3. `interaction_recommender.py` - Generates recommendations based on interactions
|
||||
4. `interaction_pipeline.py` - Orchestrates the full pipeline
|
||||
|
||||
## Issues Found
|
||||
|
||||
### 1. Import Inconsistency (Critical)
|
||||
**File**: `interaction_pipeline.py`
|
||||
**Issue**: Complex import for `sessionmaker`
|
||||
```python
|
||||
self.SessionLocal = __import__('sqlalchemy.orm', fromlist=['sessionmaker']).sessionmaker(bind=self.engine)
|
||||
```
|
||||
**Fix**: Use direct import at module level:
|
||||
```python
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
# ...
|
||||
self.SessionLocal = sessionmaker(bind=self.engine)
|
||||
```
|
||||
|
||||
### 2. Type Hints Inconsistency (Medium)
|
||||
**File**: `interaction_pipeline.py`
|
||||
**Issue**: Inconsistent type hints
|
||||
```python
|
||||
def extract_profiles(self, cards: List[Dict]) -> List: # Missing type parameter
|
||||
def determine_interactions(self, profiles) -> dict: # Missing parameter type
|
||||
```
|
||||
**Fix**: Add proper type hints:
|
||||
```python
|
||||
def extract_profiles(self, cards: List[Dict]) -> List[CardProfile]:
|
||||
def determine_interactions(self, profiles: List[CardProfile]) -> dict:
|
||||
```
|
||||
|
||||
### 3. Complex Conditional Logic (High)
|
||||
**File**: `interaction_pipeline.py`
|
||||
**Issue**: Nested ternary operators for synergy_type and counter_type determination
|
||||
```python
|
||||
"synergy_type": "archetype" if interaction.metadata and interaction.metadata.get('common_archetypes') else
|
||||
"mechanic" if interaction.metadata and interaction.metadata.get('mechanics') else
|
||||
"mana" if interaction.metadata and interaction.metadata.get('colors') else
|
||||
"combo" if interaction.metadata and interaction.metadata.get('card_a_targets') else
|
||||
"support",
|
||||
```
|
||||
**Fix**: Extract to helper methods or use lookup dictionaries
|
||||
|
||||
### 4. Missing Validation (Medium)
|
||||
**File**: `interaction_pipeline.py`
|
||||
**Issue**: No validation for empty card lists or invalid data
|
||||
**Fix**: Add validation at the start of methods
|
||||
|
||||
### 5. Evolution Type Mapping (High)
|
||||
**File**: `interaction_pipeline.py`
|
||||
**Issue**: Using `interaction.interaction_type` which is 'evolution' for all evolutions
|
||||
**Fix**: Map to specific evolution types based on metadata
|
||||
|
||||
## Recommended Fixes
|
||||
|
||||
### Fix 1: Import Structure
|
||||
```python
|
||||
# At top of file
|
||||
from sqlalchemy import create_engine, text
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
# In __init__
|
||||
self.SessionLocal = sessionmaker(bind=self.engine)
|
||||
```
|
||||
|
||||
### Fix 2: Type Hints
|
||||
```python
|
||||
def extract_profiles(self, cards: List[Dict]) -> List[CardProfile]:
|
||||
return self.profile_extractor.extract_profiles_batch(cards)
|
||||
|
||||
def determine_interactions(self, profiles: List[CardProfile]) -> dict:
|
||||
return self.determinator.determine_all_interactions(profiles)
|
||||
```
|
||||
|
||||
### Fix 3: Helper Methods for Type Determination
|
||||
```python
|
||||
def _determine_synergy_type(self, interaction) -> str:
|
||||
"""Determine synergy type from interaction metadata."""
|
||||
metadata = interaction.metadata or {}
|
||||
|
||||
if 'common_archetypes' in metadata:
|
||||
return 'archetype'
|
||||
elif 'mechanics' in metadata:
|
||||
return 'mechanic'
|
||||
elif 'colors' in metadata:
|
||||
return 'mana'
|
||||
elif 'card_a_targets' in metadata:
|
||||
return 'combo'
|
||||
else:
|
||||
return 'support'
|
||||
|
||||
def _determine_counter_type(self, interaction) -> str:
|
||||
"""Determine counter type from interaction metadata."""
|
||||
metadata = interaction.metadata or {}
|
||||
|
||||
if 'colors_a' in metadata:
|
||||
return 'color'
|
||||
elif 'power_a' in metadata:
|
||||
return 'stats'
|
||||
else:
|
||||
return 'keyword'
|
||||
|
||||
def _determine_evolution_type(self, interaction) -> str:
|
||||
"""Determine evolution type from interaction metadata."""
|
||||
metadata = interaction.metadata or {}
|
||||
|
||||
if 'card_name' in metadata:
|
||||
return 'reprint'
|
||||
else:
|
||||
return 'evolution'
|
||||
```
|
||||
|
||||
### Fix 4: Add Validation
|
||||
```python
|
||||
def run_initial_load(self, set_code: Optional[str] = None):
|
||||
"""Run initial load with validation."""
|
||||
if not set_code:
|
||||
logger.info("No set code provided, loading all cards")
|
||||
|
||||
all_cards = self.load_cards_from_db(set_code)
|
||||
|
||||
if not all_cards:
|
||||
logger.warning("No cards found in database")
|
||||
return
|
||||
|
||||
# Continue with processing...
|
||||
```
|
||||
|
||||
## Accuracy Review
|
||||
|
||||
### Profile Extraction
|
||||
✅ **Correct**: Color extraction from mana cost
|
||||
✅ **Correct**: Mechanic extraction using regex patterns
|
||||
✅ **Correct**: Archetype extraction from subtypes
|
||||
✅ **Correct**: Target extraction from oracle text
|
||||
✅ **Correct**: Trigger and effect extraction
|
||||
✅ **Correct**: Theme extraction based on characteristics
|
||||
|
||||
### Interaction Determination
|
||||
✅ **Correct**: Archetype synergy detection
|
||||
✅ **Correct**: Mana synergy detection
|
||||
✅ **Correct**: Mechanic synergy detection (haste+trample, lifelink+combat)
|
||||
✅ **Correct**: Combo synergy detection (targets + triggers)
|
||||
✅ **Correct**: Support synergy detection
|
||||
✅ **Correct**: Counter detection (color, stats, keywords)
|
||||
✅ **Correct**: Evolution detection (reprints)
|
||||
|
||||
### Database Schema
|
||||
✅ **Correct**: Synergies table with proper constraints
|
||||
✅ **Correct**: Counters table with proper constraints
|
||||
✅ **Correct**: Evolutions table with proper constraints
|
||||
✅ **Correct**: Statistics table with proper aggregations
|
||||
✅ **Correct**: Foreign key relationships
|
||||
✅ **Correct**: Unique constraints to prevent duplicates
|
||||
|
||||
## Consistency Issues
|
||||
|
||||
### 1. File Organization
|
||||
- All files in `/home/wall-o/projects/mtgonline/backend/scripts/`
|
||||
- No clear separation between core logic and pipeline
|
||||
- **Recommendation**: Keep as is for simplicity
|
||||
|
||||
### 2. Naming Conventions
|
||||
- **Good**: Consistent use of snake_case for methods
|
||||
- **Good**: Consistent use of CamelCase for classes
|
||||
- **Issue**: Mixed use of `set_code` parameter naming
|
||||
- **Recommendation**: Standardize on `set_code`
|
||||
|
||||
### 3. Error Handling
|
||||
- **Good**: Try/finally blocks for database connections
|
||||
- **Issue**: No specific exception handling for database errors
|
||||
- **Recommendation**: Add specific exception types
|
||||
|
||||
### 4. Logging
|
||||
- **Good**: Consistent logging format
|
||||
- **Good**: Appropriate log levels (INFO, WARNING, ERROR)
|
||||
- **Issue**: Missing DEBUG logging for development
|
||||
- **Recommendation**: Add DEBUG level logging
|
||||
|
||||
## Summary
|
||||
|
||||
### Critical Issues (Must Fix)
|
||||
1. ❌ Import structure for sessionmaker
|
||||
2. ❌ Complex conditional logic for type determination
|
||||
|
||||
### High Priority Issues (Should Fix)
|
||||
3. ❌ Missing type hints
|
||||
4. ❌ Evolution type mapping
|
||||
5. ❌ Missing validation
|
||||
|
||||
### Medium Priority Issues (Nice to Have)
|
||||
6. ⚠️ Add specific exception handling
|
||||
7. ⚠️ Add DEBUG logging
|
||||
8. ⚠️ Standardize parameter naming
|
||||
|
||||
### Low Priority Issues (Can Defer)
|
||||
9. ✅ All core logic is accurate and correct
|
||||
10. ✅ Database schema is well-designed
|
||||
11. ✅ Interaction determination logic is sound
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Fix Critical Issues**: Update import structure and simplify conditional logic
|
||||
2. **Fix High Priority**: Add proper type hints and validation
|
||||
3. **Test**: Run pipeline with sample data to verify functionality
|
||||
4. **Document**: Add docstrings and inline comments for complex logic
|
||||
Reference in New Issue
Block a user