feat: Adding color themes + .ignore files update

This commit is contained in:
gauvainboiche
2026-08-29 15:09:50 +02:00
parent 257e187964
commit 786b87270c
16 changed files with 419 additions and 169 deletions
+51 -16
View File
@@ -8,7 +8,7 @@
/**
* Version unique de l'application (Centralisée)
*/
export const APP_VERSION = '0.16.0';
export const APP_VERSION = '0.18.0';
export const MODES = {
ESKETAMINE: 'ESKETAMINE',
@@ -142,32 +142,67 @@ export function processTimelineEvents(timelineInputs, weightKg, infusionUnit) {
}
/**
* Superposition Linéaire des Bolus et Perfusions sur 300 min (ng/mL arrondis à l'entier)
* Convertit le débit de perfusion courant en mg/kg/min, quelle que soit l'unité saisie
*/
function infusionRateToMgKgPerMin(rate, unit, weightKg) {
if (!rate || rate <= 0) return 0;
switch (unit) {
case INFUSION_UNITS.MG_KG_H:
return rate / 60;
case INFUSION_UNITS.MCG_KG_MIN:
return rate / 1000;
case INFUSION_UNITS.MG_H:
return weightKg > 0 ? (rate / weightKg) / 60 : 0;
default:
return rate / 60;
}
}
/**
* Résolution exacte (méthode récursive discrétisée, cf. formule KétaPK) des bolus et
* perfusions (à débit variable) sur la timeline, ng/mL arrondis à l'entier.
*/
export function generateSimulationData({ model, weightKg, timelineInputs, infusionUnit = INFUSION_UNITS.MG_KG_H }) {
const processedTimeline = processTimelineEvents(timelineInputs, weightKg, infusionUnit);
const { A, alpha, B, beta, C, gamma, refDose } = model;
const cpResults = [];
processedTimeline.forEach((targetEvent, targetIndex) => {
let totalCp = 0;
if (weightKg <= 0 || !refDose) {
return processedTimeline.map(event => ({ time: event.time, cp: 0 }));
}
for (let i = 0; i <= targetIndex; i++) {
const sourceEvent = processedTimeline[i];
const deltaTime = targetEvent.time - sourceEvent.time;
let X1 = 0, X2 = 0, X3 = 0;
if (sourceEvent.bolusMg > 0) {
totalCp += calculateBolusCp(model, sourceEvent.bolusMg, weightKg, deltaTime);
}
if (sourceEvent.infusionMg5Min > 0) {
totalCp += calculateBolusCp(model, sourceEvent.infusionMg5Min, weightKg, deltaTime);
}
processedTimeline.forEach((event, index) => {
if (event.bolusMg > 0) {
const scaledDose = (event.bolusMg / weightKg) / refDose;
X1 += A * scaledDose;
X2 += B * scaledDose;
X3 += gamma ? C * scaledDose : 0;
}
cpResults.push({
time: targetEvent.time,
cp: Math.round(totalCp)
time: event.time,
cp: Math.round(X1 + X2 + X3)
});
const nextEvent = processedTimeline[index + 1];
if (!nextEvent) return;
const deltaT = nextEvent.time - event.time;
const Rn = infusionRateToMgKgPerMin(event.infusionRate, infusionUnit, weightKg) / refDose;
const Falpha = Math.exp(-alpha * deltaT);
const Fbeta = Math.exp(-beta * deltaT);
X1 = Falpha * X1 + (A / alpha) * (1 - Falpha) * Rn;
X2 = Fbeta * X2 + (B / beta) * (1 - Fbeta) * Rn;
if (gamma) {
const Fgamma = Math.exp(-gamma * deltaT);
X3 = Fgamma * X3 + (C / gamma) * (1 - Fgamma) * Rn;
}
});
return cpResults;