609 lines
18 KiB
Markdown
609 lines
18 KiB
Markdown
# Estrategia Técnica: Búsqueda por Siglas y Acrónimos TES
|
|
## Arquitectura Frontend - PWA Sanitaria Crítica
|
|
|
|
**Objetivo:** Añadir soporte para búsqueda por siglas comunes del ámbito TES sin romper la búsqueda existente.
|
|
|
|
**Principio rector:** Compatibilidad total hacia atrás. La búsqueda actual debe seguir funcionando exactamente igual.
|
|
|
|
---
|
|
|
|
## 1. Análisis del Estado Actual
|
|
|
|
### Funciones de Búsqueda Existentes
|
|
|
|
**`src/data/procedures.ts`**
|
|
```typescript
|
|
export const searchProcedures = (query: string): Procedure[] => {
|
|
const lowerQuery = query.toLowerCase();
|
|
return procedures.filter(
|
|
(p) =>
|
|
p.title.toLowerCase().includes(lowerQuery) ||
|
|
p.shortTitle.toLowerCase().includes(lowerQuery) ||
|
|
p.steps.some((s) => s.toLowerCase().includes(lowerQuery))
|
|
);
|
|
};
|
|
```
|
|
|
|
**`src/data/drugs.ts`**
|
|
```typescript
|
|
export const searchDrugs = (query: string): Drug[] => {
|
|
const lowerQuery = query.toLowerCase();
|
|
return drugs.filter(
|
|
(d) =>
|
|
d.genericName.toLowerCase().includes(lowerQuery) ||
|
|
d.tradeName.toLowerCase().includes(lowerQuery) ||
|
|
d.indications.some((i) => i.toLowerCase().includes(lowerQuery))
|
|
);
|
|
};
|
|
```
|
|
|
|
### Punto de Integración Actual
|
|
|
|
**`src/components/layout/SearchModal.tsx`** (líneas 52-104)
|
|
- Llama a `searchProcedures(query)` y `searchDrugs(query)` directamente
|
|
- No hay preprocesamiento de la query
|
|
- Búsqueda case-insensitive mediante `.toLowerCase()`
|
|
|
|
### Observaciones Clave
|
|
|
|
1. ✅ **Búsqueda simple y determinista** - Usa `.includes()`, no algoritmos complejos
|
|
2. ✅ **Offline-compatible** - Todo es código TypeScript, sin llamadas externas
|
|
3. ✅ **Fácil de mantener** - Lógica clara y directa
|
|
4. ⚠️ **No soporta sinónimos** - "OVACE" no encuentra "Obstrucción de Vía Aérea"
|
|
5. ⚠️ **No soporta acrónimos** - "EAP" no encuentra "Enfermedad Arterial Periférica"
|
|
|
|
---
|
|
|
|
## 2. Propuesta de Arquitectura
|
|
|
|
### 2.1. Dónde Integrar el Mapeo de Siglas
|
|
|
|
**OPCIÓN RECOMENDADA: Capa de Preprocesamiento en SearchModal**
|
|
|
|
```
|
|
Usuario escribe "OVACE"
|
|
↓
|
|
SearchModal.tsx (expandAcronyms)
|
|
↓
|
|
Query expandida: "OVACE" → "OVACE OR obstrucción vía aérea OR cuerpo extraño"
|
|
↓
|
|
searchProcedures(query expandida) + searchDrugs(query expandida)
|
|
↓
|
|
Resultados combinados
|
|
```
|
|
|
|
**Ventajas:**
|
|
- ✅ No toca funciones de búsqueda existentes (`searchProcedures`, `searchDrugs`)
|
|
- ✅ Cambio localizado en un solo componente
|
|
- ✅ Fácil de desactivar si hay problemas (feature flag)
|
|
- ✅ Permite expandir a otros tipos de búsqueda en el futuro
|
|
|
|
**Alternativa (NO recomendada):**
|
|
- Modificar `searchProcedures` y `searchDrugs` directamente
|
|
- ❌ Riesgo: Cambia comportamiento de funciones usadas en otros lugares
|
|
- ❌ Riesgo: Más difícil de testear y revertir
|
|
|
|
### 2.2. Estructura de Archivos
|
|
|
|
```
|
|
src/data/
|
|
├── procedures.ts [NO TOCAR]
|
|
├── drugs.ts [NO TOCAR]
|
|
└── acronyms.ts [NUEVO] ← Diccionario de siglas
|
|
```
|
|
|
|
**`src/data/acronyms.ts`** - Nuevo archivo
|
|
- Diccionario estático de siglas → términos expandidos
|
|
- Type-safe con TypeScript
|
|
- Sin dependencias externas
|
|
|
|
**`src/components/layout/SearchModal.tsx`** - Modificar mínimamente
|
|
- Añadir función `expandAcronyms()` antes de llamar a búsqueda
|
|
- Mantener toda la lógica existente intacta
|
|
|
|
### 2.3. Formato del Diccionario de Siglas
|
|
|
|
```typescript
|
|
// src/data/acronyms.ts
|
|
|
|
export interface AcronymMapping {
|
|
acronym: string; // "OVACE"
|
|
expandedTerms: string[]; // ["obstrucción vía aérea", "cuerpo extraño"]
|
|
context?: 'procedure' | 'drug' | 'both'; // Opcional: filtrar contexto
|
|
priority?: number; // Opcional: prioridad en resultados
|
|
}
|
|
|
|
export const acronymMappings: AcronymMapping[] = [
|
|
{
|
|
acronym: 'OVACE',
|
|
expandedTerms: ['obstrucción vía aérea', 'cuerpo extraño', 'vía aérea'],
|
|
context: 'procedure',
|
|
},
|
|
{
|
|
acronym: 'RCP',
|
|
expandedTerms: ['reanimación cardiopulmonar', 'parada cardiorrespiratoria', 'PCR'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'PCR',
|
|
expandedTerms: ['parada cardiorrespiratoria', 'reanimación cardiopulmonar', 'RCP'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'SVB',
|
|
expandedTerms: ['soporte vital básico'],
|
|
context: 'procedure',
|
|
},
|
|
{
|
|
acronym: 'SVA',
|
|
expandedTerms: ['soporte vital avanzado'],
|
|
context: 'procedure',
|
|
},
|
|
{
|
|
acronym: 'EAP',
|
|
expandedTerms: ['enfermedad arterial periférica'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'IAM',
|
|
expandedTerms: ['infarto agudo miocardio', 'síndrome coronario agudo'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'SCACEST',
|
|
expandedTerms: ['síndrome coronario agudo con elevación ST', 'infarto con elevación ST'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'IOT',
|
|
expandedTerms: ['intubación orotraqueal', 'vía aérea avanzada'],
|
|
context: 'procedure',
|
|
},
|
|
{
|
|
acronym: 'DEA',
|
|
expandedTerms: ['desfibrilador externo automático'],
|
|
context: 'procedure',
|
|
},
|
|
{
|
|
acronym: 'ROSC',
|
|
expandedTerms: ['retorno circulación espontánea'],
|
|
context: 'procedure',
|
|
},
|
|
{
|
|
acronym: 'GCS',
|
|
expandedTerms: ['glasgow', 'escala glasgow'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'AVDN',
|
|
expandedTerms: ['alerta verbal dolor no responde'],
|
|
context: 'procedure',
|
|
},
|
|
{
|
|
acronym: 'FR',
|
|
expandedTerms: ['frecuencia respiratoria'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'FC',
|
|
expandedTerms: ['frecuencia cardiaca'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'TA',
|
|
expandedTerms: ['tensión arterial'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'SpO2',
|
|
expandedTerms: ['saturación oxígeno', 'saturación'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'ETCO2',
|
|
expandedTerms: ['capnografía', 'dióxido carbono espirado'],
|
|
context: 'procedure',
|
|
},
|
|
{
|
|
acronym: 'FV',
|
|
expandedTerms: ['fibrilación ventricular'],
|
|
context: 'procedure',
|
|
},
|
|
{
|
|
acronym: 'TVSP',
|
|
expandedTerms: ['taquicardia ventricular sin pulso'],
|
|
context: 'procedure',
|
|
},
|
|
{
|
|
acronym: 'AESP',
|
|
expandedTerms: ['actividad eléctrica sin pulso'],
|
|
context: 'procedure',
|
|
},
|
|
{
|
|
acronym: 'ACR',
|
|
expandedTerms: ['asistolia', 'parada cardiorrespiratoria'],
|
|
context: 'procedure',
|
|
},
|
|
{
|
|
acronym: 'TCE',
|
|
expandedTerms: ['traumatismo craneoencefálico'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'TEP',
|
|
expandedTerms: ['tromboembolismo pulmonar'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'EPOC',
|
|
expandedTerms: ['enfermedad pulmonar obstructiva crónica'],
|
|
context: 'both',
|
|
},
|
|
{
|
|
acronym: 'INR',
|
|
expandedTerms: ['razón normalizada internacional', 'coagulación'],
|
|
context: 'both',
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Expande una sigla/acrónimo a sus términos relacionados
|
|
* @param acronym - La sigla a expandir (ej: "OVACE")
|
|
* @returns Array de términos expandidos (ej: ["obstrucción vía aérea", "cuerpo extraño"])
|
|
*/
|
|
export function expandAcronym(acronym: string): string[] {
|
|
const upperAcronym = acronym.toUpperCase();
|
|
const mapping = acronymMappings.find(m => m.acronym.toUpperCase() === upperAcronym);
|
|
return mapping ? mapping.expandedTerms : [];
|
|
}
|
|
|
|
/**
|
|
* Obtiene todas las siglas que contienen un término
|
|
* Útil para búsqueda inversa: "vía aérea" → ["OVACE", "IOT"]
|
|
*/
|
|
export function getAcronymsByTerm(term: string): string[] {
|
|
const lowerTerm = term.toLowerCase();
|
|
return acronymMappings
|
|
.filter(m =>
|
|
m.expandedTerms.some(expanded => expanded.toLowerCase().includes(lowerTerm))
|
|
)
|
|
.map(m => m.acronym);
|
|
}
|
|
```
|
|
|
|
### 2.4. Algoritmo de Expansión de Query
|
|
|
|
**Estrategia: Búsqueda OR con términos expandidos**
|
|
|
|
```typescript
|
|
// Pseudocódigo de expandAcronyms()
|
|
|
|
function expandAcronyms(query: string): string {
|
|
const terms = query.split(/\s+/); // Dividir por espacios
|
|
const expandedTerms: string[] = [];
|
|
|
|
for (const term of terms) {
|
|
// Si el término es una sigla conocida, expandir
|
|
const expanded = expandAcronym(term);
|
|
if (expanded.length > 0) {
|
|
// Añadir término original + términos expandidos
|
|
expandedTerms.push(term);
|
|
expandedTerms.push(...expanded);
|
|
} else {
|
|
// Si no es sigla, mantener término original
|
|
expandedTerms.push(term);
|
|
}
|
|
}
|
|
|
|
// Retornar query original + términos expandidos
|
|
// La búsqueda actual con .includes() encontrará cualquiera de estos términos
|
|
return expandedTerms.join(' ');
|
|
}
|
|
```
|
|
|
|
**Ejemplo de funcionamiento:**
|
|
|
|
```
|
|
Input: "OVACE"
|
|
↓ expandAcronyms()
|
|
Output: "OVACE obstrucción vía aérea cuerpo extraño"
|
|
↓ searchProcedures()
|
|
Encuentra: Procedimiento con shortTitle "OVACE" ✅
|
|
Encuentra: Procedimiento con title "Obstrucción de Vía Aérea" ✅
|
|
```
|
|
|
|
**Input: "RCP adulto"**
|
|
↓ expandAcronyms()
|
|
Output: "RCP reanimación cardiopulmonar parada cardiorrespiratoria PCR adulto"
|
|
↓ searchProcedures()
|
|
Encuentra: Procedimientos con "RCP" en shortTitle ✅
|
|
Encuentra: Procedimientos con "reanimación" en title ✅
|
|
|
|
---
|
|
|
|
## 3. Compatibilidad con Búsquedas Actuales
|
|
|
|
### 3.1. Garantías de Compatibilidad
|
|
|
|
**✅ Búsquedas existentes siguen funcionando:**
|
|
- "parada" → encuentra "parada cardiorrespiratoria" (como antes)
|
|
- "adrenalina" → encuentra fármaco (como antes)
|
|
- "glasgow" → encuentra calculadora (como antes)
|
|
|
|
**✅ Búsquedas nuevas funcionan:**
|
|
- "OVACE" → encuentra "Obstrucción de Vía Aérea" (nuevo)
|
|
- "EAP" → encuentra protocolos relacionados (nuevo)
|
|
- "SVB" → encuentra "Soporte Vital Básico" (nuevo)
|
|
|
|
**✅ Búsquedas mixtas funcionan:**
|
|
- "RCP adulto" → encuentra RCP adulto (término original + expandido)
|
|
- "OVACE pediátrico" → encuentra OVACE pediátrico
|
|
|
|
### 3.2. Estrategia de Búsqueda OR (No AND)
|
|
|
|
**Problema potencial:** Si expandimos "OVACE" a "obstrucción vía aérea cuerpo extraño", y el usuario busca "OVACE pediátrico", podríamos encontrar resultados que solo contengan "pediátrico" sin "OVACE".
|
|
|
|
**Solución:** Mantener término original en la query expandida
|
|
|
|
```
|
|
Input: "OVACE pediátrico"
|
|
Expansión: "OVACE obstrucción vía aérea cuerpo extraño pediátrico"
|
|
Búsqueda: .includes("OVACE") OR .includes("obstrucción") OR .includes("pediátrico")
|
|
```
|
|
|
|
**Resultado:** Encuentra protocolos que contengan:
|
|
- "OVACE" Y "pediátrico" ✅ (mejor match)
|
|
- "obstrucción" Y "pediátrico" ✅ (match parcial)
|
|
- Solo "OVACE" ⚠️ (match parcial, pero mejor que nada)
|
|
|
|
**Mejora futura (opcional):** Sistema de scoring para priorizar matches completos.
|
|
|
|
### 3.3. Case-Insensitive
|
|
|
|
La expansión debe ser case-insensitive:
|
|
- "ovace" → expande igual que "OVACE"
|
|
- "Rcp" → expande igual que "RCP"
|
|
|
|
Ya está cubierto porque `expandAcronym()` compara con `.toUpperCase()`.
|
|
|
|
---
|
|
|
|
## 4. Qué NO Tocar (Zonas de Riesgo)
|
|
|
|
### 4.1. Archivos que NO deben modificarse
|
|
|
|
**❌ `src/data/procedures.ts`**
|
|
- Función `searchProcedures()` - NO TOCAR
|
|
- Array `procedures` - NO TOCAR
|
|
- Interfaces `Procedure` - NO TOCAR
|
|
- **Razón:** Cambiar esto afectaría toda la aplicación
|
|
|
|
**❌ `src/data/drugs.ts`**
|
|
- Función `searchDrugs()` - NO TOCAR
|
|
- Array `drugs` - NO TOCAR
|
|
- Interfaces `Drug` - NO TOCAR
|
|
- **Razón:** Cambiar esto afectaría toda la aplicación
|
|
|
|
**❌ Estructura de datos existente**
|
|
- No añadir campos nuevos a `Procedure` o `Drug` para siglas
|
|
- No modificar `title`, `shortTitle`, etc. para incluir siglas
|
|
- **Razón:** Cambios estructurales requieren migración y testing exhaustivo
|
|
|
|
### 4.2. Componentes que NO deben modificarse (excepto SearchModal)
|
|
|
|
**❌ `src/pages/SoporteVital.tsx`**
|
|
- No añadir lógica de búsqueda aquí
|
|
- **Razón:** La búsqueda está centralizada en SearchModal
|
|
|
|
**❌ `src/pages/Farmacos.tsx`**
|
|
- No añadir lógica de búsqueda aquí
|
|
- **Razón:** La búsqueda está centralizada en SearchModal
|
|
|
|
**❌ Otros componentes de búsqueda**
|
|
- Si existen otros puntos de búsqueda, evaluar caso por caso
|
|
- **Razón:** Mantener consistencia
|
|
|
|
### 4.3. Service Worker y Offline
|
|
|
|
**❌ NO modificar `public/sw.js` o lógica de Service Worker**
|
|
- El diccionario de siglas es código TypeScript compilado
|
|
- Se incluirá automáticamente en el bundle
|
|
- **Razón:** No requiere cambios en SW, ya funciona offline
|
|
|
|
---
|
|
|
|
## 5. Orden de Implementación Recomendado
|
|
|
|
### Fase 1: Preparación (Sin riesgo)
|
|
|
|
1. **Crear `src/data/acronyms.ts`**
|
|
- Definir interfaz `AcronymMapping`
|
|
- Crear array `acronymMappings` con siglas más comunes (10-15)
|
|
- Implementar `expandAcronym()` y `getAcronymsByTerm()`
|
|
- **Testing:** Unit tests para funciones de expansión
|
|
|
|
2. **Testing aislado**
|
|
- Test: `expandAcronym("OVACE")` → `["obstrucción vía aérea", ...]`
|
|
- Test: `expandAcronym("xyz")` → `[]` (sigla desconocida)
|
|
- Test: Case-insensitive funciona
|
|
|
|
### Fase 2: Integración Mínima (Riesgo bajo)
|
|
|
|
3. **Modificar `SearchModal.tsx`**
|
|
- Importar `expandAcronym` desde `acronyms.ts`
|
|
- Crear función `expandAcronyms(query: string): string`
|
|
- Aplicar expansión ANTES de llamar a `searchProcedures()` y `searchDrugs()`
|
|
- **Cambio mínimo:** Solo añadir una línea de preprocesamiento
|
|
|
|
4. **Testing de integración**
|
|
- Test manual: Buscar "OVACE" → debe encontrar protocolo OVACE
|
|
- Test manual: Buscar "parada" → debe seguir funcionando (compatibilidad)
|
|
- Test manual: Buscar "OVACE pediátrico" → debe encontrar resultados relevantes
|
|
|
|
### Fase 3: Validación y Expansión (Riesgo bajo)
|
|
|
|
5. **Validar con usuarios TES**
|
|
- Probar búsquedas reales: "EAP", "SVB", "SVA", "IOT", etc.
|
|
- Verificar que no se rompe búsqueda existente
|
|
- Recopilar feedback sobre siglas faltantes
|
|
|
|
6. **Expandir diccionario**
|
|
- Añadir más siglas basadas en feedback
|
|
- Validar que no hay conflictos (misma sigla → diferentes significados)
|
|
- Documentar decisiones (ej: "PCR" puede ser "Parada" o "Proteína C Reactiva")
|
|
|
|
### Fase 4: Optimización (Opcional, bajo riesgo)
|
|
|
|
7. **Mejoras opcionales**
|
|
- Sistema de scoring para priorizar matches completos
|
|
- Búsqueda fuzzy para typos (ej: "OVAC" → "OVACE")
|
|
- Cache de expansiones para performance
|
|
- **Nota:** Solo si hay necesidad real, no pre-optimizar
|
|
|
|
---
|
|
|
|
## 6. Riesgos Identificados y Mitigación
|
|
|
|
### 🔴 RIESGO ALTO: Falsos positivos
|
|
|
|
**Problema:** Expandir "EAP" a "enfermedad arterial periférica" podría encontrar resultados no relevantes si el término "arterial" aparece en otros contextos.
|
|
|
|
**Mitigación:**
|
|
- Mantener término original en query expandida (prioridad al match exacto)
|
|
- Considerar contexto opcional en `AcronymMapping` (`context: 'procedure' | 'drug'`)
|
|
- Testing exhaustivo con casos reales
|
|
|
|
### 🟡 RIESGO MEDIO: Performance con muchas siglas
|
|
|
|
**Problema:** Si el diccionario crece mucho (100+ siglas), la expansión podría ser lenta.
|
|
|
|
**Mitigación:**
|
|
- Diccionario pequeño inicial (20-30 siglas más comunes)
|
|
- Expansión solo si el término coincide exactamente (no fuzzy matching inicial)
|
|
- Si es necesario, cache de expansiones
|
|
|
|
### 🟡 RIESGO MEDIO: Ambiguidad de siglas
|
|
|
|
**Problema:** "PCR" puede ser "Parada Cardiorrespiratoria" o "Proteína C Reactiva".
|
|
|
|
**Mitigación:**
|
|
- Incluir ambos significados en `expandedTerms`
|
|
- La búsqueda encontrará ambos, usuario decide cuál es relevante
|
|
- Documentar ambigüedades en comentarios del código
|
|
|
|
### 🟢 RIESGO BAJO: Cambios en comportamiento de búsqueda
|
|
|
|
**Problema:** Usuarios acostumbrados a que "OVACE" no encuentra nada podrían confundirse si ahora sí encuentra.
|
|
|
|
**Mitigación:**
|
|
- Esto es una mejora, no un problema
|
|
- Documentar en changelog
|
|
- Si hay quejas, se puede desactivar fácilmente (feature flag)
|
|
|
|
---
|
|
|
|
## 7. Testing Strategy
|
|
|
|
### Tests Unitarios (Recomendado)
|
|
|
|
```typescript
|
|
// tests/acronyms.test.ts
|
|
|
|
describe('expandAcronym', () => {
|
|
it('expande OVACE correctamente', () => {
|
|
expect(expandAcronym('OVACE')).toContain('obstrucción vía aérea');
|
|
});
|
|
|
|
it('es case-insensitive', () => {
|
|
expect(expandAcronym('ovace')).toEqual(expandAcronym('OVACE'));
|
|
});
|
|
|
|
it('retorna array vacío para sigla desconocida', () => {
|
|
expect(expandAcronym('XYZ')).toEqual([]);
|
|
});
|
|
});
|
|
```
|
|
|
|
### Tests de Integración (Manual inicialmente)
|
|
|
|
1. **Búsqueda "OVACE"** → Debe encontrar protocolo OVACE
|
|
2. **Búsqueda "parada"** → Debe seguir funcionando (compatibilidad)
|
|
3. **Búsqueda "RCP adulto"** → Debe encontrar RCP adulto
|
|
4. **Búsqueda "EAP"** → Debe encontrar protocolos relacionados
|
|
|
|
### Tests de Regresión
|
|
|
|
- Todas las búsquedas que funcionaban antes deben seguir funcionando
|
|
- No debe haber cambios en resultados para queries sin siglas
|
|
|
|
---
|
|
|
|
## 8. Consideraciones de Mantenimiento
|
|
|
|
### 8.1. Añadir Nuevas Siglas
|
|
|
|
**Proceso simple:**
|
|
1. Añadir entrada a `acronymMappings` en `acronyms.ts`
|
|
2. Testing manual
|
|
3. Deploy
|
|
|
|
**No requiere:**
|
|
- Cambios en funciones de búsqueda
|
|
- Migración de datos
|
|
- Cambios en UI
|
|
|
|
### 8.2. Documentación
|
|
|
|
**Mantener documentado:**
|
|
- Lista de siglas soportadas (en comentarios o README)
|
|
- Decisiones sobre ambigüedades (ej: "PCR" tiene 2 significados)
|
|
- Fuentes de las siglas (manual TES, protocolos oficiales)
|
|
|
|
### 8.3. Versionado
|
|
|
|
**Si hay cambios breaking (poco probable):**
|
|
- Versionar el diccionario
|
|
- Mantener versiones anteriores para compatibilidad
|
|
- Migración gradual si es necesario
|
|
|
|
---
|
|
|
|
## 9. Resumen Ejecutivo
|
|
|
|
### Cambios Propuestos
|
|
|
|
1. **Nuevo archivo:** `src/data/acronyms.ts` - Diccionario de siglas
|
|
2. **Modificación mínima:** `src/components/layout/SearchModal.tsx` - Preprocesamiento de query
|
|
3. **Sin cambios:** `src/data/procedures.ts`, `src/data/drugs.ts` - Funciones de búsqueda intactas
|
|
|
|
### Beneficios
|
|
|
|
- ✅ Búsqueda por siglas funciona (OVACE, EAP, SVB, etc.)
|
|
- ✅ Compatibilidad total con búsqueda existente
|
|
- ✅ Offline-compatible (todo en código TypeScript)
|
|
- ✅ Fácil de mantener (diccionario simple)
|
|
- ✅ Fácil de revertir (cambio localizado)
|
|
|
|
### Riesgos
|
|
|
|
- 🟡 Falsos positivos (mitigado con término original)
|
|
- 🟡 Performance (mitigado con diccionario pequeño)
|
|
- 🟢 Cambio de comportamiento (mejora, no problema)
|
|
|
|
### Esfuerzo Estimado
|
|
|
|
- **Fase 1 (Preparación):** 2-3 horas
|
|
- **Fase 2 (Integración):** 1-2 horas
|
|
- **Fase 3 (Validación):** 2-4 horas (testing con usuarios)
|
|
- **Total:** 5-9 horas
|
|
|
|
### Recomendación Final
|
|
|
|
**✅ PROCEDER con la implementación**
|
|
|
|
La estrategia es segura, localizada y reversible. El riesgo es bajo y el beneficio es alto para usuarios TES que usan siglas constantemente.
|
|
|
|
---
|
|
|
|
*Documento de arquitectura - No incluye código de implementación, solo diseño y estrategia.*
|