Compare commits

..

2 Commits

Author SHA1 Message Date
a8c1d96b54 adición mapa 2026-02-23 10:57:04 +01:00
e62e48f78d añadidas más megafonías y cambios en js 2026-02-18 07:19:40 +01:00
60 changed files with 484 additions and 732 deletions

104
editor_lineas.html Normal file
View File

@@ -0,0 +1,104 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Bus Editor - EMTUSA Simulator</title>
<style>
body { font-family: sans-serif; background: #f0f0f0; padding: 20px; display: flex; gap: 20px; }
.panel { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); flex: 1; }
h2 { color: #004a99; margin-top: 0; }
label { display: block; margin: 10px 0 5px; font-weight: bold; }
input, select, textarea { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }
button { background: #004a99; color: white; border: none; padding: 10px 15px; border-radius: 4px; cursor: pointer; margin-top: 10px; }
button:hover { background: #003366; }
.output { background: #222; color: #0f0; padding: 15px; border-radius: 5px; font-family: 'Courier New', monospace; overflow-y: auto; max-height: 500px; white-space: pre-wrap; }
.parada-item { border: 1px solid #eee; padding: 10px; margin-bottom: 10px; border-radius: 4px; background: #fafafa; }
</style>
</head>
<body>
<div class="panel">
<h2>Configuración de Línea</h2>
<label>ID de Línea (ej: L3):</label>
<input type="text" id="linea-id" placeholder="L3">
<label>Nombre Completo:</label>
<input type="text" id="linea-nombre" placeholder="Línea 3: Zafra - Orden Baja">
<h3>Añadir Parada</h3>
<div id="form-parada" style="border-top: 1px solid #ccc; padding-top: 10px;">
<label>ID Parada (Audio):</label>
<input type="text" id="parada-id" placeholder="molino_vega">
<label>Nombre Visual:</label>
<input type="text" id="parada-nombre" placeholder="Molino de la Vega">
<label>Enlaces (separados por coma):</label>
<input type="text" id="parada-enlaces" placeholder="L2, L4">
<button onclick="addParada()">Añadir a la lista</button>
</div>
<h3>Paradas Actuales</h3>
<div id="lista-paradas"></div>
</div>
<div class="panel">
<h2>JSON Resultante</h2>
<p>Copia este código y pégalo en tu archivo .json usando VIM:</p>
<button onclick="generarJSON()">Generar JSON</button>
<div id="json-output" class="output">El JSON aparecerá aquí...</div>
</div>
<script>
let paradas = [];
function addParada() {
const id = document.getElementById('parada-id').value;
const nombre = document.getElementById('parada-nombre').value;
const enlaces = document.getElementById('parada-enlaces').value.split(',').map(e => e.trim()).filter(e => e !== "");
if(!id || !nombre) return alert("Rellena ID y Nombre de parada");
paradas.push({ id, nombre, enlaces });
renderParadas();
// Limpiar campos
document.getElementById('parada-id').value = "";
document.getElementById('parada-nombre').value = "";
document.getElementById('parada-enlaces').value = "";
}
function renderParadas() {
const div = document.getElementById('lista-paradas');
div.innerHTML = paradas.map((p, index) => `
<div class="parada-item">
<strong>${p.nombre}</strong> (${p.id})
<br><small>Enlaces: ${p.enlaces.join(', ') || 'Ninguno'}</small>
<button style="background:red; padding:2px 5px; font-size:10px;" onclick="eliminarParada(${index})">X</button>
</div>
`).join('');
}
function eliminarParada(index) {
paradas.splice(index, 1);
renderParadas();
}
function generarJSON() {
const lineaId = document.getElementById('linea-id').value || "LX";
const lineaNombre = document.getElementById('linea-nombre').value || "Nueva Línea";
const resultado = {
[lineaId]: {
nombre: lineaNombre,
paradas: paradas
}
};
document.getElementById('json-output').innerText = JSON.stringify(resultado, null, 2);
}
</script>
</body>
</html>

View File

@@ -6,6 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Megafonías TsSAEx</title> <title>Megafonías TsSAEx</title>
<link rel="stylesheet" href="/src/style.css"> <link rel="stylesheet" href="/src/style.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet" />
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -39,7 +40,7 @@
<label><md-radio name="tipo" value="siguiente"></md-radio>Parada siguiente</label> <label><md-radio name="tipo" value="siguiente"></md-radio>Parada siguiente</label>
</div> </div>
<div id="container-regulacion" class="regulacion-box"> <div id="container-regulacion" class="regulacion-box" style="display: none;">
<md-checkbox id="chk-regulacion"></md-checkbox> <md-checkbox id="chk-regulacion"></md-checkbox>
<label for="chk-regulacion">Parada de regulación</label> <label for="chk-regulacion">Parada de regulación</label>
</div> </div>
@@ -49,8 +50,7 @@
<section class="m3-card secondary"> <section class="m3-card secondary">
<div class="vol-header"><md-icon>campaign</md-icon><span>Exterior</span></div> <div class="vol-header"><md-icon>campaign</md-icon><span>Exterior</span></div>
<p style="margin:0; opacity:0.7; font-size:0.9rem;">Configuración de letrero y megafonía externa para paradas. <p style="margin:0; opacity:0.7; font-size:0.9rem;">Configuración de letrero y megafonía externa.</p>
</p>
<md-filled-tonal-button id="btn-abrir-exterior"> <md-filled-tonal-button id="btn-abrir-exterior">
<md-icon slot="icon">open_in_new</md-icon>Configurar Exterior <md-icon slot="icon">open_in_new</md-icon>Configurar Exterior
</md-filled-tonal-button> </md-filled-tonal-button>
@@ -79,20 +79,13 @@
<md-slider id="vol" min="0" max="1" step="0.01" value="0.8"></md-slider> <md-slider id="vol" min="0" max="1" step="0.01" value="0.8"></md-slider>
</section> </section>
<section class="m3-card editor-card"> <section class="m3-card map-card" style="grid-column: span 2; min-height: 400px; padding: 0; overflow: hidden; position: relative;">
<div class="vol-header"><md-icon>edit_note</md-icon><span>Editor de Líneas</span></div> <div class="vol-header" style="position: absolute; top: 16px; left: 16px; z-index: 1000; background: rgba(255,255,255,0.8); padding: 4px 12px; border-radius: 20px; backdrop-filter: blur(4px);">
<div class="editor-controls"> <md-icon>map</md-icon><span>Mapa de Red TsSAEx</span>
<md-outlined-text-field id="ed-id-linea" label="ID Línea (ej. L1)"></md-outlined-text-field>
<md-outlined-text-field id="ed-nombre-linea" label="Nombre (ej. Línea 1)"></md-outlined-text-field>
</div> </div>
<div id="lista-paradas-editor"></div> <div id="map" style="width: 100%; height: 100%; min-height: 400px;"></div>
<div class="editor-actions">
<md-filled-tonal-button id="btn-add-parada-ed"><md-icon slot="icon">add</md-icon>Añadir
Parada</md-filled-tonal-button>
<md-filled-button id="btn-generar-json">Exportar JSON</md-filled-button>
</div>
<pre id="output-json" class="json-preview"></pre>
</section> </section>
</div> </div>
<md-dialog id="dialog-exterior"> <md-dialog id="dialog-exterior">

153
package-lock.json generated
View File

@@ -9,7 +9,8 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@fontsource/roboto": "^5.2.9", "@fontsource/roboto": "^5.2.9",
"@material/web": "^2.4.1" "@material/web": "^2.4.1",
"leaflet": "^1.9.4"
}, },
"devDependencies": { "devDependencies": {
"vite": "^8.0.0-beta.13" "vite": "^8.0.0-beta.13"
@@ -104,9 +105,9 @@
} }
}, },
"node_modules/@oxc-project/runtime": { "node_modules/@oxc-project/runtime": {
"version": "0.112.0", "version": "0.113.0",
"resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.112.0.tgz", "resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.113.0.tgz",
"integrity": "sha512-4vYtWXMnXM6EaweCxbJ6bISAhkNHeN33SihvuX3wrpqaSJA4ZEoW35i9mSvE74+GDf1yTeVE+aEHA+WBpjDk/g==", "integrity": "sha512-apRWH/gXeAsl/sQiblIZnLu7f8P/C9S2fJIicuHV9KOK9J7Hv1JPyTwB8WAcOrDBfjs+cbzjMOGe9UR2ue4ZQg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -114,9 +115,9 @@
} }
}, },
"node_modules/@oxc-project/types": { "node_modules/@oxc-project/types": {
"version": "0.112.0", "version": "0.113.0",
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.112.0.tgz", "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.113.0.tgz",
"integrity": "sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ==", "integrity": "sha512-Tp3XmgxwNQ9pEN9vxgJBAqdRamHibi76iowQ38O2I4PMpcvNRQNVsU2n1x1nv9yh0XoTrGFzf7cZSGxmixxrhA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"funding": { "funding": {
@@ -124,9 +125,9 @@
} }
}, },
"node_modules/@rolldown/binding-android-arm64": { "node_modules/@rolldown/binding-android-arm64": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.4.tgz",
"integrity": "sha512-0T1k9FinuBZ/t7rZ8jN6OpUKPnUjNdYHoj/cESWrQ3ZraAJ4OMm6z7QjSfCxqj8mOp9kTKc1zHK3kGz5vMu+nQ==", "integrity": "sha512-vRq9f4NzvbdZavhQbjkJBx7rRebDKYR9zHfO/Wg486+I7bSecdUapzCm5cyXoK+LHokTxgSq7A5baAXUZkIz0w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -141,9 +142,9 @@
} }
}, },
"node_modules/@rolldown/binding-darwin-arm64": { "node_modules/@rolldown/binding-darwin-arm64": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.4.tgz",
"integrity": "sha512-JWWLzvcmc/3pe7qdJqPpuPk91SoE/N+f3PcWx/6ZwuyDVyungAEJPvKm/eEldiDdwTmaEzWfIR+HORxYWrCi1A==", "integrity": "sha512-kFgEvkWLqt3YCgKB5re9RlIrx9bRsvyVUnaTakEpOPuLGzLpLapYxE9BufJNvPg8GjT6mB1alN4yN1NjzoeM8Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -158,9 +159,9 @@
} }
}, },
"node_modules/@rolldown/binding-darwin-x64": { "node_modules/@rolldown/binding-darwin-x64": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.4.tgz",
"integrity": "sha512-MTakBxfx3tde5WSmbHxuqlDsIW0EzQym+PJYGF4P6lG2NmKzi128OGynoFUqoD5ryCySEY85dug4v+LWGBElIw==", "integrity": "sha512-JXmaOJGsL/+rsmMfutcDjxWM2fTaVgCHGoXS7nE8Z3c9NAYjGqHvXrAhMUZvMpHS/k7Mg+X7n/MVKb7NYWKKww==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -175,9 +176,9 @@
} }
}, },
"node_modules/@rolldown/binding-freebsd-x64": { "node_modules/@rolldown/binding-freebsd-x64": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.4.tgz",
"integrity": "sha512-jje3oopyOLs7IwfvXoS6Lxnmie5JJO7vW29fdGFu5YGY1EDbVDhD+P9vDihqS5X6fFiqL3ZQZCMBg6jyHkSVww==", "integrity": "sha512-ep3Catd6sPnHTM0P4hNEvIv5arnDvk01PfyJIJ+J3wVCG1eEaPo09tvFqdtcaTrkwQy0VWR24uz+cb4IsK53Qw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -192,9 +193,9 @@
} }
}, },
"node_modules/@rolldown/binding-linux-arm-gnueabihf": { "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.4.tgz",
"integrity": "sha512-A0n8P3hdLAaqzSFrQoA42p23ZKBYQOw+8EH5r15Sa9X1kD9/JXe0YT2gph2QTWvdr0CVK2BOXiK6ENfy6DXOag==", "integrity": "sha512-LwA5ayKIpnsgXJEwWc3h8wPiS33NMIHd9BhsV92T8VetVAbGe2qXlJwNVDGHN5cOQ22R9uYvbrQir2AB+ntT2w==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -209,9 +210,9 @@
} }
}, },
"node_modules/@rolldown/binding-linux-arm64-gnu": { "node_modules/@rolldown/binding-linux-arm64-gnu": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.4.tgz",
"integrity": "sha512-kWXkoxxarYISBJ4bLNf5vFkEbb4JvccOwxWDxuK9yee8lg5XA7OpvlTptfRuwEvYcOZf+7VS69Uenpmpyo5Bjw==", "integrity": "sha512-AC1WsGdlV1MtGay/OQ4J9T7GRadVnpYRzTcygV1hKnypbYN20Yh4t6O1Sa2qRBMqv1etulUknqXjc3CTIsBu6A==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -226,9 +227,9 @@
} }
}, },
"node_modules/@rolldown/binding-linux-arm64-musl": { "node_modules/@rolldown/binding-linux-arm64-musl": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.4.tgz",
"integrity": "sha512-Z03/wrqau9Bicfgb3Dbs6SYTHliELk2PM2LpG2nFd+cGupTMF5kanLEcj2vuuJLLhptNyS61rtk7SOZ+lPsTUA==", "integrity": "sha512-lU+6rgXXViO61B4EudxtVMXSOfiZONR29Sys5VGSetUY7X8mg9FCKIIjcPPj8xNDeYzKl+H8F/qSKOBVFJChCQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -243,9 +244,9 @@
} }
}, },
"node_modules/@rolldown/binding-linux-x64-gnu": { "node_modules/@rolldown/binding-linux-x64-gnu": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.4.tgz",
"integrity": "sha512-iSXXZsQp08CSilff/DCTFZHSVEpEwdicV3W8idHyrByrcsRDVh9sGC3sev6d8BygSGj3vt8GvUKBPCoyMA4tgQ==", "integrity": "sha512-DZaN1f0PGp/bSvKhtw50pPsnln4T13ycDq1FrDWRiHmWt1JeW+UtYg9touPFf8yt993p8tS2QjybpzKNTxYEwg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -260,9 +261,9 @@
} }
}, },
"node_modules/@rolldown/binding-linux-x64-musl": { "node_modules/@rolldown/binding-linux-x64-musl": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.4.tgz",
"integrity": "sha512-qaj+MFudtdCv9xZo9znFvkgoajLdc+vwf0Kz5N44g+LU5XMe+IsACgn3UG7uTRlCCvhMAGXm1XlpEA5bZBrOcw==", "integrity": "sha512-RnGxwZLN7fhMMAItnD6dZ7lvy+TI7ba+2V54UF4dhaWa/p8I/ys1E73KO6HmPmgz92ZkfD8TXS1IMV8+uhbR9g==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -277,9 +278,9 @@
} }
}, },
"node_modules/@rolldown/binding-openharmony-arm64": { "node_modules/@rolldown/binding-openharmony-arm64": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.4.tgz",
"integrity": "sha512-U662UnMETyjT65gFmG9ma+XziENrs7BBnENi/27swZPYagubfHRirXHG2oMl+pEax2WvO7Kb9gHZmMakpYqBHQ==", "integrity": "sha512-6lcI79+X8klGiGd8yHuTgQRjuuJYNggmEml+RsyN596P23l/zf9FVmJ7K0KVKkFAeYEdg0iMUKyIxiV5vebDNQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -294,9 +295,9 @@
} }
}, },
"node_modules/@rolldown/binding-wasm32-wasi": { "node_modules/@rolldown/binding-wasm32-wasi": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.4.tgz",
"integrity": "sha512-gekrQ3Q2HiC1T5njGyuUJoGpK/l6B/TNXKed3fZXNf9YRTJn3L5MOZsFBn4bN2+UX+8+7hgdlTcEsexX988G4g==", "integrity": "sha512-wz7ohsKCAIWy91blZ/1FlpPdqrsm1xpcEOQVveWoL6+aSPKL4VUcoYmmzuLTssyZxRpEwzuIxL/GDsvpjaBtOw==",
"cpu": [ "cpu": [
"wasm32" "wasm32"
], ],
@@ -311,9 +312,9 @@
} }
}, },
"node_modules/@rolldown/binding-win32-arm64-msvc": { "node_modules/@rolldown/binding-win32-arm64-msvc": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.4.tgz",
"integrity": "sha512-85y5JifyMgs8m5K2XzR/VDsapKbiFiohl7s5lEj7nmNGO0pkTXE7q6TQScei96BNAsoK7JC3pA7ukA8WRHVJpg==", "integrity": "sha512-cfiMrfuWCIgsFmcVG0IPuO6qTRHvF7NuG3wngX1RZzc6dU8FuBFb+J3MIR5WrdTNozlumfgL4cvz+R4ozBCvsQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -328,9 +329,9 @@
} }
}, },
"node_modules/@rolldown/binding-win32-x64-msvc": { "node_modules/@rolldown/binding-win32-x64-msvc": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.4.tgz",
"integrity": "sha512-a4VUQZH7LxGbUJ3qJ/TzQG8HxdHvf+jOnqf7B7oFx1TEBm+j2KNL2zr5SQ7wHkNAcaPevF6gf9tQnVBnC4mD+A==", "integrity": "sha512-p6UeR9y7ht82AH57qwGuFYn69S6CZ7LLKdCKy/8T3zS9VTrJei2/CGsTUV45Da4Z9Rbhc7G4gyWQ/Ioamqn09g==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -345,9 +346,9 @@
} }
}, },
"node_modules/@rolldown/pluginutils": { "node_modules/@rolldown/pluginutils": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.4.tgz",
"integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", "integrity": "sha512-1BrrmTu0TWfOP1riA8uakjFc9bpIUGzVKETsOtzY39pPga8zELGDl8eu1Dx7/gjM5CAz14UknsUMpBO8L+YntQ==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
@@ -411,6 +412,12 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0" "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
} }
}, },
"node_modules/leaflet": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
"license": "BSD-2-Clause"
},
"node_modules/lightningcss": { "node_modules/lightningcss": {
"version": "1.31.1", "version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz",
@@ -773,14 +780,14 @@
} }
}, },
"node_modules/rolldown": { "node_modules/rolldown": {
"version": "1.0.0-rc.3", "version": "1.0.0-rc.4",
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.3.tgz", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.4.tgz",
"integrity": "sha512-Po/YZECDOqVXjIXrtC5h++a5NLvKAQNrd9ggrIG3sbDfGO5BqTUsrI6l8zdniKRp3r5Tp/2JTrXqx4GIguFCMw==", "integrity": "sha512-V2tPDUrY3WSevrvU2E41ijZlpF+5PbZu4giH+VpNraaadsJGHa4fR6IFwsocVwEXDoAdIv5qgPPxgrvKAOIPtA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@oxc-project/types": "=0.112.0", "@oxc-project/types": "=0.113.0",
"@rolldown/pluginutils": "1.0.0-rc.3" "@rolldown/pluginutils": "1.0.0-rc.4"
}, },
"bin": { "bin": {
"rolldown": "bin/cli.mjs" "rolldown": "bin/cli.mjs"
@@ -789,19 +796,19 @@
"node": "^20.19.0 || >=22.12.0" "node": "^20.19.0 || >=22.12.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@rolldown/binding-android-arm64": "1.0.0-rc.3", "@rolldown/binding-android-arm64": "1.0.0-rc.4",
"@rolldown/binding-darwin-arm64": "1.0.0-rc.3", "@rolldown/binding-darwin-arm64": "1.0.0-rc.4",
"@rolldown/binding-darwin-x64": "1.0.0-rc.3", "@rolldown/binding-darwin-x64": "1.0.0-rc.4",
"@rolldown/binding-freebsd-x64": "1.0.0-rc.3", "@rolldown/binding-freebsd-x64": "1.0.0-rc.4",
"@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.3", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.4",
"@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.3", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.4",
"@rolldown/binding-linux-arm64-musl": "1.0.0-rc.3", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.4",
"@rolldown/binding-linux-x64-gnu": "1.0.0-rc.3", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.4",
"@rolldown/binding-linux-x64-musl": "1.0.0-rc.3", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.4",
"@rolldown/binding-openharmony-arm64": "1.0.0-rc.3", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.4",
"@rolldown/binding-wasm32-wasi": "1.0.0-rc.3", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.4",
"@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.3", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.4",
"@rolldown/binding-win32-x64-msvc": "1.0.0-rc.3" "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.4"
} }
}, },
"node_modules/source-map-js": { "node_modules/source-map-js": {
@@ -838,18 +845,18 @@
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "8.0.0-beta.13", "version": "8.0.0-beta.14",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.0-beta.13.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.0-beta.14.tgz",
"integrity": "sha512-7s/rfpYOAo7WUHh9irzaGjhhKb12hGv0BpDegAMV5A391wdyvM45WtX6VMV7hvEtZF2j/QtpDpR6ldXI3GgARQ==", "integrity": "sha512-oLW66oi8tZcoxu6+1HFXb+5hLHco3OnEVu2Awmj5NqEo7vxaqybjBM0BXHcq+jAFhzkMGXJl8xcO5qDBczgKLg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@oxc-project/runtime": "0.112.0", "@oxc-project/runtime": "0.113.0",
"fdir": "^6.5.0", "fdir": "^6.5.0",
"lightningcss": "^1.31.1", "lightningcss": "^1.31.1",
"picomatch": "^4.0.3", "picomatch": "^4.0.3",
"postcss": "^8.5.6", "postcss": "^8.5.6",
"rolldown": "1.0.0-rc.3", "rolldown": "1.0.0-rc.4",
"tinyglobby": "^0.2.15" "tinyglobby": "^0.2.15"
}, },
"bin": { "bin": {
@@ -866,7 +873,7 @@
}, },
"peerDependencies": { "peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0", "@types/node": "^20.19.0 || >=22.12.0",
"@vitejs/devtools": "^0.0.0-alpha.24", "@vitejs/devtools": "^0.0.0-alpha.31",
"esbuild": "^0.27.0", "esbuild": "^0.27.0",
"jiti": ">=1.21.0", "jiti": ">=1.21.0",
"less": "^4.0.0", "less": "^4.0.0",

View File

@@ -16,6 +16,7 @@
}, },
"dependencies": { "dependencies": {
"@fontsource/roboto": "^5.2.9", "@fontsource/roboto": "^5.2.9",
"@material/web": "^2.4.1" "@material/web": "^2.4.1",
"leaflet": "^1.9.4"
} }
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/audio/bda_carmen.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
public/audio/cardenas.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
public/audio/don_bosco.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/audio/linea_L2.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/audio/linea_L3.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/audio/linea_L4.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/audio/linea_L8.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/audio/orden_baja.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/audio/y.wav Normal file

