-
+
+
Configuración para recalcular
+
+
+
+
+
+
diff --git a/RutasDBUS/Modelos/Historial/ConfiguracionHistorialRuta.cs b/RutasDBUS/Modelos/Historial/ConfiguracionHistorialRuta.cs
new file mode 100644
index 0000000..c74b81f
--- /dev/null
+++ b/RutasDBUS/Modelos/Historial/ConfiguracionHistorialRuta.cs
@@ -0,0 +1,70 @@
+namespace RutasDBUS.Modelos.Historial;
+
+///
+/// Instantánea completa de la configuración con la que se calculó una ruta.
+///
+public sealed class ConfiguracionHistorialRuta
+{
+ public int Version { get; set; } = 1;
+ public bool? MostrarParadas { get; set; }
+ public bool UsarHorariosTeoricos { get; set; }
+ public int SegundosPorParadaBusManual { get; set; }
+ public bool ActivarRangoLineas { get; set; }
+ public int LineaMin { get; set; }
+ public int LineaMax { get; set; }
+ public List? LineasPermitidas { get; set; }
+ public bool ActivarRangoItinerarios { get; set; }
+ public int ItinerarioMin { get; set; }
+ public int ItinerarioMax { get; set; }
+ public string? FiltroSentidoItinerario { get; set; }
+ public bool ActivarRangoTransbordos { get; set; }
+ public int MinTransbordosPermitidos { get; set; }
+ public int MaxTransbordosPermitidos { get; set; }
+ public bool UsarHoraSimulada { get; set; }
+ public string? FechaSimulada { get; set; }
+ public string? HoraSimulada { get; set; }
+ public double? FactorPenalizacionDistanciaPie { get; set; }
+ public int? VersionFactorPenalizacionPie { get; set; }
+ public double? ParametroPenalizacionDistanciaPieMetros { get; set; }
+ public double? CoeficienteEsfuerzoAltura { get; set; }
+ public int? VersionCoeficienteEsfuerzo { get; set; }
+ public double? PesoTransbordoRankingMinutos { get; set; }
+ public double? FactorEquilibradoAndarBus { get; set; }
+ public int? VersionFactorEquilibrado { get; set; }
+ public bool? MostrarElevacionesRuta { get; set; }
+ public string? FuenteElevacionCalculo { get; set; }
+ public int? VersionFuenteElevacion { get; set; }
+ public int? VersionPendientes { get; set; }
+ public int? VersionColoresPendientes { get; set; }
+ public double? UmbralPendienteSubidaRuta { get; set; }
+ public double? UmbralPendienteSubidaMediaRuta { get; set; }
+ public double? UmbralPendienteSubidaFuerteRuta { get; set; }
+ public string? ColorPendienteBajadaRuta { get; set; }
+ public string? ColorPendienteLlanoRuta { get; set; }
+ public string? ColorPendienteSubidaSuaveRuta { get; set; }
+ public string? ColorPendienteSubidaMediaRuta { get; set; }
+ public string? ColorPendienteSubidaFuerteRuta { get; set; }
+ public double? UmbralPendienteBajadaRuta { get; set; }
+ public double? UmbralAlturaAlertaPendienteRutaMetros { get; set; }
+ public double? UmbralPisosPendienteRuta { get; set; }
+ public double VelocidadPieKmH { get; set; }
+ public double VelocidadBusKmH { get; set; }
+ public int ElevMaxPuntosPorTramo { get; set; }
+ public int RadioCandidatasMetros { get; set; }
+ public int? MaxCandidatasPorLado { get; set; }
+ public int? MinutosTransbordo { get; set; }
+ public int MargenTransbordoSegundos { get; set; }
+ public string? WalkProvider { get; set; }
+ public int NivelBrilloMapa { get; set; }
+ public bool UsarColorRealLineaEnItinerarios { get; set; }
+ public bool UsarOsrmParaRanking { get; set; }
+ public string? CriterioPrioritarioRuta { get; set; }
+ public string? PreferenciaEtiquetaRuta { get; set; }
+
+ public ConfiguracionHistorialRuta Clonar()
+ {
+ var copia = (ConfiguracionHistorialRuta)MemberwiseClone();
+ copia.LineasPermitidas = LineasPermitidas?.ToList();
+ return copia;
+ }
+}
diff --git a/RutasDBUS/Modelos/Historial/RegistroHistorialRuta.cs b/RutasDBUS/Modelos/Historial/RegistroHistorialRuta.cs
index a365b91..12547bb 100644
--- a/RutasDBUS/Modelos/Historial/RegistroHistorialRuta.cs
+++ b/RutasDBUS/Modelos/Historial/RegistroHistorialRuta.cs
@@ -21,6 +21,7 @@ public sealed class RegistroHistorialRuta
public double? FactorEquilibradoAndarBus { get; set; }
public bool ActivarFiltroLineas { get; set; }
public List LineasPermitidas { get; set; } = new();
+ public ConfiguracionHistorialRuta? Configuracion { get; set; }
public DateTime FechaCreacionUtc { get; set; } = DateTime.UtcNow;
public DateTime FechaActualizacionUtc { get; set; } = DateTime.UtcNow;
}
diff --git a/RutasDBUS/Modelos/RedBus/LineaBus.cs b/RutasDBUS/Modelos/RedBus/LineaBus.cs
index 5617e4d..f1e4e65 100644
--- a/RutasDBUS/Modelos/RedBus/LineaBus.cs
+++ b/RutasDBUS/Modelos/RedBus/LineaBus.cs
@@ -55,6 +55,9 @@ public class Variante
/// Código interno de la variante.
public int Codigo { get; set; }
+ /// Destino indicado por DIR_DESTINO en las expediciones del itinerario.
+ public string Destino { get; set; } = "";
+
///
/// Identificadores de trayectos que se recorren en esta variante, en orden.
///
diff --git a/RutasDBUS/Servicios/Historial/ServicioHistorialRutasCompartido.cs b/RutasDBUS/Servicios/Historial/ServicioHistorialRutasCompartido.cs
index 7762edb..c3430b1 100644
--- a/RutasDBUS/Servicios/Historial/ServicioHistorialRutasCompartido.cs
+++ b/RutasDBUS/Servicios/Historial/ServicioHistorialRutasCompartido.cs
@@ -89,6 +89,8 @@ public sealed class ServicioHistorialRutasCompartido : IHistorialRutasCompartido
existente.FactorEquilibradoAndarBus = registro.FactorEquilibradoAndarBus;
existente.ActivarFiltroLineas = registro.ActivarFiltroLineas;
existente.LineasPermitidas = NormalizarLineas(registro.LineasPermitidas).ToList();
+ if (registro.Configuracion is not null)
+ existente.Configuracion = CopiarConfiguracion(registro.Configuracion);
if (registro.FechaCreacionUtc != default)
existente.FechaCreacionUtc = registro.FechaCreacionUtc;
@@ -300,10 +302,20 @@ public sealed class ServicioHistorialRutasCompartido : IHistorialRutasCompartido
FactorEquilibradoAndarBus = item.FactorEquilibradoAndarBus,
ActivarFiltroLineas = item.ActivarFiltroLineas,
LineasPermitidas = NormalizarLineas(item.LineasPermitidas).ToList(),
+ Configuracion = item.Configuracion is null
+ ? null
+ : CopiarConfiguracion(item.Configuracion),
FechaCreacionUtc = item.FechaCreacionUtc,
FechaActualizacionUtc = item.FechaActualizacionUtc
};
+ private static ConfiguracionHistorialRuta CopiarConfiguracion(ConfiguracionHistorialRuta configuracion)
+ {
+ var copia = configuracion.Clonar();
+ copia.LineasPermitidas = NormalizarLineas(copia.LineasPermitidas).ToList();
+ return copia;
+ }
+
private static string CalcularClaveEscenario(RegistroHistorialRuta item)
{
var origenLat = Math.Round(item.OrigenLatitud, 6).ToString("0.000000", CultureInfo.InvariantCulture);
diff --git a/RutasDBUS/Servicios/RedBus/CreadorRedTransporteDbus.cs b/RutasDBUS/Servicios/RedBus/CreadorRedTransporteDbus.cs
index 62805a9..04fba2b 100644
--- a/RutasDBUS/Servicios/RedBus/CreadorRedTransporteDbus.cs
+++ b/RutasDBUS/Servicios/RedBus/CreadorRedTransporteDbus.cs
@@ -95,7 +95,7 @@ public sealed class CreadorRedTransporteDbus
var codigoVariante = ExtraerCodigoVariante(exp.IdPatronExp);
var key = $"{exp.IdRuta}|{codigoItinerario}|{sentido}|{exp.IdPatronExp}";
- if (!variantesTemp.ContainsKey(key))
+ if (!variantesTemp.TryGetValue(key, out var varianteTemp))
{
variantesTemp[key] = new VarianteTemporal
{
@@ -108,6 +108,11 @@ public sealed class CreadorRedTransporteDbus
StopIds = stopIds
};
}
+ else if (string.IsNullOrWhiteSpace(varianteTemp.Destino) &&
+ !string.IsNullOrWhiteSpace(exp.DirDestino))
+ {
+ varianteTemp.Destino = exp.DirDestino;
+ }
}
var nextTrayectoId = 1;
@@ -132,7 +137,11 @@ public sealed class CreadorRedTransporteDbus
itinerario.Sentidos.Add(sentido);
}
- var variante = new Variante { Codigo = temp.CodigoVariante };
+ var variante = new Variante
+ {
+ Codigo = temp.CodigoVariante,
+ Destino = temp.Destino?.Trim() ?? ""
+ };
var stopIdsValidos = temp.StopIds.Where(paradaById.ContainsKey).ToList();
var codigosParadas = stopIdsValidos
.Select(id => paradaById[id].Codigo)
diff --git a/RutasDBUS/wwwroot/app.css b/RutasDBUS/wwwroot/app.css
index 41b06f0..c2b8bff 100644
--- a/RutasDBUS/wwwroot/app.css
+++ b/RutasDBUS/wwwroot/app.css
@@ -55,14 +55,16 @@
.inspector-previous-point {
display: grid;
- gap: 4px;
+ gap: 5px;
margin: 7px 0 6px;
- padding: 7px 0 2px;
+ padding: 8px 0 2px;
border-top: 1px solid rgba(148, 163, 184, .25);
}
-.inspector-previous-point__distance {
- line-height: 1.3;
+.inspector-previous-point__title {
+ color: #e2e8f0;
+ font-size: .78rem;
+ font-weight: 700;
}
.inspector-previous-point__details {
@@ -74,10 +76,8 @@
line-height: 1.25;
}
-.inspector-previous-point__details > span:first-child {
+.inspector-previous-point__detail--full {
flex-basis: 100%;
- color: #cbd5e1;
- font-weight: 700;
}
.rt-inspector-place-icon {
@@ -788,12 +788,6 @@ html, body {
line-height: 1.3;
}
-.popup-itinerario-header__destination {
- margin-left: .3rem;
- color: #bae6fd;
- font-weight: 600;
-}
-
.popup-parada-body {
font-size: .8rem;
}
@@ -1374,70 +1368,59 @@ html, body {
gap: .75rem;
}
-.history-parameters-toggle {
+.history-config-mode {
display: grid;
- grid-template-columns: minmax(0, 1fr) auto;
- align-items: center;
- gap: .65rem;
- min-height: 30px;
- padding-bottom: .6rem;
+ gap: .35rem;
+ padding-bottom: .65rem;
border-bottom: 1px solid rgba(148,163,184,.2);
- color: #cbd5e1;
- cursor: pointer;
- user-select: none;
}
-.history-parameters-toggle__label {
- min-width: 0;
- font-size: .78rem;
+.history-config-mode__label {
+ color: #cbd5e1;
+ font-size: .75rem;
font-weight: 700;
}
-.history-parameters-toggle input {
- position: absolute;
- opacity: 0;
- pointer-events: none;
+.history-config-mode__options {
+ display: grid;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ gap: 2px;
+ padding: 2px;
+ border: 1px solid rgba(148,163,184,.42);
+ border-radius: 8px;
+ background: rgba(2,6,23,.58);
}
-.history-parameters-toggle__track {
- position: relative;
- width: 36px;
- height: 20px;
- border: 1px solid rgba(148,163,184,.55);
- border-radius: 999px;
- background: rgba(2,6,23,.72);
- transition: background .15s ease, border-color .15s ease;
+.history-config-mode__option {
+ min-width: 0;
+ height: 28px;
+ overflow: hidden;
+ border: 0;
+ border-radius: 6px;
+ padding: 0 .35rem;
+ background: transparent;
+ color: #94a3b8;
+ font-size: .7rem;
+ font-weight: 700;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ cursor: pointer;
}
-.history-parameters-toggle__thumb {
- position: absolute;
- top: 2px;
- left: 2px;
- width: 14px;
- height: 14px;
- border-radius: 999px;
- background: #94a3b8;
- box-shadow: 0 1px 4px rgba(0,0,0,.35);
- transition: transform .15s ease, background .15s ease;
-}
-
-.history-parameters-toggle--active {
+.history-config-mode__option:hover:not(:disabled) {
+ background: rgba(51,65,85,.72);
color: #f8fafc;
}
-.history-parameters-toggle--active .history-parameters-toggle__track {
- border-color: rgba(59,130,246,.85);
- background: rgba(37,99,235,.82);
+.history-config-mode__option--active {
+ background: #2563eb;
+ color: #fff;
+ box-shadow: 0 1px 4px rgba(0,0,0,.3);
}
-.history-parameters-toggle--active .history-parameters-toggle__thumb {
- transform: translateX(16px);
- background: #f8fafc;
-}
-
-.history-parameters-toggle:has(input:disabled) {
+.history-config-mode__option:disabled {
cursor: default;
- opacity: .6;
+ opacity: .58;
}
.history-section {
diff --git a/RutasDBUS/wwwroot/app.js b/RutasDBUS/wwwroot/app.js
index d50c7c4..e9ff6a7 100644
--- a/RutasDBUS/wwwroot/app.js
+++ b/RutasDBUS/wwwroot/app.js
@@ -7,16 +7,22 @@
};
window.initAltInspector = function (dotNetHelper) {
+ const setInspectorActive = function (active) {
+ window.rt = window.rt || {};
+ window.rt._inspectorActive = !!active;
+ dotNetHelper.invokeMethodAsync("SetInspectorActivo", !!active);
+ };
+
document.addEventListener("keydown", function (e) {
- if (e.key === "Z" || e.key === "z") dotNetHelper.invokeMethodAsync("SetInspectorActivo", true);
+ if (e.key === "Z" || e.key === "z") setInspectorActive(true);
}, true);
document.addEventListener("keyup", function (e) {
- if (e.key === "Z" || e.key === "z") dotNetHelper.invokeMethodAsync("SetInspectorActivo", false);
+ if (e.key === "Z" || e.key === "z") setInspectorActive(false);
}, true);
window.addEventListener("blur", function () {
- dotNetHelper.invokeMethodAsync("SetInspectorActivo", false);
+ setInspectorActive(false);
});
};
@@ -84,6 +90,40 @@ window.initAltInspector = function (dotNetHelper) {
window.rt = window.rt || {};
+window.rt.handleInspectorLayerClick = function (event) {
+ if (!window.rt._inspectorActive) return false;
+
+ const originalEvent = event && event.originalEvent;
+ if (originalEvent) {
+ if (originalEvent.preventDefault) originalEvent.preventDefault();
+ if (originalEvent.stopPropagation) originalEvent.stopPropagation();
+ if (originalEvent.stopImmediatePropagation) originalEvent.stopImmediatePropagation();
+ }
+
+ const alreadyHandled = !!(
+ (event && event.__rtInspectorHandled) ||
+ (originalEvent && originalEvent.__rtInspectorHandled));
+
+ if (event) event.__rtInspectorHandled = true;
+ if (originalEvent) originalEvent.__rtInspectorHandled = true;
+
+ if (!alreadyHandled && window.rt._dotNetHelper) {
+ const latLng = event && event.latlng
+ ? event.latlng
+ : event && event.target && typeof event.target.getLatLng === "function"
+ ? event.target.getLatLng()
+ : null;
+ const lat = Number(latLng && latLng.lat);
+ const lon = Number(latLng && latLng.lng);
+
+ if (Number.isFinite(lat) && Number.isFinite(lon)) {
+ window.rt._dotNetHelper.invokeMethodAsync("OnInspectorOverlayClick", lat, lon);
+ }
+ }
+
+ return true;
+};
+
window.rt.ensureRouteLayer = function () {
const map = window.__rtLeafletMap;
if (!map || !window.L) {
@@ -290,6 +330,8 @@ window.rt.drawRoute = function (id, coords, options) {
const attachRouteClick = function (line) {
line.on("click", function (e) {
try {
+ if (window.rt.handleInspectorLayerClick(e)) return;
+
if (e && e.originalEvent) {
if (e.originalEvent.preventDefault) e.originalEvent.preventDefault();
if (e.originalEvent.stopPropagation) e.originalEvent.stopPropagation();
@@ -422,6 +464,8 @@ window.rt.drawRoute = function (id, coords, options) {
segmentLine.on("mouseover", updateTooltipAtCursor);
segmentLine.on("mousemove", updateTooltipAtCursor);
segmentLine.on("click", function (e) {
+ if (window.rt.handleInspectorLayerClick(e)) return;
+
window.rt.selectElevationSegment(
id,
segmentLine,
@@ -732,12 +776,15 @@ window.rt.drawElevPoints = function (id, points, options) {
opacity: 0.92,
className: "rt-elev-tooltip"
});
- m.on("click", function (e) {
- if (!window.rt.isMobileLayout || !window.rt.isMobileLayout()) return;
- try { m.openTooltip(e && e.latlng); } catch { }
- });
}
+ m.on("click", function (e) {
+ if (window.rt.handleInspectorLayerClick(e)) return;
+ if (!showSlopeTooltips || !p || typeof p.slope !== "number" || !Number.isFinite(p.slope)) return;
+ if (!window.rt.isMobileLayout || !window.rt.isMobileLayout()) return;
+ try { m.openTooltip(e && e.latlng); } catch { }
+ });
+
m.addTo(group);
}
}
@@ -978,6 +1025,8 @@ window.rt.drawPreviewLine = function (id, coords, options) {
// ✅ Hacer la línea clicable y avisar a Blazor
line.on("click", function (e) {
try {
+ if (window.rt.handleInspectorLayerClick(e)) return;
+
if (e && e.originalEvent) {
if (e.originalEvent.preventDefault) e.originalEvent.preventDefault();
if (e.originalEvent.stopPropagation) e.originalEvent.stopPropagation();
@@ -1166,6 +1215,8 @@ window.rt.createHighlightedStopMarker = function (stop, pane, options) {
if (stop.code && window.rt._dotNetHelper) {
marker.on("click", function (event) {
try {
+ if (window.rt.handleInspectorLayerClick(event)) return;
+
if (event && event.originalEvent) {
if (event.originalEvent.preventDefault) event.originalEvent.preventDefault();
if (event.originalEvent.stopPropagation) event.originalEvent.stopPropagation();
@@ -1355,7 +1406,10 @@ window.rt.setEndpointMarker = function (kind, lat, lon, options) {
if (e.originalEvent.stopImmediatePropagation) e.originalEvent.stopImmediatePropagation();
};
- marker.on("click", stopEvent);
+ marker.on("click", function (event) {
+ if (window.rt.handleInspectorLayerClick(event)) return;
+ stopEvent(event);
+ });
marker.on("mousedown", stopEvent);
marker.on("dragend", function (e) {
@@ -1438,6 +1492,9 @@ window.rt.setInspectorMarkers = function (lat, lon, places) {
opacity: 0.95,
className: "rt-inspector-tooltip"
});
+ puntoZ.on("click", function (event) {
+ window.rt.handleInspectorLayerClick(event);
+ });
puntoZ.addTo(window.rt._inspectorLayer);
const lugares = Array.isArray(places) ? places.slice(0, 3) : [];
@@ -1510,6 +1567,9 @@ window.rt.setInspectorMarkers = function (lat, lon, places) {
opacity: 0.95,
className: "rt-inspector-tooltip"
});
+ marker.on("click", function (event) {
+ window.rt.handleInspectorLayerClick(event);
+ });
marker.addTo(window.rt._inspectorLayer);
});
};