# T2 - Geolocalización Ligera ## Implementación Completada ✅ ### Cambios Realizados #### 1. **Modelo Actualizado** (`models/news.go`) - Añadidos campos opcionales: - `Latitude *float64` - `Longitude *float64` - `LocationName *string` - Nuevo tipo `Location` para el diccionario #### 2. **Base de Datos** (`db/database.go`) - **Schema actualizado**: columnas `latitude`, `longitude`, `location_name` - **Nuevos métodos**: - `GetNewsWithoutLocation(limit)`: obtiene noticias sin coordenadas - `UpdateNewsLocation(newsID, lat, lon, name)`: actualiza coordenadas - **Método actualizado**: `GetLatestNews` ahora incluye campos de geolocalización #### 3. **Worker de Geolocalización** (`workers/geo_enricher.go`) - Carga diccionario local desde JSON - Procesa noticias sin coordenadas cada 90 segundos - Matching case-insensitive de keywords en títulos - Primera coincidencia gana - Logs detallados del proceso #### 4. **Diccionario de Ubicaciones** (`data/locations.json`) - 29 ubicaciones predefinidas - Países y ciudades principales - Formato: `{"keyword": {"lat": X, "lon": Y, "name": "Nombre"}}` #### 5. **Integración en main.go** - Worker de geolocalización iniciado automáticamente - Variable de entorno `LOCATIONS_PATH` (default: `./data/locations.json`) - Procesamiento cada 90 segundos ### Estructura de Archivos ``` mang-service/ ├── data/ │ └── locations.json # Diccionario de ubicaciones ├── db/ │ └── database.go # BD + métodos de geolocalización ├── models/ │ └── news.go # Modelo con campos geo ├── workers/ │ ├── geo_enricher.go # Worker de geolocalización │ ├── geo_enricher_test.go # Tests unitarios │ └── rss_ingester.go # Worker RSS (T1) ├── handlers/ │ └── news.go # API HTTP ├── main.go # Integración completa ├── test_t2.sh # Test de integración └── mang-service # Binario compilado ``` ### Testing #### Tests Unitarios ```bash go test -v ./workers -run TestFindLocation ``` **Resultado**: ✅ PASS (6/6 casos) #### Test de Integración ```bash ./test_t2.sh ``` **Resultado**: ✅ PASS - Diccionario cargado: 29 ubicaciones - 4/5 noticias geolocalizadas correctamente - Casos validados: - ✓ "Terremoto en Japón" → Japón (36.2048, 138.2529) - ✓ "Cumbre en París" → París (48.8566, 2.3522) - ✓ "Madrid acoge conferencia" → Madrid (40.4168, -3.7038) - ✓ "Nuevas medidas en Berlín" → Berlín (52.5200, 13.4050) ### Criterios de Aceptación ✅ **El diccionario local se carga correctamente** - 29 ubicaciones desde `data/locations.json` - Validación en startup con log del count ✅ **Casos simples como 'Terremoto en Japón' producen coordenadas** - Matching case-insensitive - Primera keyword coincidente asigna coordenadas - Verificado en tests ✅ **Las noticias enriquecidas quedan guardadas en SQLite** - Columnas `latitude`, `longitude`, `location_name` pobladas - Endpoint `/news` devuelve coordenadas - Verificado con test de integración ### API Response Example ```json GET /news [ { "id": 1, "title": "Terremoto en Japón causa daños importantes", "link": "https://example.com/1", "published_at": "2026-04-05T13:50:00Z", "created_at": "2026-04-05T13:50:00Z", "latitude": 36.2048, "longitude": 138.2529, "location_name": "Japón" }, { "id": 2, "title": "Noticia sin ubicación", "link": "https://example.com/2", "published_at": "2026-04-05T13:50:00Z", "created_at": "2026-04-05T13:50:00Z" } ] ``` ### Variables de Entorno ```bash DB_PATH=/data/mang.db # Ruta de la BD SQLite LOCATIONS_PATH=./data/locations.json # Diccionario de ubicaciones RSS_FEED_URL=https://... # Feed RSS (T1) PORT=8080 # Puerto HTTP ``` ### Ejecución ```bash # Compilar go build -o mang-service # Ejecutar ./mang-service ``` **Logs esperados**: ``` [GeoEnricher] Loaded 29 locations from ./data/locations.json [GeoEnricher] Starting geo enrichment worker (interval: 1m30s) [GeoEnricher] Processing 5 news without location [GeoEnricher] Enriched news 1 'Terremoto en Japón...' with location Japón [GeoEnricher] Enriched 4/5 news with coordinates ``` ### Extensiones Futuras - Ampliar diccionario con más ubicaciones - Soporte para múltiples keywords por ubicación - Priorización de matches (ciudad > país) - Geocoding API para ubicaciones no en diccionario - Cache de matches frecuentes --- **Estado**: ✅ **T2 COMPLETADO** Todos los requisitos y criterios de aceptación cumplidos.