Binary file not shown.

View File

@@ -11,6 +11,38 @@
"L3": { "L3": {
"nombre": "Línea 3", "nombre": "Línea 3",
"destinos": ["Zafra", "Orden Baja"] "destinos": ["Zafra", "Orden Baja"]
},
"L3CE": {
"nombre": "Línea 3CE",
"destinos": ["Zafra", "Orden Baja"]
},
"L4": {
"nombre": "Línea 4",
"destinos": ["Zafra", "Orden Baja"]
},
"L4CE": {
"nombre": "Línea 4CE",
"destinos": ["Zafra", "Orden Baja"]
},
"L5": {
"nombre": "Línea 5",
"destinos": ["Zafra", "Hospital JRJ"]
},
"L6": {
"nombre": "Línea 6",
"destinos": ["Zafra", "Hospital JRJ"]
},
"L7": {
"nombre": "Línea 7",
"destinos": ["Zafra", "Hospital JRJ"]
},
"L7HP": {
"nombre": "Línea 7HP",
"destinos": ["Zafra", "Hospital JRJ"]
},
"L8": {
"nombre": "Línea 8",
"destinos": ["Zafra", "Orden Baja"]
} }
} }
} }

View File

@@ -2,484 +2,57 @@
"L1": { "L1": {
"nombre": "Línea 1", "nombre": "Línea 1",
"paradas": [ "paradas": [
{ { "id": "zafra", "nombre": "Zafra", "enlaces": ["todas"], "coords": [37.2548, -6.9531] },
"id": "zafra", { "id": "caro_baroja", "nombre": "Julio Caro Baroja (Aqualon)", "enlaces": [], "coords": [37.2585, -6.9556] },
"nombre": "Zafra", { "id": "alemania_ruiz_alda", "nombre": "Avda. Alemania (Ruiz de Alda)", "enlaces": [], "coords": [37.2628, -6.9535] },
"enlaces": [ { "id": "alemania_plaza_toros", "nombre": "Avda. Alemania (Plaza de Toros)", "enlaces": [], "coords": [37.2671, -6.9532] },
"todas" { "id": "bda_navidad", "nombre": "Bda. Navidad", "enlaces": [], "coords": [37.2721, -6.9575] },
] { "id": "don_bosco", "nombre": "Don Bosco", "enlaces": [], "coords": [37.2715, -6.9525] },
}, { "id": "plaza_dolores", "nombre": "Plaza de los Dolores", "enlaces": [], "coords": [37.2724, -6.9495] },
{ { "id": "bda_carmen", "nombre": "Barriada del Carmen", "enlaces": [], "coords": [37.2750, -6.9498] },
"id": "caro_baroja", { "id": "humilladero", "nombre": "Humilladero", "enlaces": [], "coords": [37.2798, -6.9501] },
"nombre": "Julio Caro Baroja (Aqualon)", { "id": "cardenas", "nombre": "Cardeñas", "enlaces": [], "coords": [37.2842, -6.9485] },
"enlaces": [] { "id": "orden_baja", "nombre": "Orden Baja", "enlaces": ["L2", "L3", "L4", "L8"], "coords": [37.2785, -6.9492] },
}, { "id": "gonzalo_berceo", "nombre": "Gonzalo de Berceo", "enlaces": ["L8"], "coords": [37.2762, -6.9442] },
{ { "id": "plaza_nino_miguel", "nombre": "Plaza Niño Miguel", "enlaces": [], "coords": [37.2748, -6.9385] },
"id": "alemania_ruiz_alda", { "id": "magnolia", "nombre": "Magnolia", "enlaces": ["L7"], "coords": [37.2725, -6.9358] },
"nombre": "Avda. Alemania (Ruiz de Alda)", { "id": "hospital_jrj", "nombre": "Hospital Juan Ramón Jiménez", "enlaces": [], "coords": [37.2728, -6.9315] },
"enlaces": [] { "id": "plaza_amapolas", "nombre": "Plaza las Amapolas", "enlaces": [], "coords": [37.2695, -6.9328] },
}, { "id": "andalucia_castano", "nombre": "Av. Andalucía (Castaño Robledo)", "enlaces": [], "coords": [37.2682, -6.9378] },
{ { "id": "monumento_futbol", "nombre": "Monumento al Fútbol", "enlaces": [], "coords": [37.2655, -6.9405] },
"id": "alemania_plaza_toros", { "id": "relaciones_laborales", "nombre": "Relaciones Laborales (Univ.)", "enlaces": [], "coords": [37.2678, -6.9285] },
"nombre": "Avda. Alemania (Plaza de Toros)", { "id": "vista_alegre", "nombre": "Vista Alegre-Universidad", "enlaces": [], "coords": [37.2685, -6.9225] },
"enlaces": [] { "id": "holea", "nombre": "Centro Comercial Holea", "enlaces": [], "coords": [37.2698, -6.9185] },
}, { "id": "cruce_romeralejo", "nombre": "Cruce Romeralejo", "enlaces": [], "coords": [37.2652, -6.9155] },
{ { "id": "universidad_artes", "nombre": "Univ. Avenida de las Artes", "enlaces": [], "coords": [37.2605, -6.9188] },
"id": "bda_navidad", { "id": "palacio_deportes", "nombre": "Palacio de Deportes", "enlaces": [], "coords": [37.2575, -6.9245] },
"nombre": "Bda. Navidad", { "id": "higueral", "nombre": "Higueral (Fuerzas Armadas)", "enlaces": [], "coords": [37.2588, -6.9312] },
"enlaces": [] { "id": "bda_jose_antonio", "nombre": "Bda. José Antonio", "enlaces": [], "coords": [37.2562, -6.9352] },
}, { "id": "isla_chica", "nombre": "Isla Chica", "enlaces": ["L3", "L5", "L6"], "coords": [37.2545, -6.9382] },
{ { "id": "las_delicias", "nombre": "Las Delicias", "enlaces": [], "coords": [37.2528, -6.9425] },
"id": "don_bosco", { "id": "el_arbol", "nombre": "El Árbol", "enlaces": [], "coords": [37.2512, -6.9465] },
"nombre": "Don Bosco", { "id": "gasolinera", "nombre": "Gasolinera", "enlaces": [], "coords": [37.2498, -6.9495] },
"enlaces": [] { "id": "estacion_ffcc", "nombre": "Estación de Ferrocarril", "enlaces": ["L2", "L8"], "coords": [37.2485, -6.9452] },
}, { "id": "punto", "nombre": "El Punto", "enlaces": ["L2"], "coords": [37.2525, -6.9472] },
{ { "id": "estacion_sevilla", "nombre": "Estación de Sevilla", "enlaces": [], "coords": [37.2515, -6.9515] },
"id": "plaza_dolores", { "id": "nuevo_mercado", "nombre": "Nuevo Mercado", "enlaces": ["L2"], "coords": [37.2535, -6.9545] }
"nombre": "Plaza de los Dolores",
"enlaces": []
},
{
"id": "bda_carmen",
"nombre": "Barriada del Carmen",
"enlaces": []
},
{
"id": "humilladero",
"nombre": "Humilladero",
"enlaces": []
},
{
"id": "cardenas",
"nombre": "Cardeñas",
"enlaces": []
},
{
"id": "orden_baja",
"nombre": "Orden Baja",
"enlaces": [
"L2",
"L3",
"L4",
"L8"
]
},
{
"id": "gonzalo_berceo",
"nombre": "Gonzalo de Berceo",
"enlaces": [
"L8"
]
},
{
"id": "plaza_nino_miguel",
"nombre": "Plaza Niño Miguel",
"enlaces": []
},
{
"id": "magnolia",
"nombre": "Magnolia",
"enlaces": [
"L7"
]
},
{
"id": "hospital_jrj",
"nombre": "Hospital Juan Ramón Jiménez",
"enlaces": [
""
]
},
{
"id": "plaza_amapolas",
"nombre": "Plaza las Amapolas",
"enlaces": []
},
{
"id": "andalucia_castano",
"nombre": "Av. Andalucía (Castaño Robledo)",
"enlaces": []
},
{
"id": "monumento_futbol",
"nombre": "Monumento al Fútbol",
"enlaces": []
},
{
"id": "relaciones_laborales",
"nombre": "Relaciones Laborales (Univ.)",
"enlaces": []
},
{
"id": "vista_alegre",
"nombre": "Vista Alegre-Universidad",
"enlaces": []
},
{
"id": "holea",
"nombre": "Centro Comercial Holea",
"enlaces": []
},
{
"id": "cruce_romeralejo",
"nombre": "Cruce Romeralejo",
"enlaces": []
},
{
"id": "universidad_artes",
"nombre": "Univ. Avenida de las Artes",
"enlaces": []
},
{
"id": "palacio_deportes",
"nombre": "Palacio de Deportes",
"enlaces": []
},
{
"id": "higueral",
"nombre": "Higueral (Fuerzas Armadas)",
"enlaces": []
},
{
"id": "bda_jose_antonio",
"nombre": "Bda. José Antonio",
"enlaces": []
},
{
"id": "isla_chica",
"nombre": "Isla Chica",
"enlaces": [
"L3",
"L5",
"L6"
]
},
{
"id": "las_delicias",
"nombre": "Las Delicias",
"enlaces": []
},
{
"id": "el_arbol",
"nombre": "El Árbol",
"enlaces": []
},
{
"id": "gasolinera",
"nombre": "Gasolinera",
"enlaces": []
},
{
"id": "estacion_ffcc",
"nombre": "Estación de Ferrocarril",
"enlaces": [
"L2",
"L8"
]
},
{
"id": "punto",
"nombre": "El Punto",
"enlaces": [
"L2"
]
},
{
"id": "estacion_sevilla",
"nombre": "Estación de Sevilla",
"enlaces": []
},
{
"id": "nuevo_mercado",
"nombre": "Nuevo Mercado",
"enlaces": [
"L2"
]
}
] ]
}, },
"L2": { "L2": {
"nombre": "Línea 2", "nombre": "Línea 2",
"paradas": [ "paradas": [
{ { "id": "zafra", "nombre": "Zafra", "enlaces": ["todas"], "coords": [37.2548, -6.9531] },
"id": "zafra", { "id": "nuevo-mercado", "nombre": "Nuevo Mercado", "enlaces": ["L6"], "coords": [37.2535, -6.9545] },
"nombre": "Zafra", { "id": "villa-madrid", "nombre": "Villa de Madrid", "enlaces": ["L6"], "coords": [37.2518, -6.9562] },
"enlaces": [ { "id": "avenida-italia", "nombre": "Avenida Italia Estación de Sevilla", "enlaces": ["L6"], "coords": [37.2515, -6.9515] },
"todas" { "id": "el-punto", "nombre": "El Punto", "enlaces": ["L6"], "coords": [37.2525, -6.9472] },
] { "id": "estacion-ferrocarril", "nombre": "Estación de Ferrocarril", "enlaces": ["L1", "L5", "L6", "L8"], "coords": [37.2485, -6.9452] },
}, { "id": "barrio-obrero", "nombre": "Barrio Obrero", "enlaces": [], "coords": [37.2548, -6.9362] },
{ { "id": "isla-chica", "nombre": "Isla Chica", "enlaces": ["L4"], "coords": [37.2545, -6.9382] },
"id": "nuevo-mercado", { "id": "hospital", "nombre": "Hospital JRJ", "enlaces": ["L1", "L8"], "coords": [37.2728, -6.9315] },
"nombre": "Nuevo Mercado", { "id": "orden-alta", "nombre": "Orden Alta", "enlaces": ["L4"], "coords": [37.2782, -6.9422] },
"enlaces": [ { "id": "molino-vega", "nombre": "Molino de la Vega", "enlaces": ["L3", "L4", "L6"], "coords": [37.2612, -6.9555] },
"L6" { "id": "zafra_fin", "id_real": "zafra", "nombre": "Zafra", "enlaces": ["todas"], "coords": [37.2548, -6.9531] }
]
},
{
"id": "villa-madrid",
"nombre": "Villa de Madrid",
"enlaces": [
"L6"
]
},
{
"id": "avenida-italia",
"nombre": "Avenida Italia Estación de Sevilla",
"enlaces": [
"L6"
]
},
{
"id": "el-punto",
"nombre": "El Punto",
"enlaces": [
"L6"
]
},
{
"id": "estacion-ferrocarril",
"nombre": "Estación de Ferrocarril",
"enlaces": [
"L1",
"L5",
"L6",
"L7",
"L7H",
"L7HP",
"L8"
]
},
{
"id": "juzgados",
"nombre": "Juzgados",
"enlaces": [
"L6"
]
},
{
"id": "barrio-obrero",
"nombre": "Barrio Obrero",
"enlaces": []
},
{
"id": "el-porvenir",
"nombre": "El Porvenir",
"enlaces": [
"L4"
]
},
{
"id": "las-delicias",
"nombre": "Las Delicias",
"enlaces": [
"L4"
]
},
{
"id": "isla-chica",
"nombre": "Isla Chica",
"enlaces": [
"L4"
]
},
{
"id": "jose-antonio",
"nombre": "Bda. José Antonio",
"enlaces": []
},
{
"id": "fuerzas-armadas",
"nombre": "Fuerzas Armadas Los Rosales",
"enlaces": []
},
{
"id": "palacio-deportes",
"nombre": "Palacio de Deportes",
"enlaces": [
"L6"
]
},
{
"id": "ciencias-educacion",
"nombre": "Ciencias de la Educación (Universidad)",
"enlaces": []
},
{
"id": "biblioteca-universidad",
"nombre": "Biblioteca (Universidad)",
"enlaces": []
},
{
"id": "monumento-futbol",
"nombre": "Monumento al Fútbol",
"enlaces": [
"L1",
"L7",
"L7H",
"L7HP"
]
},
{
"id": "relaciones-laborales",
"nombre": "Relaciones Laborales (Universidad)",
"enlaces": [
"L1",
"L6",
"L7",
"L7H",
"L7HP"
]
},
{
"id": "vista-alegre",
"nombre": "Vista Alegre-Universidad",
"enlaces": [
"L1",
"L5",
"L6",
"L7",
"L7H",
"L7HP"
]
},
{
"id": "holea",
"nombre": "Centro Comercial Holea",
"enlaces": [
"L1",
"L5",
"L6",
"L7",
"L7H",
"L7HP"
]
},
{
"id": "plaza-amapolas",
"nombre": "Plaza las Amapolas",
"enlaces": [
"L6",
"L7",
"L7H",
"L7HP"
]
},
{
"id": "hospital",
"nombre": "Hospital JRJ",
"enlaces": [
"L1",
"L5",
"L6",
"L7",
"L7H",
"L7HP",
"L8"
]
},
{
"id": "magnolia",
"nombre": "Magnolia",
"enlaces": [
"L8"
]
},
{
"id": "orden-alta",
"nombre": "Orden Alta",
"enlaces": [
"L4"
]
},
{
"id": "gonzalo-berceo-alto",
"nombre": "Gonzalo de Berceo (Alto)",
"enlaces": [
"L8"
]
},
{
"id": "gonzalo-berceo-bajo",
"nombre": "Gonzalo de Berceo (Bajo)",
"enlaces": [
"L8"
]
},
{
"id": "orden-baja",
"nombre": "Orden Baja",
"enlaces": [
"L1",
"L3",
"L4",
"L8"
]
},
{
"id": "legion-espanola",
"nombre": "Legión Española",
"enlaces": []
},
{
"id": "cardenas",
"nombre": "Cardeñas",
"enlaces": []
},
{
"id": "humilladero",
"nombre": "Humilladero",
"enlaces": []
},
{
"id": "barriada-carmen",
"nombre": "Barriada del Carmen",
"enlaces": []
},
{
"id": "santa-lucia",
"nombre": "Santa Lucía",
"enlaces": []
},
{
"id": "santa-eulalia",
"nombre": "Santa Eulalia",
"enlaces": []
},
{
"id": "barriada-navidad",
"nombre": "Bda. Navidad",
"enlaces": []
},
{
"id": "molino-vega",
"nombre": "Molino de la Vega",
"enlaces": [
"L3",
"L4",
"L6"
]
},
{
"id": "paseo-palmeras",
"nombre": "Paseo de las Palmeras",
"enlaces": [
"L3",
"L4",
"L6"
]
},
{
"id": "aqualon",
"nombre": "Julio Caro Baroja (Aqualon)",
"enlaces": []
},
{
"id": "zafra",
"nombre": "Zafra",
"enlaces": [
"todas"
]
}
] ]
} }
} }

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,9 +0,0 @@
export function setupCounter(element) {
let counter = 0
const setCounter = (count) => {
counter = count
element.innerHTML = `count is ${counter}`
}
element.addEventListener('click', () => setCounter(counter + 1))
setCounter(0)
}

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path fill="#F7DF1E" d="M0 0h256v256H0V0Z"></path><path d="m67.312 213.932l19.59-11.856c3.78 6.701 7.218 12.371 15.465 12.371c7.905 0 12.89-3.092 12.89-15.12v-81.798h24.057v82.138c0 24.917-14.606 36.259-35.916 36.259c-19.245 0-30.416-9.967-36.087-21.996m85.07-2.576l19.588-11.341c5.157 8.421 11.859 14.607 23.715 14.607c9.969 0 16.325-4.984 16.325-11.858c0-8.248-6.53-11.17-17.528-15.98l-6.013-2.58c-17.357-7.387-28.87-16.667-28.87-36.257c0-18.044 13.747-31.792 35.228-31.792c15.294 0 26.292 5.328 34.196 19.247l-18.732 12.03c-4.125-7.389-8.591-10.31-15.465-10.31c-7.046 0-11.514 4.468-11.514 10.31c0 7.217 4.468 10.14 14.778 14.608l6.014 2.577c20.45 8.765 31.963 17.7 31.963 37.804c0 21.654-17.012 33.51-39.867 33.51c-22.339 0-36.774-10.654-43.819-24.574"></path></svg>

