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:
LemonNexus 2026-02-09 16:55:38 +00:00
parent 1b176b96a8
commit 1ba8acb7e2
2 changed files with 237 additions and 6 deletions

View File

@ -1,7 +1,7 @@
# 2026-02-09 - Lemontropia Suite Development # 2026-02-09 - Lemontropia Suite Development
## Session Summary ## 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 ## 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 - **Decay**: All equipped enhancers contribute to total decay per shot
- **Commit**: `b58af87` - **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 ## Data Model Updates
Added to `LoadoutConfig`:
- `mindforce_implant: Optional[str]` - Selected MF chip name ### LoadoutConfig additions:
- `mindforce_decay_pec: Decimal` - Decay cost per use - `mindforce_implant: Optional[str]` - Selected MF chip
- `enhancers: Dict[int, NexusEnhancer]` - Tier-based enhancer slots - `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 ## Git Commits
- `b8fc0a8` - fix(api): fix NexusPlate dataclass - `b8fc0a8` - fix(api): fix NexusPlate dataclass
@ -60,6 +143,15 @@ Added to `LoadoutConfig`:
- `6bcd0ca` - feat(api): add armor sets and mindforce implants endpoints - `6bcd0ca` - feat(api): add armor sets and mindforce implants endpoints
- `1e115db` - feat(ui): add armor set and mindforce implant selectors - `1e115db` - feat(ui): add armor set and mindforce implant selectors
- `b58af87` - feat(loadout): add mindforce implant field and tier-based enhancers - `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 ## 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

139
migrate_db.py Normal file
View File

@ -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))