add alpha implementation of route search
This commit is contained in:
parent
806a139d3d
commit
7d3ad666c6
14
AutobusApi.Api/Controllers/RouteSearchController.cs
Normal file
14
AutobusApi.Api/Controllers/RouteSearchController.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using AutobusApi.Application.RouteSearch;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace AutobusApi.Api.Controllers;
|
||||||
|
|
||||||
|
[Route("search")]
|
||||||
|
public class RouteSearchController : BaseController
|
||||||
|
{
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<List<RouteWithTransfersDto>> Search([FromBody] RouteSearchQuery query, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return await Mediator.Send(query, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
18
AutobusApi.Api/OpenApi/TimeSpanSchemaFilter.cs
Normal file
18
AutobusApi.Api/OpenApi/TimeSpanSchemaFilter.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
|
||||||
|
namespace AutobusApi.Api.OpenApi;
|
||||||
|
|
||||||
|
public class TimeSpanSchemaFilter : ISchemaFilter
|
||||||
|
{
|
||||||
|
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
|
||||||
|
{
|
||||||
|
if (context.Type == typeof(TimeSpan))
|
||||||
|
{
|
||||||
|
schema.Type = "string";
|
||||||
|
schema.Format = "time-span";
|
||||||
|
schema.Pattern = @"^\d{2}:\d{2}:\d{2}\.\d{3}$";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,8 @@ using AutobusApi.Application;
|
|||||||
using AutobusApi.Api.Middlewares;
|
using AutobusApi.Api.Middlewares;
|
||||||
using AutoubsApi.Infrastructure.Data;
|
using AutoubsApi.Infrastructure.Data;
|
||||||
using AutobusApi.Infrastructure.Identity;
|
using AutobusApi.Infrastructure.Identity;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using AutobusApi.Api.OpenApi;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@ -11,7 +13,33 @@ builder.Services.AddApplication();
|
|||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
|
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen(options =>
|
||||||
|
{
|
||||||
|
options.SchemaFilter<TimeSpanSchemaFilter>();
|
||||||
|
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Scheme = "Bearer",
|
||||||
|
BearerFormat = "Jwt",
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Name = "Authorization",
|
||||||
|
Description = "Bearer Authentication With Jwt",
|
||||||
|
Type = SecuritySchemeType.Http
|
||||||
|
});
|
||||||
|
options.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||||
|
{
|
||||||
|
{
|
||||||
|
new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Reference = new OpenApiReference
|
||||||
|
{
|
||||||
|
Id = "Bearer",
|
||||||
|
Type = ReferenceType.SecurityScheme
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new List<string>()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
builder.Services.AddTransient<GlobalExceptionHandlerMiddleware>();
|
builder.Services.AddTransient<GlobalExceptionHandlerMiddleware>();
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"Issuer": "",
|
"Issuer": "",
|
||||||
"Audience": "",
|
"Audience": "",
|
||||||
"IssuerSigningKey": "a2c98dec80787a4e85ffb5bcbc24f7e4cc014d8a4fe43e9520480a50759164bc",
|
"IssuerSigningKey": "a2c98dec80787a4e85ffb5bcbc24f7e4cc014d8a4fe43e9520480a50759164bc",
|
||||||
"AccessTokenValidityInMinutes": "5",
|
"AccessTokenValidityInMinutes": "60",
|
||||||
"RefreshTokenValidityInDays": "15",
|
"RefreshTokenValidityInDays": "15",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
<Version>7.0.14</Version>
|
<Version>7.0.14</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.7" />
|
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.7" />
|
||||||
|
<PackageReference Include="QuikGraph" Version="2.5.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
22
AutobusApi.Application/Common/Behaviours/LoggingBehaviour.cs
Normal file
22
AutobusApi.Application/Common/Behaviours/LoggingBehaviour.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using MediatR.Pipeline;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace AutobusApi.Application.Common.Behaviours;
|
||||||
|
|
||||||
|
public class LoggingBehaviour<TRequest> : IRequestPreProcessor<TRequest> where TRequest : notnull
|
||||||
|
{
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public LoggingBehaviour(ILogger<TRequest> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Process(TRequest request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var requestName = typeof(TRequest).Name;
|
||||||
|
|
||||||
|
_logger.LogInformation("Request: {Name} {@UserId} {@UserName} {@Request}",
|
||||||
|
requestName, request);
|
||||||
|
}
|
||||||
|
}
|
@ -13,9 +13,9 @@ public class RegisterCommandHandler : IRequestHandler<RegisterCommand>
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task Handle(
|
public async Task Handle(
|
||||||
RegisterCommand command,
|
RegisterCommand request,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await _identityService.RegisterAsync(command.Email, command.Password, cancellationToken);
|
await _identityService.RegisterAsync(request.Email, request.Password, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ public class RenewAccessTokenCommandHandler : IRequestHandler<RenewAccessTokenCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TokensModel> Handle(
|
public async Task<TokensModel> Handle(
|
||||||
RenewAccessTokenCommand command,
|
RenewAccessTokenCommand request,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return await _identityService.RenewAccessTokenAsync(command.RefreshToken, cancellationToken);
|
return await _identityService.RenewAccessTokenAsync(request.RefreshToken, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,9 @@ public class RevokeRefreshTokenCommandHandler : IRequestHandler<RevokeRefreshTok
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task Handle(
|
public async Task Handle(
|
||||||
RevokeRefreshTokenCommand command,
|
RevokeRefreshTokenCommand request,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await _identityService.RevokeRefreshTokenAsync(command.RefreshToken, cancellationToken);
|
await _identityService.RevokeRefreshTokenAsync(request.RefreshToken, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ public class LoginQueryHandler : IRequestHandler<LoginQuery, TokensModel>
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TokensModel> Handle(
|
public async Task<TokensModel> Handle(
|
||||||
LoginQuery query,
|
LoginQuery request,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return await _identityService.LoginAsync(query.Email, query.Password, cancellationToken);
|
return await _identityService.LoginAsync(request.Email, request.Password, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
using AutobusApi.Domain.Entities;
|
||||||
|
|
||||||
|
namespace AutobusApi.Application.RouteSearch;
|
||||||
|
|
||||||
|
public class EnrollmentAddressVertex
|
||||||
|
{
|
||||||
|
public EnrollmentAddressVertex(VehicleEnrollment vehicleEnrollment, Address address)
|
||||||
|
{
|
||||||
|
VehicleEnrollment = vehicleEnrollment;
|
||||||
|
Address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VehicleEnrollment VehicleEnrollment { get; set; }
|
||||||
|
|
||||||
|
public Address Address { get; set; }
|
||||||
|
|
||||||
|
public DateTime GetDepartureDateTimeUtc()
|
||||||
|
{
|
||||||
|
DateTime result = VehicleEnrollment.DepartureDateTimeUtc;
|
||||||
|
|
||||||
|
var rouetAddressDetails = VehicleEnrollment.RouteAddressDetails.OrderBy(rad => rad.RouteAddress.Order);
|
||||||
|
rouetAddressDetails.First().CurrentAddressStopTime = TimeSpan.Zero;
|
||||||
|
|
||||||
|
foreach (var rad in rouetAddressDetails)
|
||||||
|
{
|
||||||
|
result += rad.CurrentAddressStopTime;
|
||||||
|
|
||||||
|
if (rad.RouteAddress.Address.Id == Address.Id)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result += rad.TimeToNextAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime GetArrivalDateTimeUtc()
|
||||||
|
{
|
||||||
|
DateTime result = VehicleEnrollment.DepartureDateTimeUtc;
|
||||||
|
|
||||||
|
var rouetAddressDetails = VehicleEnrollment.RouteAddressDetails.OrderBy(rad => rad.RouteAddress.Order);
|
||||||
|
rouetAddressDetails.First().CurrentAddressStopTime = TimeSpan.Zero;
|
||||||
|
|
||||||
|
foreach (var rad in rouetAddressDetails)
|
||||||
|
{
|
||||||
|
if (rad.RouteAddress.Address.Id == Address.Id)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result += rad.CurrentAddressStopTime;
|
||||||
|
result += rad.TimeToNextAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
if (obj == null || !(obj is EnrollmentAddressVertex))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnrollmentAddressVertex other = (EnrollmentAddressVertex)obj;
|
||||||
|
return this.Address.Id == other.Address.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Address.Id.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
18
AutobusApi.Application/RouteSearch/RouteSearchQuery.cs
Normal file
18
AutobusApi.Application/RouteSearch/RouteSearchQuery.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using MediatR;
|
||||||
|
|
||||||
|
namespace AutobusApi.Application.RouteSearch;
|
||||||
|
|
||||||
|
public record RouteSearchQuery : IRequest<List<RouteWithTransfersDto>>
|
||||||
|
{
|
||||||
|
public required int DepartureAddressId { get; set; }
|
||||||
|
|
||||||
|
public required int ArrivalAddressId { get; set; }
|
||||||
|
|
||||||
|
public required DateOnly DepartureDate { get; set; }
|
||||||
|
|
||||||
|
public required TimeSpan MinTransferTime { get; set; } = TimeSpan.FromMinutes(15);
|
||||||
|
|
||||||
|
public required TimeSpan MaxTransferTime { get; set; } = TimeSpan.FromHours(12);
|
||||||
|
|
||||||
|
public required double MaxTransferDistanceInMeters { get; set; } = 1000;
|
||||||
|
}
|
220
AutobusApi.Application/RouteSearch/RouteSearchQueryHandler.cs
Normal file
220
AutobusApi.Application/RouteSearch/RouteSearchQueryHandler.cs
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
using AutobusApi.Application.Common.Exceptions;
|
||||||
|
using AutobusApi.Application.Common.Interfaces;
|
||||||
|
using AutoMapper;
|
||||||
|
using AutoMapper.QueryableExtensions;
|
||||||
|
using FluentValidation.Results;
|
||||||
|
using MediatR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using QuikGraph;
|
||||||
|
|
||||||
|
namespace AutobusApi.Application.RouteSearch;
|
||||||
|
|
||||||
|
public class RouteSearchQueryHandler : IRequestHandler<RouteSearchQuery, List<RouteWithTransfersDto>>
|
||||||
|
{
|
||||||
|
private readonly IApplicationDbContext _dbContext;
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
|
public RouteSearchQueryHandler(
|
||||||
|
IApplicationDbContext dbContext,
|
||||||
|
IMapper mapper)
|
||||||
|
{
|
||||||
|
_dbContext = dbContext;
|
||||||
|
_mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<RouteWithTransfersDto>> Handle(
|
||||||
|
RouteSearchQuery request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var departureEnrollmentAddressVertex = await GetEnrollmentAddressVertexAsync(request.DepartureAddressId);
|
||||||
|
var arrivalEnrollmentAddressVertex = await GetEnrollmentAddressVertexAsync(request.ArrivalAddressId);
|
||||||
|
|
||||||
|
var graph = await InitializeGraphAsync(request.DepartureDate, cancellationToken);
|
||||||
|
|
||||||
|
var paths = FindAllPaths(graph, departureEnrollmentAddressVertex, arrivalEnrollmentAddressVertex,
|
||||||
|
request.MinTransferTime, request.MaxTransferTime, request.MaxTransferDistanceInMeters);
|
||||||
|
|
||||||
|
return paths.AsQueryable().ProjectTo<RouteWithTransfersDto>(_mapper.ConfigurationProvider).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<AdjacencyGraph<EnrollmentAddressVertex, SEquatableEdge<EnrollmentAddressVertex>>> InitializeGraphAsync(
|
||||||
|
DateOnly departureDate,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var graph = new AdjacencyGraph<EnrollmentAddressVertex, SEquatableEdge<EnrollmentAddressVertex>>();
|
||||||
|
|
||||||
|
var vehicleEnrollmentsArray = await _dbContext.VehicleEnrollments
|
||||||
|
.Include(ve => ve.Route)
|
||||||
|
.ThenInclude(r => r.RouteAddresses)
|
||||||
|
.ThenInclude(ra => ra.Address)
|
||||||
|
.ThenInclude(a => a.City)
|
||||||
|
.ThenInclude(c => c.Region)
|
||||||
|
.ThenInclude(r => r.Country)
|
||||||
|
.Include(ve => ve.Route)
|
||||||
|
.ThenInclude(r => r.RouteAddresses)
|
||||||
|
.ThenInclude(ra => ra.RouteAddressDetails)
|
||||||
|
.Include(ve => ve.Tickets)
|
||||||
|
.ThenInclude(t => t.TicketGroup)
|
||||||
|
.Include(ve => ve.Vehicle)
|
||||||
|
.ThenInclude(v => v.Company)
|
||||||
|
.Where(ve =>
|
||||||
|
DateOnly.FromDateTime(ve.DepartureDateTimeUtc) >= departureDate &&
|
||||||
|
DateOnly.FromDateTime(ve.DepartureDateTimeUtc) < departureDate.AddDays(1))
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var enrollment in vehicleEnrollmentsArray)
|
||||||
|
{
|
||||||
|
var routeAddressesArray = enrollment.Route.RouteAddresses.OrderBy(ra => ra.Order).ToArray();
|
||||||
|
|
||||||
|
var previousVertex = new EnrollmentAddressVertex(enrollment, routeAddressesArray[0].Address);
|
||||||
|
graph.AddVertex(previousVertex);
|
||||||
|
|
||||||
|
for (int i = 1; i < routeAddressesArray.Length; i++)
|
||||||
|
{
|
||||||
|
var currentVertex = new EnrollmentAddressVertex(enrollment, routeAddressesArray[i].Address);
|
||||||
|
graph.AddVertex(currentVertex);
|
||||||
|
graph.AddEdge(new SEquatableEdge<EnrollmentAddressVertex>(previousVertex, currentVertex));
|
||||||
|
|
||||||
|
var vertexFromDifferentRoute = graph.Vertices.FirstOrDefault(v => v.Address.Id == currentVertex.Address.Id);
|
||||||
|
|
||||||
|
if (vertexFromDifferentRoute != null)
|
||||||
|
{
|
||||||
|
graph.AddEdge(new SEquatableEdge<EnrollmentAddressVertex>(currentVertex, vertexFromDifferentRoute));
|
||||||
|
}
|
||||||
|
|
||||||
|
previousVertex = currentVertex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<EnrollmentAddressVertex> GetEnrollmentAddressVertexAsync(int addressId)
|
||||||
|
{
|
||||||
|
var routeAddress = await _dbContext.VehicleEnrollments
|
||||||
|
.Include(ve => ve.Route)
|
||||||
|
.ThenInclude(r => r.RouteAddresses)
|
||||||
|
.ThenInclude(ra => ra.Address)
|
||||||
|
.ThenInclude(a => a.City)
|
||||||
|
.ThenInclude(c => c.Region)
|
||||||
|
.ThenInclude(r => r.Country)
|
||||||
|
.Include(ve => ve.Route)
|
||||||
|
.ThenInclude(r => r.RouteAddresses)
|
||||||
|
.ThenInclude(ra => ra.RouteAddressDetails)
|
||||||
|
.Include(ve => ve.Tickets)
|
||||||
|
.ThenInclude(t => t.TicketGroup)
|
||||||
|
.Include(ve => ve.Vehicle)
|
||||||
|
.ThenInclude(v => v.Company)
|
||||||
|
.SelectMany(ve => ve.Route.RouteAddresses)
|
||||||
|
.FirstOrDefaultAsync(ra => ra.Address.Id == addressId);
|
||||||
|
|
||||||
|
if (routeAddress == null)
|
||||||
|
{
|
||||||
|
throw new ValidationException(new ValidationFailure[] { new ValidationFailure("AddressId", "Departure or Arrival Address with given Id is not found") });
|
||||||
|
}
|
||||||
|
|
||||||
|
return new EnrollmentAddressVertex(null, routeAddress.Address);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<List<EnrollmentAddressVertex>> FindAllPaths(
|
||||||
|
AdjacencyGraph<EnrollmentAddressVertex, SEquatableEdge<EnrollmentAddressVertex>> graph,
|
||||||
|
EnrollmentAddressVertex startVertex,
|
||||||
|
EnrollmentAddressVertex endVertex,
|
||||||
|
TimeSpan minTransferTime,
|
||||||
|
TimeSpan maxTransferTime,
|
||||||
|
double maxTransferDistanceInMeters)
|
||||||
|
{
|
||||||
|
var paths = new List<List<EnrollmentAddressVertex>>();
|
||||||
|
var visited = new HashSet<EnrollmentAddressVertex>();
|
||||||
|
var currentPath = new List<EnrollmentAddressVertex>();
|
||||||
|
|
||||||
|
FindAllPathsDFS(graph, startVertex, endVertex, visited, currentPath, paths, minTransferTime,
|
||||||
|
maxTransferTime, maxTransferDistanceInMeters);
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FindAllPathsDFS(
|
||||||
|
AdjacencyGraph<EnrollmentAddressVertex, SEquatableEdge<EnrollmentAddressVertex>> graph,
|
||||||
|
EnrollmentAddressVertex current,
|
||||||
|
EnrollmentAddressVertex endVertex,
|
||||||
|
HashSet<EnrollmentAddressVertex> visited,
|
||||||
|
List<EnrollmentAddressVertex> currentPath,
|
||||||
|
List<List<EnrollmentAddressVertex>> paths,
|
||||||
|
TimeSpan minTransferTime,
|
||||||
|
TimeSpan maxTransferTime,
|
||||||
|
double maxTransferDistanceInMeters)
|
||||||
|
{
|
||||||
|
visited.Add(current);
|
||||||
|
currentPath.Add(current);
|
||||||
|
|
||||||
|
if (current.Equals(endVertex))
|
||||||
|
{
|
||||||
|
paths.Add(new List<EnrollmentAddressVertex>(currentPath));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var edge in graph.OutEdges(current))
|
||||||
|
{
|
||||||
|
if (!visited.Contains(edge.Target))
|
||||||
|
{
|
||||||
|
if (current.VehicleEnrollment == null)
|
||||||
|
{
|
||||||
|
current.VehicleEnrollment = edge.Target.VehicleEnrollment;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If transfering to other vehicle enrollment
|
||||||
|
if (current.VehicleEnrollment.Id != edge.Target.VehicleEnrollment.Id)
|
||||||
|
{
|
||||||
|
// Skip paths where there is a singular vertex from any Vehicle Enrollment
|
||||||
|
// A - A - A - _B_ <- - C - C
|
||||||
|
|
||||||
|
var threeLast = currentPath.TakeLast(3).ToArray();
|
||||||
|
|
||||||
|
if (currentPath.Count >= 4 &&
|
||||||
|
threeLast[0].VehicleEnrollment.Id != threeLast[1].VehicleEnrollment.Id &&
|
||||||
|
threeLast[1].VehicleEnrollment.Id != threeLast[2].VehicleEnrollment.Id)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by amount of free time between enrollment 1 arrives and enrollment 2 departures
|
||||||
|
|
||||||
|
var freeTime = edge.Target.GetDepartureDateTimeUtc() - current.GetArrivalDateTimeUtc();
|
||||||
|
|
||||||
|
if (freeTime < minTransferTime ||
|
||||||
|
freeTime > maxTransferTime)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by distance between transfer locations
|
||||||
|
|
||||||
|
var currentLocation = current.Address.Location;
|
||||||
|
var targetLocation = edge.Target.Address.Location;
|
||||||
|
|
||||||
|
const double metersInDegree = 111_111.111;
|
||||||
|
|
||||||
|
var distanceInDegrees = Math.Sqrt(
|
||||||
|
Math.Pow(currentLocation.Latitude - targetLocation.Latitude, 2) +
|
||||||
|
Math.Pow(currentLocation.Longitude - targetLocation.Longitude, 2));
|
||||||
|
|
||||||
|
var distanceInMeters = distanceInDegrees * metersInDegree;
|
||||||
|
|
||||||
|
if (distanceInMeters > maxTransferDistanceInMeters)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FindAllPathsDFS(graph, edge.Target, endVertex, visited, currentPath, paths,
|
||||||
|
minTransferTime, maxTransferTime, maxTransferDistanceInMeters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
visited.Remove(current);
|
||||||
|
currentPath.RemoveAt(currentPath.Count - 1);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
using FluentValidation;
|
||||||
|
|
||||||
|
namespace AutobusApi.Application.RouteSearch;
|
||||||
|
|
||||||
|
public class RouteSearchQueryValidator : AbstractValidator<RouteSearchQuery>
|
||||||
|
{
|
||||||
|
public RouteSearchQueryValidator()
|
||||||
|
{
|
||||||
|
// RuleFor(v => v.Email)
|
||||||
|
// .NotEmpty().WithMessage("Email address is required.")
|
||||||
|
// .EmailAddress().WithMessage("Email address is invalid.");
|
||||||
|
}
|
||||||
|
}
|
143
AutobusApi.Application/RouteSearch/RouteWithTransfersDto.cs
Normal file
143
AutobusApi.Application/RouteSearch/RouteWithTransfersDto.cs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
using AutobusApi.Application.Common.Mappings;
|
||||||
|
using AutoMapper;
|
||||||
|
|
||||||
|
namespace AutobusApi.Application.RouteSearch;
|
||||||
|
|
||||||
|
public class RouteWithTransfersDto : IMapFrom<List<EnrollmentAddressVertex>>
|
||||||
|
{
|
||||||
|
public List<SubRouteDto> Routes { get; set; } = null!;
|
||||||
|
|
||||||
|
public TimeSpan TotalTravelTime { get; set; }
|
||||||
|
|
||||||
|
public double TotalCost { get; set; }
|
||||||
|
|
||||||
|
// public int NumberOfTransfers { get; set; }
|
||||||
|
|
||||||
|
public DateTime DeparuteDateTime { get; set; }
|
||||||
|
|
||||||
|
public DateTime ArrivalDateTime { get; set; }
|
||||||
|
|
||||||
|
public void Mapping(Profile profile)
|
||||||
|
{
|
||||||
|
profile.CreateMap<List<EnrollmentAddressVertex>, RouteWithTransfersDto>()
|
||||||
|
.ForMember(
|
||||||
|
d => d.TotalCost,
|
||||||
|
opt => opt.MapFrom(
|
||||||
|
s => s
|
||||||
|
.SkipLast(1)
|
||||||
|
.Select(eav => eav.VehicleEnrollment)
|
||||||
|
.SelectMany(ve => ve.RouteAddressDetails)
|
||||||
|
.Select(rad => rad.CostToNextAddress)
|
||||||
|
.Aggregate(0.0, (sum, val) => sum + val)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.ForMember(
|
||||||
|
d => d.TotalTravelTime,
|
||||||
|
opt => opt.MapFrom(
|
||||||
|
s =>
|
||||||
|
s.Last().VehicleEnrollment.GetArrivalDateTimeUtc(s.Last().Address.Id) -
|
||||||
|
s.First().VehicleEnrollment.GetDepartureDateTimeUtc(s.First().Address.Id)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.ForMember(d => d.DeparuteDateTime, opt => opt.MapFrom(s => s.First().VehicleEnrollment.GetDepartureDateTimeUtc(s.First().Address.Id)))
|
||||||
|
.ForMember(d => d.ArrivalDateTime, opt => opt.MapFrom(s => s.Last().VehicleEnrollment.GetArrivalDateTimeUtc(s.Last().Address.Id)))
|
||||||
|
.ForMember(d => d.Routes, opt => opt.MapFrom(s => CreateRoutes(s)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SubRouteDto> CreateRoutes(List<EnrollmentAddressVertex> vertices)
|
||||||
|
{
|
||||||
|
var result = new List<SubRouteDto>();
|
||||||
|
|
||||||
|
var groupedByVehicle = vertices.GroupBy(ev => ev.VehicleEnrollment);
|
||||||
|
|
||||||
|
int order = 1;
|
||||||
|
foreach (var group in groupedByVehicle)
|
||||||
|
{
|
||||||
|
|
||||||
|
var subRouteDto = new SubRouteDto
|
||||||
|
{
|
||||||
|
Stations = new List<StationDto>(),
|
||||||
|
VehicleType = "Unknown",//group.Key.Vehicle.Type, // Replace with the actual property to fetch VehicleType
|
||||||
|
CompanyName = group.Key.Vehicle.Company.Name, // Replace with the actual property to fetch CompanyName
|
||||||
|
CompanyId = group.Key.Vehicle.Company.Id, // Replace with the actual property to fetch CompanyId
|
||||||
|
Order = order
|
||||||
|
// Other properties initialization
|
||||||
|
};
|
||||||
|
|
||||||
|
order++;
|
||||||
|
|
||||||
|
foreach (var enrollmentVertex in group)
|
||||||
|
{
|
||||||
|
var stationDto = new StationDto
|
||||||
|
{
|
||||||
|
AddressId = enrollmentVertex.Address.Id,
|
||||||
|
AddressName = enrollmentVertex.Address.Name,
|
||||||
|
CityId = enrollmentVertex.Address.CityId,
|
||||||
|
CityName = enrollmentVertex.Address.City.Name,
|
||||||
|
RegionId = enrollmentVertex.Address.City.RegionId,
|
||||||
|
RegionName = enrollmentVertex.Address.City.Region.Name,
|
||||||
|
CountryId = enrollmentVertex.Address.City.Region.CountryId,
|
||||||
|
CountryName = enrollmentVertex.Address.City.Region.Country.Name,
|
||||||
|
DeparureTime = enrollmentVertex.GetDepartureDateTimeUtc(),
|
||||||
|
ArrivalTime = enrollmentVertex.GetArrivalDateTimeUtc(),
|
||||||
|
StopTime = enrollmentVertex.GetDepartureDateTimeUtc() - enrollmentVertex.GetArrivalDateTimeUtc(),
|
||||||
|
Latitude = enrollmentVertex.Address.Location.Latitude,
|
||||||
|
Longitude = enrollmentVertex.Address.Location.Longitude
|
||||||
|
};
|
||||||
|
|
||||||
|
subRouteDto.Stations.Add(stationDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Add(subRouteDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SubRouteDto
|
||||||
|
{
|
||||||
|
public List<StationDto> Stations { get; set; } = null!;
|
||||||
|
|
||||||
|
public string VehicleType { get; set; } = null!;
|
||||||
|
|
||||||
|
public string CompanyName { get; set; } = null!;
|
||||||
|
|
||||||
|
public int CompanyId { get; set; }
|
||||||
|
|
||||||
|
public int TicketsAvailable { get; set; }
|
||||||
|
|
||||||
|
public int TicketsBought { get; set; }
|
||||||
|
|
||||||
|
public int Order { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StationDto : IMapFrom<EnrollmentAddressVertex>
|
||||||
|
{
|
||||||
|
public int AddressId { get; set; }
|
||||||
|
|
||||||
|
public string AddressName { get; set; } = null!;
|
||||||
|
|
||||||
|
public int CityId { get; set; }
|
||||||
|
|
||||||
|
public string CityName { get; set; } = null!;
|
||||||
|
|
||||||
|
public int RegionId { get; set; }
|
||||||
|
|
||||||
|
public string RegionName { get; set; } = null!;
|
||||||
|
|
||||||
|
public int CountryId { get; set; }
|
||||||
|
|
||||||
|
public string CountryName { get; set; } = null!;
|
||||||
|
|
||||||
|
public DateTime DeparureTime { get; set; }
|
||||||
|
|
||||||
|
public DateTime ArrivalTime { get; set; }
|
||||||
|
|
||||||
|
public TimeSpan StopTime { get; set; }
|
||||||
|
|
||||||
|
public double Latitude { get; set; }
|
||||||
|
|
||||||
|
public double Longitude { get; set; }
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
|
using AutobusApi.Domain.Entities;
|
||||||
using AutobusApi.Domain.Enums;
|
using AutobusApi.Domain.Enums;
|
||||||
|
using AutobusApi.Infrastructure.Data.Entities;
|
||||||
using AutobusApi.Infrastructure.Identity;
|
using AutobusApi.Infrastructure.Identity;
|
||||||
using AutoubsApi.Infrastructure.Data;
|
using AutoubsApi.Infrastructure.Data;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
@ -46,6 +48,454 @@ public static class DbInitializer
|
|||||||
private static void InitializeDomain(ApplicationDbContext dbContext)
|
private static void InitializeDomain(ApplicationDbContext dbContext)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
var country1 = new Country()
|
||||||
|
{
|
||||||
|
Name = "Country A"
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Countries.AddRange(new[] { country1 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var region1 = new Region()
|
||||||
|
{
|
||||||
|
Name = "Region A",
|
||||||
|
Country = country1
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Regions.AddRange(new[] { region1 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var city1 = new City()
|
||||||
|
{
|
||||||
|
Name = "City A",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city2 = new City()
|
||||||
|
{
|
||||||
|
Name = "City B",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city3 = new City()
|
||||||
|
{
|
||||||
|
Name = "City C",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city4 = new City()
|
||||||
|
{
|
||||||
|
Name = "City D",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city5 = new City()
|
||||||
|
{
|
||||||
|
Name = "City E",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city6 = new City()
|
||||||
|
{
|
||||||
|
Name = "City F",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city7 = new City()
|
||||||
|
{
|
||||||
|
Name = "City G",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city8 = new City()
|
||||||
|
{
|
||||||
|
Name = "City H",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city9 = new City()
|
||||||
|
{
|
||||||
|
Name = "City I",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city10 = new City()
|
||||||
|
{
|
||||||
|
Name = "City J",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Cities.AddRange(new[] { city1, city2, city3, city4, city5, city6, city7, city8, city9, city10 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var address1 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address A",
|
||||||
|
Location = new Coordinates(11, 11),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city1
|
||||||
|
};
|
||||||
|
|
||||||
|
var address2 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address B",
|
||||||
|
Location = new Coordinates(22, 22),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city2
|
||||||
|
};
|
||||||
|
|
||||||
|
var address3 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address C",
|
||||||
|
Location = new Coordinates(33, 33),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city3
|
||||||
|
};
|
||||||
|
|
||||||
|
var address4 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address E",
|
||||||
|
Location = new Coordinates(44, 44),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city4
|
||||||
|
};
|
||||||
|
|
||||||
|
var address5 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address F",
|
||||||
|
Location = new Coordinates(55, 55),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city5
|
||||||
|
};
|
||||||
|
|
||||||
|
var address6 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address G",
|
||||||
|
Location = new Coordinates(66, 66),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city6
|
||||||
|
};
|
||||||
|
|
||||||
|
var address7 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address H",
|
||||||
|
Location = new Coordinates(77, 77),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city7
|
||||||
|
};
|
||||||
|
|
||||||
|
var address8 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address I",
|
||||||
|
Location = new Coordinates(88, 88),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city8
|
||||||
|
};
|
||||||
|
|
||||||
|
var address9 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address J",
|
||||||
|
Location = new Coordinates(99, 99),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city9
|
||||||
|
};
|
||||||
|
|
||||||
|
var address10 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address K",
|
||||||
|
Location = new Coordinates(110, 110),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city10
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Addresses.AddRange(new[] { address1, address2, address3, address4, address5, address6, address7, address8, address9, address10 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var route1 = new Route()
|
||||||
|
{
|
||||||
|
RouteAddresses = new RouteAddress[]
|
||||||
|
{
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 1,
|
||||||
|
Address = address1
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 2,
|
||||||
|
Address = address2
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 3,
|
||||||
|
Address = address3
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 4,
|
||||||
|
Address = address4
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 5,
|
||||||
|
Address = address5
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 6,
|
||||||
|
Address = address8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var route2 = new Route()
|
||||||
|
{
|
||||||
|
RouteAddresses = new RouteAddress[]
|
||||||
|
{
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 1,
|
||||||
|
Address = address2
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 2,
|
||||||
|
Address = address3
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 3,
|
||||||
|
Address = address6
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 4,
|
||||||
|
Address = address7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var route3 = new Route()
|
||||||
|
{
|
||||||
|
RouteAddresses = new RouteAddress[]
|
||||||
|
{
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 1,
|
||||||
|
Address = address6
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 2,
|
||||||
|
Address = address8
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 3,
|
||||||
|
Address = address9
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 4,
|
||||||
|
Address = address10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Routes.AddRange(new[] { route1, route2, route3 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var company1 = new Company
|
||||||
|
{
|
||||||
|
Name = "Smartlines",
|
||||||
|
LegalAddress = "1234 Spectrum Avenue, Metroville, XYZ 98765, United States",
|
||||||
|
ContactEmail = "support@smartlines.com",
|
||||||
|
ContactPhoneNumber = "+00000000000"
|
||||||
|
};
|
||||||
|
|
||||||
|
var company2 = new Company
|
||||||
|
{
|
||||||
|
Name = "ecobus",
|
||||||
|
LegalAddress = "5678 Galaxy Street, Cosmic City, ABC 54321, United States",
|
||||||
|
ContactEmail = "support@ecobus.com",
|
||||||
|
ContactPhoneNumber = "+00000000000"
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Companies.AddRange(new[] { company1, company2 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var vehicle1 = new Bus()
|
||||||
|
{
|
||||||
|
Number = "AC8236HK",
|
||||||
|
Model = "Mercedes-Benz Citaro",
|
||||||
|
Capacity = 20,
|
||||||
|
HasWC = true,
|
||||||
|
HasWiFi = false,
|
||||||
|
HasOutlets = true,
|
||||||
|
HasMultimedia = false,
|
||||||
|
HasClimateControl = true,
|
||||||
|
Company = company1
|
||||||
|
};
|
||||||
|
|
||||||
|
var vehicle2 = new Bus()
|
||||||
|
{
|
||||||
|
Number = "EP2566MK",
|
||||||
|
Model = "Van Hool TDX25",
|
||||||
|
Capacity = 25,
|
||||||
|
HasWC = true,
|
||||||
|
HasWiFi = false,
|
||||||
|
HasOutlets = true,
|
||||||
|
HasMultimedia = false,
|
||||||
|
HasClimateControl = true,
|
||||||
|
Company = company2
|
||||||
|
};
|
||||||
|
|
||||||
|
var vehicle3 = new Bus()
|
||||||
|
{
|
||||||
|
Number = "OK8634MC",
|
||||||
|
Model = "New Flyer Xcelsior",
|
||||||
|
Capacity = 30,
|
||||||
|
HasWC = true,
|
||||||
|
HasWiFi = false,
|
||||||
|
HasOutlets = true,
|
||||||
|
HasMultimedia = false,
|
||||||
|
HasClimateControl = true,
|
||||||
|
Company = company1
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Vehicles.AddRange(new[] { vehicle1, vehicle2, vehicle3 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var vehicleEnrollment1 = new VehicleEnrollment()
|
||||||
|
{
|
||||||
|
DepartureDateTimeUtc = DateTime.UtcNow,
|
||||||
|
Vehicle = vehicle1,
|
||||||
|
Route = route1,
|
||||||
|
RouteAddressDetails = new RouteAddressDetails[]
|
||||||
|
{
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(50),
|
||||||
|
CostToNextAddress = 25,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route1.RouteAddresses.ToArray()[0],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(40),
|
||||||
|
CostToNextAddress = 20,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route1.RouteAddresses.ToArray()[1],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(45),
|
||||||
|
CostToNextAddress = 23.33,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route1.RouteAddresses.ToArray()[2],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(25),
|
||||||
|
CostToNextAddress = 15,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route1.RouteAddresses.ToArray()[3],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(30),
|
||||||
|
CostToNextAddress = 17.5,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route1.RouteAddresses.ToArray()[4],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(35),
|
||||||
|
CostToNextAddress = 19,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route1.RouteAddresses.ToArray()[5],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var vehicleEnrollment2 = new VehicleEnrollment()
|
||||||
|
{
|
||||||
|
DepartureDateTimeUtc = DateTime.UtcNow.AddMinutes(30),
|
||||||
|
Vehicle = vehicle2,
|
||||||
|
Route = route2,
|
||||||
|
RouteAddressDetails = new RouteAddressDetails[]
|
||||||
|
{
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(40),
|
||||||
|
CostToNextAddress = 25,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[0],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(50),
|
||||||
|
CostToNextAddress = 20,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[1],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(45),
|
||||||
|
CostToNextAddress = 23.33,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[2],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(25),
|
||||||
|
CostToNextAddress = 15,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[3],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var vehicleEnrollment3 = new VehicleEnrollment()
|
||||||
|
{
|
||||||
|
DepartureDateTimeUtc = DateTime.UtcNow.AddMinutes(175),
|
||||||
|
Vehicle = vehicle3,
|
||||||
|
Route = route3,
|
||||||
|
RouteAddressDetails = new RouteAddressDetails[]
|
||||||
|
{
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(50),
|
||||||
|
CostToNextAddress = 25,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[0],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(40),
|
||||||
|
CostToNextAddress = 20,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[1],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(45),
|
||||||
|
CostToNextAddress = 23.33,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[2],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(25),
|
||||||
|
CostToNextAddress = 15,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[3],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.VehicleEnrollments.AddRange(new[] { vehicleEnrollment1, vehicleEnrollment2/* , vehicleEnrollment3 */ });
|
||||||
|
dbContext.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void InitializeIdentity(ApplicationIdentityDbContext identityDbContext)
|
private static void InitializeIdentity(ApplicationIdentityDbContext identityDbContext)
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
using AutobusApi.Domain.Entities;
|
||||||
|
using AutobusApi.Domain.Enums;
|
||||||
|
using AutobusApi.Infrastructure.Data.Entities;
|
||||||
using AutobusApi.Infrastructure.Identity;
|
using AutobusApi.Infrastructure.Identity;
|
||||||
using AutoubsApi.Infrastructure.Data;
|
using AutoubsApi.Infrastructure.Data;
|
||||||
|
using Route = AutobusApi.Domain.Entities.Route;
|
||||||
|
|
||||||
namespace AutobusApi.IntegrationTests;
|
namespace AutobusApi.IntegrationTests;
|
||||||
|
|
||||||
@ -14,7 +18,454 @@ public static class DbInitializer
|
|||||||
|
|
||||||
private static void InitializeDomain(ApplicationDbContext dbContext)
|
private static void InitializeDomain(ApplicationDbContext dbContext)
|
||||||
{
|
{
|
||||||
|
var country1 = new Country()
|
||||||
|
{
|
||||||
|
Name = "Country A"
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Countries.AddRange(new[] { country1 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var region1 = new Region()
|
||||||
|
{
|
||||||
|
Name = "Region A",
|
||||||
|
Country = country1
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Regions.AddRange(new[] { region1 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var city1 = new City()
|
||||||
|
{
|
||||||
|
Name = "City A",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city2 = new City()
|
||||||
|
{
|
||||||
|
Name = "City B",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city3 = new City()
|
||||||
|
{
|
||||||
|
Name = "City C",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city4 = new City()
|
||||||
|
{
|
||||||
|
Name = "City D",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city5 = new City()
|
||||||
|
{
|
||||||
|
Name = "City E",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city6 = new City()
|
||||||
|
{
|
||||||
|
Name = "City F",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city7 = new City()
|
||||||
|
{
|
||||||
|
Name = "City G",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city8 = new City()
|
||||||
|
{
|
||||||
|
Name = "City H",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city9 = new City()
|
||||||
|
{
|
||||||
|
Name = "City I",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
var city10 = new City()
|
||||||
|
{
|
||||||
|
Name = "City J",
|
||||||
|
Region = region1
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Cities.AddRange(new[] { city1, city2, city3, city4, city5, city6, city7, city8, city9, city10 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var address1 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address A",
|
||||||
|
Location = new Coordinates(11, 11),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city1
|
||||||
|
};
|
||||||
|
|
||||||
|
var address2 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address B",
|
||||||
|
Location = new Coordinates(22, 22),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city2
|
||||||
|
};
|
||||||
|
|
||||||
|
var address3 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address C",
|
||||||
|
Location = new Coordinates(33, 33),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city3
|
||||||
|
};
|
||||||
|
|
||||||
|
var address4 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address E",
|
||||||
|
Location = new Coordinates(44, 44),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city4
|
||||||
|
};
|
||||||
|
|
||||||
|
var address5 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address F",
|
||||||
|
Location = new Coordinates(55, 55),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city5
|
||||||
|
};
|
||||||
|
|
||||||
|
var address6 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address G",
|
||||||
|
Location = new Coordinates(66, 66),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city6
|
||||||
|
};
|
||||||
|
|
||||||
|
var address7 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address H",
|
||||||
|
Location = new Coordinates(77, 77),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city7
|
||||||
|
};
|
||||||
|
|
||||||
|
var address8 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address I",
|
||||||
|
Location = new Coordinates(88, 88),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city8
|
||||||
|
};
|
||||||
|
|
||||||
|
var address9 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address J",
|
||||||
|
Location = new Coordinates(99, 99),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city9
|
||||||
|
};
|
||||||
|
|
||||||
|
var address10 = new Address()
|
||||||
|
{
|
||||||
|
Name = "address K",
|
||||||
|
Location = new Coordinates(110, 110),
|
||||||
|
VehicleType = VehicleType.Bus,
|
||||||
|
City = city10
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Addresses.AddRange(new[] { address1, address2, address3, address4, address5, address6, address7, address8, address9, address10 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var route1 = new Route()
|
||||||
|
{
|
||||||
|
RouteAddresses = new RouteAddress[]
|
||||||
|
{
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 1,
|
||||||
|
Address = address1
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 2,
|
||||||
|
Address = address2
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 3,
|
||||||
|
Address = address3
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 4,
|
||||||
|
Address = address4
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 5,
|
||||||
|
Address = address5
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 6,
|
||||||
|
Address = address8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var route2 = new Route()
|
||||||
|
{
|
||||||
|
RouteAddresses = new RouteAddress[]
|
||||||
|
{
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 1,
|
||||||
|
Address = address2
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 2,
|
||||||
|
Address = address3
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 3,
|
||||||
|
Address = address6
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 4,
|
||||||
|
Address = address7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var route3 = new Route()
|
||||||
|
{
|
||||||
|
RouteAddresses = new RouteAddress[]
|
||||||
|
{
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 1,
|
||||||
|
Address = address6
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 2,
|
||||||
|
Address = address8
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 3,
|
||||||
|
Address = address9
|
||||||
|
},
|
||||||
|
new RouteAddress
|
||||||
|
{
|
||||||
|
Order = 4,
|
||||||
|
Address = address10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Routes.AddRange(new[] { route1, route2, route3 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var company1 = new Company
|
||||||
|
{
|
||||||
|
Name = "Smartlines",
|
||||||
|
LegalAddress = "1234 Spectrum Avenue, Metroville, XYZ 98765, United States",
|
||||||
|
ContactEmail = "support@smartlines.com",
|
||||||
|
ContactPhoneNumber = "+00000000000"
|
||||||
|
};
|
||||||
|
|
||||||
|
var company2 = new Company
|
||||||
|
{
|
||||||
|
Name = "ecobus",
|
||||||
|
LegalAddress = "5678 Galaxy Street, Cosmic City, ABC 54321, United States",
|
||||||
|
ContactEmail = "support@ecobus.com",
|
||||||
|
ContactPhoneNumber = "+00000000000"
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Companies.AddRange(new[] { company1, company2 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var vehicle1 = new Bus()
|
||||||
|
{
|
||||||
|
Number = "AC8236HK",
|
||||||
|
Model = "Mercedes-Benz Citaro",
|
||||||
|
Capacity = 20,
|
||||||
|
HasWC = true,
|
||||||
|
HasWiFi = false,
|
||||||
|
HasOutlets = true,
|
||||||
|
HasMultimedia = false,
|
||||||
|
HasClimateControl = true,
|
||||||
|
Company = company1
|
||||||
|
};
|
||||||
|
|
||||||
|
var vehicle2 = new Bus()
|
||||||
|
{
|
||||||
|
Number = "EP2566MK",
|
||||||
|
Model = "Van Hool TDX25",
|
||||||
|
Capacity = 25,
|
||||||
|
HasWC = true,
|
||||||
|
HasWiFi = false,
|
||||||
|
HasOutlets = true,
|
||||||
|
HasMultimedia = false,
|
||||||
|
HasClimateControl = true,
|
||||||
|
Company = company2
|
||||||
|
};
|
||||||
|
|
||||||
|
var vehicle3 = new Bus()
|
||||||
|
{
|
||||||
|
Number = "OK8634MC",
|
||||||
|
Model = "New Flyer Xcelsior",
|
||||||
|
Capacity = 30,
|
||||||
|
HasWC = true,
|
||||||
|
HasWiFi = false,
|
||||||
|
HasOutlets = true,
|
||||||
|
HasMultimedia = false,
|
||||||
|
HasClimateControl = true,
|
||||||
|
Company = company1
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.Vehicles.AddRange(new[] { vehicle1, vehicle2, vehicle3 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var vehicleEnrollment1 = new VehicleEnrollment()
|
||||||
|
{
|
||||||
|
DepartureDateTimeUtc = DateTime.UtcNow,
|
||||||
|
Vehicle = vehicle1,
|
||||||
|
Route = route1,
|
||||||
|
RouteAddressDetails = new RouteAddressDetails[]
|
||||||
|
{
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(50),
|
||||||
|
CostToNextAddress = 25,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route1.RouteAddresses.ToArray()[0],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(40),
|
||||||
|
CostToNextAddress = 20,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route1.RouteAddresses.ToArray()[1],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(45),
|
||||||
|
CostToNextAddress = 23.33,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route1.RouteAddresses.ToArray()[2],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(25),
|
||||||
|
CostToNextAddress = 15,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route1.RouteAddresses.ToArray()[3],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(30),
|
||||||
|
CostToNextAddress = 17.5,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route1.RouteAddresses.ToArray()[4],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(35),
|
||||||
|
CostToNextAddress = 19,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route1.RouteAddresses.ToArray()[5],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var vehicleEnrollment2 = new VehicleEnrollment()
|
||||||
|
{
|
||||||
|
DepartureDateTimeUtc = DateTime.UtcNow.AddMinutes(30),
|
||||||
|
Vehicle = vehicle2,
|
||||||
|
Route = route2,
|
||||||
|
RouteAddressDetails = new RouteAddressDetails[]
|
||||||
|
{
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(40),
|
||||||
|
CostToNextAddress = 25,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[0],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(50),
|
||||||
|
CostToNextAddress = 20,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[1],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(45),
|
||||||
|
CostToNextAddress = 23.33,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[2],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(25),
|
||||||
|
CostToNextAddress = 15,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[3],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var vehicleEnrollment3 = new VehicleEnrollment()
|
||||||
|
{
|
||||||
|
DepartureDateTimeUtc = DateTime.UtcNow.AddMinutes(175),
|
||||||
|
Vehicle = vehicle3,
|
||||||
|
Route = route3,
|
||||||
|
RouteAddressDetails = new RouteAddressDetails[]
|
||||||
|
{
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(50),
|
||||||
|
CostToNextAddress = 25,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[0],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(40),
|
||||||
|
CostToNextAddress = 20,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[1],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(45),
|
||||||
|
CostToNextAddress = 23.33,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[2],
|
||||||
|
},
|
||||||
|
new RouteAddressDetails()
|
||||||
|
{
|
||||||
|
TimeToNextAddress = TimeSpan.FromMinutes(25),
|
||||||
|
CostToNextAddress = 15,
|
||||||
|
CurrentAddressStopTime = TimeSpan.FromMinutes(5),
|
||||||
|
RouteAddress = route2.RouteAddresses.ToArray()[3],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dbContext.VehicleEnrollments.AddRange(new[] { vehicleEnrollment1, vehicleEnrollment2, vehicleEnrollment3 });
|
||||||
|
dbContext.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void InitializeIdentity(ApplicationIdentityDbContext identityDbContext)
|
private static void InitializeIdentity(ApplicationIdentityDbContext identityDbContext)
|
||||||
|
31
AutobusApi.IntegrationTests/Tests/RouteSearchTests.cs
Normal file
31
AutobusApi.IntegrationTests/Tests/RouteSearchTests.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using System.Net;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace AutobusApi.IntegrationTests.Tests;
|
||||||
|
|
||||||
|
public class RouteSearchTests : TestsBase
|
||||||
|
{
|
||||||
|
public RouteSearchTests(CustomWebApplicationFactory<Program> factory)
|
||||||
|
: base(factory) {}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(1, 10)]
|
||||||
|
public async Task RouteSearch_ValidStationsAndDate_Returns200OK(int fromId, int toId)
|
||||||
|
{
|
||||||
|
var query = new
|
||||||
|
{
|
||||||
|
DepartureAddressId = fromId,
|
||||||
|
ArrivalAddressId = toId,
|
||||||
|
DepartureDate = DateOnly.FromDateTime(DateTime.UtcNow.Date),
|
||||||
|
MinTransferTime = TimeSpan.FromMinutes(15),
|
||||||
|
MaxTransferTime = TimeSpan.FromHours(12),
|
||||||
|
MaxTransferDistanceInMeters = 1000
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await _httpClient.PostAsJsonAsync("search", query);
|
||||||
|
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
|
||||||
|
var content = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user