115 lines
6.3 KiB
MySQL
115 lines
6.3 KiB
MySQL
|
|
-- Migration 014: Training Type Profiles & Activity Evaluation
|
||
|
|
-- Training Type Profiles System - Schema Extensions
|
||
|
|
-- Date: 2026-03-23
|
||
|
|
-- Issue: #15
|
||
|
|
|
||
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
-- EXTEND TRAINING TYPES
|
||
|
|
-- Add profile column for comprehensive training type configuration
|
||
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
|
||
|
|
ALTER TABLE training_types ADD COLUMN IF NOT EXISTS profile JSONB DEFAULT NULL;
|
||
|
|
|
||
|
|
CREATE INDEX idx_training_types_profile_enabled ON training_types
|
||
|
|
((profile->'rule_sets'->'minimum_requirements'->>'enabled'))
|
||
|
|
WHERE profile IS NOT NULL;
|
||
|
|
|
||
|
|
COMMENT ON COLUMN training_types.profile IS 'Comprehensive training type profile with 7 dimensions (rule_sets, intensity_zones, training_effects, periodization, performance_indicators, safety, ai_context)';
|
||
|
|
|
||
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
-- EXTEND ACTIVITY LOG
|
||
|
|
-- Add evaluation results and quality labels
|
||
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
|
||
|
|
ALTER TABLE activity_log ADD COLUMN IF NOT EXISTS evaluation JSONB DEFAULT NULL;
|
||
|
|
ALTER TABLE activity_log ADD COLUMN IF NOT EXISTS quality_label VARCHAR(20);
|
||
|
|
ALTER TABLE activity_log ADD COLUMN IF NOT EXISTS overall_score FLOAT;
|
||
|
|
|
||
|
|
CREATE INDEX idx_activity_quality_label ON activity_log(quality_label)
|
||
|
|
WHERE quality_label IS NOT NULL;
|
||
|
|
|
||
|
|
CREATE INDEX idx_activity_overall_score ON activity_log(overall_score DESC)
|
||
|
|
WHERE overall_score IS NOT NULL;
|
||
|
|
|
||
|
|
CREATE INDEX idx_activity_evaluation_passed ON activity_log
|
||
|
|
((evaluation->'rule_set_results'->'minimum_requirements'->>'passed'))
|
||
|
|
WHERE evaluation IS NOT NULL;
|
||
|
|
|
||
|
|
COMMENT ON COLUMN activity_log.evaluation IS 'Complete evaluation result (7 dimensions, scores, recommendations, warnings)';
|
||
|
|
COMMENT ON COLUMN activity_log.quality_label IS 'Quality label: excellent, good, acceptable, poor (for quick filtering)';
|
||
|
|
COMMENT ON COLUMN activity_log.overall_score IS 'Overall quality score 0.0-1.0 (for sorting)';
|
||
|
|
|
||
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
-- ADD MISSING COLUMNS (if not already added by previous migrations)
|
||
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
|
||
|
|
-- Add HR columns if not exist (might be in Migration 008)
|
||
|
|
DO $$
|
||
|
|
BEGIN
|
||
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
||
|
|
WHERE table_name='activity_log' AND column_name='hr_min') THEN
|
||
|
|
ALTER TABLE activity_log ADD COLUMN hr_min INTEGER CHECK (hr_min > 0 AND hr_min < 200);
|
||
|
|
END IF;
|
||
|
|
END $$;
|
||
|
|
|
||
|
|
-- Add performance columns for calculated values
|
||
|
|
ALTER TABLE activity_log ADD COLUMN IF NOT EXISTS avg_hr_percent FLOAT;
|
||
|
|
ALTER TABLE activity_log ADD COLUMN IF NOT EXISTS kcal_per_km FLOAT;
|
||
|
|
ALTER TABLE activity_log ADD COLUMN IF NOT EXISTS pace_min_per_km FLOAT;
|
||
|
|
ALTER TABLE activity_log ADD COLUMN IF NOT EXISTS cadence INTEGER;
|
||
|
|
ALTER TABLE activity_log ADD COLUMN IF NOT EXISTS avg_power INTEGER;
|
||
|
|
ALTER TABLE activity_log ADD COLUMN IF NOT EXISTS elevation_gain INTEGER;
|
||
|
|
ALTER TABLE activity_log ADD COLUMN IF NOT EXISTS temperature_celsius FLOAT;
|
||
|
|
ALTER TABLE activity_log ADD COLUMN IF NOT EXISTS humidity_percent INTEGER;
|
||
|
|
|
||
|
|
COMMENT ON COLUMN activity_log.avg_hr_percent IS 'Average HR as percentage of user max HR (calculated)';
|
||
|
|
COMMENT ON COLUMN activity_log.kcal_per_km IS 'Calories burned per kilometer (calculated)';
|
||
|
|
|
||
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
-- HELPER FUNCTION: Calculate avg_hr_percent
|
||
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
|
||
|
|
CREATE OR REPLACE FUNCTION calculate_avg_hr_percent()
|
||
|
|
RETURNS TRIGGER AS $$
|
||
|
|
DECLARE
|
||
|
|
user_max_hr INTEGER;
|
||
|
|
BEGIN
|
||
|
|
-- Get user's max HR from profile
|
||
|
|
SELECT hf_max INTO user_max_hr
|
||
|
|
FROM profiles
|
||
|
|
WHERE id = NEW.profile_id;
|
||
|
|
|
||
|
|
-- Calculate percentage if both values exist
|
||
|
|
IF NEW.hr_avg IS NOT NULL AND user_max_hr IS NOT NULL AND user_max_hr > 0 THEN
|
||
|
|
NEW.avg_hr_percent := (NEW.hr_avg::float / user_max_hr::float) * 100;
|
||
|
|
END IF;
|
||
|
|
|
||
|
|
-- Calculate kcal per km
|
||
|
|
IF NEW.kcal_active IS NOT NULL AND NEW.distance_km IS NOT NULL AND NEW.distance_km > 0 THEN
|
||
|
|
NEW.kcal_per_km := NEW.kcal_active::float / NEW.distance_km;
|
||
|
|
END IF;
|
||
|
|
|
||
|
|
RETURN NEW;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
|
||
|
|
-- Trigger for automatic calculation
|
||
|
|
DROP TRIGGER IF EXISTS trg_calculate_performance_metrics ON activity_log;
|
||
|
|
CREATE TRIGGER trg_calculate_performance_metrics
|
||
|
|
BEFORE INSERT OR UPDATE ON activity_log
|
||
|
|
FOR EACH ROW
|
||
|
|
EXECUTE FUNCTION calculate_avg_hr_percent();
|
||
|
|
|
||
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
-- SUMMARY
|
||
|
|
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
|
||
|
|
DO $$
|
||
|
|
BEGIN
|
||
|
|
RAISE NOTICE '✓ Migration 014 completed';
|
||
|
|
RAISE NOTICE ' - Extended training_types with profile column';
|
||
|
|
RAISE NOTICE ' - Extended activity_log with evaluation columns';
|
||
|
|
RAISE NOTICE ' - Added performance metric calculations';
|
||
|
|
RAISE NOTICE ' - Created indexes for fast queries';
|
||
|
|
END $$;
|