Añadidas mejoras en rutas sugeridas, elevaciones e historial
- Añadido interruptor de elevaciones en rutas sugeridas. - Los tramos a pie mantienen la línea punteada y muestran puntos coloreados por pendiente. - Se quita el score equilibrado de las tarjetas para limpiar la vista. - Se destaca la distancia a pie también en modo Equilib. A. - El factor equilibrado se guarda y restaura desde el historial local y compartido. - Ajustes visuales y limpieza de estilos asociados.
This commit is contained in:
@@ -55,10 +55,12 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
private const double CoeficienteEsfuerzoAlturaPorDefecto = 5.2;
|
||||
private double _coeficienteEsfuerzoAltura = CoeficienteEsfuerzoAlturaPorDefecto;
|
||||
private double _pesoTransbordoRankingMinutos = 4.0;
|
||||
private double _factorEquilibradoAndarBus = 12.0;
|
||||
private string _factorPenalizacionDistanciaPieTextoEdicion = "1.60";
|
||||
private string _parametroPenalizacionDistanciaPieTextoEdicion = "100";
|
||||
private string _coeficienteEsfuerzoAlturaTextoEdicion = "5.20";
|
||||
private string _pesoTransbordoRankingTextoEdicion = "4,0";
|
||||
private string _factorEquilibradoAndarBusTextoEdicion = "12";
|
||||
private double _velocidadBusKmH = 16.0;
|
||||
private int _minutosTransbordo = 5;
|
||||
private int _margenTransbordoSegundos = 120;
|
||||
@@ -142,6 +144,25 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expone el factor que convierte metros andando a metros equivalentes de bus en el modo equilibrado.
|
||||
/// </summary>
|
||||
private string FactorEquilibradoAndarBusTexto
|
||||
{
|
||||
get => _factorEquilibradoAndarBusTextoEdicion;
|
||||
set
|
||||
{
|
||||
var texto = (value ?? "").Replace(',', '.');
|
||||
_factorEquilibradoAndarBusTextoEdicion = texto;
|
||||
|
||||
if (!double.TryParse(texto, NumberStyles.Float, CultureInfo.InvariantCulture, out var valor))
|
||||
return;
|
||||
|
||||
if (double.IsFinite(valor))
|
||||
_factorEquilibradoAndarBus = Math.Max(0, valor);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryParseDuracionMinutos(string texto, out double minutos)
|
||||
{
|
||||
minutos = 0;
|
||||
@@ -220,6 +241,7 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
_parametroPenalizacionDistanciaPieTextoEdicion = _parametroPenalizacionDistanciaPieMetros.ToString("0", CultureInfo.InvariantCulture);
|
||||
_coeficienteEsfuerzoAlturaTextoEdicion = _coeficienteEsfuerzoAltura.ToString("0.00", CultureInfo.InvariantCulture);
|
||||
_pesoTransbordoRankingTextoEdicion = FormatearDuracionMinutos(_pesoTransbordoRankingMinutos);
|
||||
_factorEquilibradoAndarBusTextoEdicion = _factorEquilibradoAndarBus.ToString("0.##", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -257,6 +279,16 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
SincronizarTextosPenalizacionPie();
|
||||
await PersistirConfiguracionAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normaliza el factor equilibrado al salir del campo.
|
||||
/// </summary>
|
||||
private async Task OnBlurFactorEquilibradoAndarBus()
|
||||
{
|
||||
SincronizarTextosPenalizacionPie();
|
||||
await PersistirConfiguracionAsync();
|
||||
await RecalcularRutaEquilibradaTrasCambioFactorAsync();
|
||||
}
|
||||
|
||||
private int _radioCandidatasMetros = 1200;
|
||||
private int _maxCandidatasPorLado = 12;
|
||||
@@ -317,6 +349,8 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
private int _indiceAlternativaSeleccionada = 0;
|
||||
private DateTime? _ultimaHoraReferenciaRuta = null;
|
||||
private TimeSpan? _tiempoUltimoCalculoRuta = null;
|
||||
private bool _mostrarElevacionesRuta = false;
|
||||
private bool _pintandoElevacionesRuta = false;
|
||||
private readonly Dictionary<string, List<Parada>> _paradasItinerarioVisiblesPorId = new(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly Dictionary<string, List<Parada>> _paradasRutaVisiblesPorId = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
@@ -1016,6 +1050,23 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private async Task DrawRouteElevationPointsJsAsync(string id, IReadOnlyList<object> points)
|
||||
{
|
||||
try
|
||||
{
|
||||
await JS.InvokeVoidAsync("rt.drawElevPoints", $"route_elev_{id}", points, new
|
||||
{
|
||||
radius = 4,
|
||||
opacity = 0.98,
|
||||
fillOpacity = 0.95,
|
||||
showLabels = false,
|
||||
showSlopeTooltips = true,
|
||||
className = "rt-route-elev-point"
|
||||
});
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ajusta rutas js.
|
||||
@@ -1168,55 +1219,6 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
+ UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaMetros(alternativa.DistanciaPieFinAprox, parametros);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Estima si una alternativa equilibrada se parece mas al criterio Tiempo o al criterio Andar.
|
||||
/// </summary>
|
||||
private string FormatearBalanceEquilibradoAlternativa(AlternativaRuta? alternativa)
|
||||
{
|
||||
if (alternativa is null || alternativa.EsSoloAPie)
|
||||
return string.Empty;
|
||||
|
||||
var alternativasBus = _opcionesRuta
|
||||
.Where(opcion => !opcion.EsSoloAPie)
|
||||
.ToList();
|
||||
|
||||
if (alternativasBus.Count < 2)
|
||||
return string.Empty;
|
||||
|
||||
var duraciones = alternativasBus
|
||||
.Select(DuracionOrdenacion)
|
||||
.Where(double.IsFinite)
|
||||
.ToList();
|
||||
|
||||
var costesAndar = alternativasBus
|
||||
.Select(CalcularCosteAndarEquilibradoSegundos)
|
||||
.Where(double.IsFinite)
|
||||
.ToList();
|
||||
|
||||
if (duraciones.Count == 0 || costesAndar.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var ventajaTiempo = CalcularVentajaNormalizada(
|
||||
DuracionOrdenacion(alternativa),
|
||||
duraciones.Min(),
|
||||
duraciones.Max());
|
||||
|
||||
var ventajaAndar = CalcularVentajaNormalizada(
|
||||
CalcularCosteAndarEquilibradoSegundos(alternativa),
|
||||
costesAndar.Min(),
|
||||
costesAndar.Max());
|
||||
|
||||
var total = ventajaTiempo + ventajaAndar;
|
||||
if (!double.IsFinite(total) || total <= 0.000001)
|
||||
return string.Empty;
|
||||
|
||||
var porcentajeTiempo = (int)Math.Round((ventajaTiempo / total) * 100.0);
|
||||
porcentajeTiempo = Math.Clamp(porcentajeTiempo, 0, 100);
|
||||
var porcentajeAndar = 100 - porcentajeTiempo;
|
||||
|
||||
return $"Tiempo {porcentajeTiempo}% / Andar {porcentajeAndar}%";
|
||||
}
|
||||
|
||||
private double CalcularCosteAndarEquilibradoSegundos(AlternativaRuta? alternativa)
|
||||
{
|
||||
if (alternativa is null)
|
||||
@@ -1229,30 +1231,70 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
return EstimarDuracionPieSegundos(distanciaCorregida);
|
||||
}
|
||||
|
||||
private static double CalcularVentajaNormalizada(double valor, double mejor, double peor)
|
||||
private double CalcularScoreEquilibradoFactor(AlternativaRuta? alternativa)
|
||||
{
|
||||
if (!double.IsFinite(valor) ||
|
||||
!double.IsFinite(mejor) ||
|
||||
!double.IsFinite(peor) ||
|
||||
peor <= mejor)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (alternativa is null || alternativa.EsSoloAPie || alternativa.AlternativaBus is null)
|
||||
return double.PositiveInfinity;
|
||||
|
||||
return Math.Clamp((peor - valor) / (peor - mejor), 0.0, 1.0);
|
||||
var distanciaBus = Math.Max(0, alternativa.AlternativaBus.DistanciaTotalBus);
|
||||
var distanciaAndando = Math.Max(0, alternativa.DistanciaPieTotalAprox);
|
||||
var factor = double.IsFinite(_factorEquilibradoAndarBus)
|
||||
? Math.Max(0, _factorEquilibradoAndarBus)
|
||||
: 12.0;
|
||||
|
||||
var score = distanciaBus + (distanciaAndando * factor);
|
||||
return double.IsFinite(score) && score >= 0
|
||||
? score
|
||||
: double.PositiveInfinity;
|
||||
}
|
||||
|
||||
private static double CalcularSacrificioNormalizado(double valor, double mejor, double peor)
|
||||
private string FormatearScoreEquilibradoAlternativa(AlternativaRuta? alternativa)
|
||||
{
|
||||
if (!double.IsFinite(valor) ||
|
||||
!double.IsFinite(mejor) ||
|
||||
!double.IsFinite(peor) ||
|
||||
peor <= mejor)
|
||||
var score = CalcularScoreEquilibradoFactor(alternativa);
|
||||
if (!double.IsFinite(score))
|
||||
return string.Empty;
|
||||
|
||||
return $"Score {FormatearDistanciaTarjeta(score)} (x{_factorEquilibradoAndarBus.ToString("0.##", CultureInfo.InvariantCulture)})";
|
||||
}
|
||||
|
||||
private string FactorEquilibradoAndarBusResumen
|
||||
=> _factorEquilibradoAndarBus.ToString("0.##", CultureInfo.InvariantCulture);
|
||||
|
||||
private async Task RecalcularRutaEquilibradaTrasCambioFactorAsync()
|
||||
{
|
||||
if (!CriterioPrioritarioEquilibradoActivo)
|
||||
return;
|
||||
|
||||
if (_mapa is not null && _coordenadasOrigen is not null && _coordenadasDestino is not null)
|
||||
{
|
||||
return 0;
|
||||
_omitirRegistroHistorialEnSiguienteCalculo = true;
|
||||
await CalcularRutaCompletaAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
return Math.Clamp((valor - mejor) / (peor - mejor), 0.0, 1.0);
|
||||
if (_opcionesRuta.Count == 0)
|
||||
{
|
||||
StateHasChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
OrdenarOpcionesRutaSegunCriterio();
|
||||
var indicePreferido = BuscarIndiceEquilibrado();
|
||||
if (indicePreferido < 0 || indicePreferido >= _opcionesRuta.Count)
|
||||
{
|
||||
StateHasChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
await CerrarTodasLasPreviewsAsync();
|
||||
_indiceAlternativaSeleccionada = indicePreferido;
|
||||
await CerrarPopupsAsync();
|
||||
ResetEstadoRuta(limpiarOpciones: false, limpiarMensaje: false);
|
||||
_mensajeRuta = "Representando ruta seleccionada...";
|
||||
StateHasChanged();
|
||||
await Task.Yield();
|
||||
await PintarOpcionRutaCompleta(_opcionesRuta[indicePreferido]);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user