using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text; using Observatory.Framework; using Observatory.Framework.Files.Journal; using Observatory.Framework.Interfaces; namespace Observatory.Explorer { internal class Explorer { private IObservatoryCore ObservatoryCore; private ObservableCollection Results; private ExplorerWorker ExplorerWorker; private Dictionary> SystemBodyHistory; private Dictionary> BodySignalHistory; private Dictionary> BarycentreHistory; private CustomCriteriaManager CustomCriteriaManager; private DateTime CriteriaLastModified; internal Explorer(ExplorerWorker explorerWorker, IObservatoryCore core, ObservableCollection results) { SystemBodyHistory = new(); BodySignalHistory = new(); BarycentreHistory = new(); ExplorerWorker = explorerWorker; ObservatoryCore = core; Results = results; CustomCriteriaManager = new(core.GetPluginErrorLogger(explorerWorker)); CriteriaLastModified = new DateTime(0); } public void Clear() { SystemBodyHistory.Clear(); BodySignalHistory.Clear(); BarycentreHistory.Clear(); } public void RecordSignal(FSSBodySignals bodySignals) { if (!BodySignalHistory.ContainsKey(bodySignals.SystemAddress)) { BodySignalHistory.Add(bodySignals.SystemAddress, new Dictionary()); } if (!BodySignalHistory[bodySignals.SystemAddress].ContainsKey(bodySignals.BodyID)) { BodySignalHistory[bodySignals.SystemAddress].Add(bodySignals.BodyID, bodySignals); } } public void RecordBarycentre(ScanBaryCentre scan) { if (!BarycentreHistory.ContainsKey(scan.SystemAddress)) { BarycentreHistory.Add(scan.SystemAddress, new Dictionary()); } if (!BarycentreHistory[scan.SystemAddress].ContainsKey(scan.BodyID)) { BarycentreHistory[scan.SystemAddress].Add(scan.BodyID, scan); } } public Scan ConvertBarycentre(ScanBaryCentre barycentre, Scan childScan) { string childAffix = childScan.BodyName .Replace(childScan.StarSystem, string.Empty); char childOrdinal = childAffix.ToCharArray().Last(); bool lowChild = childScan.BodyID - barycentre.BodyID == 1; string baryAffix; if (lowChild) { baryAffix = new string(new char[] { childOrdinal, (char)(childOrdinal + 1) }); } else { baryAffix = new string(new char[] { (char)(childOrdinal - 1), childOrdinal }); } baryAffix = childAffix.Replace(childOrdinal.ToString(), baryAffix); Scan barycentreScan = new() { Timestamp = barycentre.Timestamp, BodyName = barycentre.StarSystem + baryAffix, Parents = childScan.Parents.RemoveAt(0), PlanetClass = "Barycentre", StarSystem = barycentre.StarSystem, SystemAddress = barycentre.SystemAddress, BodyID = barycentre.BodyID, SemiMajorAxis = barycentre.SemiMajorAxis, Eccentricity = barycentre.Eccentricity, OrbitalInclination = barycentre.OrbitalInclination, Periapsis = barycentre.Periapsis, OrbitalPeriod = barycentre.OrbitalPeriod, AscendingNode = barycentre.AscendingNode, MeanAnomaly = barycentre.MeanAnomaly, Json = barycentre.Json }; return barycentreScan; } public void ProcessScan(Scan scanEvent, bool readAll) { if (!readAll) { string criteriaFilePath = ((ExplorerSettings)ExplorerWorker.Settings).CustomCriteriaFile; if (File.Exists(criteriaFilePath)) { DateTime fileModified = new FileInfo(criteriaFilePath).LastWriteTime; if (fileModified != CriteriaLastModified) { try { CustomCriteriaManager.RefreshCriteria(criteriaFilePath); } catch (CriteriaLoadException e) { var exceptionResult = new ExplorerUIResults() { BodyName = "Error Reading Custom Criteria File", Time = DateTime.Now.ToString("G"), Description = e.Message, Details = e.OriginalScript }; ObservatoryCore.AddGridItem(ExplorerWorker, exceptionResult); ((ExplorerSettings)ExplorerWorker.Settings).EnableCustomCriteria = false; } CriteriaLastModified = fileModified; } } } Dictionary systemBodies; if (SystemBodyHistory.ContainsKey(scanEvent.SystemAddress)) { systemBodies = SystemBodyHistory[scanEvent.SystemAddress]; if (systemBodies.ContainsKey(scanEvent.BodyID)) { if (scanEvent.SystemAddress != 0) { //We've already checked this object. return; } } } else { systemBodies = new(); SystemBodyHistory.Add(scanEvent.SystemAddress, systemBodies); } if (SystemBodyHistory.Count > 1000) { foreach (var entry in SystemBodyHistory.Where(entry => entry.Key != scanEvent.SystemAddress).ToList()) { SystemBodyHistory.Remove(entry.Key); } SystemBodyHistory.TrimExcess(); } if (scanEvent.SystemAddress != 0 && !systemBodies.ContainsKey(scanEvent.BodyID)) systemBodies.Add(scanEvent.BodyID, scanEvent); var results = DefaultCriteria.CheckInterest(scanEvent, SystemBodyHistory, BodySignalHistory, (ExplorerSettings)ExplorerWorker.Settings); if (BarycentreHistory.ContainsKey(scanEvent.SystemAddress) && scanEvent.Parent != null && BarycentreHistory[scanEvent.SystemAddress].ContainsKey(scanEvent.Parent[0].Body)) { ProcessScan(ConvertBarycentre(BarycentreHistory[scanEvent.SystemAddress][scanEvent.Parent[0].Body], scanEvent), readAll); } if (((ExplorerSettings)ExplorerWorker.Settings).EnableCustomCriteria) results.AddRange(CustomCriteriaManager.CheckInterest(scanEvent, SystemBodyHistory, BodySignalHistory, (ExplorerSettings)ExplorerWorker.Settings)); if (results.Count > 0) { StringBuilder notificationDetail = new(); foreach (var result in results) { var scanResult = new ExplorerUIResults() { BodyName = result.SystemWide ? scanEvent.StarSystem : scanEvent.BodyName, Time = scanEvent.TimestampDateTime.ToString("G"), Description = result.Description, Details = result.Detail }; ObservatoryCore.AddGridItem(ExplorerWorker, scanResult); notificationDetail.AppendLine(result.Description); } string bodyAffix; if (scanEvent.StarSystem != null && scanEvent.BodyName.StartsWith(scanEvent.StarSystem)) { bodyAffix = scanEvent.BodyName.Replace(scanEvent.StarSystem, string.Empty); } else { bodyAffix = string.Empty; } string bodyLabel = scanEvent.PlanetClass == "Barycentre" ? "Barycentre" : "Body"; string spokenAffix; if (bodyAffix.Length > 0) { if (bodyAffix.Contains("Ring")) { int ringIndex = bodyAffix.Length - 6; spokenAffix = "" + bodyAffix.Substring(0, ringIndex) + "" + bodyAffix.Substring(ringIndex, 1) + "" + bodyAffix.Substring(ringIndex + 1, bodyAffix.Length - (ringIndex + 1)); } else { spokenAffix = "" + bodyAffix + ""; } } else { bodyLabel = "Primary Star"; spokenAffix = string.Empty; } NotificationArgs args = new() { Title = bodyLabel + bodyAffix, TitleSsml = $"{bodyLabel} {spokenAffix}", Detail = notificationDetail.ToString() }; ObservatoryCore.SendNotification(args); } } } }