public IReadOnlyCollection<Itinerary> CalculateItineraries(Route route, IReadOnlyCollection<Voyage> voyages) { var voyageIds = ( from v in voyages from c in v.Schedule.CarrierMovements select new { VoyageId = v.Id, CarrierMovementId = c.Id } ) .ToDictionary(a => a.CarrierMovementId, a => a.VoyageId); var paths = CalculatePaths(route, voyages.Select(v => v.Schedule)); var itineraries = paths .Select(p => new Itinerary(p.CarrierMovements.Select(m => new TransportLeg(TransportLegId.New, m.DepartureLocationId, m.ArrivalLocationId, m.DepartureTime, m.ArrivalTime, voyageIds[m.Id], m.Id)))) .ToList(); return itineraries; }
public async Task<CargoId> BookCargoAsync(Route route, CancellationToken cancellationToken) { var cargoId = CargoId.New; await _commandBus.PublishAsync(new CargoBookCommand(cargoId, route), cancellationToken).ConfigureAwait(false); var itineraries = await _routingService.CalculateItinerariesAsync(route, cancellationToken).ConfigureAwait(false); var itinerary = itineraries.FirstOrDefault(); if (itinerary == null) { throw DomainError.With("Could not find itinerary"); } await _commandBus.PublishAsync(new CargoSetItineraryCommand(cargoId, itinerary), cancellationToken).ConfigureAwait(false); return cargoId; }
private static IEnumerable<Path> CalculatePaths(Route route, IEnumerable<Schedule> schedules) { var graph = new Graph(); foreach (var carrierMovement in schedules.SelectMany(s => s.CarrierMovements)) { graph.Add(carrierMovement); } var paths = new List<Path> { new Path(0.0, route.DepartureTime, graph.Nodes[route.OriginLocationId.Value]) }; var possiblePaths = new List<Path>(); while (true) { if (!paths.Any()) { return possiblePaths.OrderBy(p => p.Distance); } var orderedPaths = paths .Where(p => !double.IsPositiveInfinity(p.Distance)) .OrderBy(p => p.Distance); paths = new List<Path>(); foreach (var path in orderedPaths) { if (path.CurrentNode.Name == route.DestinationLocationId.Value) { possiblePaths.Add(path); continue; } paths.AddRange(path.CurrentNode.Edges.Select(e => CreatePath(route, path, e.CarrierMovement, e.Target)).Where(p => p != null)); } } }
public async Task<IReadOnlyCollection<Itinerary>> CalculateItinerariesAsync(Route route, CancellationToken cancellationToken) { var schedules = await _queryProcessor.ProcessAsync(new GetAllVoyagesQuery(), cancellationToken).ConfigureAwait(false); return CalculateItineraries(route, schedules); }
private static Path CreatePath(Route route, Path currentPath, CarrierMovement carrierMovement, Node target) { if (currentPath.CurrentTime.IsAfter(carrierMovement.DepartureTime)) { return null; } if (carrierMovement.ArrivalTime.IsAfter(route.ArrivalDeadline)) { return null; } var distance = (carrierMovement.ArrivalTime - currentPath.CurrentTime).TotalHours; return currentPath.AppendAndCreate( distance, carrierMovement.ArrivalTime, target, carrierMovement); }