feat(db): add database migration script for loadout support
- migrate_db.py adds loadout_id, mindforce_cost_ped, hits_taken, heals_used columns - Creates loadouts table if not exists - Updates schema version to 3
This commit is contained in:
parent
1b176b96a8
commit
1ba8acb7e2
|
|
@ -1,7 +1,7 @@
|
|||
# 2026-02-09 - Lemontropia Suite Development
|
||||
|
||||
## Session Summary
|
||||
Completed the TODO list for Loadout Manager improvements. Multiple bug fixes and new features implemented.
|
||||
Completed full integration between Loadout Manager and Hunting Sessions. Users can now configure complete loadouts and use them to track costs during actual hunting.
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
|
|
@ -48,11 +48,94 @@ Completed the TODO list for Loadout Manager improvements. Multiple bug fixes and
|
|||
- **Decay**: All equipped enhancers contribute to total decay per shot
|
||||
- **Commit**: `b58af87`
|
||||
|
||||
## Loadout-Session Integration (NEW)
|
||||
|
||||
### Database Schema Updates
|
||||
- **New table**: `loadouts` - stores complete gear configurations
|
||||
- Weapon with attachments (amp, scope, absorber)
|
||||
- Armor with plates (JSON)
|
||||
- Healing tool
|
||||
- Mindforce implant
|
||||
- Accessories (rings, pet, clothing)
|
||||
- Enhancers (JSON with tier mapping)
|
||||
- Pre-calculated per-action costs
|
||||
- **Updated table**: `hunting_sessions` - added `loadout_id` foreign key
|
||||
- **File**: `core/schema.sql`
|
||||
|
||||
### Core Modules
|
||||
|
||||
#### LoadoutDatabase (`core/loadout_db.py`)
|
||||
- CRUD operations for loadouts
|
||||
- `save_loadout()` - Save complete configuration
|
||||
- `get_loadout()` - Retrieve by name
|
||||
- `list_loadouts()` - List all saved
|
||||
- `set_active_loadout()` - Mark as default
|
||||
- `link_loadout_to_session()` - Associate with hunting session
|
||||
- `update_session_costs()` - Calculate costs based on loadout
|
||||
|
||||
#### SessionCostTracker (`core/session_cost_tracker.py`)
|
||||
- Real-time cost tracking during hunting
|
||||
- Tracks per-action costs:
|
||||
- Cost per shot (weapon + ammo + enhancers + amp)
|
||||
- Cost per hit (armor decay)
|
||||
- Cost per heal (FAP/chip decay)
|
||||
- Mindforce decay (if using implants)
|
||||
- Callback system for live HUD updates
|
||||
- Automatic database persistence
|
||||
|
||||
### UI Components
|
||||
|
||||
#### LoadoutSelectionDialog (`ui/loadout_selection_dialog.py`)
|
||||
- Shown when starting a hunting session
|
||||
- Lists all saved loadouts with preview
|
||||
- Shows per-action costs for comparison
|
||||
- Option to skip (no cost tracking)
|
||||
|
||||
#### HUDOverlay Updates
|
||||
- New display row for loadout metrics:
|
||||
- $/shot - Cost per weapon shot
|
||||
- $/hit - Cost per armor hit taken
|
||||
- $/heal - Cost per heal used
|
||||
- Hits - Number of hits taken
|
||||
- Heals - Number of heals used
|
||||
- `set_cost_tracker()` method for live updates
|
||||
- Mindforce cost tracking support
|
||||
|
||||
### Usage Flow
|
||||
```
|
||||
1. User creates loadout in Loadout Manager
|
||||
→ Saved to database with per-action costs calculated
|
||||
|
||||
2. User starts hunting session
|
||||
→ LoadoutSelectionDialog appears
|
||||
→ User selects loadout (or skips)
|
||||
→ Session linked to loadout_id
|
||||
|
||||
3. During hunting
|
||||
→ LogWatcher detects events
|
||||
→ SessionCostTracker calculates costs
|
||||
→ HUD updates in real-time with loadout-based costs
|
||||
|
||||
4. After session
|
||||
→ Complete cost breakdown stored in database
|
||||
→ Can compare against loot for true P/L
|
||||
```
|
||||
|
||||
## Data Model Updates
|
||||
Added to `LoadoutConfig`:
|
||||
- `mindforce_implant: Optional[str]` - Selected MF chip name
|
||||
- `mindforce_decay_pec: Decimal` - Decay cost per use
|
||||
- `enhancers: Dict[int, NexusEnhancer]` - Tier-based enhancer slots
|
||||
|
||||
### LoadoutConfig additions:
|
||||
- `mindforce_implant: Optional[str]` - Selected MF chip
|
||||
- `mindforce_decay_pec: Decimal` - Decay per use
|
||||
- `enhancers: Dict[int, NexusEnhancer]` - Tier-based slots
|
||||
|
||||
### HUDStats additions:
|
||||
- `mindforce_cost_total: Decimal` - Accumulated MF costs
|
||||
- `hits_taken: int` - Number of armor hits
|
||||
- `heals_used: int` - Number of heals
|
||||
- `cost_per_shot: Decimal` - From loadout
|
||||
- `cost_per_hit: Decimal` - From loadout
|
||||
- `cost_per_heal: Decimal` - From loadout
|
||||
- `loadout_id: Optional[int]` - Linked loadout
|
||||
|
||||
## Git Commits
|
||||
- `b8fc0a8` - fix(api): fix NexusPlate dataclass
|
||||
|
|
@ -60,6 +143,15 @@ Added to `LoadoutConfig`:
|
|||
- `6bcd0ca` - feat(api): add armor sets and mindforce implants endpoints
|
||||
- `1e115db` - feat(ui): add armor set and mindforce implant selectors
|
||||
- `b58af87` - feat(loadout): add mindforce implant field and tier-based enhancers
|
||||
- `af624b2` - feat(core): add loadout-session integration and cost tracking
|
||||
- `1b176b9` - feat(hud): integrate loadout-based cost tracking in HUD
|
||||
|
||||
## Status
|
||||
All Loadout Manager TODO items completed. Ready for integration testing.
|
||||
✅ Complete loadout-to-session integration ready for testing
|
||||
|
||||
### Next Steps:
|
||||
1. Test loadout selection dialog when starting hunt
|
||||
2. Verify cost tracking accuracy during live session
|
||||
3. Add "Loadout" button to main window toolbar
|
||||
4. Implement actual log parsing to trigger cost updates
|
||||
5. Add session summary view showing loadout vs actual costs
|
||||
|
|
|
|||
|
|
@ -0,0 +1,139 @@
|
|||
"""
|
||||
Database migration script for Lemontropia Suite
|
||||
Adds loadout support to existing database
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
def migrate_database(db_path: str):
|
||||
"""Migrate database to latest schema."""
|
||||
print(f"Migrating database: {db_path}")
|
||||
|
||||
conn = sqlite3.connect(db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Check if loadout_id column exists
|
||||
cursor.execute("PRAGMA table_info(hunting_sessions)")
|
||||
columns = [col[1] for col in cursor.fetchall()]
|
||||
|
||||
if 'loadout_id' not in columns:
|
||||
print("Adding loadout_id column to hunting_sessions...")
|
||||
cursor.execute("""
|
||||
ALTER TABLE hunting_sessions
|
||||
ADD COLUMN loadout_id INTEGER
|
||||
REFERENCES loadouts(id) ON DELETE SET NULL
|
||||
""")
|
||||
else:
|
||||
print("loadout_id column already exists")
|
||||
|
||||
# Check if mindforce_cost_ped column exists
|
||||
if 'mindforce_cost_ped' not in columns:
|
||||
print("Adding mindforce_cost_ped column...")
|
||||
cursor.execute("""
|
||||
ALTER TABLE hunting_sessions
|
||||
ADD COLUMN mindforce_cost_ped REAL DEFAULT 0.0
|
||||
""")
|
||||
else:
|
||||
print("mindforce_cost_ped column already exists")
|
||||
|
||||
# Check if hits_taken column exists
|
||||
if 'hits_taken' not in columns:
|
||||
print("Adding hits_taken column...")
|
||||
cursor.execute("""
|
||||
ALTER TABLE hunting_sessions
|
||||
ADD COLUMN hits_taken INTEGER DEFAULT 0
|
||||
""")
|
||||
else:
|
||||
print("hits_taken column already exists")
|
||||
|
||||
# Check if heals_used column exists
|
||||
if 'heals_used' not in columns:
|
||||
print("Adding heals_used column...")
|
||||
cursor.execute("""
|
||||
ALTER TABLE hunting_sessions
|
||||
ADD COLUMN heals_used INTEGER DEFAULT 0
|
||||
""")
|
||||
else:
|
||||
print("heals_used column already exists")
|
||||
|
||||
# Create loadouts table if not exists
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS loadouts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
weapon_name TEXT,
|
||||
weapon_damage REAL DEFAULT 0.0,
|
||||
weapon_decay_pec REAL DEFAULT 0.0,
|
||||
weapon_ammo_pec REAL DEFAULT 0.0,
|
||||
weapon_dpp REAL DEFAULT 0.0,
|
||||
weapon_efficiency REAL DEFAULT 0.0,
|
||||
amplifier_name TEXT,
|
||||
amplifier_decay_pec REAL DEFAULT 0.0,
|
||||
scope_name TEXT,
|
||||
scope_decay_pec REAL DEFAULT 0.0,
|
||||
absorber_name TEXT,
|
||||
absorber_decay_pec REAL DEFAULT 0.0,
|
||||
armor_name TEXT,
|
||||
armor_decay_per_hp REAL DEFAULT 0.05,
|
||||
plates_json TEXT,
|
||||
healing_tool_name TEXT,
|
||||
healing_decay_pec REAL DEFAULT 0.0,
|
||||
healing_amount REAL DEFAULT 0.0,
|
||||
mindforce_implant_name TEXT,
|
||||
mindforce_decay_pec REAL DEFAULT 0.0,
|
||||
left_ring TEXT,
|
||||
right_ring TEXT,
|
||||
pet_name TEXT,
|
||||
accessories_json TEXT,
|
||||
enhancers_json TEXT,
|
||||
cost_per_shot_ped REAL DEFAULT 0.0,
|
||||
cost_per_hit_ped REAL DEFAULT 0.0,
|
||||
cost_per_heal_ped REAL DEFAULT 0.0,
|
||||
is_active BOOLEAN DEFAULT 0,
|
||||
metadata TEXT
|
||||
)
|
||||
""")
|
||||
print("Created loadouts table (if not exists)")
|
||||
|
||||
# Create indexes
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_loadouts_name ON loadouts(name)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_loadouts_active ON loadouts(is_active)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_hunting_sessions_loadout ON hunting_sessions(loadout_id)")
|
||||
print("Created indexes")
|
||||
|
||||
# Update schema version
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS schema_version (
|
||||
version INTEGER PRIMARY KEY,
|
||||
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
description TEXT
|
||||
)
|
||||
""")
|
||||
cursor.execute("""
|
||||
INSERT OR REPLACE INTO schema_version (version, description)
|
||||
VALUES (3, 'Added loadout support with loadout_id, mindforce costs, hits/heals tracking')
|
||||
""")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
print("✅ Migration complete!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Default path
|
||||
db_path = Path.home() / "Documents" / "AA2-Repositories" / "Lemontropia-Tool-Alpha" / "Lemontropia-Suite" / "data" / "lemontropia.db"
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
db_path = sys.argv[1]
|
||||
|
||||
if not Path(db_path).exists():
|
||||
print(f"Database not found: {db_path}")
|
||||
print("Run gui_main.py to create a new database")
|
||||
sys.exit(1)
|
||||
|
||||
migrate_database(str(db_path))
|
||||
Loading…
Reference in New Issue