""" Pydantic Validation Example Demonstrates automatic parsing and validation of health data """ from health_data import ( PydanticUserHealthProfile, PydanticHealthRecord, NutritionRecord, ExerciseRecord, HealthDataParser, merge_records, RecordType ) from datetime import datetime, timedelta def test_height_parsing(): """Test parsing height from various formats""" print("=" * 60) print("HEIGHT PARSING TEST") print("=" * 60) test_cases = [ "1.78m", # Meters "1,78m", # Comma separator "178cm", # Centimeters "178", # Just number "1.78", # Decimal "5'10\"", # Feet/inches ] for test in test_cases: result = HealthDataParser.parse_height(test) print(f"Input: {test:15} → {result} cm") def test_weight_parsing(): """Test parsing weight from various formats""" print("\n" + "=" * 60) print("WEIGHT PARSING TEST") print("=" * 60) test_cases = [ "70kg", # Kilograms "70", # Just number "154lbs", # Pounds "70.5", # Decimal ] for test in test_cases: result = HealthDataParser.parse_weight(test) print(f"Input: {test:15} → {result} kg") def test_pydantic_validation(): """Test Pydantic automatic validation""" print("\n" + "=" * 60) print("PYDANTIC VALIDATION TEST") print("=" * 60) # Test 1: Valid data with various formats print("\n✅ Test 1: Valid data with mixed formats") try: profile = PydanticUserHealthProfile( user_id="user123", age="25 tuổi", # Will parse to 25 gender="male", weight="70kg", # Will parse to 70.0 height="1.78m" # Will parse to 178.0 ) print(f" Age: {profile.age}") print(f" Weight: {profile.weight} kg") print(f" Height: {profile.height} cm") print(f" BMI: {profile.bmi} ({profile.get_bmi_category()})") print(" ✅ Success!") except Exception as e: print(f" ❌ Error: {e}") # Test 2: Invalid height (too high) print("\n❌ Test 2: Invalid height (too high)") try: profile = PydanticUserHealthProfile( user_id="user456", height="500cm" # Too high! ) print(" ❌ Should have failed!") except Exception as e: print(f" ✅ Caught error: {e}") # Test 3: Invalid age (too young) print("\n❌ Test 3: Invalid age (too young)") try: profile = PydanticUserHealthProfile( user_id="user789", age=10 # Too young! ) print(" ❌ Should have failed!") except Exception as e: print(f" ✅ Caught error: {e}") # Test 4: Auto BMI calculation print("\n✅ Test 4: Auto BMI calculation") profile = PydanticUserHealthProfile( user_id="user999", weight="70kg", height="1,75m" # Comma separator! ) print(f" Weight: {profile.weight} kg") print(f" Height: {profile.height} cm") print(f" BMI: {profile.bmi} (auto-calculated)") print(f" Category: {profile.get_bmi_category()}") def test_health_records(): """Test health records with validation""" print("\n" + "=" * 60) print("HEALTH RECORDS TEST") print("=" * 60) # Create nutrition record print("\n📊 Creating Nutrition Record") nutrition = NutritionRecord( user_id="user123", height="1.78m", weight="70kg", data={ 'calories': 2000, 'protein': 150, 'carbs': 200, 'fat': 60 } ) print(f" Height: {nutrition.height} cm") print(f" Weight: {nutrition.weight} kg") print(f" BMI: {nutrition.bmi}") print(f" Calories: {nutrition.data['calories']}") # Create exercise record print("\n🏃 Creating Exercise Record") exercise = ExerciseRecord( user_id="user123", data={ 'exercise_type': 'cardio', 'duration_minutes': 30, 'calories_burned': 300 } ) print(f" Type: {exercise.data['exercise_type']}") print(f" Duration: {exercise.data['duration_minutes']} min") print(f" Calories: {exercise.data['calories_burned']}") def test_merge_records(): """Test merging records from multiple days""" print("\n" + "=" * 60) print("MERGE RECORDS TEST") print("=" * 60) # Create sample records over 7 days records = [] base_date = datetime.now() - timedelta(days=7) for i in range(7): # Nutrition record nutrition = NutritionRecord( user_id="user123", weight=70 - i * 0.2, # Gradually losing weight height=178, data={ 'calories': 1800 + i * 50, 'protein': 140 + i * 5, } ) nutrition.timestamp = base_date + timedelta(days=i) records.append(nutrition) # Exercise record exercise = ExerciseRecord( user_id="user123", data={ 'exercise_type': 'cardio' if i % 2 == 0 else 'strength', 'duration_minutes': 30 + i * 5, 'calories_burned': 250 + i * 20 } ) exercise.timestamp = base_date + timedelta(days=i) records.append(exercise) print(f"\n📦 Created {len(records)} records over 7 days") # Merge with average strategy print("\n📊 Merging with 'average' strategy:") merged = merge_records(records, strategy='average') print(f"\nTotal records: {merged['total_records']}") print(f"Date range: {merged['date_range']['start'][:10]} to {merged['date_range']['end'][:10]}") if 'nutrition' in merged['by_type']: nutrition_data = merged['by_type']['nutrition'] print(f"\n🍎 Nutrition Summary:") print(f" Average calories: {nutrition_data['average_daily']['calories']}") print(f" Average protein: {nutrition_data['average_daily']['protein']}g") if 'exercise' in merged['by_type']: exercise_data = merged['by_type']['exercise'] print(f"\n🏃 Exercise Summary:") print(f" Total workouts: {exercise_data['total_workouts']}") print(f" Total duration: {exercise_data['total_duration_minutes']} min") print(f" Total calories burned: {exercise_data['total_calories_burned']}") print(f" Exercise types: {exercise_data['exercise_types']}") if 'health_metrics' in merged and 'weight' in merged['health_metrics']: weight_data = merged['health_metrics']['weight'] print(f"\n⚖️ Weight Progress:") print(f" Start: {weight_data['max']} kg") print(f" End: {weight_data['latest']} kg") print(f" Change: {weight_data['change']} kg") print(f" Average: {weight_data['average']} kg") if __name__ == '__main__': test_height_parsing() test_weight_parsing() test_pydantic_validation() test_health_records() test_merge_records() print("\n" + "=" * 60) print("✅ ALL TESTS COMPLETE!") print("=" * 60)