private void Decode(List <string> notamList) { foreach (string singleNotam in notamList) { // Try to find what kind of NOTAM we are dealing with NotamTypeQ qNotamContainer = AssessNotamTypeQ(singleNotam); NotamTypeD dNotamContainer = AssessNotamTypeD(singleNotam); if (qNotamContainer == null && dNotamContainer == null) { // Pass RAW value to container FillContainerWithRawLines(singleNotam); } else if (qNotamContainer != null) { FillContainerWithNotamQInformation(qNotamContainer); DecodedNotam.NotamRaw.Add(singleNotam); } else if (dNotamContainer != null) { // Placeholder for implementation of USA Notams // FillContainerWithNotamD(dNotamContainer); // DecodedNotam.NotamRaw.Add(singleNotam); } } }
private NotamTypeQ AssessNotamTypeQ(string singleNotam) { NotamTypeQ myNotamTypeQ = new NotamTypeQ(); try { string[] myNotamSections = Regex.Split((singleNotam), @"\s(?=([A-Z]\)\s))"); foreach (string line in myNotamSections) { // NOTAM ID Regex idRegex = new Regex(@"(^|\s)(?<ID>[A-Z][0-9]{4}\/[0-9]{2}) (NOTAMN|NOTAMR|NOTAMC)"); Match idMatch = idRegex.Match(line); if (idMatch.Success) { myNotamTypeQ.NotamId = idMatch.Groups["ID"].Value; } // GROUP Q) else if (Regex.IsMatch(line, @"(^|\s)Q\) (.*)")) { string shortQline = line.Replace(" ", ""); Regex qRegex = new Regex(@"Q\)(?<FIR>[A-Z]{4})\/(?<CODE>[A-Z]{5})\/(?<TRAFFIC>IV|I|V|K)?\/(?<PURPOSE>[A-Z]{1,3})?\/(?<SCOPE>[A-Z]{1,2})?\/(?<LOWER>[0-9]{3})?\/(?<UPPER>[0-9]{3})?\/((?<LAT>[0-9]{4})(?<LAT_CODE>N|S)(?<LON>[0-9]{5})(?<LON_CODE>E|W)(?<RADIUS>[0-9]{3}))?"); Match qMatch = qRegex.Match(shortQline); if (qMatch.Success) { myNotamTypeQ.QMatch = qMatch; } } // GROUP B) else if (Regex.IsMatch(line, @"(^|\s)B\) ([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})")) { Regex bRegex = new Regex(@"(^|\s)B\) (?<TIME_START>([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2}))"); Match bMatch = bRegex.Match(line); if (bMatch.Success) { string startTimeRaw = bMatch.Groups["TIME_START"].Value; DateTime myStartTime = DateTime.ParseExact(startTimeRaw, "yyMMddHHmm", null); myNotamTypeQ.StartTime = myStartTime; } } // GROUP C) EST else if (Regex.IsMatch(line, @"(^|\s)C\) ([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2}) (EST)")) { Regex cRegex = new Regex(@"(^|\s)C\) (?<TIME_END>([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})) (EST)"); Match cMatch = cRegex.Match(line); if (cMatch.Success) { string endTimeRaw = cMatch.Groups["TIME_END"].Value; DateTime myEndTime = DateTime.ParseExact(endTimeRaw, "yyMMddHHmm", null); myNotamTypeQ.EndTime = myEndTime; myNotamTypeQ.CEstimated = true; } } // GROUP C) NORMAL else if (Regex.IsMatch(line, @"(^|\s)C\) ([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})")) { Regex cRegex = new Regex(@"(^|\s)C\) (?<TIME_END>([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2}))"); Match cMatch = cRegex.Match(line); if (cMatch.Success) { string endTimeRaw = cMatch.Groups["TIME_END"].Value; DateTime myEndTime = DateTime.ParseExact(endTimeRaw, "yyMMddHHmm", null); myNotamTypeQ.EndTime = myEndTime; } } // GROUP C) PERM else if (Regex.IsMatch(line, @"(^|\s)C\) (PERM)")) { myNotamTypeQ.EndTime = DateTime.MaxValue; myNotamTypeQ.CPermanent = true; } // GROUP D) else if (Regex.IsMatch(line, @"(^|\s)D\) ([.\n|\W|\w]*)")) { Regex dRegex = new Regex(@"(^|\s)D\) (?<SPAN>[.\n|\W|\w]*)"); Match dMatch = dRegex.Match(line); if (dMatch.Success) { string spanTimeRaw = dMatch.Groups["SPAN"].Value.Replace('\n', ' '); myNotamTypeQ.SpanTime = spanTimeRaw; } } // GROUP E) else if (Regex.IsMatch(line, @"(^|\s)E\) ([.\n|\W|\w]*)")) { Regex eRegex = new Regex(@"(^|\s)E\) (?<FREE_TEXT>[.\n|\W|\w]*)"); Match eMatch = eRegex.Match(line); if (eMatch.Success) { myNotamTypeQ.EText = eMatch.Groups["FREE_TEXT"].Value; } } // GROUP F) else if (Regex.IsMatch(line, @"(^|\s)F\) ([.\n|\W|\w]*)")) { Regex fRegex = new Regex(@"(^|\s)F\) (?<BOTTOM_LIMIT>[.\n|\W|\w]*)"); Match fMatch = fRegex.Match(line); if (fMatch.Success) { myNotamTypeQ.BottomLimit = fMatch.Groups["BOTTOM_LIMIT"].Value.Replace('\n', ' '); } } // GROUP G) else if (Regex.IsMatch(line, @"(^|\s)G\) ([.\n|\W|\w]*)")) { Regex gRegex = new Regex(@"(^|\s)G\) (?<TOP_LIMIT>[.\n|\W|\w]*)"); Match gMatch = gRegex.Match(line); if (gMatch.Success) { myNotamTypeQ.TopLimit = gMatch.Groups["TOP_LIMIT"].Value.Replace('\n', ' '); } } } } catch { return(null); } // If we have filled all the (minimum) required data, pass the NOTAM Q if (myNotamTypeQ.NotamId != String.Empty && myNotamTypeQ.QMatch != Match.Empty && myNotamTypeQ.StartTime != DateTime.MinValue && myNotamTypeQ.EndTime != DateTime.MinValue && myNotamTypeQ.EText != String.Empty) { return(myNotamTypeQ); } // Otherwise, return null (NOTAM to be processed as raw) return(null); }
private void FillContainerWithNotamQInformation(NotamTypeQ myNotamQ) { DecodedNotam.NotamQ.Add(true); DecodedNotam.NotamD.Add(false); DecodedNotam.NotamId.Add(myNotamQ.NotamId); DecodedNotam.StartTime.Add(myNotamQ.StartTime); DecodedNotam.EndTime.Add(myNotamQ.EndTime); DecodedNotam.Span.Add(myNotamQ.SpanTime); DecodedNotam.NotamFreeText.Add(myNotamQ.EText); // Notam Codes string secondThird = myNotamQ.QMatch.Groups["CODE"].Value.Substring(1, 2); DecodedNotam.CodeSecondThird.Add(secondThird); string fourthFifth = myNotamQ.QMatch.Groups["CODE"].Value.Substring(3, 2); DecodedNotam.CodeFourthFifth.Add(fourthFifth); // Try to pass coordinates try { string latitude = myNotamQ.QMatch.Groups["LAT"].Value + myNotamQ.QMatch.Groups["LAT_CODE"].Value; string latitudeCode = myNotamQ.QMatch.Groups["LAT_CODE"].Value; string longitude = myNotamQ.QMatch.Groups["LON"].Value + myNotamQ.QMatch.Groups["LON_CODE"].Value; string longitudeCode = myNotamQ.QMatch.Groups["LON_CODE"].Value; string radius = myNotamQ.QMatch.Groups["RADIUS"].Value; Int32.TryParse(radius, out int radiusInt); string degreesLatString = latitude.Substring(0, 2); string minutesLatString = latitude.Substring(2, 2); float.TryParse(degreesLatString, out var degreesLat); float.TryParse(minutesLatString, out var minutesLat); minutesLat = minutesLat / 60; float finalLat = degreesLat + minutesLat; if (latitudeCode == "S") { finalLat = -finalLat; } string degreesLonString = longitude.Substring(0, 3); string minutesLonString = longitude.Substring(3, 2); float.TryParse(degreesLonString, out float degreesLon); float.TryParse(minutesLonString, out float minutesLon); minutesLon = minutesLon / 60; float finalLon = degreesLon + minutesLon; if (longitudeCode == "W") { finalLon = -finalLon; } // Add all of them at the end (to avoid disparities in case of exception) DecodedNotam.Latitude.Add(finalLat); DecodedNotam.Longitude.Add(finalLon); DecodedNotam.Radius.Add(radiusInt); } catch { DecodedNotam.Latitude.Add(9999); DecodedNotam.Longitude.Add(9999); DecodedNotam.Radius.Add(9999); } // Estimated time? if (myNotamQ.CEstimated) { DecodedNotam.CEstimated.Add(true); } else { DecodedNotam.CEstimated.Add(false); } // Permanent time? if (myNotamQ.CPermanent) { DecodedNotam.CPermanent.Add(true); } else { DecodedNotam.CPermanent.Add(false); } // Top and bottom limits? if (myNotamQ.BottomLimit != String.Empty || myNotamQ.TopLimit != String.Empty) { if (myNotamQ.BottomLimit != String.Empty) { DecodedNotam.BottomLimit.Add(myNotamQ.BottomLimit); } else { DecodedNotam.BottomLimit.Add("(not reported)"); } if (myNotamQ.TopLimit != String.Empty) { DecodedNotam.TopLimit.Add(myNotamQ.TopLimit); } else { DecodedNotam.TopLimit.Add("(not reported)"); } } else { DecodedNotam.BottomLimit.Add(String.Empty); DecodedNotam.TopLimit.Add(String.Empty); } }