private Task <MapsResult> FindFlightRouteAsync(TravelRequestData data)
        {
            // Setup Flight Calculator Crawling
            var baseUrl    = $"https://www.travelmath.com/flying-time";
            var parameters = new Dictionary <string, string>()
            {
                { "from", data.From },
                { "to", data.To }
            };
            var url = baseUrl + "/" + string.Join('/', parameters.Select(pair => $"{pair.Key}/{pair.Value}"));

            // Get response
            var client     = new RestClient(url);
            var response   = client.Execute(new RestRequest());
            var sourceCode = response.Content;

            // Find flight time
            const string regex   = "<h3 class=\"space\" id=\"flyingtime\">((\\d+) hours?, )?(\\d+) minutes?</h3>";
            var          match   = Regex.Match(sourceCode, regex);
            var          hours   = int.Parse(string.IsNullOrEmpty(match.Groups[2].Value) ? "0" : match.Groups[2].Value);
            var          minutes = int.Parse(match.Groups[3].Value);
            var          time    = new TimeSpan(hours, minutes, 0) + new TimeSpan(0, 40, 0);

            var result = new MapsResult()
            {
                Original_time = time.Hours + (time.Minutes / 60.0),
                Departure     = data.From,
                Destination   = data.To,
                LocationUrl   = null,
                Method        = "Flight"
            };

            return(Task.FromResult(result));
        }
        private Task <double> CalculateSavingAsync(MapsResult transitData, MapsResult flightData)
        {
            var flightEmissions  = flightData.Original_time * 200.0;
            var transitEmissions = flightEmissions * 0.15;

            return(Task.FromResult(flightEmissions - transitEmissions));
        }
        private Task <MapsResult> FindTransitAlternativeAsync(TravelRequestData data)
        {
            // Call Google API
            var baseUrl    = $"https://maps.googleapis.com/maps/api/directions/json?key={GoogleApiKey}";
            var parameters = new Dictionary <string, string>()
            {
                { "origin", data.From },
                { "destination", data.To },
                //{ "departure_time", "now" },
                { "departure_time", ((DateTimeOffset)data.Date.AddHours(9)).ToUnixTimeSeconds().ToString() },
                { "mode", "transit" }
            };
            var url = baseUrl + "&" + string.Join('&', parameters.Select(pair => $"{pair.Key}={pair.Value}"));

            // Get response
            var     client   = new RestClient(url);
            var     response = client.Execute(new RestRequest());
            dynamic result   = JsonConvert.DeserializeObject(response.Content);

            // Parse response
            if (result.status != "OK" || result.routes.Count == 0)
            {
                throw new AlternativeNotFoundException();
            }
            MapsResult bestResult = null;

            foreach (var route in result.routes)
            {
                var leg  = route.legs[0];
                var time = leg.duration.value / 3600.0;
                if (bestResult != null && time > bestResult.Travel_time)
                {
                    continue;
                }

                // Prepare result
                bestResult = new MapsResult()
                {
                    Travel_time = time,
                    Departure   = leg.start_address,
                    Destination = leg.end_address,
                    Method      = "Transit",
                    LocationUrl = $"https://www.google.com/maps/dir/{leg.start_address}/{leg.end_address}/"
                };
            }

            if (bestResult == null)
            {
                throw new AlternativeNotFoundException();
            }

            return(Task.FromResult(bestResult));
        }