in Source/Internal/TruckDistanceMatrixGenerator.cs [55:180]
public async Task<Response> Calculate(DistanceMatrixRequest request, Action<int> remainingTimeCallback)
{
if (request.Destinations == null || request.Destinations.Count == 0)
{
request.Destinations = request.Origins;
}
int numIntervals = 1;
int intervalMin = 0;
double numBatches = 0;
if (request.StartTime != null && request.StartTime.HasValue)
{
TimeIntervals = new List<DateTime>() { request.StartTime.Value };
if (request.EndTime != null && request.EndTime.HasValue)
{
intervalMin = request.Resolution * 15;
numIntervals = (int)Math.Floor((request.EndTime.Value - request.StartTime.Value).TotalMinutes / intervalMin);
}
numBatches = Math.Ceiling((double)(request.Destinations.Count * request.Origins.Count * numIntervals) / (double)ServiceManager.QpsLimit);
}
else
{
TimeIntervals = null;
numBatches = Math.Ceiling((double)(request.Destinations.Count * request.Origins.Count) / (double)ServiceManager.QpsLimit);
}
//Assume an average processing time of 2 seconds per batch.
remainingTimeCallback?.Invoke((int)Math.Round(numBatches * 2));
MatrixCells = new List<DistanceMatrixCell>();
//Calculate the first cell on it's own to verify that the request can be made. If it fails, do not proceed.
var firstResponse = await CalculateTruckRoute(request.Origins[0], request.Destinations[0], 0, request).ConfigureAwait(false);
if(firstResponse != null && firstResponse.ErrorDetails != null && firstResponse.ErrorDetails.Length > 0){
return firstResponse;
}
else if (firstResponse == null || firstResponse.ResourceSets == null || firstResponse.ResourceSets.Length == 0 ||
firstResponse.ResourceSets[0].Resources == null || firstResponse.ResourceSets[0].Resources.Length == 0)
{
return new Response()
{
ErrorDetails = new string[] { "Unabble to calculate distance matrix." },
StatusCode = 400,
StatusDescription = "Bad request"
};
}
var truckRoute = firstResponse.ResourceSets[0].Resources[0] as Route;
MatrixCells.Add(new DistanceMatrixCell()
{
OriginIndex = 0,
DestinationIndex = 0,
HasError = false,
TravelDistance = truckRoute.TravelDistance,
TravelDuration = (request.TimeUnits == TimeUnitType.Minute) ? truckRoute.TravelDuration * 60 : truckRoute.TravelDuration
});
var cellTasks = new List<Task>();
if (request.StartTime != null && request.StartTime.HasValue)
{
TimeIntervals.Clear();
for (var k = 0; k < numIntervals; k++)
{
TimeIntervals.Add(request.StartTime.Value.AddMinutes(k * intervalMin));
for (var i = 0; i < request.Origins.Count; i++)
{
for (var j = 0; j < request.Destinations.Count; j++)
{
//Skip the first cell as we already calculated it.
if (!(k==0 && i == 0 && j == 0))
{
cellTasks.Add(CalculateCell(i, j, k, request));
}
}
}
}
}
else
{
for (var i = 0; i < request.Origins.Count; i++)
{
for (var j = 0; j < request.Destinations.Count; j++)
{
//Skip the first cell as we already calculated it.
if (!(i == 0 && j == 0))
{
cellTasks.Add(CalculateCell(i, j, -1, request));
}
}
}
}
await ServiceHelper.WhenAllTaskLimiter(cellTasks).ConfigureAwait(false);
var dm = new DistanceMatrix()
{
Origins = request.Origins,
Destinations = request.Destinations,
Results = MatrixCells.ToArray(),
TimeIntervals = TimeIntervals
};
return new Response()
{
StatusCode = firstResponse.StatusCode,
StatusDescription = firstResponse.StatusDescription,
TraceId = firstResponse.TraceId,
AuthenticationResultCode = firstResponse.AuthenticationResultCode,
BrandLogoUri = firstResponse.BrandLogoUri,
Copyright = firstResponse.Copyright,
ResourceSets = new ResourceSet[]
{
new ResourceSet() {
Resources = new Resource[] { dm }
}
}
};
}