From e8e3c4cba8ffa0056e984c113cfbb75319e00022 Mon Sep 17 00:00:00 2001 From: Jake Mannens Date: Fri, 20 Sep 2024 16:21:09 +1000 Subject: v0.4-rc1 --- PagerMessage.cs | 71 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 15 deletions(-) (limited to 'PagerMessage.cs') diff --git a/PagerMessage.cs b/PagerMessage.cs index b817d23..765636c 100644 --- a/PagerMessage.cs +++ b/PagerMessage.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore; -using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json.Serialization; using System.Text.RegularExpressions; namespace PagerParser; @@ -21,6 +21,7 @@ public enum EmergencyService { [Index(nameof(Message))] public class PagerMessage { + [JsonIgnore] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int PagerMessageId { get; set; } public DateTime Timestamp { get; set; } @@ -32,8 +33,19 @@ public class PagerMessage { (Timestamp, Message).GetHashCode(); } +public enum MapType { + Melways = 1, + SpacialVisionCentral = 2, + SpacialVisionNorthEast = 3, + SpacialVisionNorthWest = 4, + SpacialVisionSouthEast = 5, + SpacialVisionSouthWest = 6 +} + [Index(nameof(FirecomJobNo))] +[Index(nameof(PageDestination))] public class ParsedPagerMessage { + [JsonIgnore] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ParsedPagerMessageId { get; set; } public int FirecomJobNo { get; set; } @@ -41,16 +53,19 @@ public class ParsedPagerMessage { public string JobType { get; set; } public AlertLevel AlertLevel { get; set; } public string Description { get; set; } - public int? MelwaysMapNo { get; set; } - public string? MelwaysGrid { get; set; } + public MapType? MapType { get; set; } + public int? MapNo { get; set; } + public string? MapGrid { get; set; } public int? GridReference { get; set; } public EmergencyService AttendingServices { get; set; } public string? Note { get; set; } public int? FireGroundChannel { get; set; } + public List PagedServices { get; set; } = new(); public string PageDestination { get; set; } public virtual GpsPosition? GpsPosition { get; set; } + [JsonIgnore] [ForeignKey(nameof(PagerMessage))] public virtual PagerMessage OriginalMessage { get; set; } } @@ -67,10 +82,23 @@ public interface IPagerMessageParserService { // Running a single instance of the service isn't an issue, as this // service is only used by the fetch service for parsing new messages. public class PagerMessageParserService : IPagerMessageParserService { + public static readonly Dictionary MapTypeMap = new() { + { "M", MapType.Melways }, + { "SVC", MapType.SpacialVisionCentral }, + { "SVNE", MapType.SpacialVisionNorthEast }, + { "SVNW", MapType.SpacialVisionNorthWest }, + { "SVSE", MapType.SpacialVisionSouthEast }, + { "SVSW", MapType.SpacialVisionSouthWest }, + }; + private const string Pattern = - @"^@@ALERT\s+([A-Z]*[0-9]+)\s+([A-Z&]+)C([13])\s+(\*\s+)?(.*)\s+M\s+(\d+)\s+([A-Z]\d+)\s+\((\d+)\)\s+(\*\s+[^*]+\*\s+)?([AFPRS]+)\s+(([A-Z0-9]+\s)+)F([0-9]+)\s+\[([A-Z]+)\]$"; + @"^@@ALERT\s+([A-Z]*[0-9]+)\s+([A-Z&]+)C([13])\s+(\*\s+)?(.*)\s+(M|SVC|SVNE|SVNW|SVSE|SVSW)\s+(\d+)\s+([A-Z]\d+)\s+\((\d+)\)\s+(\*\s+[^*]+\*\s+)?([AFPRS]+)\s+(([A-Z0-9]+\s)+)F([0-9]+)\s+\[([A-Z0-9]+)[_]?\]$"; + + private Regex pageMessageRegex = + new Regex(Pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); - private Regex pageMessageRegex = new Regex(Pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); + private Regex firegroundRegex = + new Regex("^FGD([0-9]+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase); public ParsedPagerMessage Parse(string message) { ParsedPagerMessage m = new(); @@ -84,25 +112,38 @@ public class PagerMessageParserService : IPagerMessageParserService { m.AssignmentArea = match.Groups[1].Value; m.JobType = match.Groups[2].Value; m.Description = match.Groups[5].Value; - m.FirecomJobNo = Int32.Parse(match.Groups[13].Value); - m.PageDestination = match.Groups[14].Value; + m.FirecomJobNo = Int32.Parse(match.Groups[14].Value); + m.PageDestination = match.Groups[15].Value; // Parse optional message components - if(match.Groups[6].Success) m.MelwaysMapNo = Int32.Parse(match.Groups[6].Value); - if(match.Groups[7].Success) m.MelwaysGrid = match.Groups[7].Value; - if(match.Groups[8].Success) m.GridReference = Int32.Parse(match.Groups[8].Value); - if(match.Groups[9].Success) m.Note = match.Groups[9].Value; + if(match.Groups[7].Success) m.MapNo = Int32.Parse(match.Groups[7].Value); + if(match.Groups[8].Success) m.MapGrid = match.Groups[8].Value; + if(match.Groups[9].Success) m.GridReference = Int32.Parse(match.Groups[9].Value); + if(match.Groups[10].Success) m.Note = match.Groups[10].Value; + + // Parse map type using map type dictionary + if(match.Groups[6].Success) { + MapTypeMap.TryGetValue(match.Groups[6].Value, out var mapType); + m.MapType = mapType; + } + + var pagedServicesField = match.Groups[12].Value.Split(" "); // Attempt to extract the fire-ground channel as it can be mixed // into the list of paged services. - m.FireGroundChannel = match.Groups[11].Value - .Split(" ") - .Select(x => Regex.Match(x, "^FGD([0-9]+)$")) + m.FireGroundChannel = pagedServicesField + .Select(x => firegroundRegex.Match(x)) .Where(m => m.Success) .Select(m => (int?) int.Parse(m.Groups[1].Value)) .DefaultIfEmpty(null) .First(); + // Parse the paged services, ignoring the fireground channel + m.PagedServices = pagedServicesField + .Where(x => !firegroundRegex.IsMatch(x)) + .Where(x => !string.IsNullOrEmpty(x)) + .ToList(); + switch(match.Groups[3].Value) { case "1": m.AlertLevel = AlertLevel.Code1; break; case "3": m.AlertLevel = AlertLevel.Code3; break; @@ -110,7 +151,7 @@ public class PagerMessageParserService : IPagerMessageParserService { } // Handle each character to construct a bitmap of attending services - foreach(char c in match.Groups[10].Value) { + foreach(char c in match.Groups[11].Value) { switch(c) { case 'A': m.AttendingServices |= EmergencyService.Ambulance; break; case 'F': m.AttendingServices |= EmergencyService.Fire; break; -- cgit v1.3