Lemontropia-Suite/core/schema.sql

349 lines
12 KiB
SQL

-- Description: SQLite database schema for Lemontropia Suite
-- Implements the Data Principle: Every session is a Project
-- Schema version: 2.0.0 - Added comprehensive hunting session tracking
-- Created: 2026-02-08
-- Updated: 2026-02-09
-- Enable foreign key support
PRAGMA foreign_keys = ON;
-- ============================================================================
-- PROJECT MANAGEMENT (Data Principle Core)
-- ============================================================================
CREATE TABLE IF NOT EXISTS projects (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
type TEXT NOT NULL CHECK (type IN ('hunt', 'mine', 'craft', 'inventory')),
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'paused', 'completed', 'archived')),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
archived_at TIMESTAMP,
metadata TEXT -- JSON blob for extensible project data
);
CREATE INDEX IF NOT EXISTS idx_projects_type ON projects(type);
CREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status);
CREATE INDEX IF NOT EXISTS idx_projects_created ON projects(created_at);
-- ============================================================================
-- SESSIONS (Active gameplay instances)
-- ============================================================================
CREATE TABLE IF NOT EXISTS sessions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
project_id INTEGER NOT NULL,
started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ended_at TIMESTAMP,
duration_seconds INTEGER DEFAULT 0,
total_spent_ped REAL DEFAULT 0.0, -- Decimal stored as REAL, handled in code
total_return_ped REAL DEFAULT 0.0,
net_profit_ped REAL DEFAULT 0.0,
notes TEXT,
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_id);
CREATE INDEX IF NOT EXISTS idx_sessions_started ON sessions(started_at);
-- ============================================================================
-- HUNTING SESSIONS (Extended tracking for hunting activities)
-- ============================================================================
CREATE TABLE IF NOT EXISTS hunting_sessions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id INTEGER NOT NULL UNIQUE,
started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ended_at TIMESTAMP,
-- Loot breakdown
total_loot_ped REAL DEFAULT 0.0,
total_shrapnel_ped REAL DEFAULT 0.0,
total_universal_ammo_ped REAL DEFAULT 0.0,
total_other_loot_ped REAL DEFAULT 0.0, -- Marketable loot excluding shrapnel/UA
-- Cost breakdown
weapon_cost_ped REAL DEFAULT 0.0,
armor_cost_ped REAL DEFAULT 0.0,
healing_cost_ped REAL DEFAULT 0.0,
plates_cost_ped REAL DEFAULT 0.0,
enhancer_cost_ped REAL DEFAULT 0.0,
total_cost_ped REAL DEFAULT 0.0,
-- Combat statistics
damage_dealt REAL DEFAULT 0.0,
damage_taken REAL DEFAULT 0.0,
healing_done REAL DEFAULT 0.0,
shots_fired INTEGER DEFAULT 0,
shots_missed INTEGER DEFAULT 0,
evades INTEGER DEFAULT 0,
kills INTEGER DEFAULT 0,
-- Special events
globals_count INTEGER DEFAULT 0,
hofs_count INTEGER DEFAULT 0,
-- Equipment used
weapon_name TEXT,
weapon_dpp REAL DEFAULT 0.0,
armor_name TEXT,
fap_name TEXT,
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_hunting_sessions_session ON hunting_sessions(session_id);
CREATE INDEX IF NOT EXISTS idx_hunting_sessions_weapon ON hunting_sessions(weapon_name);
-- ============================================================================
-- HUNTING GLOBALS/HoFs (Record of notable loot events)
-- ============================================================================
CREATE TABLE IF NOT EXISTS hunting_globals (
id INTEGER PRIMARY KEY AUTOINCREMENT,
hunting_session_id INTEGER NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
creature_name TEXT,
value_ped REAL NOT NULL,
is_hof BOOLEAN DEFAULT 0,
screenshot_path TEXT,
FOREIGN KEY (hunting_session_id) REFERENCES hunting_sessions(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_hunting_globals_session ON hunting_globals(hunting_session_id);
CREATE INDEX IF NOT EXISTS idx_hunting_globals_value ON hunting_globals(value_ped);
-- ============================================================================
-- LOOT EVENTS (Core data capture)
-- ============================================================================
CREATE TABLE IF NOT EXISTS loot_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id INTEGER NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
event_type TEXT NOT NULL CHECK (event_type IN ('global', 'hof', 'regular', 'skill')),
-- Loot data
item_name TEXT,
quantity INTEGER DEFAULT 1,
value_ped REAL DEFAULT 0.0,
is_shrapnel BOOLEAN DEFAULT 0,
is_universal_ammo BOOLEAN DEFAULT 0,
-- Context
creature_name TEXT, -- For hunter module
zone_name TEXT,
-- Raw log line for debugging/audit
raw_log_line TEXT,
-- Screenshot reference (if triggered)
screenshot_path TEXT,
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_loot_session ON loot_events(session_id);
CREATE INDEX IF NOT EXISTS idx_loot_timestamp ON loot_events(timestamp);
CREATE INDEX IF NOT EXISTS idx_loot_type ON loot_events(event_type);
CREATE INDEX IF NOT EXISTS idx_loot_value ON loot_events(value_ped);
-- ============================================================================
-- COMBAT EVENTS (Detailed combat tracking)
-- ============================================================================
CREATE TABLE IF NOT EXISTS combat_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id INTEGER NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
event_type TEXT NOT NULL CHECK (event_type IN ('damage_dealt', 'damage_taken', 'heal', 'evade', 'kill', 'critical_hit')),
damage_amount REAL,
heal_amount REAL,
creature_name TEXT,
weapon_name TEXT,
raw_log_line TEXT,
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_combat_session ON combat_events(session_id);
CREATE INDEX IF NOT EXISTS idx_combat_type ON combat_events(event_type);
-- ============================================================================
-- SKILL GAINS (Character progression tracking)
-- ============================================================================
CREATE TABLE IF NOT EXISTS skill_gains (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id INTEGER NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
skill_name TEXT NOT NULL,
gained_amount REAL DEFAULT 0.0,
new_total REAL,
raw_log_line TEXT,
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_skill_session ON skill_gains(session_id);
CREATE INDEX IF NOT EXISTS idx_skill_name ON skill_gains(skill_name);
-- ============================================================================
-- DECAY TRACKING (Weapon/tool durability)
-- ============================================================================
CREATE TABLE IF NOT EXISTS decay_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id INTEGER NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
item_name TEXT NOT NULL,
decay_amount_ped REAL DEFAULT 0.0,
decay_amount_pec REAL DEFAULT 0.0,
shots_fired INTEGER DEFAULT 0,
raw_log_line TEXT,
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_decay_session ON decay_events(session_id);
-- ============================================================================
-- SCREENSHOTS (Auto-capture on high-value events)
-- ============================================================================
CREATE TABLE IF NOT EXISTS screenshots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id INTEGER NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
file_path TEXT NOT NULL,
trigger_event TEXT, -- What triggered the screenshot
trigger_value_ped REAL,
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_screenshots_session ON screenshots(session_id);
-- ============================================================================
-- APPLICATION STATE (Singleton table for app settings)
-- ============================================================================
CREATE TABLE IF NOT EXISTS app_state (
key TEXT PRIMARY KEY,
value TEXT,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- ============================================================================
-- DATABASE VERSION TRACKING
-- ============================================================================
CREATE TABLE IF NOT EXISTS schema_version (
version INTEGER PRIMARY KEY,
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
description TEXT
);
-- Insert/update version
INSERT OR REPLACE INTO schema_version (version, description)
VALUES (2, 'Added comprehensive hunting session tracking with loot/cost breakdown');
-- ============================================================================
-- VIEWS FOR COMMON QUERIES (Performance optimization)
-- ============================================================================
-- Active project summary
CREATE VIEW IF NOT EXISTS v_project_summary AS
SELECT
p.id,
p.name,
p.type,
p.status,
p.created_at,
COUNT(DISTINCT s.id) as session_count,
SUM(s.total_spent_ped) as total_spent,
SUM(s.total_return_ped) as total_return,
SUM(s.net_profit_ped) as net_profit,
SUM(CASE WHEN l.event_type = 'global' THEN 1 ELSE 0 END) as global_count,
SUM(CASE WHEN l.event_type = 'hof' THEN 1 ELSE 0 END) as hof_count
FROM projects p
LEFT JOIN sessions s ON p.id = s.project_id
LEFT JOIN loot_events l ON s.id = l.session_id
GROUP BY p.id;
-- Session performance metrics
CREATE VIEW IF NOT EXISTS v_session_metrics AS
SELECT
s.id,
s.project_id,
p.name as project_name,
s.started_at,
s.ended_at,
s.duration_seconds,
s.total_spent_ped,
s.total_return_ped,
s.net_profit_ped,
CASE
WHEN s.total_spent_ped > 0
THEN ROUND((s.net_profit_ped / s.total_spent_ped) * 100, 2)
ELSE 0
END as roi_percent,
COUNT(l.id) as loot_events,
SUM(CASE WHEN l.event_type IN ('global', 'hof') THEN 1 ELSE 0 END) as notable_events
FROM sessions s
JOIN projects p ON s.project_id = p.id
LEFT JOIN loot_events l ON s.id = l.session_id
GROUP BY s.id;
-- Hunting session detailed view
CREATE VIEW IF NOT EXISTS v_hunting_session_summary AS
SELECT
hs.id,
hs.session_id,
s.project_id,
p.name as project_name,
hs.started_at,
hs.ended_at,
hs.total_loot_ped,
hs.total_other_loot_ped,
hs.total_cost_ped,
hs.damage_dealt,
hs.kills,
hs.globals_count,
hs.hofs_count,
hs.weapon_name,
hs.weapon_dpp,
CASE
WHEN hs.total_cost_ped > 0
THEN ROUND((hs.total_other_loot_ped / hs.total_cost_ped) * 100, 2)
ELSE 0
END as return_percent,
CASE
WHEN hs.kills > 0
THEN ROUND(hs.total_cost_ped / hs.kills, 4)
ELSE 0
END as cost_per_kill,
CASE
WHEN hs.total_cost_ped > 0
THEN ROUND(hs.damage_dealt / hs.total_cost_ped, 2)
ELSE 0
END as dpp
FROM hunting_sessions hs
JOIN sessions s ON hs.session_id = s.id
JOIN projects p ON s.project_id = p.id;
-- Weapon performance analysis
CREATE VIEW IF NOT EXISTS v_weapon_performance AS
SELECT
weapon_name,
COUNT(*) as sessions_count,
AVG(total_other_loot_ped) as avg_loot,
AVG(total_cost_ped) as avg_cost,
AVG(CASE WHEN total_cost_ped > 0 THEN (total_other_loot_ped / total_cost_ped) * 100 ELSE 0 END) as avg_return_percent,
AVG(dpp) as avg_dpp,
SUM(kills) as total_kills,
SUM(globals_count) as total_globals,
SUM(hofs_count) as total_hofs
FROM hunting_sessions
WHERE weapon_name IS NOT NULL AND weapon_name != ''
GROUP BY weapon_name;