static async Task Main(string[] args) { Console.WriteLine("All data generated by this script is contained in scripts/unitinfo.js"); Console.Write("Enter URL of target XML (Leave empty if using the same URL as previous run): "); string serviceUrl = Console.ReadLine(); string executablePath = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location); Dictionary <string, string> overrideTable = GetOverrideTable(ref serviceUrl, executablePath); if (serviceUrl.ToLower() == "amend") { await Amender.AmendUnitInfo(overrideTable, executablePath); Console.ReadLine(); return; } Console.WriteLine("XML request sent"); XDocument serviceRoot = await RequestServiceXml(serviceUrl); XNamespace xmlnsUrl = Regex.Match(serviceRoot.Document.Root.Name.ToString(), @"(?<={)(https?://[^}]*)(?=})").Value; Console.WriteLine("Parsing address"); Tuple <int[], string[], Tuple <int, int> > resultList = ParseAddress(serviceRoot, xmlnsUrl, overrideTable, executablePath); Console.WriteLine("Requesting for geospatial information"); await BatchReq(resultList.Item1, resultList.Item2, serviceRoot, xmlnsUrl, resultList.Item3, overrideTable, executablePath); Console.WriteLine("Executed getinfo succesfully"); Console.ReadLine(); }
// take in valid address list and perform API request private static async Task BatchReq(int[] parsedIndex, string[] parsedAddress, XDocument root, XNamespace xmlnsUrl, Tuple <int, int> ratio, Dictionary <string, string> overrideTable, string executablePath) { string lookupUrl = "https://www.als.ogcio.gov.hk/lookup?n=1&q="; // allocate full length longlat list XElement[] unitList = root.Descendants(xmlnsUrl + "serviceUnit").ToArray(); Tuple <float, float>[] longlatList = new Tuple <float, float> [unitList.Length] .Select(t => new Tuple <float, float>(0, -91)).ToArray(); // encode and request multiple URL simultaneously IEnumerable <string> requestGen = parsedAddress.Select((s, i) => lookupUrl + HttpUtility.UrlEncode(s) + "&i=" + parsedIndex[i]); StreamWriter overrideStream = new StreamWriter(executablePath + "/../override.csv", true, Encoding.UTF8); Pacer estimatePacer = new Pacer(parsedIndex.Length); Task <GeoInfo>[] taskResponse; for (int batchStart = 0; batchStart < parsedIndex.Length; batchStart += batchSize) { taskResponse = requestGen.Skip(batchStart).Take(batchSize) .Select(s => GeoInfo.FromUrl(s, estimatePacer)).ToArray(); await Task.WhenAll(taskResponse); estimatePacer.Stop(); foreach (GeoInfo response in taskResponse.Select(t => t.Result)) { // check district correctness int unitIndex = int.Parse(response.requestKey); XElement targetUnit = unitList[unitIndex]; string parsedDistrict = targetUnit.Descendants(xmlnsUrl + "districtEnglish").First().Value; parsedDistrict = parsedDistrict.ToUpper().Replace(" AND ", " & "); string longlatDistrict = response.root.Descendants("DcDistrict").First().Value; string name = targetUnit.Descendants(xmlnsUrl + "nameTChinese").First().Value.ToUpper(); // append to override table if district test failed and no entry exists if (!longlatDistrict.Contains(parsedDistrict) && !overrideTable.ContainsKey(name)) { Console.WriteLine("District test failed for " + response.address); string tcaddress = targetUnit.Descendants(xmlnsUrl + "addressTChinese").First().Value; overrideStream.Write($"\n{name}\t[NO OVERRIDE]\t0\t0\t{tcaddress}"); ratio = new Tuple <int, int>(ratio.Item1 - 1, ratio.Item2 + 1); continue; } longlatList[unitIndex] = response.longlat; } } Console.WriteLine($"Query ratio is {ratio.Item1}:{ratio.Item2}"); overrideStream.Close(); (Dictionary <string, Tuple <float, float> > longlatOverrideTable, _) = await Amender.RequestOverrideLonglat(overrideTable); Console.WriteLine("Applying override table"); List <Dictionary <string, string> > unitDictList = new List <Dictionary <string, string> >(); foreach (XElement unit in root.Descendants(xmlnsUrl + "serviceUnit")) { Dictionary <string, string> propDict = new Dictionary <string, string>(); foreach (XElement prop in unit.Descendants()) { propDict.Add(prop.Name.LocalName, prop.Value); } unitDictList.Add(propDict); } for (int index = 0; index < unitDictList.Count; index++) { // define None for default address override unitDictList[index].Add("addressOverride", ""); string nameKey = unitDictList[index]["nameTChinese"].ToUpper(); if (longlatOverrideTable.ContainsKey(nameKey)) { longlatList[index] = longlatOverrideTable[nameKey]; unitDictList[index]["addressOverride"] = overrideTable[nameKey].Split('\t')[0]; } } Amender.PatchUnitInfo(longlatList, unitDictList[0].Keys, unitDictList.Select(d => d.Values.ToArray()).ToArray(), executablePath); }