Files
RutasDBUS/RutasDBUS/Components/Pages/PlanificadorRutas.Persistencia.cs
Pedro 402ce90a95 - panel de colores puestos en la configuracion
- oscurecido el tb6.
- ordenado el bsucador
- añadido switch de parametros en historial compartido
2026-09-01 08:07:37 +02:00

511 lines
24 KiB
C#

using System.Globalization;
using System.Text.Json;
using Microsoft.JSInterop;
using RutasDBUS.Modelos.Planificacion;
namespace RutasDBUS.Components.Pages;
public partial class PlanificadorRutas
{
private const string ClaveConfiguracionLocal = "rutasdbus.planificador.config.v1";
private const int VersionPersistenciaFactorEquilibrado = 2;
private const int VersionPersistenciaPendientes = 2;
private const int VersionPersistenciaCoeficienteEsfuerzo = 1;
private const int VersionPersistenciaFuenteElevacion = 1;
private bool _configuracionLocalCargada = false;
private bool _mostrarConfirmacionRestablecer = false;
/// <summary>
/// Instantánea persistida de la configuración del planificador.
/// </summary>
private sealed class ConfiguracionLocalPlanificador
{
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<int>? 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 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 double? UmbralPendienteSubidaRuta { get; set; }
public double? UmbralPendienteSubidaMediaRuta { get; set; }
public double? UmbralPendienteSubidaFuerteRuta { 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; }
// Compatibilidad con configuraciones guardadas cuando el umbral se expresaba en pisos.
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 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; }
}
/// <summary>
/// Carga la configuración persistida del navegador y la aplica al estado actual.
/// </summary>
private async Task CargarConfiguracionLocalAsync()
{
try
{
var json = await JS.InvokeAsync<string?>("rt.loadLocalValue", ClaveConfiguracionLocal);
if (string.IsNullOrWhiteSpace(json))
return;
var config = JsonSerializer.Deserialize<ConfiguracionLocalPlanificador>(json);
if (config is null)
return;
AplicarConfiguracionLocal(config);
}
catch (JSException)
{
}
catch (JsonException)
{
}
finally
{
_configuracionLocalCargada = true;
}
}
/// <summary>
/// Guarda la configuración actual del planificador en el navegador.
/// </summary>
private async Task PersistirConfiguracionAsync()
{
if (!_configuracionLocalCargada)
return;
try
{
if (!_usarHorariosTeoricos)
_segundosPorParadaBusManual = Math.Max(0, _segundosPorParadaBus);
var json = JsonSerializer.Serialize(CrearConfiguracionLocal());
await JS.InvokeVoidAsync("rt.saveLocalValue", ClaveConfiguracionLocal, json);
}
catch (JSException)
{
}
}
/// <summary>
/// Sincroniza el valor manual de segundos por parada y persiste la configuración.
/// </summary>
private async Task OnSegundosPorParadaBusChanged()
{
_segundosPorParadaBus = Math.Max(0, _segundosPorParadaBus);
_segundosPorParadaBusManual = _segundosPorParadaBus;
await PersistirConfiguracionAsync();
}
private async Task OnFuenteElevacionChangedAsync()
{
_fuenteElevacionCalculo = NormalizarFuenteElevacion(_fuenteElevacionCalculo);
await PersistirConfiguracionAsync();
}
/// <summary>
/// Construye la instantánea persistible a partir del estado actual.
/// </summary>
private ConfiguracionLocalPlanificador CrearConfiguracionLocal()
=> new()
{
MostrarParadas = _mostrarParadas,
UsarHorariosTeoricos = _usarHorariosTeoricos,
SegundosPorParadaBusManual = Math.Max(0, _segundosPorParadaBusManual),
ActivarRangoLineas = _activarRangoLineas,
LineaMin = _lineaMin,
LineaMax = _lineaMax,
LineasPermitidas = ObtenerLineasPermitidasSeleccionadas().ToList(),
ActivarRangoItinerarios = _activarRangoItinerarios,
ItinerarioMin = _itinerarioMin,
ItinerarioMax = _itinerarioMax,
FiltroSentidoItinerario = _filtroSentidoItinerario.ToString(),
ActivarRangoTransbordos = _activarRangoTransbordos,
MinTransbordosPermitidos = _minTransbordosPermitidos,
MaxTransbordosPermitidos = _maxTransbordosPermitidos,
UsarHoraSimulada = _usarHoraSimulada,
FechaSimulada = _fechaSimulada.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture),
HoraSimulada = _horaSimulada.ToString("HH:mm:ss", CultureInfo.InvariantCulture),
FactorPenalizacionDistanciaPie = _factorPenalizacionDistanciaPie,
ParametroPenalizacionDistanciaPieMetros = _parametroPenalizacionDistanciaPieMetros,
CoeficienteEsfuerzoAltura = _coeficienteEsfuerzoAltura,
VersionCoeficienteEsfuerzo = VersionPersistenciaCoeficienteEsfuerzo,
PesoTransbordoRankingMinutos = _pesoTransbordoRankingMinutos,
FactorEquilibradoAndarBus = _factorEquilibradoAndarBus,
VersionFactorEquilibrado = VersionPersistenciaFactorEquilibrado,
MostrarElevacionesRuta = _mostrarElevacionesRutaConfiguracion,
FuenteElevacionCalculo = _fuenteElevacionCalculo,
VersionFuenteElevacion = VersionPersistenciaFuenteElevacion,
VersionPendientes = VersionPersistenciaPendientes,
UmbralPendienteSubidaRuta = _umbralPendienteSubidaRuta,
UmbralPendienteSubidaMediaRuta = _umbralPendienteSubidaMediaRuta,
UmbralPendienteSubidaFuerteRuta = _umbralPendienteSubidaFuerteRuta,
ColorPendienteSubidaSuaveRuta = _colorPendienteSubidaSuaveRuta,
ColorPendienteSubidaMediaRuta = _colorPendienteSubidaMediaRuta,
ColorPendienteSubidaFuerteRuta = _colorPendienteSubidaFuerteRuta,
UmbralPendienteBajadaRuta = _umbralPendienteBajadaRuta,
UmbralAlturaAlertaPendienteRutaMetros = _umbralAlturaAlertaPendienteRutaMetros,
VelocidadPieKmH = _velocidadPieKmH,
VelocidadBusKmH = _velocidadBusKmH,
ElevMaxPuntosPorTramo = _elevMaxPuntosPorTramo,
RadioCandidatasMetros = _radioCandidatasMetros,
MargenTransbordoSegundos = _margenTransbordoSegundos,
WalkProvider = _walkProvider.ToString(),
NivelBrilloMapa = _nivelBrilloMapa,
UsarColorRealLineaEnItinerarios = _usarColorRealLineaEnItinerarios,
UsarOsrmParaRanking = _usarOsrmParaRanking,
CriterioPrioritarioRuta = _criterioPrioritarioRuta,
PreferenciaEtiquetaRuta = _preferenciaEtiquetaRuta
};
/// <summary>
/// Aplica al componente una configuración previamente persistida.
/// </summary>
private void AplicarConfiguracionLocal(ConfiguracionLocalPlanificador config)
{
_mostrarParadas = config.MostrarParadas ?? true;
_usarHorariosTeoricos = config.UsarHorariosTeoricos;
_segundosPorParadaBusManual = Math.Clamp(config.SegundosPorParadaBusManual, 0, 3600);
_segundosPorParadaBus = _segundosPorParadaBusManual;
_lineaMin = Math.Clamp(config.LineaMin, 1, 200);
_lineaMax = Math.Clamp(config.LineaMax, 1, 200);
_lineasPermitidas.Clear();
foreach (var linea in NormalizarLineasPermitidas(config.LineasPermitidas, config.LineaMin, config.LineaMax))
_lineasPermitidas.Add(linea);
_activarRangoLineas = config.ActivarRangoLineas;
_activarRangoItinerarios = config.ActivarRangoItinerarios;
_itinerarioMin = Math.Clamp(config.ItinerarioMin, 1, 99);
_itinerarioMax = Math.Clamp(config.ItinerarioMax, 1, 99);
_filtroSentidoItinerario = NormalizarFiltroSentidoItinerario(config.FiltroSentidoItinerario);
_activarRangoTransbordos = config.ActivarRangoTransbordos;
_minTransbordosPermitidos = Math.Clamp(config.MinTransbordosPermitidos, 0, 10);
_maxTransbordosPermitidos = Math.Clamp(config.MaxTransbordosPermitidos, 0, 10);
_usarHoraSimulada = config.UsarHoraSimulada;
if (DateOnly.TryParse(config.FechaSimulada, out var fechaSimulada))
_fechaSimulada = fechaSimulada;
if (TimeOnly.TryParse(config.HoraSimulada, out var horaSimulada))
_horaSimulada = horaSimulada;
if (config.FactorPenalizacionDistanciaPie is { } factor && double.IsFinite(factor))
_factorPenalizacionDistanciaPie =
Math.Abs(factor - 1.3) < 0.0001 || Math.Abs(factor - 1.6) < 0.0001
? FactorPenalizacionDistanciaPiePorDefecto
: factor;
if (config.ParametroPenalizacionDistanciaPieMetros is { } parametro && double.IsFinite(parametro))
_parametroPenalizacionDistanciaPieMetros =
Math.Abs(parametro - 100.0) < 0.0001
? ParametroPenalizacionDistanciaPieMetrosPorDefecto
: parametro;
var migrarCoeficienteEsfuerzo =
(config.VersionCoeficienteEsfuerzo ?? 0) < VersionPersistenciaCoeficienteEsfuerzo;
if (config.CoeficienteEsfuerzoAltura is { } coeficienteAltura && double.IsFinite(coeficienteAltura))
_coeficienteEsfuerzoAltura =
migrarCoeficienteEsfuerzo &&
(Math.Abs(coeficienteAltura - 1.6) < 0.0001 ||
Math.Abs(coeficienteAltura - 5.2) < 0.0001 ||
Math.Abs(coeficienteAltura - 8.2) < 0.0001 ||
Math.Abs(coeficienteAltura - 9.2) < 0.0001)
? CoeficienteEsfuerzoAlturaPorDefecto
: coeficienteAltura;
if (config.PesoTransbordoRankingMinutos is { } pesoTransbordo && double.IsFinite(pesoTransbordo))
_pesoTransbordoRankingMinutos = Math.Abs(pesoTransbordo - 8.0) < 0.0001 ? 4.0 : Math.Max(0, pesoTransbordo);
if (config.FactorEquilibradoAndarBus is { } factorEquilibrado &&
double.IsFinite(factorEquilibrado) &&
factorEquilibrado > 0)
_factorEquilibradoAndarBus = (config.VersionFactorEquilibrado ?? 0) < VersionPersistenciaFactorEquilibrado &&
Math.Abs(factorEquilibrado - 12.0) < 0.0001
? FactorEquilibradoAndarBusPorDefecto
: factorEquilibrado;
var migrarValoresPendientes = (config.VersionPendientes ?? 0) < VersionPersistenciaPendientes;
_mostrarElevacionesRuta = migrarValoresPendientes
? true
: config.MostrarElevacionesRuta ?? true;
_mostrarElevacionesRutaConfiguracion = _mostrarElevacionesRuta;
var migrarFuenteElevacion =
(config.VersionFuenteElevacion ?? 0) < VersionPersistenciaFuenteElevacion;
_fuenteElevacionCalculo = migrarFuenteElevacion &&
string.Equals(
config.FuenteElevacionCalculo,
FuenteElevacionLocal1,
StringComparison.OrdinalIgnoreCase)
? FuenteElevacionLocal5
: NormalizarFuenteElevacion(config.FuenteElevacionCalculo);
if (config.UmbralPendienteSubidaRuta is { } umbralSubida && double.IsFinite(umbralSubida))
_umbralPendienteSubidaRuta = Math.Abs(umbralSubida - 3.0) < 0.0001
? UmbralPendienteSubidaRutaPorDefecto
: NormalizarUmbralPendienteRuta(umbralSubida);
_umbralPendienteSubidaMediaRuta =
config.UmbralPendienteSubidaMediaRuta is { } umbralSubidaMedia &&
double.IsFinite(umbralSubidaMedia)
? NormalizarUmbralPendienteRuta(umbralSubidaMedia)
: UmbralPendienteSubidaMediaRutaPorDefecto;
_umbralPendienteSubidaFuerteRuta =
config.UmbralPendienteSubidaFuerteRuta is { } umbralSubidaFuerte &&
double.IsFinite(umbralSubidaFuerte)
? NormalizarUmbralPendienteRuta(umbralSubidaFuerte)
: UmbralPendienteSubidaFuerteRutaPorDefecto;
_colorPendienteSubidaSuaveRuta = NormalizarColorHexRuta(
config.ColorPendienteSubidaSuaveRuta,
ColorPendienteSubidaSuaveRutaPorDefecto);
_colorPendienteSubidaMediaRuta = NormalizarColorHexRuta(
config.ColorPendienteSubidaMediaRuta,
ColorPendienteSubidaMediaRutaPorDefecto);
_colorPendienteSubidaFuerteRuta = NormalizarColorHexRuta(
config.ColorPendienteSubidaFuerteRuta,
ColorPendienteSubidaFuerteRutaPorDefecto);
NormalizarOrdenUmbralesColorSubidaRuta();
if (config.UmbralPendienteBajadaRuta is { } umbralBajada && double.IsFinite(umbralBajada))
_umbralPendienteBajadaRuta =
Math.Abs(umbralBajada - 3.0) < 0.0001 ||
Math.Abs(umbralBajada - 6.0) < 0.0001
? UmbralPendienteBajadaRutaPorDefecto
: NormalizarUmbralPendienteRuta(umbralBajada);
if (config.UmbralAlturaAlertaPendienteRutaMetros is { } umbralAltura && double.IsFinite(umbralAltura))
{
_umbralAlturaAlertaPendienteRutaMetros =
NormalizarUmbralAlturaAlertaPendienteRutaMetros(umbralAltura);
}
else if (config.UmbralPisosPendienteRuta is { } umbralPisos && double.IsFinite(umbralPisos))
{
_umbralAlturaAlertaPendienteRutaMetros =
NormalizarUmbralAlturaAlertaPendienteRutaMetros(umbralPisos * MetrosPorPiso);
}
_velocidadPieKmH = Math.Clamp(config.VelocidadPieKmH, 0.5, 25.0);
_velocidadBusKmH = Math.Clamp(
Math.Abs(config.VelocidadBusKmH - 15.0) < 0.0001 ||
Math.Abs(config.VelocidadBusKmH - 16.6) < 0.0001
? 16.0
: config.VelocidadBusKmH,
1.0,
120.0);
_elevMaxPuntosPorTramo = Math.Clamp(config.ElevMaxPuntosPorTramo, 2, 999);
_radioCandidatasMetros = Math.Clamp(config.RadioCandidatasMetros, 200, 3500);
_margenTransbordoSegundos = Math.Clamp(config.MargenTransbordoSegundos, 0, 1800);
_nivelBrilloMapa = Math.Clamp(config.NivelBrilloMapa, 0, 4);
_usarColorRealLineaEnItinerarios = config.UsarColorRealLineaEnItinerarios;
_usarOsrmParaRanking = config.UsarOsrmParaRanking;
_criterioPrioritarioRuta = NormalizarCriterioRuta(config.CriterioPrioritarioRuta, config.PreferenciaEtiquetaRuta);
SincronizarPreferenciaDesdeCriterioRuta();
if (Enum.TryParse<ProveedorCaminata>(config.WalkProvider, ignoreCase: true, out var walkProvider))
_walkProvider = walkProvider;
SincronizarTextosPenalizacionPie();
SincronizarSegundosPorParadaConHorarios();
}
private static FiltroSentidoItinerario NormalizarFiltroSentidoItinerario(string? valor)
=> Enum.TryParse<FiltroSentidoItinerario>(valor, ignoreCase: true, out var filtro) &&
Enum.IsDefined(typeof(FiltroSentidoItinerario), filtro)
? filtro
: FiltroSentidoItinerario.Ambos;
private static IReadOnlyList<int> NormalizarLineasPermitidas(
IReadOnlyList<int>? lineas,
int lineaMinLegacy,
int lineaMaxLegacy)
{
if (lineas is { Count: > 0 })
{
return lineas
.Where(linea => linea > 0 && linea <= 999)
.Distinct()
.OrderBy(linea => linea)
.ToList();
}
if (lineaMinLegacy <= 0 && lineaMaxLegacy <= 0)
return Array.Empty<int>();
var min = Math.Clamp(Math.Min(lineaMinLegacy, lineaMaxLegacy), 1, 999);
var max = Math.Clamp(Math.Max(lineaMinLegacy, lineaMaxLegacy), 1, 999);
var esRangoPorDefecto = min <= 1 && max >= 200;
if (esRangoPorDefecto)
return Array.Empty<int>();
return Enumerable.Range(min, max - min + 1).ToList();
}
/// <summary>
/// Abre el cuadro de confirmación para restablecer valores.
/// </summary>
private void PedirConfirmacionRestablecer()
{
_mostrarConfirmacionRestablecer = true;
}
/// <summary>
/// Cierra el cuadro de confirmación de restablecer.
/// </summary>
private void CancelarConfirmacionRestablecer()
{
_mostrarConfirmacionRestablecer = false;
}
/// <summary>
/// Restablece la configuracion avanzada a los valores por defecto de la aplicacion.
/// </summary>
private async Task RestablecerConfiguracionPorDefectoAsync()
{
_mostrarConfirmacionRestablecer = false;
bool confirmado = true;
try
{
confirmado = await JS.InvokeAsync<bool>("confirm", "¿Seguro que quieres restablecer la configuración avanzada a sus valores por defecto?");
}
catch (JSException)
{
confirmado = false;
}
if (!confirmado)
return;
_mostrarParadas = true;
_usarHorariosTeoricos = true;
_segundosPorParadaBusManual = 30;
_segundosPorParadaBus = 30;
_activarRangoItinerarios = true;
_itinerarioMin = 1;
_itinerarioMax = 99;
_filtroSentidoItinerario = FiltroSentidoItinerario.Ambos;
_activarRangoTransbordos = true;
_minTransbordosPermitidos = 0;
_maxTransbordosPermitidos = 3;
_factorPenalizacionDistanciaPie = FactorPenalizacionDistanciaPiePorDefecto;
_parametroPenalizacionDistanciaPieMetros = ParametroPenalizacionDistanciaPieMetrosPorDefecto;
_coeficienteEsfuerzoAltura = CoeficienteEsfuerzoAlturaPorDefecto;
_pesoTransbordoRankingMinutos = 4.0;
_factorEquilibradoAndarBus = FactorEquilibradoAndarBusPorDefecto;
_mostrarElevacionesRutaConfiguracion = true;
_fuenteElevacionCalculo = FuenteElevacionLocal5;
_umbralPendienteSubidaRuta = UmbralPendienteSubidaRutaPorDefecto;
_umbralPendienteSubidaMediaRuta = UmbralPendienteSubidaMediaRutaPorDefecto;
_umbralPendienteSubidaFuerteRuta = UmbralPendienteSubidaFuerteRutaPorDefecto;
_colorPendienteSubidaSuaveRuta = ColorPendienteSubidaSuaveRutaPorDefecto;
_colorPendienteSubidaMediaRuta = ColorPendienteSubidaMediaRutaPorDefecto;
_colorPendienteSubidaFuerteRuta = ColorPendienteSubidaFuerteRutaPorDefecto;
_umbralPendienteBajadaRuta = UmbralPendienteBajadaRutaPorDefecto;
_umbralAlturaAlertaPendienteRutaMetros = UmbralAlturaAlertaPendienteRutaMetrosPorDefecto;
_velocidadPieKmH = 3.6;
_velocidadBusKmH = 16.0;
_minutosTransbordo = 5;
_margenTransbordoSegundos = 120;
_elevMaxPuntosPorTramo = 999;
_radioCandidatasMetros = 1200;
_walkProvider = ProveedorCaminata.Valhalla;
_nivelBrilloMapa = 0;
_usarColorRealLineaEnItinerarios = false;
_usarOsrmParaRanking = false;
if (_usarHoraSimulada)
StopClock();
else
StartClock();
SincronizarTextosPenalizacionPie();
SincronizarSegundosPorParadaConHorarios();
await RefrescarHoraUIAsync();
await PersistirConfiguracionAsync();
StateHasChanged();
}
/// <summary>
/// Restablece la configuración desde el modal personalizado centrado.
/// </summary>
private async Task ConfirmarRestablecerConfiguracionAsync()
{
_mostrarConfirmacionRestablecer = false;
_mostrarParadas = true;
_usarHorariosTeoricos = true;
_segundosPorParadaBusManual = 30;
_segundosPorParadaBus = 30;
_activarRangoItinerarios = true;
_itinerarioMin = 1;
_itinerarioMax = 99;
_filtroSentidoItinerario = FiltroSentidoItinerario.Ambos;
_activarRangoTransbordos = true;
_minTransbordosPermitidos = 0;
_maxTransbordosPermitidos = 3;
_factorPenalizacionDistanciaPie = FactorPenalizacionDistanciaPiePorDefecto;
_parametroPenalizacionDistanciaPieMetros = ParametroPenalizacionDistanciaPieMetrosPorDefecto;
_coeficienteEsfuerzoAltura = CoeficienteEsfuerzoAlturaPorDefecto;
_pesoTransbordoRankingMinutos = 4.0;
_factorEquilibradoAndarBus = FactorEquilibradoAndarBusPorDefecto;
_mostrarElevacionesRutaConfiguracion = true;
_fuenteElevacionCalculo = FuenteElevacionLocal5;
_umbralPendienteSubidaRuta = UmbralPendienteSubidaRutaPorDefecto;
_umbralPendienteSubidaMediaRuta = UmbralPendienteSubidaMediaRutaPorDefecto;
_umbralPendienteSubidaFuerteRuta = UmbralPendienteSubidaFuerteRutaPorDefecto;
_colorPendienteSubidaSuaveRuta = ColorPendienteSubidaSuaveRutaPorDefecto;
_colorPendienteSubidaMediaRuta = ColorPendienteSubidaMediaRutaPorDefecto;
_colorPendienteSubidaFuerteRuta = ColorPendienteSubidaFuerteRutaPorDefecto;
_umbralPendienteBajadaRuta = UmbralPendienteBajadaRutaPorDefecto;
_umbralAlturaAlertaPendienteRutaMetros = UmbralAlturaAlertaPendienteRutaMetrosPorDefecto;
_velocidadPieKmH = 3.6;
_velocidadBusKmH = 16.0;
_minutosTransbordo = 5;
_margenTransbordoSegundos = 120;
_elevMaxPuntosPorTramo = 999;
_radioCandidatasMetros = 1200;
_walkProvider = ProveedorCaminata.Valhalla;
_nivelBrilloMapa = 0;
_usarColorRealLineaEnItinerarios = false;
_usarOsrmParaRanking = false;
if (_usarHoraSimulada)
StopClock();
else
StartClock();
SincronizarTextosPenalizacionPie();
SincronizarSegundosPorParadaConHorarios();
await RefrescarHoraUIAsync();
await PersistirConfiguracionAsync();
StateHasChanged();
}
}