require "json" require "./drug_lut" require "./alcohol_lut" require "./caffeine_lut" require "./cannabis_lut" require "./meds_lut" require "./vitals_tracker" require "./data_analysis" require "./data_files" require "./fuzzy" module JosieHealth module LUT VERSION = "0.1.0" # Main entry point for drug normalization def self.normalize_substance(input : String) : String? DrugLUT.normalize(input.strip.downcase) end # Get all known aliases for a substance def self.get_aliases(canonical_name : String) : Array(String) DrugLUT.get_aliases(canonical_name) end # Check if a substance is known def self.known_substance?(input : String) : Bool normalize_substance(input) != nil end # Get all canonical substance names def self.all_substances : Array(String) DrugLUT.all_canonical_names end # Get substance info with metadata def self.substance_info(input : String) : NamedTuple(canonical_name: String?, aliases: Array(String)) canonical = normalize_substance(input) aliases = canonical ? get_aliases(canonical) : [] of String {canonical_name: canonical, aliases: aliases} end # Export all mappings as JSON for diffing/migration purposes # Returns a hash with alias -> canonical for both substances and routes def self.export_mappings : String { "version" => VERSION, "substances" => DrugLUT.export_alias_map, "routes" => RouteLUT.export_alias_map, }.to_json end # Normalize route of administration def self.normalize_route(input : String) : String? RouteLUT.normalize(input) end # Fuzzy substance normalization (exact match first, then Damerau-Levenshtein) def self.fuzzy_normalize_substance(input : String) : FuzzyResult? DrugLUT.fuzzy_normalize(input) end # Fuzzy route normalization (exact match first, then Damerau-Levenshtein) def self.fuzzy_normalize_route(input : String) : FuzzyResult? RouteLUT.fuzzy_normalize(input) end # ============================================ # Alcohol LUT methods # ============================================ # Look up an alcoholic beverage by brand name def self.lookup_alcohol(name : String) AlcoholLUT.lookup_brand(name) end # Check if a substance is an alcoholic beverage def self.is_alcohol?(name : String) : Bool AlcoholLUT.is_alcohol?(name) end # Calculate alcohol dose from dosage string and substance def self.calculate_alcohol_dose(dosage : String, substance : String, abv_override : Float64? = nil) AlcoholLUT.calculate_dose(dosage, substance, abv_override) end # Parse dosage string for alcohol (e.g., "2pints", "500ml") def self.parse_alcohol_dosage(dosage : String) AlcoholLUT.parse_dosage(dosage) end # Calculate alcohol grams from volume and ABV def self.calculate_alcohol_grams(volume_ml : Float64, abv_percent : Float64) : Float64 AlcoholLUT.calculate_grams(volume_ml, abv_percent) end # Get the default serving unit for an alcohol brand (e.g., "can" for beer) def self.alcohol_default_serving(name : String) : String? AlcoholLUT.default_serving_for(name) end # ============================================ # Caffeine LUT methods # ============================================ # Look up a caffeinated product by brand name def self.lookup_caffeine(name : String) CaffeineLUT.lookup_brand(name) end # Check if a substance is a caffeinated beverage/product def self.is_caffeine_source?(name : String) : Bool CaffeineLUT.is_caffeine_source?(name) end # Calculate caffeine dose from dosage string and substance def self.calculate_caffeine_dose(dosage : String, substance : String) CaffeineLUT.calculate_dose(dosage, substance) end # Parse dosage string for caffeine (e.g., "2cans", "500ml", "2g") def self.parse_caffeine_dosage(dosage : String) CaffeineLUT.parse_dosage(dosage) end # Lookup caffeine mg per gram for powder sources (e.g., matcha) def self.lookup_caffeine_powder_mg_per_g(name : String) : Int32? CaffeineLUT.lookup_powder_mg_per_g(name) end # Get the default serving unit for a caffeine brand (e.g., "can" for energy drinks) def self.caffeine_default_serving(name : String) : String? CaffeineLUT.default_serving_for(name) end # ============================================ # Meds LUT methods (injectable medications) # ============================================ # Look up an injectable medication by name def self.lookup_medication(name : String) MedsLUT.lookup_medication(name) end # Check if a substance is an injectable medication def self.is_injectable_med?(name : String) : Bool MedsLUT.is_injectable_med?(name) end # Calculate medication dose from ml to mg # Supports @concentration syntax (e.g., "een@20" for 20mg/ml) def self.calculate_meds_dose(substance : String, dosage : String, unit : String) MedsLUT.calculate_dose(substance, dosage, unit) end # Parse substance name with optional concentration override def self.parse_meds_concentration(name : String) MedsLUT.parse_substance_concentration(name) end # ============================================ # Cannabis LUT methods # ============================================ # Look up a cannabis source by name (joint, cart, bowl, etc.) def self.lookup_cannabis(name : String) CannabisLUT.lookup_source(name) end # Check if a substance is a cannabis source def self.is_cannabis_source?(name : String) : Bool CannabisLUT.is_cannabis_source?(name) end # Calculate cannabis dose from dosage string and source def self.calculate_cannabis_dose(dosage : String, source : String) CannabisLUT.calculate_dose(dosage, source) end # Parse dosage string for cannabis (e.g., "5puff", "1/3", "2hit") def self.parse_cannabis_dosage(dosage : String) CannabisLUT.parse_dosage(dosage) end end end