-- Migration 013: Training Parameters Registry -- Training Type Profiles System - Foundation -- Date: 2026-03-23 -- Issue: #15 -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -- TRAINING PARAMETERS REGISTRY -- Zentrale Definition aller messbaren Parameter für Aktivitäten -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CREATE TABLE IF NOT EXISTS training_parameters ( id SERIAL PRIMARY KEY, key VARCHAR(50) UNIQUE NOT NULL, name_de VARCHAR(100) NOT NULL, name_en VARCHAR(100) NOT NULL, category VARCHAR(50) NOT NULL, data_type VARCHAR(20) NOT NULL, unit VARCHAR(20), description_de TEXT, description_en TEXT, source_field VARCHAR(100), validation_rules JSONB DEFAULT '{}'::jsonb, is_active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT NOW(), CONSTRAINT chk_category CHECK (category IN ( 'physical', 'physiological', 'subjective', 'environmental', 'performance' )), CONSTRAINT chk_data_type CHECK (data_type IN ( 'integer', 'float', 'string', 'boolean' )) ); CREATE INDEX idx_training_parameters_category ON training_parameters(category) WHERE is_active = true; CREATE INDEX idx_training_parameters_key ON training_parameters(key) WHERE is_active = true; COMMENT ON TABLE training_parameters IS 'Registry of all measurable activity parameters (Training Type Profiles System)'; COMMENT ON COLUMN training_parameters.key IS 'Unique identifier (e.g. "avg_hr", "duration_min")'; COMMENT ON COLUMN training_parameters.category IS 'Parameter category: physical, physiological, subjective, environmental, performance'; COMMENT ON COLUMN training_parameters.data_type IS 'Data type: integer, float, string, boolean'; COMMENT ON COLUMN training_parameters.source_field IS 'Mapping to activity_log column name'; COMMENT ON COLUMN training_parameters.validation_rules IS 'Min/Max/Enum for validation (JSONB)'; -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -- STANDARD PARAMETERS -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ INSERT INTO training_parameters (key, name_de, name_en, category, data_type, unit, source_field, validation_rules, description_de, description_en) VALUES -- Physical Parameters ('duration_min', 'Dauer', 'Duration', 'physical', 'integer', 'min', 'duration_min', '{"min": 0, "max": 600}'::jsonb, 'Trainingsdauer in Minuten', 'Training duration in minutes'), ('distance_km', 'Distanz', 'Distance', 'physical', 'float', 'km', 'distance_km', '{"min": 0, "max": 200}'::jsonb, 'Zurückgelegte Distanz in Kilometern', 'Distance covered in kilometers'), ('kcal_active', 'Aktive Kalorien', 'Active Calories', 'physical', 'integer', 'kcal', 'kcal_active', '{"min": 0, "max": 5000}'::jsonb, 'Aktiver Kalorienverbrauch', 'Active calorie burn'), ('kcal_resting', 'Ruhekalorien', 'Resting Calories', 'physical', 'integer', 'kcal', 'kcal_resting', '{"min": 0, "max": 2000}'::jsonb, 'Ruheumsatz während Training', 'Resting calorie burn during training'), ('elevation_gain', 'Höhenmeter', 'Elevation Gain', 'physical', 'integer', 'm', 'elevation_gain', '{"min": 0, "max": 5000}'::jsonb, 'Überwundene Höhenmeter', 'Elevation gain in meters'), ('pace_min_per_km', 'Pace', 'Pace', 'physical', 'float', 'min/km', 'pace_min_per_km', '{"min": 2, "max": 20}'::jsonb, 'Durchschnittstempo in Minuten pro Kilometer', 'Average pace in minutes per kilometer'), ('cadence', 'Trittfrequenz', 'Cadence', 'physical', 'integer', 'spm', 'cadence', '{"min": 0, "max": 220}'::jsonb, 'Schrittfrequenz (Schritte pro Minute)', 'Step frequency (steps per minute)'), -- Physiological Parameters ('avg_hr', 'Durchschnittspuls', 'Average Heart Rate', 'physiological', 'integer', 'bpm', 'hr_avg', '{"min": 30, "max": 220}'::jsonb, 'Durchschnittliche Herzfrequenz', 'Average heart rate'), ('max_hr', 'Maximalpuls', 'Max Heart Rate', 'physiological', 'integer', 'bpm', 'hr_max', '{"min": 40, "max": 220}'::jsonb, 'Maximale Herzfrequenz', 'Maximum heart rate'), ('min_hr', 'Minimalpuls', 'Min Heart Rate', 'physiological', 'integer', 'bpm', 'hr_min', '{"min": 30, "max": 200}'::jsonb, 'Minimale Herzfrequenz', 'Minimum heart rate'), ('avg_power', 'Durchschnittsleistung', 'Average Power', 'physiological', 'integer', 'W', 'avg_power', '{"min": 0, "max": 1000}'::jsonb, 'Durchschnittliche Leistung in Watt', 'Average power output in watts'), -- Subjective Parameters ('rpe', 'RPE (Anstrengung)', 'RPE (Perceived Exertion)', 'subjective', 'integer', 'scale', 'rpe', '{"min": 1, "max": 10}'::jsonb, 'Subjektive Anstrengung (Rate of Perceived Exertion)', 'Rate of Perceived Exertion'), -- Environmental Parameters ('temperature_celsius', 'Temperatur', 'Temperature', 'environmental', 'float', '°C', 'temperature_celsius', '{"min": -30, "max": 50}'::jsonb, 'Umgebungstemperatur in Celsius', 'Ambient temperature in Celsius'), ('humidity_percent', 'Luftfeuchtigkeit', 'Humidity', 'environmental', 'integer', '%', 'humidity_percent', '{"min": 0, "max": 100}'::jsonb, 'Relative Luftfeuchtigkeit in Prozent', 'Relative humidity in percent'), -- Performance Parameters (calculated) ('avg_hr_percent', '% Max-HF', '% Max HR', 'performance', 'float', '%', 'avg_hr_percent', '{"min": 0, "max": 100}'::jsonb, 'Durchschnittspuls als Prozent der maximalen Herzfrequenz', 'Average heart rate as percentage of max heart rate'), ('kcal_per_km', 'Kalorien pro km', 'Calories per km', 'performance', 'float', 'kcal/km', 'kcal_per_km', '{"min": 0, "max": 1000}'::jsonb, 'Kalorienverbrauch pro Kilometer', 'Calorie burn per kilometer'); -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -- SUMMARY -- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -- Display inserted parameters DO $$ BEGIN RAISE NOTICE '✓ Migration 013 completed'; RAISE NOTICE ' - Created training_parameters table'; RAISE NOTICE ' - Inserted % standard parameters', (SELECT COUNT(*) FROM training_parameters); END $$;