public static StarSystem StarSystemFromEDDP(dynamic json)
        {
            StarSystem StarSystem = new StarSystem();

            StarSystem.Name = (string)json["name"];
            StarSystem.Population = (long?)json["population"] == null ? 0 : (long)json["population"];
            StarSystem.Allegiance = (string)json["allegiance"];
            StarSystem.Government = (string)json["government"];
            StarSystem.Faction = (string)json["faction"];
            StarSystem.PrimaryEconomy = (string)json["primary_economy"];
            StarSystem.State = (string)json["state"] == "None" ? null : (string)json["state"];
            StarSystem.Security = (string)json["security"];
            StarSystem.Power = (string)json["power"];
            StarSystem.PowerState = (string)json["power_state"];

            StarSystem.X = (decimal?)json["x"];
            StarSystem.Y = (decimal?)json["y"];
            StarSystem.Z = (decimal?)json["z"];

            StarSystem.Stations = StationsFromEDDP(json);
            return StarSystem;
        }
        public static void VA_Init1(ref Dictionary<string, object> state, ref Dictionary<string, Int16?> shortIntValues, ref Dictionary<string, string> textValues, ref Dictionary<string, int?> intValues, ref Dictionary<string, decimal?> decimalValues, ref Dictionary<string, Boolean?> booleanValues, ref Dictionary<string, DateTime?> dateTimeValues, ref Dictionary<string, object> extendedValues)
        {
            if (!initialised)
            {
                lock (initLock)
                {
                    if (!initialised)
                    {
                        try
                        {
                            logInfo("EDDI " + PLUGIN_VERSION + " starting");

                            // Set up and/or open our database
                            String dataDir = Environment.GetEnvironmentVariable("AppData") + "\\EDDI";
                            System.IO.Directory.CreateDirectory(dataDir);

                            // Set up our local star system repository
                            starSystemRepository = new EDDIStarSystemSqLiteRepository();

                            // Set up the EDDI configuration
                            EDDIConfiguration eddiConfiguration = EDDIConfiguration.FromFile();
                            setString(ref textValues, "Home system", eddiConfiguration.HomeSystem != null && eddiConfiguration.HomeSystem.Trim().Length > 0 ? eddiConfiguration.HomeSystem : null);
                            setString(ref textValues, "Home system (spoken)", eddiConfiguration.HomeSystem != null && eddiConfiguration.HomeSystem.Trim().Length > 0 ? Translations.StarSystem(eddiConfiguration.HomeSystem) : null);
                            setString(ref textValues, "Home station", eddiConfiguration.HomeStation != null && eddiConfiguration.HomeStation.Trim().Length > 0 ? eddiConfiguration.HomeStation : null);
                            setDecimal(ref decimalValues, "Insurance", eddiConfiguration.Insurance);
                            if (eddiConfiguration.HomeSystem != null && eddiConfiguration.HomeSystem.Trim().Length > 0)
                            {
                                EDDIStarSystem HomeStarSystemData = starSystemRepository.GetEDDIStarSystem(eddiConfiguration.HomeSystem.Trim());
                                if (HomeStarSystemData == null)
                                {
                                    // We have no record of this system; set it up
                                    HomeStarSystemData = new EDDIStarSystem();
                                    HomeStarSystemData.Name = eddiConfiguration.HomeSystem.Trim();
                                    HomeStarSystemData.StarSystem = DataProviderService.GetSystemData(eddiConfiguration.HomeSystem.Trim());
                                    HomeStarSystemData.LastVisit = DateTime.Now;
                                    HomeStarSystemData.StarSystemLastUpdated = HomeStarSystemData.LastVisit;
                                    HomeStarSystemData.TotalVisits = 1;
                                    starSystemRepository.SaveEDDIStarSystem(HomeStarSystemData);
                                }
                                HomeStarSystem = HomeStarSystemData.StarSystem;
                            }

                            enableDebugging = eddiConfiguration.Debug;
                            setBoolean(ref booleanValues, "EDDI debug", enableDebugging);

                            // Set up the app service
                            appService = new CompanionAppService(enableDebugging);
                            if (appService.CurrentState == CompanionAppService.State.READY)
                            {
                                // Carry out initial population of profile
                                InvokeUpdateProfile(ref state, ref shortIntValues, ref textValues, ref intValues, ref decimalValues, ref booleanValues, ref dateTimeValues, ref extendedValues);
                            }
                            if (Cmdr != null && Cmdr.Name != null)
                            {
                                setString(ref textValues, "EDDI plugin profile status", "Enabled");
                                logInfo("EDDI access to the companion app is enabled");
                            }
                            else
                            {
                                // If InvokeUpdatePlugin failed then it will have have left an error message, but this once we ignore it
                                setPluginStatus(ref textValues, "Operational", null, null);
                                setString(ref textValues, "EDDI plugin profile status", "Disabled");
                                logInfo("EDDI access to the companion app is disabled");
                                // We create a commander anyway, as data such as starsystem uses it
                                Cmdr = new Commander();
                            }

                            // Set up the star map service
                            StarMapConfiguration starMapCredentials = StarMapConfiguration.FromFile();
                            if (starMapCredentials != null && starMapCredentials.apiKey != null)
                            {
                                // Commander name might come from star map credentials or the companion app's profile
                                string commanderName = null;
                                if (starMapCredentials.commanderName != null)
                                {
                                    commanderName = starMapCredentials.commanderName;
                                }
                                else if (Cmdr.Name != null)
                                {
                                    commanderName = Cmdr.Name;
                                }
                                if (commanderName != null)
                                {
                                    starMapService = new StarMapService(starMapCredentials.apiKey, commanderName);
                                    setString(ref textValues, "EDDI plugin EDSM status", "Enabled");
                                    logInfo("EDDI access to EDSM is enabled");
                                }
                            }
                            if (starMapService == null)
                            {
                                setString(ref textValues, "EDDI plugin EDSM status", "Disabled");
                                logInfo("EDDI access to EDSM is disabled");
                            }

                            setString(ref textValues, "EDDI version", PLUGIN_VERSION);

                            speechService = new SpeechService(SpeechServiceConfiguration.FromFile());

                            InvokeNewSystem(ref state, ref shortIntValues, ref textValues, ref intValues, ref decimalValues, ref booleanValues, ref dateTimeValues, ref extendedValues);
                            CurrentEnvironment = ENVIRONMENT_NORMAL_SPACE;
                            setString(ref textValues, "Environment", CurrentEnvironment);

                            // Set up log monitor
                            NetLogConfiguration netLogConfiguration = NetLogConfiguration.FromFile();
                            if (netLogConfiguration != null && netLogConfiguration.path != null)
                            {
                                logWatcherThread = new Thread(() => StartLogMonitor(netLogConfiguration));
                                logWatcherThread.IsBackground = true;
                                logWatcherThread.Name = "EDDI netlog watcher";
                                logWatcherThread.Start();
                                setString(ref textValues, "EDDI plugin NetLog status", "Enabled");
                                logInfo("EDDI netlog monitor is enabled for " + netLogConfiguration.path);
                            }
                            else
                            {
                                setString(ref textValues, "EDDI plugin NetLog status", "Disabled");
                                logInfo("EDDI netlog monitor is disabled");
                            }

                            setPluginStatus(ref textValues, "Operational", null, null);

                            initialised = true;
                        }
                        catch (Exception ex)
                        {
                            setPluginStatus(ref textValues, "Failed", "Failed to initialise", ex);
                        }
                    }
                }
            }
        }
        public static void InvokeNewSystem(ref Dictionary<string, object> state, ref Dictionary<string, Int16?> shortIntValues, ref Dictionary<string, string> textValues, ref Dictionary<string, int?> intValues, ref Dictionary<string, decimal?> decimalValues, ref Dictionary<string, Boolean?> booleanValues, ref Dictionary<string, DateTime?> dateTimeValues, ref Dictionary<string, object> extendedValues)
        {
            try
            {
                if (Cmdr == null)
                {
                    // Refetch the profile to set our system
                    InvokeUpdateProfile(ref state, ref shortIntValues, ref textValues, ref intValues, ref decimalValues, ref booleanValues, ref dateTimeValues, ref extendedValues);
                    if (Cmdr == null)
                    {
                        // Still no luck; assume an error of some sort has been logged by InvokeUpdateProfile()
                        return;
                    }
                }

                bool RecordUpdated = false;
                if (CurrentStarSystem == null || Cmdr.StarSystem != CurrentStarSystem.Name)
                {
                    // The star system has changed or we're in init; obtain the data ready for setting the VA values
                    EDDIStarSystem CurrentStarSystemData = starSystemRepository.GetEDDIStarSystem(Cmdr.StarSystem);
                    if (CurrentStarSystemData == null)
                    {
                        // We have no record of this system; set it up
                        CurrentStarSystemData = new EDDIStarSystem();
                        CurrentStarSystemData.Name = Cmdr.StarSystem;
                        CurrentStarSystemData.StarSystem = DataProviderService.GetSystemData(Cmdr.StarSystem);
                        CurrentStarSystemData.LastVisit = DateTime.Now;
                        CurrentStarSystemData.StarSystemLastUpdated = CurrentStarSystemData.LastVisit;
                        CurrentStarSystemData.TotalVisits = 1;
                        RecordUpdated = true;
                    }
                    else
                    {
                        if ((DateTime.Now - CurrentStarSystemData.StarSystemLastUpdated).TotalHours > 12)
                        {
                            // Data is stale; refresh it
                            CurrentStarSystemData.StarSystem = DataProviderService.GetSystemData(CurrentStarSystemData.Name);
                            CurrentStarSystemData.StarSystemLastUpdated = CurrentStarSystemData.LastVisit;
                            RecordUpdated = true;
                        }
                        // Only update if we have moved (as opposed to reinitialised here)
                        if (CurrentStarSystem != null)
                        {
                            CurrentStarSystemData.PreviousVisit = CurrentStarSystemData.LastVisit;
                            CurrentStarSystemData.LastVisit = DateTime.Now;
                            CurrentStarSystemData.TotalVisits++;
                            RecordUpdated = true;
                        }
                    }
                    if (RecordUpdated)
                    {
                        starSystemRepository.SaveEDDIStarSystem(CurrentStarSystemData);
                    }

                    StarSystem ThisStarSystem = CurrentStarSystemData.StarSystem;
                    LastStarSystem = CurrentStarSystem;
                    CurrentStarSystem = ThisStarSystem;

                    setString(ref textValues, "System name", CurrentStarSystem.Name);
                    setString(ref textValues, "System name (spoken)", VATranslations.StarSystem(CurrentStarSystem.Name));
                    setInt(ref intValues, "System visits", CurrentStarSystemData.TotalVisits);
                    setDateTime(ref dateTimeValues, "System previous visit", CurrentStarSystemData.PreviousVisit);
                    setInt(ref intValues, "System population", (int)(CurrentStarSystem.Population / 1000));  // TODO remove in next major release
                    setDecimal(ref decimalValues, "System population", (decimal)CurrentStarSystem.Population);
                    setString(ref textValues, "System population", humanize(CurrentStarSystem.Population)); // TODO remove in next major release
                    setString(ref textValues, "System population (spoken)", humanize(CurrentStarSystem.Population));
                    setString(ref textValues, "System allegiance", CurrentStarSystem.Allegiance);
                    setString(ref textValues, "System government", CurrentStarSystem.Government);
                    setString(ref textValues, "System faction", CurrentStarSystem.Faction);
                    setString(ref textValues, "System primary economy", CurrentStarSystem.PrimaryEconomy);
                    setString(ref textValues, "System state", CurrentStarSystem.State);
                    setString(ref textValues, "System security", CurrentStarSystem.Security);
                    setString(ref textValues, "System power", CurrentStarSystem.Power);
                    setString(ref textValues, "System power (spoken)", VATranslations.Power(CurrentStarSystem.Power));
                    setString(ref textValues, "System power state", CurrentStarSystem.PowerState);

                    setDecimal(ref decimalValues, "System X", CurrentStarSystem.X);
                    setDecimal(ref decimalValues, "System Y", CurrentStarSystem.Y);
                    setDecimal(ref decimalValues, "System Z", CurrentStarSystem.Z);

                    // Allegiance-specific rank
                    string systemRank = "Commander";
                    if (CurrentStarSystem.Allegiance == "Federation" && Cmdr.FederationRating >= minFederationRatingForTitle)
                    {
                        systemRank = Cmdr.FederationRank;
                    }
                    else if (CurrentStarSystem.Allegiance == "Empire" && Cmdr.EmpireRating >= minEmpireRatingForTitle)
                    {
                        systemRank = Cmdr.EmpireRank;
                    }
                    setString(ref textValues, "System rank", systemRank);

                    // Stations
                    foreach (Station Station in CurrentStarSystem.Stations)
                    {
                        setString(ref textValues, "System station name", Station.Name);
                    }
                    setInt(ref intValues, "System stations", CurrentStarSystem.Stations.Count);
                    setInt(ref intValues, "System starports", CurrentStarSystem.Stations.Count(s => s.IsStarport()));
                    setInt(ref intValues, "System outposts", CurrentStarSystem.Stations.Count(s => s.IsOutpost()));
                    setInt(ref intValues, "System planetary stations", CurrentStarSystem.Stations.Count(s => s.IsPlanetary()));
                    setInt(ref intValues, "System planetary outposts", CurrentStarSystem.Stations.Count(s => s.IsPlanetaryOutpost()));
                    setInt(ref intValues, "System planetary ports", CurrentStarSystem.Stations.Count(s => s.IsPlanetaryPort()));

                    if (LastStarSystem != null)
                    {
                        setString(ref textValues, "Last system name", LastStarSystem.Name);
                        setString(ref textValues, "Last system name (spoken)", VATranslations.StarSystem(LastStarSystem.Name));
                        setInt(ref intValues, "Last system population", (int)(LastStarSystem.Population / 1000));  // TODO remove in next major release
                        setDecimal(ref decimalValues, "Last system population", (decimal)LastStarSystem.Population);
                        setString(ref textValues, "Last system population", humanize(LastStarSystem.Population)); // TODO remove in next major release
                        setString(ref textValues, "Last system population (spoken)", humanize(LastStarSystem.Population));
                        setString(ref textValues, "Last system allegiance", LastStarSystem.Allegiance);
                        setString(ref textValues, "Last system government", LastStarSystem.Government);
                        setString(ref textValues, "Last system faction", LastStarSystem.Faction);
                        setString(ref textValues, "Last system primary economy", LastStarSystem.PrimaryEconomy);
                        setString(ref textValues, "Last system state", LastStarSystem.State);
                        setString(ref textValues, "Last system security", LastStarSystem.Security);
                        setString(ref textValues, "Last system power", LastStarSystem.Power);
                        setString(ref textValues, "Last system power (spoken)", VATranslations.Power(LastStarSystem.Power));
                        setString(ref textValues, "Last system power state", LastStarSystem.PowerState);

                        setDecimal(ref decimalValues, "Last system X", LastStarSystem.X);
                        setDecimal(ref decimalValues, "Last system Y", LastStarSystem.Y);
                        setDecimal(ref decimalValues, "Last system Z", LastStarSystem.Z);

                        if (LastStarSystem.X != null && CurrentStarSystem.X != null)
                        {
                            setDecimal(ref decimalValues, "Last jump", (decimal)Math.Round(Math.Sqrt(Math.Pow((double)(CurrentStarSystem.X - LastStarSystem.X), 2) + Math.Pow((double)(CurrentStarSystem.Y - LastStarSystem.Y), 2) + Math.Pow((double)(CurrentStarSystem.Z - LastStarSystem.Z), 2)), 2));
                        }

                        // Stations
                        foreach (Station Station in LastStarSystem.Stations)
                        {
                            setString(ref textValues, "Last system station name", Station.Name);
                        }
                        setInt(ref intValues, "Last system stations", LastStarSystem.Stations.Count);
                        setInt(ref intValues, "Last system starports", LastStarSystem.Stations.Count(s => s.IsStarport()));
                        setInt(ref intValues, "Last system outposts", LastStarSystem.Stations.Count(s => s.IsOutpost()));
                        setInt(ref intValues, "Last system planetary stations", LastStarSystem.Stations.Count(s => s.IsPlanetary()));
                        setInt(ref intValues, "Last system planetary outposts", LastStarSystem.Stations.Count(s => s.IsPlanetaryOutpost()));
                        setInt(ref intValues, "Last system planetary ports", LastStarSystem.Stations.Count(s => s.IsPlanetaryPort()));
                    }
                }

                setPluginStatus(ref textValues, "Operational", null, null);
            }
            catch (Exception e)
            {
                setPluginStatus(ref textValues, "Failed", "Failed to obtain system data", e);
            }
        }
        public static void InvokeNewSystem(ref Dictionary<string, object> state, ref Dictionary<string, Int16?> shortIntValues, ref Dictionary<string, string> textValues, ref Dictionary<string, int?> intValues, ref Dictionary<string, decimal?> decimalValues, ref Dictionary<string, Boolean?> booleanValues, ref Dictionary<string, DateTime?> dateTimeValues, ref Dictionary<string, object> extendedValues)
        {
            debug("InvokeNewSystem() entered");
            try
            {
                if (Cmdr == null)
                {
                    debug("InvokeNewSystem() Cmdr is NULL - attempting to refetch");
                    // Refetch the profile to set our system
                    InvokeUpdateProfile(ref state, ref shortIntValues, ref textValues, ref intValues, ref decimalValues, ref booleanValues, ref dateTimeValues, ref extendedValues);
                    if (Cmdr == null)
                    {
                        // Still no luck; assume an error of some sort has been logged by InvokeUpdateProfile()
                        debug("InvokeNewSystem() Cmdr remained NULL - giving up");
                        return;
                    }
                }

                debug("InvokeNewSystem() CurrentStarSystem is " +  (CurrentStarSystem == null ? "<null>" : JsonConvert.SerializeObject(CurrentStarSystem)));
                debug("InvokeNewSystem() Cmdr is " + (Cmdr == null ? "<null>" : JsonConvert.SerializeObject(Cmdr)));

                if (Cmdr.StarSystem == null)
                {
                    // No information available
                    debug("InvokeNewSystem() No starsystem data available");
                    return;
                }

                bool RecordUpdated = false;
                if ((!initialised) || CurrentStarSystem == null || Cmdr.StarSystem != CurrentStarSystem.Name)
                {
                    debug("InvokeNewSystem() In init or starsystem has changed");
                    // The star system has changed or we're in init; obtain the data ready for setting the VA values
                    EDDIStarSystem CurrentStarSystemData = starSystemRepository.GetEDDIStarSystem(Cmdr.StarSystem);
                    debug("InvokeNewSystem() CurrentStarSystemData is " + (CurrentStarSystemData == null ? "<null>" : JsonConvert.SerializeObject(CurrentStarSystemData)));
                    if (CurrentStarSystemData == null)
                    {
                        debug("InvokeNewSystem() Creating new starsystemdata");
                        // We have no record of this system; set it up
                        CurrentStarSystemData = new EDDIStarSystem();
                        CurrentStarSystemData.Name = Cmdr.StarSystem;
                        CurrentStarSystemData.StarSystem = DataProviderService.GetSystemData(Cmdr.StarSystem);
                        CurrentStarSystemData.LastVisit = DateTime.Now;
                        CurrentStarSystemData.StarSystemLastUpdated = CurrentStarSystemData.LastVisit;
                        CurrentStarSystemData.TotalVisits = 1;
                        RecordUpdated = true;
                    }
                    else
                    {
                        debug("InvokeNewSystem() Checking existing starsystemdata");
                        if (CurrentStarSystemData.StarSystem == null || (DateTime.Now - CurrentStarSystemData.StarSystemLastUpdated).TotalHours > 12)
                        {
                            debug("InvokeNewSystem() Refreshing stale or missing data");
                            // Data is stale; refresh it
                            CurrentStarSystemData.StarSystem = DataProviderService.GetSystemData(CurrentStarSystemData.Name);
                            CurrentStarSystemData.StarSystemLastUpdated = CurrentStarSystemData.LastVisit;
                            RecordUpdated = true;
                        }
                        // Only update if we have moved (as opposed to reinitialising here)
                        if (initialised)
                        {
                            debug("InvokeNewSystem() Updating visit information");
                            CurrentStarSystemData.PreviousVisit = CurrentStarSystemData.LastVisit;
                            CurrentStarSystemData.LastVisit = DateTime.Now;
                            CurrentStarSystemData.TotalVisits++;
                            RecordUpdated = true;
                        }
                    }
                    debug("InvokeNewSystem() CurrentStarSystemData is now " + (CurrentStarSystemData == null ? "<null>" : JsonConvert.SerializeObject(CurrentStarSystemData)));
                    if (RecordUpdated)
                    {
                        debug("InvokeNewSystem() Storing updated starsystemdata");
                        starSystemRepository.SaveEDDIStarSystem(CurrentStarSystemData);
                    }

                    StarSystem ThisStarSystem = CurrentStarSystemData.StarSystem;
                    LastStarSystem = CurrentStarSystem;
                    CurrentStarSystem = ThisStarSystem;

                    debug("InvokeNewSystem() CurrentStarSystem is now " + (CurrentStarSystem == null ? "<null>" : JsonConvert.SerializeObject(CurrentStarSystem)));
                    debug("InvokeNewSystem() LastStarSystem is now " + (LastStarSystem == null ? "<null>" : JsonConvert.SerializeObject(LastStarSystem)));

                    if (initialised && LastStarSystem != null && LastStarSystem.Name != CurrentStarSystem.Name)
                    {
                        // We have travelled; let EDSM know
                        if (starMapService != null)
                        {
                            debug("InvokeNewSystem() Sending update to EDSM");
                            starMapService.sendStarMapLog(CurrentStarSystem.Name);
                            debug("InvokeNewSystem() Update sent");
                        }
                    }

                    debug("InvokeNewSystem() Setting system information");
                    setString(ref textValues, "System name", CurrentStarSystem.Name);
                    setString(ref textValues, "System name (spoken)", Translations.StarSystem(CurrentStarSystem.Name));
                    setInt(ref intValues, "System visits", CurrentStarSystemData.TotalVisits);
                    setDateTime(ref dateTimeValues, "System previous visit", CurrentStarSystemData.PreviousVisit);
                    setInt(ref intValues, "System minutes since previous visit", CurrentStarSystemData.PreviousVisit == null ? (int?)null : (int)(DateTime.Now - (DateTime)CurrentStarSystemData.PreviousVisit).TotalMinutes);
                    setDecimal(ref decimalValues, "System population", (decimal?)CurrentStarSystem.Population);
                    setString(ref textValues, "System population (spoken)", humanize(CurrentStarSystem.Population));
                    setString(ref textValues, "System allegiance", CurrentStarSystem.Allegiance);
                    setString(ref textValues, "System government", CurrentStarSystem.Government);
                    setString(ref textValues, "System faction", CurrentStarSystem.Faction);
                    setString(ref textValues, "System primary economy", CurrentStarSystem.PrimaryEconomy);
                    setString(ref textValues, "System state", CurrentStarSystem.State);
                    setString(ref textValues, "System security", CurrentStarSystem.Security);
                    setString(ref textValues, "System power", CurrentStarSystem.Power);
                    setString(ref textValues, "System power (spoken)", Translations.Power(CurrentStarSystem.Power));
                    setString(ref textValues, "System power state", CurrentStarSystem.PowerState);
                    setDecimal(ref decimalValues, "System X", CurrentStarSystem.X);
                    setDecimal(ref decimalValues, "System Y", CurrentStarSystem.Y);
                    setDecimal(ref decimalValues, "System Z", CurrentStarSystem.Z);
                    debug("InvokeNewSystem() Set system information");

                    debug("InvokeNewSystem() Setting system rank");
                    // Allegiance-specific rank
                    string systemRank = "Commander";
                    if (Cmdr.Name != null) // using Name as a canary to see if the data is missing
                    {
                        if (CurrentStarSystem.Allegiance == "Federation" && Cmdr.FederationRating >= minFederationRatingForTitle)
                        {
                            systemRank = Cmdr.FederationRank;
                        }
                        else if (CurrentStarSystem.Allegiance == "Empire" && Cmdr.EmpireRating >= minEmpireRatingForTitle)
                        {
                            systemRank = Cmdr.EmpireRank;
                        }
                    }
                    setString(ref textValues, "System rank", systemRank);
                    debug("InvokeNewSystem() Set system rank");

                    // Stations
                    debug("InvokeNewSystem() Setting station information");
                    foreach (Station Station in CurrentStarSystem.Stations)
                    {
                        setString(ref textValues, "System station name", Station.Name);
                    }
                    setInt(ref intValues, "System stations", CurrentStarSystem.Stations.Count);
                    setInt(ref intValues, "System starports", CurrentStarSystem.Stations.Count(s => s.IsStarport()));
                    setInt(ref intValues, "System outposts", CurrentStarSystem.Stations.Count(s => s.IsOutpost()));
                    setInt(ref intValues, "System planetary stations", CurrentStarSystem.Stations.Count(s => s.IsPlanetary()));
                    setInt(ref intValues, "System planetary outposts", CurrentStarSystem.Stations.Count(s => s.IsPlanetaryOutpost()));
                    setInt(ref intValues, "System planetary ports", CurrentStarSystem.Stations.Count(s => s.IsPlanetaryPort()));
                    debug("InvokeNewSystem() Set station information");

                    debug("InvokeNewSystem() Setting distance from home");
                    if (HomeStarSystem != null && HomeStarSystem.X != null && CurrentStarSystem.X != null)
                    {
                        setDecimal(ref decimalValues, "System distance from home", (decimal)Math.Round(Math.Sqrt(Math.Pow((double)(CurrentStarSystem.X - HomeStarSystem.X), 2) + Math.Pow((double)(CurrentStarSystem.Y - HomeStarSystem.Y), 2) + Math.Pow((double)(CurrentStarSystem.Z - HomeStarSystem.Z), 2)), 2));
                    }
                    debug("InvokeNewSystem() Set distance from home");

                    debug("InvokeNewSystem() Setting EDSM comment");
                    if (starMapService != null)
                    {
                        StarMapInfo info = starMapService.getStarMapInfo(CurrentStarSystem.Name);
                        setString(ref textValues, "System comment", info == null || info.Comment == null || info.Comment.Trim() == "" ? null : info.Comment);
                    }
                    debug("InvokeNewSystem() Set EDSM comment");

                    if (LastStarSystem != null)
                    {
                        debug("InvokeNewSystem() Setting last system information");
                        setString(ref textValues, "Last system name", LastStarSystem.Name);
                        setString(ref textValues, "Last system name (spoken)", Translations.StarSystem(LastStarSystem.Name));
                        setDecimal(ref decimalValues, "Last system population", (decimal?)LastStarSystem.Population);
                        setString(ref textValues, "Last system population (spoken)", humanize(LastStarSystem.Population));
                        setString(ref textValues, "Last system allegiance", LastStarSystem.Allegiance);
                        setString(ref textValues, "Last system government", LastStarSystem.Government);
                        setString(ref textValues, "Last system faction", LastStarSystem.Faction);
                        setString(ref textValues, "Last system primary economy", LastStarSystem.PrimaryEconomy);
                        setString(ref textValues, "Last system state", LastStarSystem.State);
                        setString(ref textValues, "Last system security", LastStarSystem.Security);
                        setString(ref textValues, "Last system power", LastStarSystem.Power);
                        setString(ref textValues, "Last system power (spoken)", Translations.Power(LastStarSystem.Power));
                        setString(ref textValues, "Last system power state", LastStarSystem.PowerState);
                        setDecimal(ref decimalValues, "Last system X", LastStarSystem.X);
                        setDecimal(ref decimalValues, "Last system Y", LastStarSystem.Y);
                        setDecimal(ref decimalValues, "Last system Z", LastStarSystem.Z);
                        debug("InvokeNewSystem() Set last system information");

                        debug("InvokeNewSystem() Setting last jump");
                        if (LastStarSystem.X != null && CurrentStarSystem.X != null)
                        {
                            setDecimal(ref decimalValues, "Last jump", (decimal)Math.Round(Math.Sqrt(Math.Pow((double)(CurrentStarSystem.X - LastStarSystem.X), 2) + Math.Pow((double)(CurrentStarSystem.Y - LastStarSystem.Y), 2) + Math.Pow((double)(CurrentStarSystem.Z - LastStarSystem.Z), 2)), 2));
                        }
                        debug("InvokeNewSystem() Set last jump");

                        debug("InvokeNewSystem() Setting last system rank");
                        // Allegiance-specific rank
                        string lastSystemRank = "Commander";
                        if (Cmdr.Name != null) // using Name as a canary to see if the data is missing
                        {
                            if (LastStarSystem.Allegiance == "Federation" && Cmdr.FederationRating >= minFederationRatingForTitle)
                            {
                                lastSystemRank = Cmdr.FederationRank;
                            }
                            else if (LastStarSystem.Allegiance == "Empire" && Cmdr.EmpireRating >= minEmpireRatingForTitle)
                            {
                                lastSystemRank = Cmdr.EmpireRank;
                            }
                        }
                        setString(ref textValues, "Last system rank", systemRank);
                        debug("InvokeNewSystem() Set last system rank");

                        // Stations
                        debug("InvokeNewSystem() Setting last system station information");
                        foreach (Station Station in LastStarSystem.Stations)
                        {
                            setString(ref textValues, "Last system station name", Station.Name);
                        }
                        setInt(ref intValues, "Last system stations", LastStarSystem.Stations.Count);
                        setInt(ref intValues, "Last system starports", LastStarSystem.Stations.Count(s => s.IsStarport()));
                        setInt(ref intValues, "Last system outposts", LastStarSystem.Stations.Count(s => s.IsOutpost()));
                        setInt(ref intValues, "Last system planetary stations", LastStarSystem.Stations.Count(s => s.IsPlanetary()));
                        setInt(ref intValues, "Last system planetary outposts", LastStarSystem.Stations.Count(s => s.IsPlanetaryOutpost()));
                        setInt(ref intValues, "Last system planetary ports", LastStarSystem.Stations.Count(s => s.IsPlanetaryPort()));
                        debug("InvokeNewSystem() Set last system station information");
                    }
                }

                if (enableDebugging)
                {
                    debug("InvokeNewSystem(): Resultant shortint values " + JsonConvert.SerializeObject(shortIntValues));
                    debug("InvokeNewSystem(): Resultant text values " + JsonConvert.SerializeObject(textValues));
                    debug("InvokeNewSystem(): Resultant int values " + JsonConvert.SerializeObject(intValues));
                    debug("InvokeNewSystem(): Resultant decimal values " + JsonConvert.SerializeObject(decimalValues));
                    debug("InvokeNewSystem(): Resultant boolean values " + JsonConvert.SerializeObject(booleanValues));
                    debug("InvokeNewSystem(): Resultant datetime values " + JsonConvert.SerializeObject(dateTimeValues));
                }

                setPluginStatus(ref textValues, "Operational", null, null);
            }
            catch (Exception e)
            {
                setPluginStatus(ref textValues, "Failed", "Failed to obtain system data", e);
            }
        }