Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assets/version.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version": "0.1.13"}
{"version": "0.1.14"}
6 changes: 6 additions & 0 deletions lib/features/home/presentation/tool_registry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ class ToolRegistry {
icon: Icons.thermostat,
route: '/hipertermia',
category: ToolCategory.signosValores),
ToolEntry(
id: 'shock_index',
name: 'Indice de Shock',
icon: Icons.show_chart,
route: '/shock-index',
category: ToolCategory.signosValores),
// Oxigenoterapia
ToolEntry(
id: 'o2_calculator',
Expand Down
92 changes: 92 additions & 0 deletions lib/features/shock_index/domain/shock_index_calculator.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import 'package:emerkit/shared/domain/entities/severity.dart';

class ShockIndexResult {
final double shockIndex;
final double modifiedShockIndex;
final double tam;
final Severity severity;
final Severity msiSeverity;
final double? sipaThreshold;

const ShockIndexResult({
required this.shockIndex,
required this.modifiedShockIndex,
required this.tam,
required this.severity,
required this.msiSeverity,
this.sipaThreshold,
});
}

class ShockIndexCalculator {
const ShockIndexCalculator();

ShockIndexResult calculate({
required int heartRate,
required int systolicBP,
required int diastolicBP,
bool isPediatric = false,
int? ageYears,
}) {
final si = heartRate / systolicBP;
final tam = diastolicBP + (systolicBP - diastolicBP) / 3;
final msi = heartRate / tam;

double? sipaThreshold;
Severity severity;

if (isPediatric && ageYears != null) {
sipaThreshold = _sipaThresholdForAge(ageYears);
severity = _sipaSeverity(si, sipaThreshold);
} else {
severity = _adultSeverity(si);
}

return ShockIndexResult(
shockIndex: si,
modifiedShockIndex: msi,
tam: tam,
severity: severity,
msiSeverity: _msiSeverity(msi),
sipaThreshold: sipaThreshold,
);
}

static Severity _adultSeverity(double si) {
if (si < 0.7) {
return const Severity(label: 'Normal', level: SeverityLevel.mild);
}
if (si < 1.0) {
return const Severity(
label: 'Normal-alto', level: SeverityLevel.moderate);
}
if (si <= 1.3) {
return const Severity(label: 'Elevado', level: SeverityLevel.severe);
}
return const Severity(label: 'Muy elevado', level: SeverityLevel.severe);
}

static Severity _msiSeverity(double msi) {
if (msi >= 0.7 && msi <= 1.3) {
return const Severity(label: 'Normal', level: SeverityLevel.mild);
}
if (msi <= 1.7) {
return const Severity(label: 'Elevado', level: SeverityLevel.moderate);
}
return const Severity(label: 'Muy elevado', level: SeverityLevel.severe);
}

static double _sipaThresholdForAge(int age) {
if (age <= 3) return 1.22;
if (age <= 6) return 1.2;
if (age <= 12) return 1.0;
return 0.9; // 13-17
}

static Severity _sipaSeverity(double si, double threshold) {
if (si < threshold) {
return const Severity(label: 'Normal', level: SeverityLevel.mild);
}
return const Severity(label: 'SIPA elevado', level: SeverityLevel.severe);
}
}
65 changes: 65 additions & 0 deletions lib/features/shock_index/domain/shock_index_data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import 'package:emerkit/shared/domain/entities/clinical_reference.dart';

class ShockIndexData {
ShockIndexData._();

static const infoSections = <String, String>{
'Que es':
'El Indice de Shock (SI) es el cociente entre la frecuencia cardiaca '
'(FC) y la tension arterial sistolica (TAS). Es una herramienta '
'rapida para detectar shock e hipovolemia oculta, mas sensible que '
'FC o TAS por separado, especialmente en la fase compensatoria.',
'Formulas': 'Indice de Shock (SI) = FC / TAS\n\n'
'Indice de Shock Modificado (MSI) = FC / TAM\n'
'TAM = TAD + 1/3 x (TAS - TAD)\n\n'
'SIPA (pediatrico) = misma formula con umbrales ajustados por edad.',
'Interpretacion adultos': 'SI < 0.7: Normal\n'
'SI 0.7 - 0.99: Normal-alto (vigilar)\n'
'SI 1.0 - 1.3: Elevado - hipovolemia o shock descompensado\n'
'SI > 1.3: Muy elevado - shock severo, resucitacion inmediata\n\n'
'MSI 0.7 - 1.3: Rango normal\n'
'MSI > 1.3: Anormal, mayor riesgo de mortalidad',
'SIPA pediatrico': '1-3 anos: anormal si >= 1.22\n'
'4-6 anos: anormal si >= 1.20\n'
'7-12 anos: anormal si >= 1.00\n'
'13-17 anos: anormal si >= 0.90',
'Aplicaciones clinicas':
'Triaje en trauma: predice necesidad de transfusion masiva e ingreso UCI.\n'
'Deteccion de hemorragia oculta en fase compensatoria.\n'
'Screening de sepsis (MSI >= 1.0).\n'
'Emergencias obstetricas: hemorragia postparto.\n'
'Triaje en urgencias: asignacion de acuidad y recursos.',
'Limitaciones': 'No usar como criterio diagnostico unico.\n'
'Confundido por: betabloqueantes, marcapasos, HTA basal, '
'embarazo, dolor, ansiedad.\n'
'Umbrales pediatricos especificos por edad.\n'
'No validado en pacientes con arritmias o medicacion cronotropica.',
};

static const references = [
ClinicalReference(
'Allgower M, Burri C. Schockindex. '
'Dtsch Med Wochenschr. 1967;92(43):1947-1950.',
),
ClinicalReference(
'Koch E, et al. Shock index in the emergency department: '
'utility and limitations. Open Access Emerg Med. 2019;11:179-199.',
),
ClinicalReference(
'Liu YC, et al. Modified shock index and mortality rate of '
'emergency patients. World J Emerg Med. 2012;3(2):114-117.',
),
ClinicalReference(
'Acker SN, et al. Shock index, pediatric age-adjusted (SIPA). '
'J Pediatr Surg. 2015;50(2):331-334.',
),
ClinicalReference(
'Schroll R, et al. Shock index as predictor of massive '
'transfusion and mortality. Crit Care. 2023;27(1):61.',
),
ClinicalReference(
'Mutschler M, et al. The Shock Index revisited — a fast guide '
'to transfusion requirement? Crit Care. 2013;17(4):R172.',
),
];
}
Loading