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" />
<title>Megafonías TsSAEx</title>
<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 rel="preconnect" href="https://fonts.googleapis.com">
<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>
</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>
<label for="chk-regulacion">Parada de regulación</label>
</div>
@@ -49,8 +50,7 @@
<section class="m3-card secondary">
<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>
<p style="margin:0; opacity:0.7; font-size:0.9rem;">Configuración de letrero y megafonía externa.</p>
<md-filled-tonal-button id="btn-abrir-exterior">
<md-icon slot="icon">open_in_new</md-icon>Configurar Exterior
</md-filled-tonal-button>
@@ -79,20 +79,13 @@
<md-slider id="vol" min="0" max="1" step="0.01" value="0.8"></md-slider>
</section>
<section class="m3-card editor-card">
<div class="vol-header"><md-icon>edit_note</md-icon><span>Editor de Líneas</span></div>
<div class="editor-controls">
<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>
<section class="m3-card map-card" style="grid-column: span 2; min-height: 400px; padding: 0; overflow: hidden; position: relative;">
<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);">
<md-icon>map</md-icon><span>Mapa de Red TsSAEx</span>
</div>
<div id="lista-paradas-editor"></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>
<div id="map" style="width: 100%; height: 100%; min-height: 400px;"></div>
</section>
</div>
<md-dialog id="dialog-exterior">

153
package-lock.json generated
View File

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

View File

