From 90b0806cecce8c5e1991025951a13305fa018452 Mon Sep 17 00:00:00 2001 From: Andreas Weyer Date: Mon, 2 Feb 2026 11:51:39 +0000 Subject: [PATCH] Fix isFed state for regular plan comparison line, simplified urin ph selection --- src/components/settings.tsx | 57 +++++++++++------------------------ src/constants/defaults.ts | 6 ++-- src/hooks/useAppState.ts | 27 ++++++++++++++++- src/hooks/useSimulation.ts | 3 +- src/locales/de.ts | 6 +++- src/locales/en.ts | 6 +++- src/utils/exportImport.ts | 1 + src/utils/pharmacokinetics.ts | 25 +++++++-------- 8 files changed, 71 insertions(+), 60 deletions(-) diff --git a/src/components/settings.tsx b/src/components/settings.tsx index 03d3fab..bd9fbef 100644 --- a/src/components/settings.tsx +++ b/src/components/settings.tsx @@ -46,7 +46,6 @@ const getDefaultsForTranslation = (pkParams: any, therapeuticRange: any, uiSetti standardVdPreset: defaults.pkParams.advanced.standardVd?.preset || 'adult', bodyWeight: defaults.pkParams.advanced.weightBasedVd.bodyWeight, tmaxDelay: defaults.pkParams.advanced.foodEffect.tmaxDelay, - phTendency: defaults.pkParams.advanced.urinePh.phTendency, fOral: defaults.pkParams.advanced.fOral, fOralPercent: String((parseFloat(defaults.pkParams.advanced.fOral) * 100).toFixed(1)), steadyStateDays: defaults.pkParams.advanced.steadyStateDays, @@ -924,12 +923,7 @@ const Settings = ({ {/* Urine pH */}
- updateAdvanced('urinePh', 'enabled', checked)} - /> -
- {pkParams.advanced.urinePh.enabled && ( -
-
- - setOpenTooltipId(open ? 'urinePHValue' : null)}> - - - - -

{tWithDefaults(t, 'urinePHValueTooltip', defaultsForT)}

-
-
-
- updateAdvanced('urinePh', 'phTendency', val)} - increment={0.1} - min={5.5} - max={8.0} - unit={t('phUnit')} - required={true} - /> -
- )} +
+ +
diff --git a/src/constants/defaults.ts b/src/constants/defaults.ts index ef4925e..7a075b2 100644 --- a/src/constants/defaults.ts +++ b/src/constants/defaults.ts @@ -26,7 +26,7 @@ const versionInfo = versionJsonDefault && Object.keys(versionJsonDefault).length gitDate: 'unknown', }; -export const LOCAL_STORAGE_KEY = 'medPlanAssistantState_v8'; // Incremented for ageGroup + renalFunction fields +export const LOCAL_STORAGE_KEY = 'medPlanAssistantState_v9'; // Incremented for urinePh mode structure change export const PROJECT_REPOSITORY_URL = 'https://git.11001001.org/cbaoth/med-plan-assistant'; export const APP_VERSION = versionInfo.version; export const BUILD_INFO = versionInfo; @@ -42,7 +42,7 @@ export interface AdvancedSettings { standardVd: { preset: 'adult' | 'child' | 'custom'; customValue: string }; // Volume of distribution (L) weightBasedVd: { enabled: boolean; bodyWeight: string }; // kg foodEffect: { enabled: boolean; tmaxDelay: string }; // hours - urinePh: { enabled: boolean; phTendency: string }; // 5.5-8.0 range + urinePh: { mode: 'normal' | 'acidic' | 'alkaline' }; // pH effect on elimination fOral: string; // bioavailability fraction steadyStateDays: string; // days of medication history to simulate // Age-specific pharmacokinetics (Research Section 5.2) @@ -141,7 +141,7 @@ export const getDefaultState = (): AppState => ({ standardVd: { preset: 'adult', customValue: '377' }, // Adult: 377L (Roberts 2015), Child: ~150-200L weightBasedVd: { enabled: false, bodyWeight: '70' }, // kg, adult average foodEffect: { enabled: false, tmaxDelay: '1.0' }, // hours delay - urinePh: { enabled: false, phTendency: '6.0' }, // pH scale (5.5-8.0) + urinePh: { mode: 'normal' }, // 'normal' (6-7.5), 'acidic' (<6), 'alkaline' (>7.5) fOral: String(DEFAULT_F_ORAL), // 0.96 bioavailability steadyStateDays: '7' // days of prior medication history } diff --git a/src/hooks/useAppState.ts b/src/hooks/useAppState.ts index fc5e8d2..1779025 100644 --- a/src/hooks/useAppState.ts +++ b/src/hooks/useAppState.ts @@ -29,10 +29,35 @@ export const useAppState = () => { migratedUiSettings.showDayTimeOnXAxis = migratedUiSettings.showDayTimeOnXAxis ? '24h' : 'continuous'; } + // Migrate urinePh from old {enabled, phTendency} to new {mode} structure + let migratedPkParams = {...defaults.pkParams, ...parsedState.pkParams}; + if (migratedPkParams.advanced) { + const oldUrinePh = migratedPkParams.advanced.urinePh as any; + if (oldUrinePh && typeof oldUrinePh === 'object' && 'enabled' in oldUrinePh) { + // Old format detected: {enabled: boolean, phTendency: string} + if (!oldUrinePh.enabled) { + migratedPkParams.advanced.urinePh = { mode: 'normal' }; + } else { + const phValue = parseFloat(oldUrinePh.phTendency); + if (!isNaN(phValue)) { + if (phValue < 6.0) { + migratedPkParams.advanced.urinePh = { mode: 'acidic' }; + } else if (phValue > 7.5) { + migratedPkParams.advanced.urinePh = { mode: 'alkaline' }; + } else { + migratedPkParams.advanced.urinePh = { mode: 'normal' }; + } + } else { + migratedPkParams.advanced.urinePh = { mode: 'normal' }; + } + } + } + } + setAppState({ ...defaults, ...parsedState, - pkParams: {...defaults.pkParams, ...parsedState.pkParams}, + pkParams: migratedPkParams, days: parsedState.days || defaults.days, uiSettings: migratedUiSettings, }); diff --git a/src/hooks/useSimulation.ts b/src/hooks/useSimulation.ts index c04459c..88fcc1e 100644 --- a/src/hooks/useSimulation.ts +++ b/src/hooks/useSimulation.ts @@ -72,7 +72,8 @@ export const useSimulation = (appState: AppState) => { doses: templateDay.doses.map(d => ({ id: `${d.id}-template-${i}`, time: d.time, - ldx: d.ldx + ldx: d.ldx, + isFed: d.isFed // Preserve food-timing flag for proper absorption delay modeling })) })); diff --git a/src/locales/de.ts b/src/locales/de.ts index b82ec9d..6fcb1d9 100644 --- a/src/locales/de.ts +++ b/src/locales/de.ts @@ -135,7 +135,11 @@ export const de = { tmaxDelayUnit: "h", urinePHTendency: "Urin-pH-Effekte", - urinePHTooltip: "Urin-pH beeinflusst Nierenrückresorption von Amphetamin. Ermöglicht pH-abhängige Halbwertszeit-Variation (7-15h Bereich). Bei Deaktivierung: neutraler pH (~11h HWZ).", + urinePHTooltip: "Urin-pH beeinflusst Nierenrückresorption von Amphetamin. Saurer Urin (<6) erhöht Elimination (schnellere Ausscheidung, t½ ~7-9h). Normaler pH (6-7,5) hält Basis-Elimination (~11h). Alkalischer Urin (>7,5) reduziert Elimination (langsamere Ausscheidung, t½ ~13-15h). Typischer Bereich: 5,5-8,0. Standard: Normaler pH (6-7,5).", + urinePHMode: "pH-Effekt", + urinePHModeNormal: "Normal (pH 6-7,5, t½ 11h)", + urinePHModeAcidic: "Sauer (pH <6, schnellere Elimination)", + urinePHModeAlkaline: "Alkalisch (pH >7,5, langsamere Elimination)", urinePHValue: "pH-Wert", urinePHValueTooltip: "Dein typischer Urin-pH (sauer=schnellere Ausscheidung, alkalisch=langsamer). Standard: {{phTendency}}. Bereich: 5,5-8,0.", phValue: "pH-Wert", diff --git a/src/locales/en.ts b/src/locales/en.ts index 8cd3fb5..d66b241 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -133,7 +133,11 @@ export const en = { tmaxDelayUnit: "h", urinePHTendency: "Urine pH Effects", - urinePHTooltip: "Urine pH affects kidney reabsorption of amphetamine. Enables pH-dependent half-life variation (7-15h range). When disabled, assumes neutral pH (~11h HL).", + urinePHTooltip: "Urine pH affects kidney reabsorption of amphetamine. Acidic urine (<6) increases elimination (faster clearance, t½ ~7-9h). Normal pH (6-7.5) maintains baseline elimination (~11h). Alkaline urine (>7.5) reduces elimination (slower clearance, t½ ~13-15h). Typical range: 5.5-8.0. Default: Normal pH (6-7.5).", + urinePHMode: "pH Effect", + urinePHModeNormal: "Normal (pH 6-7.5, t½ 11h)", + urinePHModeAcidic: "Acidic (pH <6, faster elimination)", + urinePHModeAlkaline: "Alkaline (pH >7.5, slower elimination)", urinePHValue: "pH Value", urinePHValueTooltip: "Your typical urine pH (acidic=faster clearance, alkaline=slower). Default: {{phTendency}}. Range: 5.5-8.0.", phValue: "pH Value", diff --git a/src/utils/exportImport.ts b/src/utils/exportImport.ts index b55bf8a..608c3b4 100644 --- a/src/utils/exportImport.ts +++ b/src/utils/exportImport.ts @@ -250,6 +250,7 @@ export const importSettings = ( time: dose.time || '12:00', ldx: dose.ldx || '0', damph: dose.damph, + isFed: dose.isFed, // Explicitly preserve food-timing flag })) })); } diff --git a/src/utils/pharmacokinetics.ts b/src/utils/pharmacokinetics.ts index b0da41f..a83a575 100644 --- a/src/utils/pharmacokinetics.ts +++ b/src/utils/pharmacokinetics.ts @@ -108,8 +108,7 @@ export const calculateSingleDoseConcentration = ( // Per-dose food effect takes precedence over global setting const foodEnabled = isFed !== undefined ? isFed : pkParams.advanced.foodEffect.enabled; const tmaxDelay = foodEnabled ? parseFloat(pkParams.advanced.foodEffect.tmaxDelay) : 0; - const urinePHEnabled = pkParams.advanced.urinePh.enabled; - const phTendency = urinePHEnabled ? parseFloat(pkParams.advanced.urinePh.phTendency) : 6.0; + const urinePHMode = pkParams.advanced.urinePh.mode; // Validate base parameters if (isNaN(absorptionHalfLife) || absorptionHalfLife <= 0 || @@ -125,20 +124,18 @@ export const calculateSingleDoseConcentration = ( const calculationTime = adjustedTime; // Use delayed time for all kinetic calculations // Apply urine pH effect on elimination half-life - // pH < 6: acidic (faster elimination, HL ~7-9h) - // pH 6-7: normal (HL ~10-12h) - // pH > 7: alkaline (slower elimination, HL ~13-15h up to 34h extreme) + // Acidic: pH < 6 (faster elimination, HL ~7-9h) + // Normal: pH 6-7.5 (baseline elimination, HL ~10-12h) + // Alkaline: pH > 7.5 (slower elimination, HL ~13-15h up to 34h extreme) let adjustedDamphHL = damphHalfLife; - if (urinePHEnabled) { - if (phTendency < 6.0) { - // Acidic: reduce HL by ~30% - adjustedDamphHL = damphHalfLife * 0.7; - } else if (phTendency > 7.5) { - // Alkaline: increase HL by ~30-40% - adjustedDamphHL = damphHalfLife * 1.35; - } - // else: normal pH 6-7.5, no adjustment + if (urinePHMode === 'acidic') { + // Acidic: reduce HL by ~30% + adjustedDamphHL = damphHalfLife * 0.7; + } else if (urinePHMode === 'alkaline') { + // Alkaline: increase HL by ~30-40% + adjustedDamphHL = damphHalfLife * 1.35; } + // else: normal mode, no adjustment // Calculate rate constants const ka_ldx = Math.log(2) / absorptionHalfLife;