/// <summary> /// Sort the cameras list into a the relevant categories. /// </summary> /// <param name="cameras">Unsorted list of cameras</param> /// <returns>Collection of Categories</returns> /// <exception cref="ArgumentException">Thrown when unable to identify camera type</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown when unable to assign a camera to a category</exception> public static Collection <PointOfInterestCategory> SortCameras(List <PointOfInterest> cameras) { Collection <PointOfInterestCategory> categorisedCameras = new Collection <PointOfInterestCategory>(); foreach (PointOfInterest camera in cameras) { // Parse the Camera Type CameraType cameraType = IdentifyCameraType(camera.Name); if (cameraType == CameraType.None) { throw new ArgumentException(string.Format("Unknown camera Type - {0}", camera.Name)); } // Identify the correct Category CameraCategory cameraCategory = IdentifyCameraCategory(cameraType); if (cameraCategory == CameraCategory.None) { throw new ArgumentOutOfRangeException(string.Format("Unable to identify Camera Category - {0}", cameraType.ToDescriptionString())); } // Special Case for Provisional Mobile cameras if (cameraCategory.Equals(CameraCategory.Mobile)) { if (camera.Name.Contains("pMOBILE")) { cameraCategory = CameraCategory.PMobile; } } // Add to relevant category PointOfInterestCategory targetCategory = null; foreach (PointOfInterestCategory pointOfInterestCategory in categorisedCameras) { if (pointOfInterestCategory.Name.Equals(cameraCategory.ToDescriptionString())) { targetCategory = pointOfInterestCategory; break; } } if (targetCategory == null) { targetCategory = new PointOfInterestCategory((int)cameraCategory, cameraCategory.ToDescriptionString(), LookupIcon(cameraCategory)); categorisedCameras.Add(targetCategory); } targetCategory.Items.Add(camera); } return(categorisedCameras); }
/// <summary> /// Gets the Requested POI file from the POIGraves site /// </summary> /// <param name="log">Logger Instance</param> /// <param name="category">Category to be loaded</param> /// <returns>Populated Category</returns> private static PointOfInterestCategory GetFromPoiGraves(ILogger log, CategoryEnum category) { log.LogInformation($"POIs - Category = {category}"); PointOfInterestCategory currentCategory = new PointOfInterestCategory((int)category, category.ToDescriptionString(), null); byte[] categoryZip = POIs.Download(category); log.LogInformation($"POIs - Zip Size = {categoryZip.Length}"); string categoryCsv = POIs.Unpack(categoryZip); log.LogInformation($"POIs - CSV Size = {categoryCsv.Length}"); currentCategory.Items.AddRange(POIs.ProcessCsv(categoryCsv)); log.LogInformation($"POIs - Line Count = {currentCategory.Items.Count}"); return(currentCategory); }
/// <summary> /// Get the Latest RSBP Reserves file /// </summary> /// <param name="log">Logger Instance</param> /// <returns>Category complete with reserves</returns> private static PointOfInterestCategory GetRSBPReserves(ILogger log) { log.LogInformation("POIs - Category = RSPB Reserves"); PointOfInterestCategory rspbReserves = new PointOfInterestCategory((int)CategoryEnum.RSPBReserves, CategoryEnum.RSPBReserves.ToDescriptionString(), null); WebClient client = new WebClient(); ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; string reservesCsv = client.DownloadString("https://www.rspb.org.uk/globalassets/downloads/documents/reserves/csv-data-file---reserves.csv"); log.LogInformation($"POIs - CSV Size = {reservesCsv.Length}"); rspbReserves.Items.AddRange(POIs.ProcessCsv(reservesCsv)); log.LogInformation($"POIs - Line Count = {rspbReserves.Items.Count}"); return(rspbReserves); }
/// <summary> /// Process a given GPX file extracting the Points of Interest /// </summary> /// <param name="sourceFile">Source File</param> /// <param name="skipOwner">skip caches owned by</param> /// <param name="skipFound">skip found caches</param> /// <returns>A Point of Interest Database</returns> /// <exception cref="InvalidDataException">Thrown if unable to select the relevant elements from the GPX file</exception> public static Collection <PointOfInterestCategory> ProcessGpxFile(string sourceFile, string skipOwner, bool skipFound) { Collection <PointOfInterestCategory> pois = new Collection <PointOfInterestCategory>(); //// other types to consider [Event Cache,Cache In Trash Out Event,Mega-Event Cache] // Category lookup Dictionary <string, PointOfInterestCategory> categories = new Dictionary <string, PointOfInterestCategory>() { { "Earthcache", new PointOfInterestCategory(0, "Caches - Earthcaches", Resources.earthcacheIcon) }, { "Letterbox Hybrid", new PointOfInterestCategory(1, "Caches - Letterbox", Resources.letterboxIcon) }, { "Multi-cache", new PointOfInterestCategory(2, "Caches - Multi", Resources.multiIcon) }, { "Traditional Cache", new PointOfInterestCategory(3, "Caches - Traditional", Resources.traditionalIcon) }, { "Unknown Cache", new PointOfInterestCategory(4, "Caches - Mystery", Resources.mysteryIcon) }, { "Virtual Cache", new PointOfInterestCategory(5, "Caches - Virtual", Resources.virtualIcon) }, { "Wherigo Cache", new PointOfInterestCategory(6, "Caches - Wherigo", Resources.wherigoIcon) }, { "Webcam Cache", new PointOfInterestCategory(7, "Caches - Webcam", Resources.webcamIcon) } }; // Load GPX file XmlDocument gpxFile = new XmlDocument(); gpxFile.Load(sourceFile); XmlNamespaceManager namespaceManager = new XmlNamespaceManager(gpxFile.NameTable); namespaceManager.AddNamespace("gpx", "http://www.topografix.com/GPX/1/0"); namespaceManager.AddNamespace("groundspeak", "http://www.groundspeak.com/cache/1/0/1"); XmlNodeList waypoints = gpxFile.SelectNodes(@"/gpx:gpx/gpx:wpt", namespaceManager); foreach (XmlNode waypoint in waypoints) { string type = waypoint.SelectSingleNode("gpx:type", namespaceManager).InnerText; List <string> attributes = new List <string>(type.Split(new char[] { '|' })); // We don't want include child waypoints if (attributes.Remove("Geocache")) { // Skip caches that have been found if (skipFound && attributes.Contains("Found")) { continue; } else { attributes.Remove("Found"); } if (attributes.Count.Equals(1) && categories.TryGetValue(attributes[0], out PointOfInterestCategory waypointCategory)) { string code = waypoint.SelectSingleNode("gpx:name", namespaceManager).InnerText; string name = waypoint.SelectSingleNode("groundspeak:cache/groundspeak:name", namespaceManager).InnerText; string owner = waypoint.SelectSingleNode("groundspeak:cache/groundspeak:owner", namespaceManager).InnerText; // Skip caches with the named owner if (owner.Equals(skipOwner)) { continue; } string size = waypoint.SelectSingleNode("groundspeak:cache/groundspeak:container", namespaceManager).InnerText; if (!double.TryParse(waypoint.SelectSingleNode("@lat", namespaceManager).InnerText, out double lat)) { throw new InvalidDataException(waypoint.SelectSingleNode("@lat", namespaceManager).InnerText); } if (!double.TryParse(waypoint.SelectSingleNode("@lon", namespaceManager).InnerText, out double lon)) { throw new InvalidDataException(waypoint.SelectSingleNode("@lon", namespaceManager).InnerText); } if (!double.TryParse(waypoint.SelectSingleNode("groundspeak:cache/groundspeak:difficulty", namespaceManager).InnerText, out double difficulty)) { throw new InvalidDataException(waypoint.SelectSingleNode("groundspeak:cache/groundspeak:difficulty", namespaceManager).InnerText); } if (!double.TryParse(waypoint.SelectSingleNode("groundspeak:cache/groundspeak:terrain", namespaceManager).InnerText, out double terrain)) { throw new InvalidDataException(waypoint.SelectSingleNode("groundspeak:cache/groundspeak:terrain", namespaceManager).InnerText); } PointOfInterestCategory currentCategory = pois.Where(x => x.Id == waypointCategory.Id).SingleOrDefault(); if (currentCategory == null) { currentCategory = waypointCategory; pois.Add(currentCategory); } currentCategory.Items.Add(new PointOfInterest() { Name = name, Latitude = lat, Longitude = lon, HouseNumber = string.Format("By {0}", owner), Street = string.Format("{0} [{1}/{2}]", code, difficulty, terrain), City = size, }); } } } return(pois); }