Before

Width:  |  Height:  |  Size: 995 B

View File

@@ -1,124 +1,194 @@
import 'https://cdn.jsdelivr.net/npm/@material/web/all.js/+esm'; import 'https://cdn.jsdelivr.net/npm/@material/web/all.js/+esm';
import L from 'leaflet';
let dbInt = {}; let dbInt = {};
let dbExt = { lineas: {} }; // Base de datos exterior inicializada let dbExt = { lineas: {} };
let audioActual = null; let audioActual = null;
let mapa = null;
let marcadoresActuales = []; // Para limpiar el mapa al cambiar de línea
let rutaActual = null; // Para limpiar la línea trazada
const get = (id) => document.getElementById(id); const get = (id) => document.getElementById(id);
// --- 1. INICIO DEL SISTEMA --- // --- 1. MOTOR DE AUDIO ---
async function init() {
try {
const [resInt, resExt] = await Promise.all([
fetch('data/lineas.json'),
fetch('data/exterior.json')
]);
if (!resInt.ok || !resExt.ok) throw new Error("Error cargando archivos JSON");
dbInt = await resInt.json();
dbExt = await resExt.json();
const lineasHTML = Object.keys(dbInt).map(id =>
`<md-select-option value="${id}"><div slot="headline">${id}</div></md-select-option>`
).join('');
if (get('int-linea')) get('int-linea').innerHTML = lineasHTML;
if (get('ext-linea')) get('ext-linea').innerHTML = lineasHTML;
// Generar números de coche de Huelva (315-334 y 400-409)
const coches = [...Array(20).keys()].map(i => i + 315).concat([...Array(10).keys()].map(i => i + 400));
if (get('ext-coche')) {
get('ext-coche').innerHTML = coches.map(c =>
`<md-select-option value="${c}"><div slot="headline">${c}</div></md-select-option>`
).join('');
}
} catch (err) {
console.error("Error cargando DB:", err);
} finally {
const splash = get('loading-screen');
if (splash) {
splash.style.opacity = '0';
setTimeout(() => {
splash.style.display = 'none';
get('app').style.display = 'flex';
}, 500);
}
}
}
// --- 2. MOTOR DE AUDIO ---
function play(cola, volId = 'vol') { function play(cola, volId = 'vol') {
if (audioActual) { audioActual.pause(); audioActual.currentTime = 0; } if (audioActual) {
audioActual.pause();
audioActual.currentTime = 0;
}
if (!cola || cola.length === 0) return; if (!cola || cola.length === 0) return;
const item = cola.shift(); const item = cola.shift();
audioActual = new Audio(`${item.file}?cb=${Date.now()}`); const sonido = new Audio(`${item.file}?cb=${Date.now()}`);
// Usar el slider correspondiente (interior o exterior)
const slider = get(volId); const slider = get(volId);
audioActual.volume = slider ? slider.value : 0.8; sonido.volume = slider ? slider.value : 0.8;
audioActual = sonido;
audioActual.play().catch(e => console.warn("Audio no encontrado:", item.file));
audioActual.onended = () => setTimeout(() => play(cola, volId), item.gap || 400); sonido.onended = () => {
if (item.gap && item.gap > 0) {
setTimeout(() => play(cola, volId), item.gap);
} else {
play(cola, volId);
}
};
sonido.play().catch(e => {
console.warn("Audio no encontrado:", item.file);
play(cola, volId);
});
} }
// --- 3. EVENTOS PANEL INTERIOR --- // --- 2. LÓGICA DEL MAPA ---
function inicializarMapa() {
const mapContainer = get('map');
if (mapContainer && !mapa) {
mapa = L.map('map', {
zoomControl: false,
attributionControl: false
}).setView([37.2614, -6.9447], 14);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(mapa);
L.control.zoom({ position: 'bottomright' }).addTo(mapa);
}
}
function actualizarMapa(paradas) {
// 1. Limpiar elementos previos
marcadoresActuales.forEach(m => mapa.removeLayer(m));
marcadoresActuales = [];
if (rutaActual) mapa.removeLayer(rutaActual);
const puntos = [];
// 2. Crear nuevos marcadores
paradas.forEach(p => {
if (p.coords) {
const marker = L.circleMarker(p.coords, {
radius: 8,
fillColor: "#6d5e00",
color: "#ffffff",
weight: 2,
opacity: 1,
fillOpacity: 0.8
}).addTo(mapa).bindPopup(`<b>${p.nombre}</b>`);
marcadoresActuales.push(marker);
puntos.push(p.coords);
}
});
// 3. Dibujar la línea de trayecto
if (puntos.length > 0) {
rutaActual = L.polyline(puntos, {
color: '#6d5e00',
weight: 4,
opacity: 0.6,
dashArray: '10, 10'
}).addTo(mapa);
// 4. Ajustar vista para que quepa toda la línea
mapa.fitBounds(L.latLngBounds(puntos), { padding: [50, 50] });
}
}
// --- 3. INICIO Y CARGA DE DATOS ---
async function init() {
try {
const [resInt, resExt] = await Promise.all([
fetch('data/lineas.json'),
fetch('data/exterior.json')
]);
dbInt = await resInt.json();
dbExt = await resExt.json();
// Rellenar selector de línea INTERIOR
const lineasIntHTML = Object.keys(dbInt).map(id =>
`<md-select-option value="${id}"><div slot="headline">${id}</div></md-select-option>`).join('');
if (get('int-linea')) get('int-linea').innerHTML = lineasIntHTML;
// Rellenar selector de línea EXTERIOR
if (get('ext-linea')) {
const lineasExtHTML = Object.keys(dbExt.lineas).map(id =>
`<md-select-option value="${id}"><div slot="headline">${id}</div></md-select-option>`).join('');
get('ext-linea').innerHTML = lineasExtHTML;
}
// Rellenar números de coche (Huelva)
const coches = [...Array(20).keys()].map(i => i + 315).concat([...Array(10).keys()].map(i => i + 400));
if (get('ext-coche')) {
get('ext-coche').innerHTML = coches.map(c =>
`<md-select-option value="${c}"><div slot="headline">${c}</div></md-select-option>`).join('');
}
inicializarMapa();
} catch (e) {
console.error("Error cargando archivos JSON:", e);
} finally {
get('loading-screen').style.display = 'none';
get('app').style.display = 'flex';
setTimeout(() => { if (mapa) mapa.invalidateSize(); }, 250);
}
}
// --- 4. EVENTOS PANEL INTERIOR ---
get('int-linea')?.addEventListener('change', (e) => { get('int-linea')?.addEventListener('change', (e) => {
const linea = dbInt[e.target.value]; const linea = dbInt[e.target.value];
const selParada = get('int-parada'); if (linea && get('int-parada')) {
if (linea && selParada) { get('int-parada').innerHTML = linea.paradas.map(p =>
selParada.innerHTML = linea.paradas.map(p => `<md-select-option value="${p.id}"><div slot="headline">${p.nombre}</div></md-select-option>`).join('');
`<md-select-option value="${p.id}"><div slot="headline">${p.nombre}</div></md-select-option>` get('int-parada').disabled = false;
).join('');
selParada.disabled = false; // Actualizar Waypoints en el mapa
selParada.value = ""; actualizarMapa(linea.paradas);
} }
get('container-regulacion').style.display = 'none';
});
get('int-parada')?.addEventListener('change', (e) => {
const paradasReg = ['zafra', 'orden_baja', 'hospital_jrj'];
const esReg = paradasReg.includes(e.target.value);
get('container-regulacion').style.display = esReg ? 'flex' : 'none';
if (!esReg) get('chk-regulacion').checked = false;
}); });
get('btn-int')?.addEventListener('click', () => { get('btn-int')?.addEventListener('click', () => {
const lId = get('int-linea').value, pId = get('int-parada').value; const lId = get('int-linea').value;
const pId = get('int-parada').value;
if (!lId || !pId) return; if (!lId || !pId) return;
const paradaData = dbInt[lId].paradas.find(p => p.id === pId); const paradaData = dbInt[lId].paradas.find(p => p.id === pId);
const tipo = document.querySelector('md-radio[value="siguiente"]')?.checked ? "siguiente" : "actual"; const tipo = document.querySelector('md-radio[name="tipo"][checked]')?.value || "actual";
// Mover el mapa a la parada anunciada
if (paradaData.coords) {
mapa.flyTo(paradaData.coords, 16);
}
let cola = [ let cola = [
{ file: `audio/parada_${tipo}.wav`, gap: 400 }, { file: `audio/parada_${tipo}.wav`, gap: 150 },
{ file: `audio/${pId}.wav`, gap: 600 } { file: `audio/${pId}.wav`, gap: 350 }
]; ];
if (paradaData.enlaces?.length > 0) { if (paradaData.enlaces && paradaData.enlaces.length > 0) {
const enlaces = paradaData.enlaces.filter(en => en.trim() !== ""); if (paradaData.enlaces.includes("todas")) {
if (enlaces.includes("todas")) { cola.push({ file: `audio/correspondencia_todas_las_lineas.wav`, gap: 0 });
cola.push({ file: `audio/correspondencia_todas_las_lineas.wav`, gap: 400 }); } else {
} else if (enlaces.length > 0) { const enlacesFiltrados = paradaData.enlaces.filter(en => en !== lId);
cola.push({ file: `audio/${enlaces.length === 1 ? 'correspondencia_linea' : 'correspondencia_lineas'}.wav`, gap: 300 }); if (enlacesFiltrados.length > 0) {
enlaces.forEach(en => cola.push({ file: `audio/linea_${en}.wav`, gap: 300 })); const esVarios = enlacesFiltrados.length > 1;
cola.push({ file: `audio/correspondencia_linea${esVarios ? 's' : ''}.wav`, gap: 0 });
cola.push({ file: `audio/lineas_${pId}_${lId}.wav`, gap: 400 });
}
} }
} }
if (get('chk-regulacion')?.checked) cola.push({ file: `audio/parada_regulacion.wav`, gap: 400 }); if (get('chk-regulacion')?.checked) cola.push({ file: `audio/parada_regulacion.wav`, gap: 0 });
play(cola, 'vol'); play(cola, 'vol');
}); });
// --- 4. LÓGICA EXTERIOR (RESTAURADA) --- // --- 5. EVENTOS PANEL EXTERIOR ---
get('btn-abrir-exterior').onclick = () => get('dialog-exterior').show(); get('btn-abrir-exterior').onclick = () => get('dialog-exterior').show();
get('ext-linea')?.addEventListener('change', (e) => { get('ext-linea')?.addEventListener('change', (e) => {
const lineaId = e.target.value; const lineaId = e.target.value;
const destinos = dbExt.lineas[lineaId]?.destinos || []; const datosLinea = dbExt.lineas[lineaId];
const selDest = get('ext-destino'); const selDest = get('ext-destino');
if (selDest) {
selDest.innerHTML = destinos.map(d => `<md-select-option value="${d}"><div slot="headline">${d}</div></md-select-option>`).join(''); if (selDest && datosLinea) {
selDest.innerHTML = datosLinea.destinos.map(d =>
`<md-select-option value="${d}"><div slot="headline">${d}</div></md-select-option>`).join('');
selDest.disabled = false; selDest.disabled = false;
} }
}); });
@@ -131,18 +201,16 @@ get('btn-reproducir-ext')?.addEventListener('click', () => {
if (!linea || !destino || !coche) return; if (!linea || !destino || !coche) return;
const destFile = destino.toLowerCase().replace(/ /g, "_"); const destFile = destino.toLowerCase().replace(/ /g, "_");
const lineaNum = linea.replace('L', '');
// Cola exterior: Línea X -> Autobús XXX -> Destino YYY
const colaExt = [
{ file: `audio/exterior/linea_${linea}.wav`, gap: 300 },
{ file: `audio/exterior/autobus_${coche}.wav`, gap: 500 },
{ file: `audio/exterior/destino_${destFile}.wav`, gap: 300 }
];
play(colaExt, 'vol-ext'); play([
{ file: `audio/exterior/linea_${lineaNum}.wav`, gap: 100 },
{ file: `audio/exterior/autobus_${coche}.wav`, gap: 100 },
{ file: `audio/exterior/destino_${destFile}.wav`, gap: 0 }
], 'vol-ext');
}); });
// --- 5. ESPECIALES --- // --- 6. BOTONES ESPECIALES ---
get('btn-colision').onclick = () => play([{ file: `audio/colision.wav` }]); get('btn-colision').onclick = () => play([{ file: `audio/colision.wav` }]);
get('btn-hora').onclick = () => play([{ file: `audio/hora_salida.wav` }]); get('btn-hora').onclick = () => play([{ file: `audio/hora_salida.wav` }]);
get('btn-saldo').onclick = () => play([{ file: `audio/atencion_saldo.wav` }]); get('btn-saldo').onclick = () => play([{ file: `audio/atencion_saldo.wav` }]);

