"""Synthetic patient generation.""" from __future__ import annotations import random from app.common.enums import Difficulty, DoseBucket from app.common.types import LabSummary, Medication, PatientProfile _DRUG_POOL = [ ("warfarin_like", "anticoagulant"), ("benzodiazepine_like", "sedative"), ("metformin_like", "glucose_lowering"), ("statin_like", "lipid_lowering"), ("ace_inhibitor_like", "antihypertensive"), ("nsaid_like", "analgesic"), ("opioid_like", "analgesic"), ("ssri_like", "antidepressant"), ("ppi_like", "gastro"), ("beta_blocker_like", "antihypertensive"), ] def generate_patient_profile(seed: int, difficulty: Difficulty, patient_id: str | None = None) -> PatientProfile: random.seed(seed) med_count = {Difficulty.EASY: 5, Difficulty.MEDIUM: 8, Difficulty.HARD: 10}[difficulty] selected = random.sample(_DRUG_POOL, k=med_count) medications = [ Medication( drug=drug, class_name=cls, dose_bucket=random.choice([DoseBucket.LOW, DoseBucket.MEDIUM, DoseBucket.HIGH]), indication=f"indication_{idx}", requires_taper=drug in {"benzodiazepine_like", "opioid_like"}, ) for idx, (drug, cls) in enumerate(selected) ] return PatientProfile( patient_id=patient_id or f"patient_{seed}", age=random.randint(55, 90), sex=random.choice(["F", "M"]), comorbidities=random.sample( ["htn", "dm2", "afib", "ckd", "copd", "depression", "fall_risk"], k=3 ), medications=medications, labs=LabSummary( egfr=round(random.uniform(20, 95), 1), ast=round(random.uniform(10, 120), 1), alt=round(random.uniform(10, 120), 1), inr=round(random.uniform(1.0, 4.0), 2), glucose=round(random.uniform(70, 280), 1), ), vitals={ "sbp": random.randint(100, 180), "dbp": random.randint(60, 105), "hr": random.randint(50, 120), "egfr_trend": round(random.uniform(-8.0, 3.0), 2), "inr_trend": round(random.uniform(-0.5, 0.7), 2), "glucose_trend": round(random.uniform(-35.0, 45.0), 2), }, specialist_conflicts=[ "duplicate_analgesic_strategy", "cardio_vs_pain_med_conflict", ] if difficulty != Difficulty.EASY else [], prior_ade_history=["fall_event", "sedation_event"] if difficulty == Difficulty.HARD else [], frailty_score=round(random.uniform(0.1, 0.9), 2), adherence_estimate=round(random.uniform(0.4, 0.95), 2), latent_confounders={ "metabolism_variability": round(random.uniform(0.1, 0.9), 3), "social_support_risk": round(random.uniform(0.0, 1.0), 3), "polyprovider_fragmentation": round(random.uniform(0.1, 0.95), 3), }, monitoring_gaps=["no_recent_inr", "missing_liver_panel"] if difficulty == Difficulty.HARD else ["missing_followup_bp"], )