/// Supported GLP-1/GIP receptor agonists and their pharmacokinetic constants. /// /// Half-lives follow the single-compartment decay values published in the /// prescribing information: /// * Semaglutide (Ozempic / Wegovy): ~168 hours (7 days) /// * Tirzepatide (Mounjaro / Zepbound): ~120 hours (5 days) /// * Liraglutide (Saxenda / Victoza): ~13 hours enum Glp1Compound { semaglutide( displayName: 'Semaglutide', brandNames: 'Ozempic / Wegovy / Rybelsus', halfLifeHours: 168, dosingInterval: Duration(hours: 168), defaultDoseMg: 0.25, aliases: ['semaglutide', 'ozempic', 'wegovy', 'rybelsus'], ), tirzepatide( displayName: 'Tirzepatide', brandNames: 'Mounjaro / Zepbound', halfLifeHours: 120, dosingInterval: Duration(hours: 168), defaultDoseMg: 2.5, aliases: ['tirzepatide', 'mounjaro', 'zepbound'], ), liraglutide( displayName: 'Liraglutide', brandNames: 'Saxenda / Victoza', halfLifeHours: 13, dosingInterval: Duration(hours: 24), defaultDoseMg: 0.6, aliases: ['liraglutide', 'saxenda', 'victoza'], ); const Glp1Compound({ required this.displayName, required this.brandNames, required this.halfLifeHours, required this.dosingInterval, required this.defaultDoseMg, required this.aliases, }); /// Generic compound name (e.g. `Tirzepatide`). final String displayName; /// Commercial brand names surfaced in the logging UI. final String brandNames; /// Elimination half-life `t_1/2` in hours, used by the pharmacokinetic /// serum-level calculator. final double halfLifeHours; /// Recommended interval between administrations (dose reminder cadence). final Duration dosingInterval; /// Titration starting dose used to pre-fill the logging form. final double defaultDoseMg; /// Lowercase names recognized when parsing free-text compound labels. final List aliases; /// Resolves a compound from a user- or database-supplied name. /// /// Matching is case-insensitive and accepts generic names, brand names, and /// compound strings that merely contain an alias (e.g. `Semaglutide /// (compounded)`). Returns `null` for unrecognized compounds so callers can /// fall back to a default half-life. static Glp1Compound? tryParse(String? raw) { if (raw == null || raw.trim().isEmpty) return null; final normalized = raw.toLowerCase(); for (final compound in values) { if (compound.aliases.contains(normalized)) return compound; } for (final compound in values) { if (compound.aliases.any(normalized.contains)) return compound; } return null; } }