Restricciones de seleccion de paradas.
señal de dereivacion de historial. importante: cambiod e formula, desaparece distancia equilibrada y el factor pasa a dividir a la distancia en bus
This commit is contained in:
@@ -151,7 +151,7 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expone el factor que convierte metros andando a metros equivalentes de bus en el modo equilibrado.
|
||||
/// Expone el factor que reduce el peso de la distancia en bus en el modo equilibrado.
|
||||
/// </summary>
|
||||
private string FactorEquilibradoAndarBusTexto
|
||||
{
|
||||
@@ -164,8 +164,8 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
if (!double.TryParse(texto, NumberStyles.Float, CultureInfo.InvariantCulture, out var valor))
|
||||
return;
|
||||
|
||||
if (double.IsFinite(valor))
|
||||
_factorEquilibradoAndarBus = Math.Max(0, valor);
|
||||
if (double.IsFinite(valor) && valor > 0)
|
||||
_factorEquilibradoAndarBus = valor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1420,25 +1420,6 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
return EstimarDuracionPieSegundos(distanciaCorregida);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calcula la aportacion de todos los tramos andando a la distancia equilibrada.
|
||||
/// </summary>
|
||||
private double CalcularDistanciaEquilibradaAndandoAlternativa(AlternativaRuta? alternativa)
|
||||
{
|
||||
if (alternativa is null)
|
||||
return 0;
|
||||
|
||||
var distanciaAndando = CalcularDistanciaCorregidaAlternativa(alternativa);
|
||||
var factor = double.IsFinite(_factorEquilibradoAndarBus)
|
||||
? Math.Max(0, _factorEquilibradoAndarBus)
|
||||
: FactorEquilibradoAndarBusPorDefecto;
|
||||
var distanciaEquilibrada = Math.Max(0, distanciaAndando) * factor;
|
||||
|
||||
return double.IsFinite(distanciaEquilibrada)
|
||||
? distanciaEquilibrada
|
||||
: 0;
|
||||
}
|
||||
|
||||
private double CalcularScoreEquilibradoFactor(AlternativaRuta? alternativa)
|
||||
{
|
||||
if (alternativa is null)
|
||||
@@ -1453,11 +1434,14 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
distanciaBus = Math.Max(0, alternativa.AlternativaBus.DistanciaTotalBus);
|
||||
}
|
||||
|
||||
var distanciaEquilibradaAndando = CalcularDistanciaEquilibradaAndandoAlternativa(alternativa);
|
||||
var distanciaAndando = CalcularDistanciaCorregidaAlternativa(alternativa);
|
||||
var factor = double.IsFinite(_factorEquilibradoAndarBus) && _factorEquilibradoAndarBus > 0
|
||||
? _factorEquilibradoAndarBus
|
||||
: FactorEquilibradoAndarBusPorDefecto;
|
||||
var penalizacionTransbordos = UtilidadesTransitoDbus.CalcularPenalizacionTransbordosRankingMetros(
|
||||
alternativa.NumeroTransbordosReales,
|
||||
CrearParametrosPenalizacionActuales());
|
||||
var score = distanciaBus + distanciaEquilibradaAndando + penalizacionTransbordos;
|
||||
var score = distanciaAndando + (distanciaBus / factor) + penalizacionTransbordos;
|
||||
return double.IsFinite(score) && score >= 0
|
||||
? score
|
||||
: double.PositiveInfinity;
|
||||
@@ -1469,7 +1453,7 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
if (!double.IsFinite(score))
|
||||
return string.Empty;
|
||||
|
||||
return (score / 1000.0).ToString("0.000", CultureInfo.InvariantCulture);
|
||||
return score.ToString("0", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private async Task RecalcularRutaEquilibradaTrasCambioFactorAsync()
|
||||
|
||||
@@ -27,6 +27,9 @@ public partial class PlanificadorRutas
|
||||
private CancellationTokenSource? _historialCompartidoCts;
|
||||
private string _historialLocalSeleccionadoId = string.Empty;
|
||||
private string _historialCompartidoSeleccionadoId = string.Empty;
|
||||
private TipoReferenciaHistorial _tipoReferenciaHistorial;
|
||||
private string _historialReferenciaId = string.Empty;
|
||||
private bool _rutaActualDerivadaDeHistorial;
|
||||
private string _mensajeHistorial = string.Empty;
|
||||
private bool _mensajeHistorialEsError = false;
|
||||
private bool _mostrarHistorialRutas = false;
|
||||
@@ -43,6 +46,13 @@ public partial class PlanificadorRutas
|
||||
private string _resumenErrorHistorialLocal = string.Empty;
|
||||
private string _detalleErrorHistorialLocal = string.Empty;
|
||||
|
||||
private enum TipoReferenciaHistorial
|
||||
{
|
||||
Ninguna,
|
||||
Personal,
|
||||
Compartido
|
||||
}
|
||||
|
||||
private sealed class ResultadoStorageNavegador
|
||||
{
|
||||
[JsonPropertyName("ok")]
|
||||
@@ -400,6 +410,11 @@ public partial class PlanificadorRutas
|
||||
_historialLocal.AddRange(items);
|
||||
if (!_historialLocal.Any(x => x.Id == _historialLocalSeleccionadoId))
|
||||
_historialLocalSeleccionadoId = string.Empty;
|
||||
if (_tipoReferenciaHistorial == TipoReferenciaHistorial.Personal &&
|
||||
!_historialLocal.Any(x => x.Id == _historialReferenciaId))
|
||||
{
|
||||
LimpiarReferenciaHistorial();
|
||||
}
|
||||
_historialLocalCargado = true;
|
||||
}
|
||||
|
||||
@@ -632,11 +647,18 @@ public partial class PlanificadorRutas
|
||||
if (_historialCompartido.Count == 0)
|
||||
{
|
||||
_historialCompartidoSeleccionadoId = string.Empty;
|
||||
if (_tipoReferenciaHistorial == TipoReferenciaHistorial.Compartido)
|
||||
LimpiarReferenciaHistorial();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_historialCompartido.Any(x => x.Id == _historialCompartidoSeleccionadoId))
|
||||
_historialCompartidoSeleccionadoId = string.Empty;
|
||||
if (_tipoReferenciaHistorial == TipoReferenciaHistorial.Compartido &&
|
||||
!_historialCompartido.Any(x => x.Id == _historialReferenciaId))
|
||||
{
|
||||
LimpiarReferenciaHistorial();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -783,12 +805,14 @@ public partial class PlanificadorRutas
|
||||
{
|
||||
_historialLocalSeleccionadoId = id;
|
||||
_historialCompartidoSeleccionadoId = string.Empty;
|
||||
EstablecerReferenciaHistorial(TipoReferenciaHistorial.Personal, id);
|
||||
}
|
||||
|
||||
private void SeleccionarHistorialCompartido(string id)
|
||||
{
|
||||
_historialLocalSeleccionadoId = string.Empty;
|
||||
_historialCompartidoSeleccionadoId = id;
|
||||
EstablecerReferenciaHistorial(TipoReferenciaHistorial.Compartido, id);
|
||||
}
|
||||
|
||||
private void LimpiarSeleccionHistorial()
|
||||
@@ -797,6 +821,74 @@ public partial class PlanificadorRutas
|
||||
_historialCompartidoSeleccionadoId = string.Empty;
|
||||
}
|
||||
|
||||
private bool PrepararDerivacionHistorialParaRecalculo()
|
||||
{
|
||||
var procedeDeHistorial = _tipoReferenciaHistorial != TipoReferenciaHistorial.Ninguna &&
|
||||
!string.IsNullOrWhiteSpace(_historialReferenciaId);
|
||||
|
||||
_rutaActualDerivadaDeHistorial = false;
|
||||
LimpiarSeleccionHistorial();
|
||||
return procedeDeHistorial;
|
||||
}
|
||||
|
||||
private void ConfirmarDerivacionHistorial()
|
||||
{
|
||||
_rutaActualDerivadaDeHistorial = ExisteReferenciaHistorialActual();
|
||||
}
|
||||
|
||||
private void EstablecerReferenciaHistorial(TipoReferenciaHistorial tipo, string id)
|
||||
{
|
||||
_tipoReferenciaHistorial = tipo;
|
||||
_historialReferenciaId = id;
|
||||
_rutaActualDerivadaDeHistorial = false;
|
||||
}
|
||||
|
||||
private void LimpiarReferenciaHistorial()
|
||||
{
|
||||
_tipoReferenciaHistorial = TipoReferenciaHistorial.Ninguna;
|
||||
_historialReferenciaId = string.Empty;
|
||||
_rutaActualDerivadaDeHistorial = false;
|
||||
}
|
||||
|
||||
private bool ExisteReferenciaHistorialActual()
|
||||
=> _tipoReferenciaHistorial switch
|
||||
{
|
||||
TipoReferenciaHistorial.Personal =>
|
||||
_historialLocal.Any(x => x.Id == _historialReferenciaId),
|
||||
TipoReferenciaHistorial.Compartido =>
|
||||
_historialCompartido.Any(x => x.Id == _historialReferenciaId),
|
||||
_ => false
|
||||
};
|
||||
|
||||
private bool EsReferenciaDerivadaHistorialPersonal(string id)
|
||||
=> _rutaActualDerivadaDeHistorial &&
|
||||
_tipoReferenciaHistorial == TipoReferenciaHistorial.Personal &&
|
||||
string.Equals(_historialReferenciaId, id, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
private bool EsReferenciaDerivadaHistorialCompartido(string id)
|
||||
=> _rutaActualDerivadaDeHistorial &&
|
||||
_tipoReferenciaHistorial == TipoReferenciaHistorial.Compartido &&
|
||||
string.Equals(_historialReferenciaId, id, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
private string TextoReferenciaHistorialDerivado()
|
||||
{
|
||||
if (!_rutaActualDerivadaDeHistorial)
|
||||
return string.Empty;
|
||||
|
||||
var (nombre, indice) = _tipoReferenciaHistorial switch
|
||||
{
|
||||
TipoReferenciaHistorial.Personal =>
|
||||
("Personal", _historialLocal.FindIndex(x => x.Id == _historialReferenciaId)),
|
||||
TipoReferenciaHistorial.Compartido =>
|
||||
("Compartido", _historialCompartido.FindIndex(x => x.Id == _historialReferenciaId)),
|
||||
_ => (string.Empty, -1)
|
||||
};
|
||||
|
||||
return indice >= 0
|
||||
? $"Ruta actual derivada del Historial {nombre} n.º {indice + 1}."
|
||||
: string.Empty;
|
||||
}
|
||||
|
||||
private async Task CompartirEscenarioActualAsync()
|
||||
{
|
||||
var actual = ConstruirRegistroHistorialActual()
|
||||
@@ -854,6 +946,11 @@ public partial class PlanificadorRutas
|
||||
|
||||
var estabaSeleccionado = _historialLocalSeleccionadoId == id;
|
||||
_historialLocal.RemoveAt(indiceEliminado);
|
||||
if (_tipoReferenciaHistorial == TipoReferenciaHistorial.Personal &&
|
||||
string.Equals(_historialReferenciaId, id, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
LimpiarReferenciaHistorial();
|
||||
}
|
||||
|
||||
await PersistirHistorialLocalAsync();
|
||||
|
||||
@@ -924,6 +1021,11 @@ public partial class PlanificadorRutas
|
||||
|
||||
await CargarHistorialCompartidoAsync();
|
||||
_historialCompartido.RemoveAll(x => x.Id == id);
|
||||
if (_tipoReferenciaHistorial == TipoReferenciaHistorial.Compartido &&
|
||||
string.Equals(_historialReferenciaId, id, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
LimpiarReferenciaHistorial();
|
||||
}
|
||||
|
||||
if (estabaSeleccionado)
|
||||
{
|
||||
@@ -973,9 +1075,11 @@ public partial class PlanificadorRutas
|
||||
_criterioPrioritarioRuta = NormalizarCriterioRuta(item.CriterioPrioritarioRuta, item.PreferenciaEtiquetaRuta);
|
||||
SincronizarPreferenciaDesdeCriterioRuta();
|
||||
|
||||
if (item.FactorEquilibradoAndarBus is { } factorEquilibrado && double.IsFinite(factorEquilibrado))
|
||||
if (item.FactorEquilibradoAndarBus is { } factorEquilibrado &&
|
||||
double.IsFinite(factorEquilibrado) &&
|
||||
factorEquilibrado > 0)
|
||||
{
|
||||
_factorEquilibradoAndarBus = Math.Max(0, factorEquilibrado);
|
||||
_factorEquilibradoAndarBus = factorEquilibrado;
|
||||
SincronizarTextosPenalizacionPie();
|
||||
|
||||
if (_configuracionTemporalPreviaHistorial is not null)
|
||||
@@ -1063,8 +1167,9 @@ public partial class PlanificadorRutas
|
||||
HoraSimulada = TimeOnly.FromDateTime(ahora).ToString("HH:mm:ss", CultureInfo.InvariantCulture),
|
||||
CriterioPrioritarioRuta = _criterioPrioritarioRuta,
|
||||
PreferenciaEtiquetaRuta = _preferenciaEtiquetaRuta,
|
||||
FactorEquilibradoAndarBus = double.IsFinite(_factorEquilibradoAndarBus)
|
||||
? Math.Max(0, _factorEquilibradoAndarBus)
|
||||
FactorEquilibradoAndarBus = double.IsFinite(_factorEquilibradoAndarBus) &&
|
||||
_factorEquilibradoAndarBus > 0
|
||||
? _factorEquilibradoAndarBus
|
||||
: FactorEquilibradoAndarBusPorDefecto,
|
||||
ActivarFiltroLineas = _activarRangoLineas,
|
||||
LineasPermitidas = ObtenerLineasPermitidasSeleccionadas().ToList(),
|
||||
@@ -1194,8 +1299,10 @@ public partial class PlanificadorRutas
|
||||
var fecha = item.UsarHoraSimulada ? item.FechaSimulada?.Trim() ?? string.Empty : string.Empty;
|
||||
var hora = item.UsarHoraSimulada ? item.HoraSimulada?.Trim() ?? string.Empty : string.Empty;
|
||||
var criterio = NormalizarCriterioRuta(item.CriterioPrioritarioRuta, item.PreferenciaEtiquetaRuta);
|
||||
var factorEquilibrado = item.FactorEquilibradoAndarBus is { } factor && double.IsFinite(factor)
|
||||
? Math.Max(0, factor).ToString("0.######", CultureInfo.InvariantCulture)
|
||||
var factorEquilibrado = item.FactorEquilibradoAndarBus is { } factor &&
|
||||
double.IsFinite(factor) &&
|
||||
factor > 0
|
||||
? factor.ToString("0.######", CultureInfo.InvariantCulture)
|
||||
: string.Empty;
|
||||
var lineas = item.ActivarFiltroLineas
|
||||
? string.Join(",", NormalizarLineasHistorial(item.LineasPermitidas))
|
||||
|
||||
@@ -1202,7 +1202,7 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
private bool _elevPopupMinimizado = false;
|
||||
|
||||
|
||||
private const string _versionApp = "(v-20260807b)";
|
||||
private const string _versionApp = "(v-20260825b)";
|
||||
|
||||
|
||||
private double? _paradaElevIdee;
|
||||
|
||||
@@ -227,11 +227,13 @@ public partial class PlanificadorRutas
|
||||
: 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))
|
||||
if (config.FactorEquilibradoAndarBus is { } factorEquilibrado &&
|
||||
double.IsFinite(factorEquilibrado) &&
|
||||
factorEquilibrado > 0)
|
||||
_factorEquilibradoAndarBus = (config.VersionFactorEquilibrado ?? 0) < VersionPersistenciaFactorEquilibrado &&
|
||||
Math.Abs(factorEquilibrado - 12.0) < 0.0001
|
||||
? FactorEquilibradoAndarBusPorDefecto
|
||||
: Math.Max(0, factorEquilibrado);
|
||||
: factorEquilibrado;
|
||||
var migrarValoresPendientes = (config.VersionPendientes ?? 0) < VersionPersistenciaPendientes;
|
||||
_mostrarElevacionesRuta = migrarValoresPendientes
|
||||
? true
|
||||
|
||||
@@ -1270,9 +1270,123 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
var listaOrdenada = ordenadas.ToList();
|
||||
_opcionesRuta.Clear();
|
||||
_opcionesRuta.AddRange(listaOrdenada);
|
||||
FiltrarAlternativasBusRedundantes();
|
||||
RenumerarEtiquetasGenericasOpcionesRuta();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Conserva la mejor alternativa de cada direccion de acceso a una misma linea
|
||||
/// y descarta rutas en bus que no ahorran ninguna distancia andando.
|
||||
/// </summary>
|
||||
private void FiltrarAlternativasBusRedundantes()
|
||||
{
|
||||
if (_opcionesRuta.Count <= 1)
|
||||
return;
|
||||
|
||||
var distanciaSoloPie = _opcionesRuta
|
||||
.Where(opcion => opcion.EsSoloAPie &&
|
||||
double.IsFinite(opcion.DistanciaSoloAPie) &&
|
||||
opcion.DistanciaSoloAPie > 0)
|
||||
.Select(opcion => opcion.DistanciaSoloAPie)
|
||||
.DefaultIfEmpty(double.PositiveInfinity)
|
||||
.Min();
|
||||
|
||||
var conservadas = new List<AlternativaRuta>(_opcionesRuta.Count);
|
||||
foreach (var candidata in _opcionesRuta)
|
||||
{
|
||||
if (candidata.EsSoloAPie)
|
||||
{
|
||||
conservadas.Add(candidata);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (double.IsFinite(distanciaSoloPie) &&
|
||||
double.IsFinite(candidata.DistanciaPieTotalAprox) &&
|
||||
candidata.DistanciaPieTotalAprox >= distanciaSoloPie)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var repiteDireccionAcceso = conservadas.Any(referencia =>
|
||||
!referencia.EsSoloAPie &&
|
||||
EsMismaLineaInicial(referencia, candidata) &&
|
||||
CaminanEnLaMismaDireccionDesdeOrigen(referencia, candidata));
|
||||
|
||||
if (!repiteDireccionAcceso)
|
||||
conservadas.Add(candidata);
|
||||
}
|
||||
|
||||
if (conservadas.Count == _opcionesRuta.Count)
|
||||
return;
|
||||
|
||||
_opcionesRuta.Clear();
|
||||
_opcionesRuta.AddRange(conservadas);
|
||||
}
|
||||
|
||||
private static bool EsMismaLineaInicial(
|
||||
AlternativaRuta referencia,
|
||||
AlternativaRuta candidata)
|
||||
{
|
||||
var tramoReferencia = referencia.AlternativaBus?.Tramos.FirstOrDefault();
|
||||
var tramoCandidata = candidata.AlternativaBus?.Tramos.FirstOrDefault();
|
||||
if (tramoReferencia is null || tramoCandidata is null)
|
||||
return false;
|
||||
|
||||
return string.Equals(
|
||||
UtilidadesTransitoDbus.LineaCodigoStr(tramoReferencia.Variante),
|
||||
UtilidadesTransitoDbus.LineaCodigoStr(tramoCandidata.Variante),
|
||||
StringComparison.OrdinalIgnoreCase) &&
|
||||
tramoReferencia.Variante.CodigoItinerario == tramoCandidata.Variante.CodigoItinerario;
|
||||
}
|
||||
|
||||
private bool CaminanEnLaMismaDireccionDesdeOrigen(
|
||||
AlternativaRuta referencia,
|
||||
AlternativaRuta candidata)
|
||||
{
|
||||
if (_coordenadasOrigen is null ||
|
||||
_coordenadasOrigen.Length < 2 ||
|
||||
referencia.OrigenParada is null ||
|
||||
candidata.OrigenParada is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var latitudOrigen = _coordenadasOrigen[0];
|
||||
var longitudOrigen = _coordenadasOrigen[1];
|
||||
if (!double.IsFinite(latitudOrigen) || !double.IsFinite(longitudOrigen))
|
||||
return false;
|
||||
|
||||
var metrosPorGradoLatitud = 111_320d;
|
||||
var metrosPorGradoLongitud =
|
||||
metrosPorGradoLatitud * Math.Cos(latitudOrigen * Math.PI / 180d);
|
||||
|
||||
var referenciaX =
|
||||
(referencia.OrigenParada.Longitud - longitudOrigen) * metrosPorGradoLongitud;
|
||||
var referenciaY =
|
||||
(referencia.OrigenParada.Latitud - latitudOrigen) * metrosPorGradoLatitud;
|
||||
var candidataX =
|
||||
(candidata.OrigenParada.Longitud - longitudOrigen) * metrosPorGradoLongitud;
|
||||
var candidataY =
|
||||
(candidata.OrigenParada.Latitud - latitudOrigen) * metrosPorGradoLatitud;
|
||||
|
||||
var moduloReferencia = Math.Sqrt(
|
||||
referenciaX * referenciaX + referenciaY * referenciaY);
|
||||
var moduloCandidata = Math.Sqrt(
|
||||
candidataX * candidataX + candidataY * candidataY);
|
||||
if (!double.IsFinite(moduloReferencia) ||
|
||||
!double.IsFinite(moduloCandidata) ||
|
||||
moduloReferencia < 1d ||
|
||||
moduloCandidata < 1d)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var cosenoDireccion =
|
||||
(referenciaX * candidataX + referenciaY * candidataY) /
|
||||
(moduloReferencia * moduloCandidata);
|
||||
return double.IsFinite(cosenoDireccion) && cosenoDireccion >= 0d;
|
||||
}
|
||||
|
||||
private void RenumerarEtiquetasGenericasOpcionesRuta()
|
||||
{
|
||||
for (var i = 0; i < _opcionesRuta.Count; i++)
|
||||
@@ -1744,8 +1858,8 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
|
||||
_mostrarElevacionesRuta = _mostrarElevacionesRutaConfiguracion;
|
||||
|
||||
if (!_aplicandoRegistroHistorial)
|
||||
LimpiarSeleccionHistorial();
|
||||
var confirmarDerivacionHistorial = !_aplicandoRegistroHistorial &&
|
||||
PrepararDerivacionHistorialParaRecalculo();
|
||||
|
||||
var cronometroCalculo = System.Diagnostics.Stopwatch.StartNew();
|
||||
_panelRutasMovilContraido = _mostrarBuscadorMapa;
|
||||
@@ -1872,6 +1986,8 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
{
|
||||
await RegistrarEscenarioActualEnHistorialLocalAsync();
|
||||
}
|
||||
if (confirmarDerivacionHistorial)
|
||||
ConfirmarDerivacionHistorial();
|
||||
await ActualizarResumenTecnicoRutaAsync(CancellationToken.None);
|
||||
_tiempoUltimoCalculoRuta = cronometroCalculo.Elapsed;
|
||||
StateHasChanged();
|
||||
|
||||
@@ -1151,6 +1151,8 @@ public partial class PlanificadorRutas : ComponentBase
|
||||
|
||||
_coordenadasOrigen = null;
|
||||
_coordenadasDestino = null;
|
||||
LimpiarSeleccionHistorial();
|
||||
LimpiarReferenciaHistorial();
|
||||
_textoBusquedaOrigen = string.Empty;
|
||||
_textoBusquedaDestino = string.Empty;
|
||||
_ubicacionOrigenSeleccionada = null;
|
||||
|
||||
@@ -913,7 +913,6 @@
|
||||
: _duracionTotalSegundos;
|
||||
var dRecta = DistanciaLineaRectaOrigenDestino();
|
||||
var dCorregida = CalcularDistanciaCorregidaAlternativa(altSeleccionada);
|
||||
var dEquilibradaAndando = CalcularDistanciaEquilibradaAndandoAlternativa(altSeleccionada);
|
||||
var xyzOrigen = FormatearResumenXYZOrigen();
|
||||
var xyzDestino = FormatearResumenXYZDestino();
|
||||
var callejeroOrigen = FormatearResumenCallejeroOrigen();
|
||||
@@ -934,7 +933,7 @@
|
||||
</p>
|
||||
}
|
||||
|
||||
@if (dRecta > 0 || dCorregida > 0 || dEquilibradaAndando > 0)
|
||||
@if (dRecta > 0 || dCorregida > 0)
|
||||
{
|
||||
<div class="muted" style="font-size:0.75rem;margin-top:4px;">
|
||||
@if (dRecta > 0)
|
||||
@@ -945,10 +944,6 @@
|
||||
{
|
||||
<div>d.Corregida a pie: @FormatearDistanciaDetalleRuta(dCorregida)</div>
|
||||
}
|
||||
@if (dEquilibradaAndando > 0)
|
||||
{
|
||||
<div>d.Equilib. A: @FormatearDistanciaDetalleRuta(dEquilibradaAndando)</div>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(scoreEquilibradoSeleccionado))
|
||||
{
|
||||
<div>Score equilibrado A: @scoreEquilibradoSeleccionado</div>
|
||||
@@ -1067,12 +1062,18 @@
|
||||
{
|
||||
var item = _historialLocal[i];
|
||||
var numeroPersonal = i + 1;
|
||||
var esReferenciaDerivada = EsReferenciaDerivadaHistorialPersonal(item.Id);
|
||||
|
||||
<div class="history-item @(item.Id == _historialLocalSeleccionadoId ? "history-item--selected" : "")">
|
||||
<div class="history-item @(item.Id == _historialLocalSeleccionadoId ? "history-item--selected" : "") @(esReferenciaDerivada ? "history-item--derived-source" : "")">
|
||||
<button type="button"
|
||||
class="history-item-main history-item-main--numbered"
|
||||
@onclick="() => CargarHistorialLocalAsync(item.Id)">
|
||||
<span class="history-item-number">@numeroPersonal.</span>
|
||||
<span class="history-item-number">
|
||||
@numeroPersonal.@if (esReferenciaDerivada)
|
||||
{
|
||||
<span class="history-derived-marker" title="La ruta actual parte de este historial">*</span>
|
||||
}
|
||||
</span>
|
||||
<span class="history-item-text">@TextoOpcionHistorial(item)</span>
|
||||
</button>
|
||||
|
||||
@@ -1129,12 +1130,18 @@
|
||||
{
|
||||
var item = _historialCompartido[i];
|
||||
var numeroCompartido = i + 1;
|
||||
var esReferenciaDerivada = EsReferenciaDerivadaHistorialCompartido(item.Id);
|
||||
|
||||
<div class="history-item @(item.Id == _historialCompartidoSeleccionadoId ? "history-item--selected" : "")">
|
||||
<div class="history-item @(item.Id == _historialCompartidoSeleccionadoId ? "history-item--selected" : "") @(esReferenciaDerivada ? "history-item--derived-source" : "")">
|
||||
<button type="button"
|
||||
class="history-item-main history-item-main--numbered"
|
||||
@onclick="() => CargarHistorialCompartidoAsync(item.Id)">
|
||||
<span class="history-item-number">@numeroCompartido.</span>
|
||||
<span class="history-item-number">
|
||||
@numeroCompartido.@if (esReferenciaDerivada)
|
||||
{
|
||||
<span class="history-derived-marker" title="La ruta actual parte de este historial">*</span>
|
||||
}
|
||||
</span>
|
||||
<span class="history-item-text">@TextoOpcionHistorial(item)</span>
|
||||
</button>
|
||||
|
||||
@@ -1150,7 +1157,17 @@
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(_mensajeHistorial))
|
||||
@{ var textoReferenciaDerivada = TextoReferenciaHistorialDerivado(); }
|
||||
@if (!string.IsNullOrWhiteSpace(textoReferenciaDerivada))
|
||||
{
|
||||
<div class="history-derived-note">
|
||||
<span class="history-derived-marker" aria-hidden="true">*</span>
|
||||
<span>@textoReferenciaDerivada</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(_mensajeHistorial) &&
|
||||
(string.IsNullOrWhiteSpace(textoReferenciaDerivada) || _mensajeHistorialEsError))
|
||||
{
|
||||
<div class="history-feedback @(_mensajeHistorialEsError ? "history-feedback--error" : "")">
|
||||
@_mensajeHistorial
|
||||
@@ -1499,9 +1516,9 @@
|
||||
<div class="config-dual-labeled">
|
||||
<label class="config-dual-labeled__field">
|
||||
<span>Equilib. A</span>
|
||||
<input type="number" class="config-input" step="0.1" min="0"
|
||||
<input type="number" class="config-input" step="0.1" min="0.1"
|
||||
placeholder="6"
|
||||
title="Factor del modo equilibrado"
|
||||
title="Divisor de la distancia en bus en el modo equilibrado"
|
||||
@bind="FactorEquilibradoAndarBusTexto" @bind:event="oninput"
|
||||
@onblur="OnBlurFactorEquilibradoAndarBus" />
|
||||
</label>
|
||||
|
||||
@@ -34,6 +34,7 @@ public sealed class ParametrosPlanificadorRuta
|
||||
public double FactorPenalizacionDistanciaPie { get; set; } = 1.35;
|
||||
public double ParametroPenalizacionDistanciaPieMetros { get; set; } = 200.0;
|
||||
public double PesoTransbordoRankingMinutos { get; set; } = 4.0;
|
||||
// Divisor aplicado a la distancia en bus dentro del score equilibrado.
|
||||
public double FactorEquilibradoAndarBus { get; set; } = 6.0;
|
||||
|
||||
// selección candidatas
|
||||
|
||||
@@ -315,8 +315,10 @@ public sealed class ServicioHistorialRutasCompartido : IHistorialRutasCompartido
|
||||
var criterio = NormalizarTextoClave(item.CriterioPrioritarioRuta);
|
||||
if (string.IsNullOrWhiteSpace(criterio))
|
||||
criterio = NormalizarTextoClave(item.PreferenciaEtiquetaRuta);
|
||||
var factorEquilibrado = item.FactorEquilibradoAndarBus is { } factor && double.IsFinite(factor)
|
||||
? Math.Max(0, factor).ToString("0.######", CultureInfo.InvariantCulture)
|
||||
var factorEquilibrado = item.FactorEquilibradoAndarBus is { } factor &&
|
||||
double.IsFinite(factor) &&
|
||||
factor > 0
|
||||
? factor.ToString("0.######", CultureInfo.InvariantCulture)
|
||||
: string.Empty;
|
||||
var lineas = item.ActivarFiltroLineas
|
||||
? string.Join(",", NormalizarLineas(item.LineasPermitidas))
|
||||
|
||||
@@ -826,14 +826,15 @@ public sealed class BuscadorRutasTemporalesDbus
|
||||
resultado.DistanciasPieTransbordosPorTramo,
|
||||
resultado.DistanciaPieFin),
|
||||
parametros);
|
||||
var factor = double.IsFinite(parametros.FactorEquilibradoAndarBus)
|
||||
? Math.Max(0, parametros.FactorEquilibradoAndarBus)
|
||||
var factor = double.IsFinite(parametros.FactorEquilibradoAndarBus) &&
|
||||
parametros.FactorEquilibradoAndarBus > 0
|
||||
? parametros.FactorEquilibradoAndarBus
|
||||
: 6.0;
|
||||
var penalizacionTransbordos = UtilidadesTransitoDbus.CalcularPenalizacionTransbordosRankingMetros(
|
||||
UtilidadesTransitoDbus.ContarTransbordosReales(resultado.RutaBus.Tramos),
|
||||
parametros);
|
||||
|
||||
var score = distanciaBus + (distanciaAndando * factor) + penalizacionTransbordos;
|
||||
var score = distanciaAndando + (distanciaBus / factor) + penalizacionTransbordos;
|
||||
return double.IsFinite(score) && score >= 0
|
||||
? score
|
||||
: double.PositiveInfinity;
|
||||
|
||||
@@ -1543,8 +1543,10 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
|
||||
: UtilidadesTransitoDbus.CalcularDistanciaPieCorregidaTotalMetros(
|
||||
ConstruirDistanciasPiePorTramo(resultado),
|
||||
parametros);
|
||||
var factor = parametros is not null && double.IsFinite(parametros.FactorEquilibradoAndarBus)
|
||||
? Math.Max(0, parametros.FactorEquilibradoAndarBus)
|
||||
var factor = parametros is not null &&
|
||||
double.IsFinite(parametros.FactorEquilibradoAndarBus) &&
|
||||
parametros.FactorEquilibradoAndarBus > 0
|
||||
? parametros.FactorEquilibradoAndarBus
|
||||
: 6.0;
|
||||
var penalizacionTransbordos = parametros is null
|
||||
? 0
|
||||
@@ -1552,7 +1554,7 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
|
||||
UtilidadesTransitoDbus.ContarTransbordosReales(resultado.RutaBus.Tramos),
|
||||
parametros);
|
||||
|
||||
var score = distanciaBus + (distanciaAndando * factor) + penalizacionTransbordos;
|
||||
var score = distanciaAndando + (distanciaBus / factor) + penalizacionTransbordos;
|
||||
return double.IsFinite(score) && score >= 0
|
||||
? score
|
||||
: double.PositiveInfinity;
|
||||
@@ -3244,14 +3246,15 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
|
||||
|
||||
var distanciaBus = Math.Max(0, alternativa.AlternativaBus.DistanciaTotalBus);
|
||||
var distanciaAndando = CalcularDistanciaAndandoCorregidaMetros(alternativa, parametros);
|
||||
var factor = double.IsFinite(parametros.FactorEquilibradoAndarBus)
|
||||
? Math.Max(0, parametros.FactorEquilibradoAndarBus)
|
||||
var factor = double.IsFinite(parametros.FactorEquilibradoAndarBus) &&
|
||||
parametros.FactorEquilibradoAndarBus > 0
|
||||
? parametros.FactorEquilibradoAndarBus
|
||||
: 6.0;
|
||||
var penalizacionTransbordos = UtilidadesTransitoDbus.CalcularPenalizacionTransbordosRankingMetros(
|
||||
alternativa.NumeroTransbordosReales,
|
||||
parametros);
|
||||
|
||||
var score = distanciaBus + (distanciaAndando * factor) + penalizacionTransbordos;
|
||||
var score = distanciaAndando + (distanciaBus / factor) + penalizacionTransbordos;
|
||||
return double.IsFinite(score) && score >= 0
|
||||
? score
|
||||
: double.PositiveInfinity;
|
||||
@@ -3508,8 +3511,8 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Firma orientada a UI: agrupa alternativas con la misma secuencia de lineas y sentidos
|
||||
/// aunque cambie la parada exacta.
|
||||
/// Firma orientada a UI: agrupa solo alternativas con el mismo recorrido visible.
|
||||
/// Las paradas forman parte de la identidad porque cambian el acceso a pie y sus pendientes.
|
||||
/// </summary>
|
||||
private static string CrearFirmaFamiliaRutaBus(RutaBusAlternativa alternativa)
|
||||
{
|
||||
@@ -3518,7 +3521,8 @@ public sealed class PlanificadorRutasServicio : IPlanificadorRutas
|
||||
{
|
||||
var linea = UtilidadesTransitoDbus.LineaCodigoStr(tramo.Variante);
|
||||
var sentido = UtilidadesTransitoDbus.NormalizarSentidoCodigo(tramo.Variante.Sentido?.Codigo);
|
||||
var parte = $"{linea}.{tramo.Variante.CodigoItinerario}-{sentido}";
|
||||
var parte = $"{linea}.{tramo.Variante.CodigoItinerario}-{sentido}:" +
|
||||
$"{tramo.CodigoParadaInicio}>{tramo.CodigoParadaFin}";
|
||||
if (partes.Count == 0 || !string.Equals(partes[^1], parte, StringComparison.OrdinalIgnoreCase))
|
||||
partes.Add(parte);
|
||||
}
|
||||
|
||||
@@ -1232,6 +1232,24 @@ html, body {
|
||||
background: rgba(21,128,61,.18);
|
||||
}
|
||||
|
||||
.history-item--derived-source .history-item-main {
|
||||
border-color: rgba(245,158,11,.72);
|
||||
background: rgba(120,53,15,.17);
|
||||
}
|
||||
|
||||
.history-derived-marker {
|
||||
color: #fbbf24;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.history-derived-note {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: .35rem;
|
||||
font-size: .76rem;
|
||||
color: #fcd34d;
|
||||
}
|
||||
|
||||
.history-item-action,
|
||||
.history-item-delete {
|
||||
flex: 0 0 32px;
|
||||
|
||||
Reference in New Issue
Block a user