View File

@@ -22,15 +22,13 @@ body {
md-icon { font-family: 'Material Symbols Outlined' !important; } md-icon { font-family: 'Material Symbols Outlined' !important; }
/* --- MARCA Megafonías TsSAEx --- */ /* --- MARCA --- */
.brand-name { .brand-name {
color: var(--md-sys-color-primary); color: var(--md-sys-color-primary);
text-transform: none !important;
font-variant: normal !important;
letter-spacing: -0.5px; letter-spacing: -0.5px;
} }
/* --- SPLASH SCREEN RESPONSIVE --- */ /* --- SPLASH SCREEN --- */
#loading-screen { #loading-screen {
position: fixed; position: fixed;
inset: 0; inset: 0;
@@ -39,7 +37,6 @@ md-icon { font-family: 'Material Symbols Outlined' !important; }
justify-content: center; justify-content: center;
align-items: center; align-items: center;
z-index: 2000; z-index: 2000;
transition: opacity 0.5s ease;
} }
.loading-content { .loading-content {
@@ -47,31 +44,17 @@ md-icon { font-family: 'Material Symbols Outlined' !important; }
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
width: 90%; width: 90%;
max-width: 400px;
}
.splash-logo {
width: 100%;
max-width: 250px;
height: auto;
margin-bottom: 30px;
animation: pulse 2s infinite ease-in-out;
}
.loading-title {
font-size: 2rem;
margin-bottom: 24px;
text-align: center;
} }
.splash-logo { width: 200px; height: auto; margin-bottom: 30px; animation: pulse 2s infinite ease-in-out; }
@keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } } @keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } }
/* --- LAYOUT GRID --- */ /* --- LAYOUT PRINCIPAL (DASHBOARD) --- */
#app { #app {
display: none; /* Controlado por JS */ display: none;
flex-direction: column; flex-direction: column;
padding: 24px; padding: 24px;
max-width: 1400px; max-width: 1600px;
margin: 0 auto; margin: 0 auto;
gap: 24px; gap: 24px;
} }
@@ -80,11 +63,18 @@ md-icon { font-family: 'Material Symbols Outlined' !important; }
.dashboard-grid { .dashboard-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); /* 400px para botones, 1fr para el mapa */
grid-template-columns: 400px 1fr;
grid-template-areas:
"interior mapa"
"exterior mapa"
"especiales mapa"
"volumen mapa";
gap: 20px; gap: 20px;
align-items: start; align-items: start;
} }
/* --- TARJETAS --- */
.m3-card { .m3-card {
background-color: var(--md-sys-color-surface-container); background-color: var(--md-sys-color-surface-container);
border-radius: 28px; border-radius: 28px;
@@ -95,9 +85,32 @@ md-icon { font-family: 'Material Symbols Outlined' !important; }
box-shadow: 0 1px 3px rgba(0,0,0,0.1); box-shadow: 0 1px 3px rgba(0,0,0,0.1);
} }
/* Asignación de áreas */
.m3-card:nth-child(1) { grid-area: interior; }
.m3-card:nth-child(2) { grid-area: exterior; }
.m3-card:nth-child(3) { grid-area: especiales; }
.m3-card:nth-child(4) { grid-area: volumen; }
.m3-card.secondary { background-color: var(--md-sys-color-secondary-container); } .m3-card.secondary { background-color: var(--md-sys-color-secondary-container); }
.m3-card.specials-card { background-color: #fceee9; } .m3-card.specials-card { background-color: #fceee9; }
/* --- ESTILO ESPECÍFICO DEL MAPA --- */
.map-card {
grid-area: mapa;
padding: 0; /* Para que el mapa llegue al borde */
overflow: hidden;
height: 800px; /* Altura fija para que luzca en desktop */
position: sticky;
top: 24px;
}
#map {
width: 100%;
height: 100%;
z-index: 1;
}
/* --- CONTROLES INTERNOS --- */
.vol-header { display: flex; align-items: center; gap: 10px; font-weight: 500; opacity: 0.8; } .vol-header { display: flex; align-items: center; gap: 10px; font-weight: 500; opacity: 0.8; }
.radio-container { .radio-container {
@@ -108,53 +121,25 @@ md-icon { font-family: 'Material Symbols Outlined' !important; }
padding: 16px; padding: 16px;
border-radius: 20px; border-radius: 20px;
} }
.radio-container label { display: flex; align-items: center; gap: 12px; cursor: pointer; }
/* --- ESTILOS REGULACIÓN --- */
#container-regulacion {
/* display: none; El JS lo cambia a flex */
background: rgba(109, 94, 0, 0.08); /* Uso del color primary con baja opacidad */
padding: 12px 16px;
border-radius: 20px;
border: 1px dashed var(--md-sys-color-primary);
animation: slideIn 0.3s ease-out;
}
@keyframes slideIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
/* --- BOTONES Y ESPECIALES --- */
.button-grid-specials { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } .button-grid-specials { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.danger-btn { --md-filled-tonal-button-container-color: var(--md-sys-color-error-container); } .danger-btn { --md-filled-tonal-button-container-color: var(--md-sys-color-error-container); }
/* --- EDITOR Y DIALOG --- */ /* --- RESPONSIVIDAD --- */
.editor-controls { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; } @media (max-width: 1100px) {
.parada-row { .dashboard-grid {
display: grid; grid-template-columns: 1fr;
grid-template-columns: 1fr 1fr 1fr 40px; grid-template-areas:
gap: 8px; "mapa"
margin-top: 10px; "interior"
align-items: center; "exterior"
} "especiales"
.editor-actions { display: flex; gap: 10px; margin-top: 10px; } "volumen";
}
.dialog-layout { display: flex; flex-direction: column; gap: 16px; min-width: 300px; padding-top: 12px; } .map-card { height: 400px; position: static; }
.json-preview {
background: #1e1e1e; color: #c5e1a5; padding: 15px; border-radius: 12px;
font-size: 0.8rem; overflow-x: auto; display: none;
}
/* Responsividad extra */
@media (min-width: 1100px) {
.editor-card { grid-column: span 2; }
} }
@media (max-width: 480px) { @media (max-width: 480px) {
.dashboard-grid { grid-template-columns: 1fr; } .top-app-bar h1 { font-size: 1.6rem; }
.editor-controls { grid-template-columns: 1fr; } .m3-card { padding: 16px; border-radius: 20px; }
.parada-row { grid-template-columns: 1fr 1fr; }
.top-app-bar h1 { font-size: 1.8rem; }
} }