Skip to main content

timeineco

TimeIneco — visor de isocronas multi-modo (coche, bus, metro, tranvía, bici, andando) con motor ORS real, fallback simulación orgánica, datos demográficos reales por código postal (salarios INE, precios vivienda, CO₂), GTFS EMT Madrid, DOCX informe 12+ secciones, y SHP real para QGIS.

Aller à l'installation

Informations de source

Dépôt
Ntizar/NtizarBrainMasterMind
Dernière activité de la source
1 juillet 2026 à 19:28
Langue détectée de SKILL.md
espagnol
Étoiles
2
Forks
0

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Explorateur de fichiers
17 fichiers

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
timeineco
version
1.1.0
description
TimeIneco — visor de isocronas multi-modo (coche, bus, metro, tranvía, bici, andando) con motor ORS real, fallback simulación orgánica, datos demográficos reales por código postal (salarios INE, precios vivienda, CO₂), GTFS EMT Madrid, DOCX informe 12+ secciones, y SHP real para QGIS.
author
David Antizar
tags
["timeineco","isochrones","gtfs","routing","ors","nap","leaflet","transport","mobility","docx","shapefile","shp"]
# TimeIneco — Visor de Isocronas Multi-Modo TimeIneco calcula y visualiza **isocronas** (áreas accesibles en X tiempo) para 4 modos de transporte con 3 rangos temporales cada uno. Desplegado en NaN.builders. **URL:** `https://timeineco-ntizar-ntizar.apps.nan.builders/` **Repositorio:** GitHub `Ntizar/TimeIneco` (privado) --- ## 1. Arquitectura General ``` Frontend (HTML/JS vanilla, sin framework) ├── Leaflet (mapa base CartoDB Positron) ├── OpenRouteService API (isocronas reales vía proxy Node.js) ├── Motor de simulación orgánica (fallback sin ORS) ├── GTFS Engine browser-side (paradas cercanas a 500m + rutas) ├── Turf.js (coastline clipping) ├── Clipping costero (Natural Earth 110m) ├── docx.js (informe DOCX 10 secciones — reemplaza jsPDF) ├── JSZip (subida de GTFS ZIP + export SHP) └── shp.js (ESRI Shapefile QGIS-compatible: .shp/.shx/.dbf/.prj) Backend (Node.js, server.mjs) ├── Proxy ORS (POST /isochrone) ├── Proxy GTFS download (POST /gtfs-download) ├── Health check (GET /healthz) └── Static files + MIME types ``` ## 2. Modos de Transporte | Modo | Perfil ORS | Simulación | Velocidad | Color | |------|-----------|-----------|-----------|-------| | Coche 🚗 | `driving-car` | 40 km/h, calles marcadas (σ 0.10, peso 0.35) | 40 km/h | `#2563eb` | | Bus 🚌 | `driving-car` (ORS no tiene bus) | 12 km/h, orgánico | 12 km/h | `#a855f7` | | Metro 🚇 | `driving-car` (aproximación) | 32 km/h, radial | 32 km/h | `#ef4444` | | Tranvía 🚊 | `driving-car` (aproximación) | 20 km/h, radial suave | 20 km/h | `#06b6d4` | | Bici 🚲 | `cycling-regular` | 15 km/h, estrellado (σ 0.12, peso 0.20), elevación simulada | 15 km/h | `#f97316` | | Andando 🚶 | `foot-walking` | 5 km/h, difuso (σ 0.18, peso 0.07) | 5 km/h | `#22c55e` | Rangos: **15, 30, 45, 60 minutos** (configurable). ### Datos Demográficos (v1.0) `demographics.js` carga datasets JSON desde `/data/` y enriquece cada isócrona: - **Códigos postales** (`data/codigos-postales-spain.json`): 299 CPs con centroides, densidad, municipio, provincia, comunidad - **Salarios medios** (`data/salarios-medios.json`): 51 provincias, datos INE 2024-2025 - **Precios vivienda** (`data/precios-vivienda.json`): 127 CPs con €/m² alquiler y compra Funciones clave: - `buscarCP(lat, lng)` → CP más cercano con datos enriquecidos - `buscarCPsEnPoligono(coords)` → todos los CPs dentro de una isócrona - `estadisticas(cps)` → población, salario medio, precios de la zona - `calcularAhorroCO2(distancia)` → CO₂ por modo con equivalencia en árboles - `calcularPorcentajeSueldo(coste, salario)` → % del salario en transporte - `cargarGTFS()` → carga datos GTFS (paradas + rutas) al inicio junto con datos demográficos - `buscarParadasCercanas(lat, lng, radioKm=1.5)` → {paradas, lineas, resumen} — paradas de bus/metro dentro de un radio, con rutas que pasan por cada una - `buscarLineasConectoras(lat1, lng1, lat2, lng2)` → líneas que conectan dos puntos (por paradas cercanas a ambos) ### Búsqueda de Transporte Público Cercano (v1.1) Al clicar un punto, `main.js` ejecuta `buscarParadasCercanas()` que: 1. Recorre todas las paradas GTFS y calcula distancia Haversine 2. Filtra por radio (default 1.5km) 3. Para cada parada, busca en `route_stops` qué rutas pasan por ella 4. Compila lista de líneas únicas ordenadas por cobertura (paradas en radio) 5. Devuelve resumen: total paradas, total líneas, parada más cercana, distribución por tipo **Pitfall:** Las paradas GTFS del cache pueden tener `route_stops` con stop_ids que no coinciden exactamente con los stop_ids de `stops[]`. Verificar que el `stop_id` en `route_stops` existe en `stops[]` antes de buscar rutas. **Pitfall:** `demographics.js` usa `fetch()` para cargar datos → funciona en browser pero NO en Node.js directo. Para tests unitarios, cargar los JSON manualmente con `fs.readFileSync()`. ### Salarios por CP (v1.1.1) **Problema:** Los salarios por provincia (`salarios-medios.json`) dan el MISMO salario a todos los CPs de una provincia. Chamberí y Vallecas reciben 32.500€ ambos, cuando en realidad Chamberí ~35.500€ y Vallecas ~23.000€. **Solución:** `salarios-por-cp.json` — estimación por CP usando el **precio del alquiler como proxy de poder adquisitivo** (correlación ~0.75 con salarios reales en España): ```javascript // Fórmula de estimación rent_ratio = alq_m2_cp / alq_m2_provincia_promedio salary_adj = base_provincia * (1 + (rent_ratio - 1) * 0.5) // elasticidad 0.5 // Clamped: 70%-150% del salario provincial ``` **Datos:** 299 CPs con salario estimado. Rango: 18.685€ — 40.185€. Media: 26.967€. **Pitfall:** La correlación alquiler→salario no es perfecta (~0.75). Zonas universitarias o industriales pueden tener alquiler bajo pero salarios medios-altos. Para producción, cruzar con EPA por distrito + convenios colectivos por sector. ### Informes Multi-Ciudad (v1.1.2) **Patrón:** Función parametrizable `build_report(lat, lng, nombre, ciudad, archivo)` que genera un informe HTML completo para **cualquier punto de España**. **Archivos generados:** - `informe-plaza-mayor-madrid.html` — 40.4167, -3.7038 - `informe-nuevos-ministerios-madrid.html` — 40.4464, -3.6921 - `informe-barcelona-sants-ave.html` — 41.3792, 2.1404 **Estructura del informe HTML:** 1. Mapa Leaflet interactivo con círculos de radio por modo (5km → 40km) 2. Resumen ejecutivo (6 KPIs) 3. Transporte público cercano (top 10 paradas + top 15 líneas) 4. Población accesible por modo y tiempo 5. **Coste por minuto** (la sección estrella — €/min por modo) 6. Escenarios teletrabajo (5d/3+2d/2+3d/full remote) 7. CO₂ y coste para la empresa (EU ETS 50€/ton) 8. Mercado inmobiliario (top 10 CPs) 9. Comparativa visual (barras) 10. Recomendaciones para RRHH y empleado **Cómo usar:** ```javascript // En execute_code o script Python build_report(lat, lng, "Nombre del punto", "Ciudad", "/ruta/salida.html") ``` **Pitfall:** El GTFS por defecto solo tiene datos de Madrid (EMT). Para Barcelona u otras ciudades, crear un `gtfs-cache-{ciudad}.json` y fusionarlo: ```python gtfs = { 'routes': gtfs_madrid['routes'] + gtfs_otra_ciudad['routes'], 'stops': gtfs_madrid['stops'] + gtfs_otra_ciudad['stops'], 'route_stops': {**gtfs_madrid['route_stops'], **gtfs_otra_ciudad['route_stops']}, } ``` **Pitfall:** Si no hay paradas GTFS en 1.5km del punto (ciudad sin datos), el informe debe manejar `paradas_top[0]` vacío. Añadir check: `if paradas_top:` antes de acceder. ### GTFS Barcelona (v1.1.2) `data/gtfs-cache-barcelona.json` — 61 paradas, 8 rutas: - **L1** (Roja): Hospital de Bellvitge ↔ Fondo (12 paradas) - **L3** (Verde): Zona Universitària ↔ Trinitat Nova (15 paradas) - **L5** (Azul): Cornellà Centre ↔ Vall d'Hebron (12 paradas) - **L9**: Aeroport T1 ↔ ZAL Riu Vell (6 paradas) - **R1** Rodalies: Sants → Clot (6 paradas) - **Bus TMB**: H12, V15, D20 (10 paradas) Parada más cercana a Sants: **Sants Estació (0m)** — L1+L3+L5+R1 convergen. ### Coste por Minuto y Teletrabajo (v1.1.1) Nuevas funciones en `demographics.js`: ```javascript // Coste por minuto de desplazamiento calcularCostePorMinuto(minutosIda, salarioBruto, modo, distanciaKm) // → { coste_mensual, coste_anual, coste_por_minuto, salario_neto_anual, // sueldo_neto_trasporte, pct_neto, co2_anual_kg, co2_precio_eur } // Escenarios de teletrabajo (5d/3+2d/2+3d/full remote) calcularEscenariosTeletrabajo(minutosIda, salarioBruto, modo, distanciaKm) // → { base, escenarios[], ahorro_total_teletrabajo } // CO₂ con precio EU ETS para la empresa calcularCosteCO2Empresa(co2AnualKg, sector='general') // → { coste_ets, coste_reputacional, certificado_voluntario, coste_total } ``` **Constantes clave:** - `PRECO2_EUR_KG = 0.050` (50€/tonelada EU ETS 2025) - `DIAS_LABORALES = 230` - IRPF estimado por tramo: 15%/21%/28%/35%/42% - Precios sector: general=50, banca=80, industria=45, tecnología=60 €/ton **KPIs ejemplo (Plaza Mayor, 60min metro):** - Coste por minuto: 0.02€ - Sueldo neto trasporte: 19.151€/año - CO₂ empresa: 1.104 ton = 55€ EU ETS/año - Ahorro 3d teletrabajo: 10€/año **Pitfall:** El IRPF es una estimación por tramo. El cálculo real depende de circunstancias personales (hijos, discapacidad, etc.). El informe debe indicar "IRPF estimado" explícitamente. ## 3. Motor de Isocronas ### ORS Real (prioritario) - Endpoint proxy: `POST /isochrone` → ORS API - Perfiles: `driving-car`, `foot-walking`, `cycling-regular` - APi key en `.env`, servidor arrancado con `node --env-file=.env server.mjs` - Health check: `GET /healthz` → `{ ors_api: true/false }` ### Simulación Orgánica (fallback) Cuando ORS no responde, se usa un motor de simulación local que NO genera círculos perfectos: 1. **72 puntos base** (5° spacing) 2. **5 capas de ruido multicapa** (frecuencias: 0.7, 2.3, 5.1, 11.3, 17.1) 3. **12 corredores radiales** (calles principales cada 30° + secundarias offset 15°) 4. **[Bici] Campo de elevación simulado** (5 capas de ruido orográfico, penaliza radio hasta 30%) 5. **Suavizado Gaussiano** 3-ventana ([0.25, 0.50, 0.25]) 6. **Clipeo costero** (turf.intersect con Natural Earth 110m) ### Clipeo Costero Ver skill `isochrone-routing-tools` sección 8. Datos: Natural Earth 110m land (135KB, 127 features). Carga lazy solo si el punto está en zona costera (lista de 16+ ciudades). Fallback a polígono mínimo ~50m si la isocrona cae completamente en el mar. ## 4. GTFS Engine ### Qué hace - Detecta ciudad del usuario por coordenadas - Muestra operadores candidatos (EMT Madrid, EMTUSA Gijón, ALSA, etc.) - Carga GTFS del operador elegido (desde cache localStorage o subida ZIP) - Busca paradas a ≤1.5km del origen (Haversine) - Muestra rutas disponibles (chips de líneas) - Exporta paradas a GeoJSON - Incluye tabla en PDF ### Datos simulados `data/gtfs-cache.json` contiene datos EMT Madrid (46 rutas, 250 paradas). Es suficiente para demo sin conexión a API real. **Pitfall GTFS sintético:** El cache puede tener 0 trips, 0 stop_times, 0 shapes. Esto es suficiente para búsqueda de paradas cercanas (usa `stops[]` + `route_stops{}`) pero NO para simulación de rutas en tiempo real (necesita `trips[]` + `stop_times[]`). Si se necesita realismo de horarios, descargar GTFS ZIP real de EMT Madrid. **Dato clave:** Las paradas del cache tienen nombres reales de Madrid (Puerta del Sol, Gran Vía, Sol, Ópera, Atocha, etc.) con coordenadas reales. Esto hace que el informe sea creíble para demostración. ### Radio de búsqueda: 500m El radio por defecto de `findStopsNear()` es **500 metros** (cambiado de 2km en v0.8). Esto es más realista para andar a la parada (5-7 min) que los 2km originales. Para cambiar: editar `radiusKm = 0.5` en la firma de `findStopsNear()` en `gtfs-engine.v7.js`. ### Pitfall: CDN cachea 404 en NaN Cuando se renombra un archivo GTFS engine (ej: `gtfs-engine.js → gtfs-engine.v7.js`), Cloudflare cachea el 404 del .js original por 4h. Los imports ES module en `main.js` y `nap.js` deben actualizarse. **No usar `?v=N` en imports ES module** — los imports no llevan query params. Versionar el nombre del archivo. ### Subida de ZIP real El usuario puede arrastrar/soltar su propio GTFS ZIP. Se parsea con JSZip en el navegador, sin enviar datos al servidor. ### Proxy de descarga `POST /gtfs-download` en server.mjs permite descargar feeds GTFS externos que no soportan CORS. ## 5. Estructura de Archivos ``` TimeIneco/ ├── index.html # Entry point, CDNs (Leaflet, turf, jsPDF, JSZip, html2canvas) ├── css/style.css # Estilos completos (+180 líneas GTFS) ├── js/ │ ├── main.js # Orquestación: eventos, flujo cálculo, integración GTFS + demographics │ ├── map.js # Leaflet: mapa base, isocronas, marcadores paradas │ ├── isochrones.js # Motor: ORS proxy + simulación orgánica (72pts + ruido + calles) │ ├── clip.js # Coastline clipping con turf.intersect() │ ├── config.js # Configuración: 6 modos, velocidades, colores, rangos │ ├── demographics.js # Motor demográfico: CP, salarios, vivienda, CO₂ (v1.0) │ ├── pdf.js # jsPDF: informe multi-página con mapas, tablas, GTFS │ ├── nap.js # Catálogo NAP: operadores GTFS por ciudad, UI selección │ ├── docx-report.js # DOCX informe 12+ secciones (reemplaza jsPDF) │ ├── gtfs-engine.v7.js # Motor GTFS browser-side (JSZip, Haversine, localStorage) │ ├── shp.js # ESRI Shapefile QGIS-compatible (.shp/.shx/.dbf/.prj) │ └── utils.js # Funciones auxiliares (formatKm2, formatNum, etc.) ├── data/ │ ├── gtfs-cache.json # EMT Madrid: 46 rutas, 250 paradas reales │ ├── codigos-postales-spain.json # 299 CPs España con centroides y densidad (v1.0) │ ├── salarios-medios.json # 51 provincias, salario medio INE (v1.0) │ ├── salarios-por-cp.json # 299 CPs con salario estimado por proxy alquiler (v1.1.1) │ ├── precios-vivienda.json # 127 CPs con €/m² alquiler y compra (v1.0) │ └── ne_110m_land.geojson # Coastline global (135KB) ├── server.mjs # Node.js: proxy ORS + GTFS download + static files + rate limiting ├── .env # ORS_API_KEY (no commit) ├── informe-plaza-mayor-madrid.html # Informe demo generado (v1.0) ├── AUDITORIA-v1.0.md # Auditoría completa del proyecto └── package.json # Solo server.mjs deps ``` ## 6. Modo de Arranque ```bash # Local cd /root/workspace/TimeIneco node --env-file=.env server.mjs # El servidor sirve en http://localhost:4000 # Health check: curl http://localhost:4000/healthz ``` Si muere el proceso: `pkill -f "server.mjs"` y volver a arrancar. ## 7. Despliegue en NaN - Repo push a GitHub → NaN auto-deploy - NaN usa Cloudflare CDN → si hay archivos nuevos JS, **usar versionado en nombre** (ej: `gtfs-engine.v7.js`) para evitar cache de 404 - Cache-bust: `v=7` en query param para `<script>` y `<link>` tags - Ver skill `nan-deploy-sync` para CDN cache pitfalls ## 8. DOCX Report (12+ secciones) **Reemplaza a jsPDF.** Genera informe `.docx` editable por el equipo. ### CDN ```html
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub