-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
134 lines (111 loc) · 6.28 KB
/
Program.cs
File metadata and controls
134 lines (111 loc) · 6.28 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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* TODO:
* - Report regions for which no ISO code is found
* - Report failures to get level
*/
using System.Text;
using System.Text.Json;
using AngleSharp.Dom;
using AngleSharp.Html.Dom;
using AngleSharp.Html.Parser;
namespace AdvisoryMap
{
internal class Program
{
async static Task Main(string[] args)
{
string[] RegionsToSkip = { "Azores", "Canary Islands", "Saint-Pierre-et-Miquelon" };
var entries = new SortedDictionary<string, AdvisoryEntry>();
var isoMapper = new IsoMapper();
HttpClient client = new();
HtmlParser parser = new();
var responseBody = await client.GetStringAsync("https://travel.gc.ca/");
var document = await parser.ParseDocumentAsync(responseBody);
IElement? countriesDropDown = document.QuerySelector("#CountryDropDown1_ddlCountries");
if (countriesDropDown is null)
{
Console.WriteLine("Can't find list of countries");
return;
}
foreach (var country in countriesDropDown.Children)
{
IHtmlOptionElement? countryOption = country as IHtmlOptionElement;
if (countryOption is not null && !string.IsNullOrWhiteSpace(countryOption.Value))
{
string countryName = country.Text().Split(',')[0];
string countryDirectoryName = countryOption.Value;
if (RegionsToSkip.Contains(countryName))
{
continue;
}
string isoCode = isoMapper.NameToCode(countryName);
if (string.IsNullOrEmpty(isoCode))
{
Console.WriteLine($"Can't find ISO code for {countryName}");
}
else
{
AdvisoryLevel level = await GetAdvisoryLevel(countryDirectoryName, client, parser);
if (level == AdvisoryLevel.Invalid)
{
Console.WriteLine($"Can't find advisory level for {countryName}");
}
else
{
entries[isoCode] = new AdvisoryEntry(countryName, countryDirectoryName, isoCode, level, DateTimeOffset.UtcNow);
}
}
}
}
// Add an entry for Canada
entries["CA"] = new AdvisoryEntry("Canada", "canada", "CA", AdvisoryLevel.Normal, DateTimeOffset.UtcNow);
// Add an entry for Svalbard and Jan Mayen (Norwegian islands)
entries["SJ"] = new AdvisoryEntry("Svalbard and Jan Mayen", "norway", "SJ", AdvisoryLevel.Normal, DateTimeOffset.UtcNow);
// Add an entry for Western Sahara
entries["SJ"] = new AdvisoryEntry("Western Sahara", "morocco", "EH", AdvisoryLevel.AvoidNonEssentialTravel, DateTimeOffset.UtcNow);
string jsonString = JsonSerializer.Serialize(entries);
await File.WriteAllTextAsync(@"C:\Users\gillahaye\Desktop\entries.json", jsonString);
string colorCodedMap = GenerateColorCodedMap(entries);
await File.WriteAllTextAsync(@"C:\Users\gillahaye\Desktop\map.html", colorCodedMap);
}
async static Task<AdvisoryLevel> GetAdvisoryLevel(string countryDirectory, HttpClient client, HtmlParser parser)
{
string responseBody = await client.GetStringAsync($"https://travel.gc.ca/destinations/{countryDirectory}");
var document = await parser.ParseDocumentAsync(responseBody);
IElement? riskLevelBanner = document.QuerySelector("#riskLevelBanner");
string? riskText = riskLevelBanner?.QuerySelector("div")
?.QuerySelector("div")
?.QuerySelector("a")
?.QuerySelector("div")
?.TextContent;
if (riskText?.StartsWith("Avoid all travel") == true)
{
return AdvisoryLevel.AvoidAllTravel;
}
if (riskText?.StartsWith("Avoid non-essential travel") == true)
{
return AdvisoryLevel.AvoidNonEssentialTravel;
}
if (riskText?.StartsWith("Exercise a high degree of caution") == true)
{
return AdvisoryLevel.Caution;
}
if (riskText?.StartsWith("Take normal security precautions") == true)
{
return AdvisoryLevel.Normal;
}
return AdvisoryLevel.Invalid;
}
static string GenerateColorCodedMap(SortedDictionary<string, AdvisoryEntry> entries)
{
string header = "<html>\r\n <head>\r\n <script type=\"text/javascript\" src=\"https://www.gstatic.com/charts/loader.js\"></script>\r\n <script type=\"text/javascript\">\r\n google.charts.load('upcoming', {'packages':['geochart']});\r\n google.charts.setOnLoadCallback(drawRegionsMap);\r\n\r\n function drawRegionsMap() {\r\n\r\n var data = google.visualization.arrayToDataTable([\r\n ['Country', 'Level'],";
var sb = new StringBuilder(header);
foreach (var entry in entries)
{
sb.AppendLine($"\t\t ['{entry.Key}', {(int)entry.Value.Level}],");
}
string footer = " ]);\r\n\r\n var options = { backgroundColor : '#A3CCFF',\r\n datalessRegionColor : \"#CCCCCC\",\r\n domain : 'IN',\r\n height : '640',\r\n keepAspectRatio : \"true\",\r\n legend : 'none' };\r\n\r\n var chart = new google.visualization.GeoChart(document.getElementById('regions_div'));\r\n\r\n chart.draw(data, options);\r\n }\r\n </script>\r\n </head>\r\n <body>\r\n <div id=\"regions_div\"></div>\r\n </body>\r\n</html>";
sb.AppendLine(footer);
return sb.ToString();
}
}
}