-- Migration 022: Goal System (Strategic + Tactical) -- Date: 2026-03-26 -- Purpose: Two-level goal architecture for AI-driven coaching -- ============================================================================ -- STRATEGIC LAYER: Goal Modes -- ============================================================================ -- Add goal_mode to profiles (strategic training direction) ALTER TABLE profiles ADD COLUMN IF NOT EXISTS goal_mode VARCHAR(50) DEFAULT 'health'; COMMENT ON COLUMN profiles.goal_mode IS 'Strategic goal mode: weight_loss, strength, endurance, recomposition, health. Determines score weights and interpretation context for all analyses.'; -- ============================================================================ -- TACTICAL LAYER: Concrete Goal Targets -- ============================================================================ CREATE TABLE IF NOT EXISTS goals ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), profile_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE, -- Goal Classification goal_type VARCHAR(50) NOT NULL, -- weight, body_fat, lean_mass, vo2max, strength, flexibility, bp, rhr is_primary BOOLEAN DEFAULT false, status VARCHAR(20) DEFAULT 'active', -- draft, active, reached, abandoned, expired -- Target Values target_value DECIMAL(10,2), current_value DECIMAL(10,2), start_value DECIMAL(10,2), unit VARCHAR(20), -- kg, %, ml/kg/min, bpm, mmHg, cm, reps -- Timeline start_date DATE DEFAULT CURRENT_DATE, target_date DATE, reached_date DATE, -- Metadata name VARCHAR(100), -- e.g., "Sommerfigur 2026" description TEXT, -- Progress Tracking progress_pct DECIMAL(5,2), -- Auto-calculated: (current - start) / (target - start) * 100 projection_date DATE, -- Prognose wann Ziel erreicht wird on_track BOOLEAN, -- true wenn Prognose <= target_date -- Timestamps created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_goals_profile ON goals(profile_id); CREATE INDEX IF NOT EXISTS idx_goals_status ON goals(profile_id, status); CREATE INDEX IF NOT EXISTS idx_goals_primary ON goals(profile_id, is_primary) WHERE is_primary = true; COMMENT ON TABLE goals IS 'Concrete user goals (tactical targets)'; COMMENT ON COLUMN goals.goal_type IS 'Type of goal: weight, body_fat, lean_mass, vo2max, strength, flexibility, bp, rhr'; COMMENT ON COLUMN goals.is_primary IS 'Primary goal gets highest priority in scoring and charts'; COMMENT ON COLUMN goals.status IS 'draft = not yet started, active = in progress, reached = successfully completed, abandoned = given up, expired = deadline passed'; COMMENT ON COLUMN goals.progress_pct IS 'Percentage progress: (current_value - start_value) / (target_value - start_value) * 100'; COMMENT ON COLUMN goals.projection_date IS 'Projected date when goal will be reached based on current trend'; COMMENT ON COLUMN goals.on_track IS 'true if projection_date <= target_date (goal reachable on time)'; -- ============================================================================ -- TRAINING PHASES (Auto-Detection) -- ============================================================================ CREATE TABLE IF NOT EXISTS training_phases ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), profile_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE, -- Phase Classification phase_type VARCHAR(50) NOT NULL, -- calorie_deficit, calorie_surplus, deload, maintenance, periodization detected_automatically BOOLEAN DEFAULT false, confidence_score DECIMAL(3,2), -- 0.00 - 1.00 (Wie sicher ist die Erkennung?) status VARCHAR(20) DEFAULT 'suggested', -- suggested, accepted, active, completed, rejected -- Timeframe start_date DATE NOT NULL, end_date DATE, duration_days INT, -- Detection Criteria (JSONB für Flexibilität) detection_params JSONB, -- { "avg_calories": 1800, "weight_trend": -0.3, ... } -- User Notes notes TEXT, -- Timestamps created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_training_phases_profile ON training_phases(profile_id); CREATE INDEX IF NOT EXISTS idx_training_phases_status ON training_phases(profile_id, status); CREATE INDEX IF NOT EXISTS idx_training_phases_dates ON training_phases(profile_id, start_date, end_date); COMMENT ON TABLE training_phases IS 'Training phases detected from data patterns or manually defined'; COMMENT ON COLUMN training_phases.phase_type IS 'calorie_deficit, calorie_surplus, deload, maintenance, periodization'; COMMENT ON COLUMN training_phases.detected_automatically IS 'true if AI detected this phase from data patterns'; COMMENT ON COLUMN training_phases.confidence_score IS 'AI confidence in detection (0.0 - 1.0)'; COMMENT ON COLUMN training_phases.status IS 'suggested = AI proposed, accepted = user confirmed, active = currently running, completed = finished, rejected = user dismissed'; COMMENT ON COLUMN training_phases.detection_params IS 'JSON with detection criteria: avg_calories, weight_trend, activity_volume, etc.'; -- ============================================================================ -- FITNESS TESTS (Standardized Performance Tests) -- ============================================================================ CREATE TABLE IF NOT EXISTS fitness_tests ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), profile_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE, -- Test Type test_type VARCHAR(50) NOT NULL, -- cooper_12min, step_test, pushups_max, plank_max, flexibility_sit_reach, vo2max_est, strength_1rm_squat, strength_1rm_bench result_value DECIMAL(10,2) NOT NULL, result_unit VARCHAR(20) NOT NULL, -- meters, bpm, reps, seconds, cm, ml/kg/min, kg -- Test Metadata test_date DATE NOT NULL, test_conditions TEXT, -- Optional: Notizen zu Bedingungen norm_category VARCHAR(30), -- sehr gut, gut, durchschnitt, unterdurchschnitt, schlecht -- Timestamps created_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_fitness_tests_profile ON fitness_tests(profile_id); CREATE INDEX IF NOT EXISTS idx_fitness_tests_type ON fitness_tests(profile_id, test_type); CREATE INDEX IF NOT EXISTS idx_fitness_tests_date ON fitness_tests(profile_id, test_date); COMMENT ON TABLE fitness_tests IS 'Standardized fitness tests (Cooper, step test, strength tests, etc.)'; COMMENT ON COLUMN fitness_tests.test_type IS 'cooper_12min, step_test, pushups_max, plank_max, flexibility_sit_reach, vo2max_est, strength_1rm_squat, strength_1rm_bench'; COMMENT ON COLUMN fitness_tests.norm_category IS 'Performance category based on age/gender norms';