@@ -16,6 +16,7 @@
},
"dependencies": {
"@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": {
"nombre": "Línea 3",
"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": {
"nombre": "Línea 1",
"paradas": [
{
"id": "zafra",
"nombre": "Zafra",
"enlaces": [
"todas"
]
},
{
"id": "caro_baroja",
"nombre": "Julio Caro Baroja (Aqualon)",
"enlaces": []
},
{
"id": "alemania_ruiz_alda",
"nombre": "Avda. Alemania (Ruiz de Alda)",
"enlaces": []
},
{
"id": "alemania_plaza_toros",
"nombre": "Avda. Alemania (Plaza de Toros)",
"enlaces": []
},
{
"id": "bda_navidad",
"nombre": "Bda. Navidad",
"enlaces": []
},
{
"id": "don_bosco",
"nombre": "Don Bosco",
"enlaces": []
},
{
"id": "plaza_dolores",
"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"
]
}
{ "id": "zafra", "nombre": "Zafra", "enlaces": ["todas"], "coords": [37.2548, -6.9531] },
{ "id": "caro_baroja", "nombre": "Julio Caro Baroja (Aqualon)", "enlaces": [], "coords": [37.2585, -6.9556] },
{ "id": "alemania_ruiz_alda", "nombre": "Avda. Alemania (Ruiz de Alda)", "enlaces": [], "coords": [37.2628, -6.9535] },
{ "id": "alemania_plaza_toros", "nombre": "Avda. Alemania (Plaza de Toros)", "enlaces": [], "coords": [37.2671, -6.9532] },
{ "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": "humilladero", "nombre": "Humilladero", "enlaces": [], "coords": [37.2798, -6.9501] },
{ "id": "cardenas", "nombre": "Cardeñas", "enlaces": [], "coords": [37.2842, -6.9485] },
{ "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": "magnolia", "nombre": "Magnolia", "enlaces": ["L7"], "coords": [37.2725, -6.9358] },
{ "id": "hospital_jrj", "nombre": "Hospital Juan Ramón Jiménez", "enlaces": [], "coords": [37.2728, -6.9315] },
{ "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": "relaciones_laborales", "nombre": "Relaciones Laborales (Univ.)", "enlaces": [], "coords": [37.2678, -6.9285] },
{ "id": "vista_alegre", "nombre": "Vista Alegre-Universidad", "enlaces": [], "coords": [37.2685, -6.9225] },
{ "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": "palacio_deportes", "nombre": "Palacio de Deportes", "enlaces": [], "coords": [37.2575, -6.9245] },
{ "id": "higueral", "nombre": "Higueral (Fuerzas Armadas)", "enlaces": [], "coords": [37.2588, -6.9312] },
{ "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": "el_arbol", "nombre": "El Árbol", "enlaces": [], "coords": [37.2512, -6.9465] },
{ "id": "gasolinera", "nombre": "Gasolinera", "enlaces": [], "coords": [37.2498, -6.9495] },
{ "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": "nuevo_mercado", "nombre": "Nuevo Mercado", "enlaces": ["L2"], "coords": [37.2535, -6.9545] }
]
},
"L2": {
"nombre": "Línea 2",
"paradas": [
{
"id": "zafra",
"nombre": "Zafra",
"enlaces": [
"todas"
]
},
{
"id": "nuevo-mercado",
"nombre": "Nuevo Mercado",
"enlaces": [
"L6"
]
},
{
"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"
]
}
{ "id": "zafra", "nombre": "Zafra", "enlaces": ["todas"], "coords": [37.2548, -6.9531] },
{ "id": "nuevo-mercado", "nombre": "Nuevo Mercado", "enlaces": ["L6"], "coords": [37.2535, -6.9545] },
{ "id": "villa-madrid", "nombre": "Villa de Madrid", "enlaces": ["L6"], "coords": [37.2518, -6.9562] },
{ "id": "avenida-italia", "nombre": "Avenida Italia Estación de Sevilla", "enlaces": ["L6"], "coords": [37.2515, -6.9515] },
{ "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": "hospital", "nombre": "Hospital JRJ", "enlaces": ["L1", "L8"], "coords": [37.2728, -6.9315] },
{ "id": "orden-alta", "nombre": "Orden Alta", "enlaces": ["L4"], "coords": [37.2782, -6.9422] },
{ "id": "molino-vega", "nombre": "Molino de la Vega", "enlaces": ["L3", "L4", "L6"], "coords": [37.2612, -6.9555] },
{ "id": "zafra_fin", "id_real": "zafra", "nombre": "Zafra", "enlaces": ["todas"], "coords": [37.2548, -6.9531] }
]
}
}

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 L from 'leaflet';
let dbInt = {};
let dbExt = { lineas: {} }; // Base de datos exterior inicializada
let dbExt = { lineas: {} };
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);
// --- 1. INICIO DEL SISTEMA ---
// --- 1. MOTOR DE AUDIO ---
function play(cola, volId = 'vol') {
if (audioActual) {
audioActual.pause();
audioActual.currentTime = 0;
}
if (!cola || cola.length === 0) return;
const item = cola.shift();
const sonido = new Audio(`${item.file}?cb=${Date.now()}`);
const slider = get(volId);
sonido.volume = slider ? slider.value : 0.8;
audioActual = sonido;
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);
});
}
// --- 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')
]);
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('');
// 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;
if (get('int-linea')) get('int-linea').innerHTML = lineasHTML;
if (get('ext-linea')) get('ext-linea').innerHTML = lineasHTML;
// 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;
}
// Generar números de coche de Huelva (315-334 y 400-409)
// 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('');
`<md-select-option value="${c}"><div slot="headline">${c}</div></md-select-option>`).join('');
}
} catch (err) {
console.error("Error cargando DB:", err);
inicializarMapa();
} catch (e) {
console.error("Error cargando archivos JSON:", e);
} finally {
const splash = get('loading-screen');
if (splash) {
splash.style.opacity = '0';
setTimeout(() => {
splash.style.display = 'none';
get('loading-screen').style.display = 'none';
get('app').style.display = 'flex';
}, 500);
}
setTimeout(() => { if (mapa) mapa.invalidateSize(); }, 250);
}
}
// --- 2. MOTOR DE AUDIO ---
function play(cola, volId = 'vol') {
if (audioActual) { audioActual.pause(); audioActual.currentTime = 0; }
if (!cola || cola.length === 0) return;
const item = cola.shift();
audioActual = new Audio(`${item.file}?cb=${Date.now()}`);
// Usar el slider correspondiente (interior o exterior)
const slider = get(volId);
audioActual.volume = slider ? slider.value : 0.8;
audioActual.play().catch(e => console.warn("Audio no encontrado:", item.file));
audioActual.onended = () => setTimeout(() => play(cola, volId), item.gap || 400);
}
// --- 3. EVENTOS PANEL INTERIOR ---
// --- 4. EVENTOS PANEL INTERIOR ---
get('int-linea')?.addEventListener('change', (e) => {
const linea = dbInt[e.target.value];
const selParada = get('int-parada');
if (linea && selParada) {
selParada.innerHTML = linea.paradas.map(p =>
`<md-select-option value="${p.id}"><div slot="headline">${p.nombre}</div></md-select-option>`
).join('');
selParada.disabled = false;
selParada.value = "";
}
get('container-regulacion').style.display = 'none';
});
if (linea && get('int-parada')) {
get('int-parada').innerHTML = linea.paradas.map(p =>
`<md-select-option value="${p.id}"><div slot="headline">${p.nombre}</div></md-select-option>`).join('');
get('int-parada').disabled = false;
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;
// Actualizar Waypoints en el mapa
actualizarMapa(linea.paradas);
}
});
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;
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 = [
{ file: `audio/parada_${tipo}.wav`, gap: 400 },
{ file: `audio/${pId}.wav`, gap: 600 }
{ file: `audio/parada_${tipo}.wav`, gap: 150 },
{ file: `audio/${pId}.wav`, gap: 350 }
];
if (paradaData.enlaces?.length > 0) {
const enlaces = paradaData.enlaces.filter(en => en.trim() !== "");
if (enlaces.includes("todas")) {
cola.push({ file: `audio/correspondencia_todas_las_lineas.wav`, gap: 400 });
} else if (enlaces.length > 0) {
cola.push({ file: `audio/${enlaces.length === 1 ? 'correspondencia_linea' : 'correspondencia_lineas'}.wav`, gap: 300 });
enlaces.forEach(en => cola.push({ file: `audio/linea_${en}.wav`, gap: 300 }));
if (paradaData.enlaces && paradaData.enlaces.length > 0) {
if (paradaData.enlaces.includes("todas")) {
cola.push({ file: `audio/correspondencia_todas_las_lineas.wav`, gap: 0 });
} else {
const enlacesFiltrados = paradaData.enlaces.filter(en => en !== lId);
if (enlacesFiltrados.length > 0) {
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');
});
// --- 4. LÓGICA EXTERIOR (RESTAURADA) ---
// --- 5. EVENTOS PANEL EXTERIOR ---
get('btn-abrir-exterior').onclick = () => get('dialog-exterior').show();
get('ext-linea')?.addEventListener('change', (e) => {
const lineaId = e.target.value;
const destinos = dbExt.lineas[lineaId]?.destinos || [];
const datosLinea = dbExt.lineas[lineaId];
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;
}
});
@@ -131,18 +201,16 @@ get('btn-reproducir-ext')?.addEventListener('click', () => {
if (!linea || !destino || !coche) return;
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-hora').onclick = () => play([{ file: `audio/hora_salida.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; }
/* --- MARCA Megafonías TsSAEx --- */
/* --- MARCA --- */
.brand-name {
color: var(--md-sys-color-primary);
text-transform: none !important;
font-variant: normal !important;
letter-spacing: -0.5px;
}
/* --- SPLASH SCREEN RESPONSIVE --- */
/* --- SPLASH SCREEN --- */
#loading-screen {
position: fixed;
inset: 0;
@@ -39,7 +37,6 @@ md-icon { font-family: 'Material Symbols Outlined' !important; }
justify-content: center;
align-items: center;
z-index: 2000;
transition: opacity 0.5s ease;
}
.loading-content {
@@ -47,31 +44,17 @@ md-icon { font-family: 'Material Symbols Outlined' !important; }
flex-direction: column;
align-items: center;
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); } }
/* --- LAYOUT GRID --- */
/* --- LAYOUT PRINCIPAL (DASHBOARD) --- */
#app {
display: none; /* Controlado por JS */
display: none;
flex-direction: column;
padding: 24px;
max-width: 1400px;
max-width: 1600px;
margin: 0 auto;
gap: 24px;
}
@@ -80,11 +63,18 @@ md-icon { font-family: 'Material Symbols Outlined' !important; }
.dashboard-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;
align-items: start;
}
/* --- TARJETAS --- */
.m3-card {
background-color: var(--md-sys-color-surface-container);
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);
}
/* 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.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; }
.radio-container {
@@ -108,53 +121,25 @@ md-icon { font-family: 'Material Symbols Outlined' !important; }
padding: 16px;
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; }
.danger-btn { --md-filled-tonal-button-container-color: var(--md-sys-color-error-container); }
/* --- EDITOR Y DIALOG --- */
.editor-controls { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.parada-row {
display: grid;
grid-template-columns: 1fr 1fr 1fr 40px;
gap: 8px;
margin-top: 10px;
align-items: center;
}
.editor-actions { display: flex; gap: 10px; margin-top: 10px; }
.dialog-layout { display: flex; flex-direction: column; gap: 16px; min-width: 300px; padding-top: 12px; }
.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; }
/* --- RESPONSIVIDAD --- */
@media (max-width: 1100px) {
.dashboard-grid {
grid-template-columns: 1fr;
grid-template-areas:
"mapa"
"interior"
"exterior"
"especiales"
"volumen";
}
.map-card { height: 400px; position: static; }
}
@media (max-width: 480px) {
.dashboard-grid { grid-template-columns: 1fr; }
.editor-controls { grid-template-columns: 1fr; }
.parada-row { grid-template-columns: 1fr 1fr; }
.top-app-bar h1 { font-size: 1.8rem; }
.top-app-bar h1 { font-size: 1.6rem; }
.m3-card { padding: 16px; border-radius: 20px; }
}