-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDistance.cs
More file actions
111 lines (92 loc) · 4.19 KB
/
Distance.cs
File metadata and controls
111 lines (92 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
namespace DistanceBetweenCities
{
using System;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
public static class Distance
{
private static readonly HttpClient Client = new HttpClient();
private static IConfiguration configuration;
private static string apiKey;
public static async Task<int> Run()
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json");
configuration = builder.Build();
apiKey = configuration["MapQuestApiKey"];
if (apiKey == "key")
{
System.Console.WriteLine("Dont forget to enter your API key in appsettings.json");
return 1;
}
System.Console.Write("Enter the first city: ");
string city1 = Console.ReadLine();
System.Console.Write("Enter the second city: ");
string city2 = Console.ReadLine();
double distance = await CalculateDistance(city1, city2);
System.Console.WriteLine($"The distance between {city1} and {city2} is {String.Format("{0:0.00}", (distance / 1000))} kilometers");
return 0;
}
private static async Task<double> CalculateDistance(string city1, string city2)
{
double[] city1LatLng = await GetLatLngAsync(city1);
double[] city2LatLng = await GetLatLngAsync(city2);
// algorythm and explanation by Chris Veness at: https://www.movable-type.co.uk/scripts/latlong.html
const double R = 6371e3;
double f1 = city1LatLng[0] * Math.PI / 180;
double f2 = city2LatLng[0] * Math.PI / 180;
double dFi = (city1LatLng[0] - city2LatLng[0]) * Math.PI / 180;
double dLam = (city1LatLng[1] - city2LatLng[1]) * Math.PI / 180;
double a = Math.Sin(dFi / 2) * Math.Sin(dFi / 2) +
Math.Cos(f1) * Math.Cos(f2) *
Math.Sin(dLam / 2) * Math.Sin(dLam / 2);
double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
double result = R * c;
return result;
}
private static async Task<double[]> GetLatLngAsync(string city)
{
string response = await Client.GetStringAsync($"http://open.mapquestapi.com/geocoding/v1/address?key={apiKey}&location={city}");
var jsonOptions = new JsonDocumentOptions
{
AllowTrailingCommas = true,
};
using (JsonDocument document = JsonDocument.Parse(response, jsonOptions))
{
JsonElement root = document.RootElement;
JsonElement resultsElement = root.GetProperty("results");
foreach (var field in resultsElement.EnumerateArray())
{
if (field.TryGetProperty("locations", out JsonElement locationsElement))
{
foreach (var item in locationsElement.EnumerateArray())
{
if (item.TryGetProperty("displayLatLng", out JsonElement latLngElement))
{
double[] result = new double[2];
int cnt = 0;
foreach (var item2 in latLngElement.EnumerateObject())
{
if (item2.Name == "lat")
{
result[cnt] = item2.Value.GetDouble();
cnt++;
}
else
{
result[cnt] = item2.Value.GetDouble();
cnt++;
}
}
return result;
}
}
}
}
throw new Exception("Error parsing JSON");
}
}
}
}