- Split behavioral inputs into two screens (Habits + Lifestyle) - Added 5 new modifiable factors: diet quality, processed food, drug use, social connection, and stress level - Updated hazard ratios for all new factors based on meta-analyses - Model version bumped to 1.1 - Simplified welcome screen with clearer value proposition - Updated tests for expanded behavioral model Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
248 lines
5.5 KiB
Dart
248 lines
5.5 KiB
Dart
import '../models/models.dart';
|
|
|
|
/// Hazard ratios based on conservative estimates from meta-analyses.
|
|
/// All HRs are relative to optimal baseline (HR = 1.0).
|
|
|
|
double getSmokingHR(SmokingStatus status, int cigarettesPerDay) {
|
|
switch (status) {
|
|
case SmokingStatus.never:
|
|
return 1.0;
|
|
case SmokingStatus.former:
|
|
return 1.3;
|
|
case SmokingStatus.current:
|
|
if (cigarettesPerDay < 10) return 1.8;
|
|
if (cigarettesPerDay <= 20) return 2.2;
|
|
return 2.8;
|
|
}
|
|
}
|
|
|
|
double getAlcoholHR(AlcoholLevel level) {
|
|
switch (level) {
|
|
case AlcoholLevel.none:
|
|
case AlcoholLevel.light:
|
|
return 1.0;
|
|
case AlcoholLevel.moderate:
|
|
return 1.1;
|
|
case AlcoholLevel.heavy:
|
|
return 1.3;
|
|
case AlcoholLevel.veryHeavy:
|
|
return 1.6;
|
|
}
|
|
}
|
|
|
|
double getSleepHR(double hours, bool consistent) {
|
|
double hr;
|
|
if (hours >= 7 && hours <= 8) {
|
|
hr = 1.0;
|
|
} else if (hours >= 6 && hours < 7) {
|
|
hr = 1.05;
|
|
} else if (hours < 6) {
|
|
hr = 1.15;
|
|
} else {
|
|
// > 8 hours
|
|
hr = 1.10;
|
|
}
|
|
|
|
if (!consistent) {
|
|
hr *= 1.05;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
double getActivityHR(ActivityLevel level) {
|
|
switch (level) {
|
|
case ActivityLevel.high:
|
|
return 1.0;
|
|
case ActivityLevel.moderate:
|
|
return 1.05;
|
|
case ActivityLevel.light:
|
|
return 1.15;
|
|
case ActivityLevel.sedentary:
|
|
return 1.4;
|
|
}
|
|
}
|
|
|
|
double getBmiHR(double bmi) {
|
|
if (bmi >= 18.5 && bmi < 25) return 1.0;
|
|
if (bmi >= 25 && bmi < 30) return 1.1;
|
|
if (bmi >= 30 && bmi < 35) return 1.2;
|
|
if (bmi >= 35 && bmi < 40) return 1.4;
|
|
if (bmi >= 40) return 1.8;
|
|
return 1.15; // Underweight
|
|
}
|
|
|
|
double getDrivingHR(DrivingExposure level) {
|
|
switch (level) {
|
|
case DrivingExposure.low:
|
|
return 1.0;
|
|
case DrivingExposure.moderate:
|
|
return 1.02;
|
|
case DrivingExposure.high:
|
|
return 1.04;
|
|
case DrivingExposure.veryHigh:
|
|
return 1.08;
|
|
}
|
|
}
|
|
|
|
double getWorkHoursHR(WorkHoursLevel level) {
|
|
switch (level) {
|
|
case WorkHoursLevel.normal:
|
|
return 1.0;
|
|
case WorkHoursLevel.elevated:
|
|
return 1.05;
|
|
case WorkHoursLevel.high:
|
|
return 1.15;
|
|
case WorkHoursLevel.extreme:
|
|
return 1.3;
|
|
}
|
|
}
|
|
|
|
// --- New lifestyle factors ---
|
|
|
|
/// Diet quality - based on Mediterranean diet studies
|
|
double getDietHR(DietQuality level) {
|
|
switch (level) {
|
|
case DietQuality.excellent:
|
|
return 1.0;
|
|
case DietQuality.good:
|
|
return 1.05;
|
|
case DietQuality.fair:
|
|
return 1.15;
|
|
case DietQuality.poor:
|
|
return 1.3;
|
|
}
|
|
}
|
|
|
|
/// Processed food consumption - ultra-processed food studies
|
|
double getProcessedFoodHR(ProcessedFoodLevel level) {
|
|
switch (level) {
|
|
case ProcessedFoodLevel.rarely:
|
|
return 1.0;
|
|
case ProcessedFoodLevel.occasional:
|
|
return 1.05;
|
|
case ProcessedFoodLevel.frequent:
|
|
return 1.12;
|
|
case ProcessedFoodLevel.daily:
|
|
return 1.2;
|
|
}
|
|
}
|
|
|
|
/// Drug use - excluding alcohol/tobacco (cannabis, recreational drugs)
|
|
double getDrugUseHR(DrugUse level) {
|
|
switch (level) {
|
|
case DrugUse.none:
|
|
return 1.0;
|
|
case DrugUse.occasional:
|
|
return 1.05;
|
|
case DrugUse.regular:
|
|
return 1.15;
|
|
case DrugUse.daily:
|
|
return 1.35;
|
|
}
|
|
}
|
|
|
|
/// Social connection - loneliness/isolation meta-analyses
|
|
double getSocialHR(SocialConnection level) {
|
|
switch (level) {
|
|
case SocialConnection.strong:
|
|
return 1.0;
|
|
case SocialConnection.moderate:
|
|
return 1.05;
|
|
case SocialConnection.limited:
|
|
return 1.2;
|
|
case SocialConnection.isolated:
|
|
return 1.45;
|
|
}
|
|
}
|
|
|
|
/// Chronic stress - based on allostatic load research
|
|
double getStressHR(StressLevel level) {
|
|
switch (level) {
|
|
case StressLevel.low:
|
|
return 1.0;
|
|
case StressLevel.moderate:
|
|
return 1.05;
|
|
case StressLevel.high:
|
|
return 1.15;
|
|
case StressLevel.chronic:
|
|
return 1.35;
|
|
}
|
|
}
|
|
|
|
/// Existing conditions modify baseline mortality but are NOT modifiable.
|
|
double getDiagnosisHR(Set<Diagnosis> diagnoses) {
|
|
double hr = 1.0;
|
|
for (final diagnosis in diagnoses) {
|
|
switch (diagnosis) {
|
|
case Diagnosis.cardiovascular:
|
|
hr *= 1.5;
|
|
break;
|
|
case Diagnosis.diabetes:
|
|
hr *= 1.4;
|
|
break;
|
|
case Diagnosis.cancer:
|
|
hr *= 2.0;
|
|
break;
|
|
case Diagnosis.copd:
|
|
hr *= 1.6;
|
|
break;
|
|
case Diagnosis.hypertension:
|
|
hr *= 1.2;
|
|
break;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/// Confidence levels for each behavior based on evidence quality.
|
|
Confidence getConfidenceForBehavior(String behaviorKey) {
|
|
switch (behaviorKey) {
|
|
case 'smoking':
|
|
case 'alcohol':
|
|
case 'activity':
|
|
case 'social':
|
|
return Confidence.high;
|
|
case 'sleep':
|
|
case 'workHours':
|
|
case 'diet':
|
|
case 'stress':
|
|
return Confidence.moderate;
|
|
case 'driving':
|
|
case 'processedFood':
|
|
case 'drugUse':
|
|
return Confidence.emerging;
|
|
default:
|
|
return Confidence.moderate;
|
|
}
|
|
}
|
|
|
|
/// Display names for behaviors.
|
|
String getDisplayName(String behaviorKey) {
|
|
switch (behaviorKey) {
|
|
case 'smoking':
|
|
return 'Smoking';
|
|
case 'alcohol':
|
|
return 'Alcohol Consumption';
|
|
case 'sleep':
|
|
return 'Sleep';
|
|
case 'activity':
|
|
return 'Physical Activity';
|
|
case 'driving':
|
|
return 'Driving Exposure';
|
|
case 'workHours':
|
|
return 'Work Hours';
|
|
case 'diet':
|
|
return 'Diet Quality';
|
|
case 'processedFood':
|
|
return 'Processed Food';
|
|
case 'drugUse':
|
|
return 'Drug Use';
|
|
case 'social':
|
|
return 'Social Connection';
|
|
case 'stress':
|
|
return 'Chronic Stress';
|
|
default:
|
|
return behaviorKey;
|
|
}
|
|
}
|