public async Task Calculate()

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 }
                    }
                }
            };
        }