public void Say(Commander commander, Ship ship, string script)
        {
            string shipScript;
            if (ship == null || ship.Name == null || ship.Name.Trim().Length == 0)
            {
                shipScript = "your ship";
            }
            else if (ship.PhoneticName == null || ship.PhoneticName.Trim().Length == 0)
            {
                shipScript = ship.Name;
            }
            else
            {
                shipScript = "<phoneme alphabet=\"ipa\" ph=\"" + ship.PhoneticName + "\">" + ship.Name + "</phoneme>";
            }
            script = script.Replace("$=", shipScript);

            string cmdrScript;
            if (commander == null || commander.Name == null || commander.Name.Trim().Length == 0)
            {
                cmdrScript = "commander";
            }
            else if (commander.PhoneticName == null || commander.PhoneticName.Trim().Length == 0)
            {
                cmdrScript = "commander " + commander.Name;
            }
            else
            {
                cmdrScript = "commander <phoneme alphabet=\"ipa\" ph=\"" + commander.PhoneticName + "\">" + commander.Name + "</phoneme>";
            }
            script = script.Replace("$-", cmdrScript);

            Speak(script, null, echoDelayForShip(ship), distortionLevelForShip(ship), chorusLevelForShip(ship), reverbLevelForShip(ship), 0, false);
        }
        /// <summary>Create a commander profile given the results from a /profile call</summary>
        public static Commander CommanderFromProfile(dynamic json)
        {
            Commander Commander = new Commander();

            Commander.Name = (string)json["commander"]["name"];

            Commander.CombatRating = (int)json["commander"]["rank"]["combat"];
            Commander.CombatRank = Commander.combatRanks[Commander.CombatRating];

            Commander.TradeRating = (int)json["commander"]["rank"]["trade"];
            Commander.TradeRank = Commander.tradeRanks[Commander.TradeRating];

            Commander.ExploreRating = (int)json["commander"]["rank"]["explore"];
            Commander.ExploreRank = Commander.exploreRanks[Commander.ExploreRating];

            Commander.EmpireRating = (int)json["commander"]["rank"]["empire"];
            Commander.EmpireRank = Commander.empireRanks[(int)Commander.EmpireRating];
            Commander.FederationRating = (int)json["commander"]["rank"]["federation"];
            Commander.FederationRank = Commander.federationRanks[(int)Commander.FederationRating];

            Commander.Credits = (long)json["commander"]["credits"];
            Commander.Debt = (long)json["commander"]["debt"];

            Commander.StarSystem = (string)json["lastSystem"]["name"];

            Commander.Ship = ShipFromProfile(json);

            Commander.StoredShips = StoredShipsFromProfile(json);

            Commander.Outfitting = OutfittingFromProfile(json);

            return Commander;
        }
 public StarMapData(Commander commander, decimal distanceToSol, decimal distanceToMaia, decimal distanceToRobigo, decimal distanceTo17Draconis)
 {
     this.commander = commander.Name;
     this.fromSoftware = "EDDI";
     this.fromSoftwareVersion = "0.7.2";
     this.p0 = new Reference(commander.StarSystem);
     this.refs = new List<Reference>();
     this.refs.Add(new Reference("Sol", distanceToSol));
     this.refs.Add(new Reference("Maia", distanceToMaia));
     this.refs.Add(new Reference("Robigo", distanceToRobigo));
     this.refs.Add(new Reference("17 Draconis", distanceTo17Draconis));
 }
 public void Receive(Commander commander, Ship ship, string script)
 {
     if (ship == null)
     {
         script = script.Replace("$=", "Unidentified ship");
     }
     else if (ship.CallSign == null)
     {
         script = script.Replace("$=", "Unidentified " + Translations.ShipModel(ship.Model));
     }
     else
     {
         script = script.Replace("$=", "" + ship.Model + " " + Translations.CallSign(ship.CallSign));
     }
     Speak(script, null, echoDelayForShip(ship), distortionLevelForShip(ship), chorusLevelForShip(ship), reverbLevelForShip(ship), 0, true);
 }
 public void sendStarMapSubmission(Commander commander, decimal distanceToSol, decimal distanceToMaia, decimal distanceToRobigo, decimal distanceTo17Draconis)
 {
     StarMapData data = new StarMapData(commander, distanceToSol, distanceToMaia, distanceToRobigo, distanceTo17Draconis);
     StarMapSubmission submission = new StarMapSubmission(data);
 }
        public MainWindow()
        {
            InitializeComponent();

            // Configured the EDDI tab
            eddiConfiguration = EDDIConfiguration.FromFile();
            eddiHomeSystemText.Text = eddiConfiguration.HomeSystem;
            eddiHomeStationText.Text = eddiConfiguration.HomeStation;
            eddiInsuranceDecimal.Value = eddiConfiguration.Insurance;

            // Configure the Companion App tab
            CompanionAppCredentials companionAppCredentials = CompanionAppCredentials.FromFile();
            // See if the credentials work
            companionAppService = new CompanionAppService(eddiConfiguration.Debug);
            try
            {
                commander = companionAppService.Profile();
                setUpCompanionAppComplete("Your connection to the companion app is operational, Commander " + commander.Name);
            }
            catch (Exception ex)
            {
                if (companionAppService.CurrentState == CompanionAppService.State.NEEDS_LOGIN)
                {
                    // Fall back to stage 1
                    setUpCompanionAppStage1();
                }
                else if (companionAppService.CurrentState == CompanionAppService.State.NEEDS_CONFIRMATION)
                {
                    // Fall back to stage 2
                    setUpCompanionAppStage2();
                }
            }

            if (commander != null)
            {
                setShipyardFromConfiguration();
            }

            // Configure the NetLog tab
            NetLogConfiguration netLogConfiguration = NetLogConfiguration.FromFile();
            netLogPathTextBox.Text = netLogConfiguration.path;

            // Configure the EDSM tab
            StarMapConfiguration starMapConfiguration = StarMapConfiguration.FromFile();
            edsmApiKeyTextBox.Text = starMapConfiguration.apiKey;
            edsmCommanderNameTextBox.Text = starMapConfiguration.commanderName;

            // Configure the Text-to-speech tab
            SpeechServiceConfiguration speechServiceConfiguration = SpeechServiceConfiguration.FromFile();
            List<String> speechOptions = new List<String>();
            speechOptions.Add("Windows TTS default");
            try
            {
                using (SpeechSynthesizer synth = new SpeechSynthesizer())
                {
                    foreach (InstalledVoice voice in synth.GetInstalledVoices())
                    {
                        if (voice.Enabled)
                        {
                            speechOptions.Add(voice.VoiceInfo.Name);
                        }
                    }
                }

                ttsVoiceDropDown.ItemsSource = speechOptions;
                ttsVoiceDropDown.Text = speechServiceConfiguration.StandardVoice == null ? "Windows TTS default" : speechServiceConfiguration.StandardVoice;
            }
            catch (Exception e)
            {
                using (System.IO.StreamWriter errLog = new System.IO.StreamWriter(Environment.GetEnvironmentVariable("AppData") + @"\EDDI\speech.log", true))
                {
                   errLog.WriteLine("" + System.Threading.Thread.CurrentThread.ManagedThreadId + ": Caught exception " + e);
                }
            }
            ttsRateSlider.Value = speechServiceConfiguration.Rate;
            ttsEffectsLevelSlider.Value = speechServiceConfiguration.EffectsLevel;
            ttsDistortCheckbox.IsChecked = speechServiceConfiguration.DistortOnDamage;

            ttsTestShipDropDown.ItemsSource = ShipDefinitions.ShipModels;
            ttsTestShipDropDown.Text = "Adder";
        }
 // Handle changes to the companion app tab
 private void companionAppNextClicked(object sender, RoutedEventArgs e)
 {
     // See if the user is entering their email address and password
     if (companionAppEmailText.Visibility == Visibility.Visible)
     {
         // Stage 1 of authentication - login
         companionAppService.Credentials.email = companionAppEmailText.Text.Trim();
         companionAppService.Credentials.password = companionAppPasswordText.Password.Trim();
         try
         {
             // It is possible that we have valid cookies at this point so don't log in, but we did
             // need the credentials
             if (companionAppService.CurrentState == CompanionAppService.State.NEEDS_LOGIN)
             {
                 companionAppService.Login();
             }
             if (companionAppService.CurrentState == CompanionAppService.State.NEEDS_CONFIRMATION)
             {
                 setUpCompanionAppStage2();
             }
             else if (companionAppService.CurrentState == CompanionAppService.State.READY)
             {
                 if (commander == null)
                 {
                     commander = companionAppService.Profile();
                 }
                 setUpCompanionAppComplete("Your connection to the companion app is operational, Commander " + commander.Name);
                 setShipyardFromConfiguration();
             }
         }
         catch (EliteDangerousCompanionAppAuthenticationException ex)
         {
             companionAppText.Text = ex.Message;
         }
         catch (EliteDangerousCompanionAppErrorException ex)
         {
             companionAppText.Text = ex.Message;
         }
         catch (Exception ex)
         {
             companionAppText.Text = "Unexpected problem\r\nPlease report this at http://github.com/CmdrMcDonald/EliteDangerousDataProvider/issues\r\n" + ex;
         }
     }
     else if (companionAppCodeText.Visibility == Visibility.Visible)
     {
         // Stage 2 of authentication - confirmation
         string code = companionAppCodeText.Text.Trim();
         try
         {
             companionAppService.Confirm(code);
             // All done - see if it works
             commander = companionAppService.Profile();
             setUpCompanionAppComplete("Your connection to the companion app is operational, Commander " + commander.Name);
             setShipyardFromConfiguration();
         }
         catch (EliteDangerousCompanionAppAuthenticationException ex)
         {
             setUpCompanionAppStage1(ex.Message);
         }
         catch (EliteDangerousCompanionAppErrorException ex)
         {
             setUpCompanionAppStage1(ex.Message);
         }
         catch (Exception ex)
         {
             setUpCompanionAppStage1("Unexpected problem\r\nPlease report this at http://github.com/CmdrMcDonald/EliteDangerousDataProvider/issues\r\n" + ex);
         }
     }
 }
 private static void AugmentCmdrInfo(Commander cmdr)
 {
     if (cmdr != null)
     {
         CommanderConfiguration cmdrConfiguration = CommanderConfiguration.FromFile();
         if (cmdrConfiguration.PhoneticName == null || cmdrConfiguration.PhoneticName.Trim().Length == 0)
         {
             cmdr.PhoneticName = null;
         }
         else
         {
             cmdr.PhoneticName = cmdrConfiguration.PhoneticName;
         }
     }
 }
        public Commander Profile()
        {
            if (CurrentState != State.READY)
            {
                // Shouldn't be here
                throw new EliteDangerousCompanionAppIllegalStateException("Service in incorrect state to provide profile (" + CurrentState + ")");
            }
            if (cachedProfileExpires > DateTime.Now)
            {
                // return the cached version
                return cachedProfile;
            }

            HttpWebRequest request = GetRequest(BASE_URL + PROFILE_URL);
            HttpWebResponse response = GetResponse(request);

            if (response.StatusCode == HttpStatusCode.Found && response.Headers["Location"] == LOGIN_URL)
            {
                // Need to log in again.
                CurrentState = State.NEEDS_LOGIN;
                Login();
                if (CurrentState != State.READY)
                {
                    throw new EliteDangerousCompanionAppIllegalStateException("Service in incorrect state to provide profile (" + CurrentState + ")");
                }
                // Rerun the profile request
                request = GetRequest(BASE_URL + PROFILE_URL);
                response = GetResponse(request);
            }

            // Obtain and parse our response
            var encoding = response.CharacterSet == ""
                        ? Encoding.UTF8
                        : Encoding.GetEncoding(response.CharacterSet);

            using (var stream = response.GetResponseStream())
            {
                var reader = new StreamReader(stream, encoding);
                string data = reader.ReadToEnd();
                response.Close();
                cachedProfile = CommanderFromProfile(data);
                cachedProfileExpires = DateTime.Now.AddSeconds(30);
                return cachedProfile;
            }
        }
        public static List<Ship> StoredShipsFromProfile(dynamic json, ref Commander commander)
        {
            Ship currentShip = commander.Ship;

            List<Ship> StoredShips = new List<Ship>();

            foreach (dynamic shipJson in json["ships"])
            {
                if (shipJson != null)
                {
                    dynamic ship = shipJson.Value;
                    if (ship != null)
                    {
                        if ((int)ship["id"] != currentShip.LocalId)
                        {
                            Ship Ship = new Ship();

                            if (ship["starsystem"] != null)
                            {
                                // If we have a starsystem it means that the ship is stored
                                Ship.LocalId = ship["id"];
                                Ship.Model = ship["name"];
                                if (shipTranslations.ContainsKey(Ship.Model))
                                {
                                    Ship.Model = shipTranslations[Ship.Model];
                                }

                                Ship.StarSystem = ship["starsystem"]["name"];
                                Ship.Station = ship["station"]["name"];

                                StoredShips.Add(Ship);
                            }
                        }
                    }
                }
            }

            return StoredShips;
        }
        /// <summary>Create a commander profile given the results from a /profile call</summary>
        public static Commander CommanderFromProfile(dynamic json)
        {
            Commander Commander = new Commander();

            if (json["commander"] != null)
            {
                Commander.Name = (string)json["commander"]["name"];

                Commander.CombatRating = (int)json["commander"]["rank"]["combat"];
                Commander.CombatRank = Commander.combatRanks[Commander.CombatRating];

                Commander.TradeRating = (int)json["commander"]["rank"]["trade"];
                Commander.TradeRank = Commander.tradeRanks[Commander.TradeRating];

                Commander.ExploreRating = (int)json["commander"]["rank"]["explore"];
                Commander.ExploreRank = Commander.exploreRanks[Commander.ExploreRating];

                Commander.EmpireRating = (int)json["commander"]["rank"]["empire"];
                Commander.EmpireRank = Commander.empireRanks[(int)Commander.EmpireRating];
                Commander.FederationRating = (int)json["commander"]["rank"]["federation"];
                Commander.FederationRank = Commander.federationRanks[(int)Commander.FederationRating];

                Commander.Credits = (long)json["commander"]["credits"];
                Commander.Debt = (long)json["commander"]["debt"];

                Commander.StarSystem = json["lastSystem"] == null ? null : (string)json["lastSystem"]["name"];

                Commander.Ship = ShipFromProfile(json);

                Commander.StoredShips = StoredShipsFromProfile(json, ref Commander);

                AugmentShipInfo(Commander.Ship, Commander.StoredShips);

                Commander.Outfitting = OutfittingFromProfile(json);

                Commander.LastStation = json["lastStarport"] == null ? null : (string)json["lastStarport"]["name"];
            }

            return Commander;
        }
        public static void InvokeUpdateProfile(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
            {
                // Obtain the command profile
                Cmdr = app.Profile();

                //
                // Commander data
                //
                setString(ref textValues, "Name", Cmdr.Name);
                setInt(ref intValues, "Combat rating", Cmdr.CombatRating);
                setString(ref textValues, "Combat rank", Cmdr.CombatRank);
                setInt(ref intValues, "Trade rating", Cmdr.TradeRating);
                setString(ref textValues, "Trade rank", Cmdr.TradeRank);
                setInt(ref intValues, "Explore rating", Cmdr.ExploreRating);
                setString(ref textValues, "Explore rank", Cmdr.ExploreRank);
                setInt(ref intValues, "Empire rating", Cmdr.EmpireRating);
                setString(ref textValues, "Empire rank", Cmdr.EmpireRank);
                setInt(ref intValues, "Federation rating", Cmdr.FederationRating);
                setString(ref textValues, "Federation rank", Cmdr.FederationRank);
                setInt(ref intValues, "Credits", (int)(Cmdr.Credits / 1000)); // TODO remove in next major release
                setDecimal(ref decimalValues, "Credits", (decimal)Cmdr.Credits);
                setString(ref textValues, "Credits", humanize(Cmdr.Credits)); // TODO remove in next major release
                setString(ref textValues, "Credits (spoken)", humanize(Cmdr.Credits));
                setInt(ref intValues, "Debt", (int)(Cmdr.Debt / 1000)); // TODO remove in next major release
                setDecimal(ref decimalValues, "Debt", (decimal)Cmdr.Debt);
                setString(ref textValues, "Debt", humanize(Cmdr.Debt)); // TODO remove in next major release
                setString(ref textValues, "Debt (spoken)", humanize(Cmdr.Debt));

                //
                // Ship data
                //
                setString(ref textValues, "Ship model", Cmdr.Ship.Model);
                setString(ref textValues, "Ship model (spoken)", VATranslations.ShipModel(Cmdr.Ship.Model));
                setString(ref textValues, "Ship size", Cmdr.Ship.Size.ToString());
                setInt(ref intValues, "Ship value", (int)(Cmdr.Ship.Value / 1000)); // TODO remove in next major release
                setDecimal(ref decimalValues, "Ship value", (decimal)Cmdr.Ship.Value);
                setString(ref textValues, "Ship value", humanize(Cmdr.Ship.Value)); // TODO remove in next major release
                setString(ref textValues, "Ship value (spoken)", humanize(Cmdr.Ship.Value));
                setDecimal(ref decimalValues, "Ship health", Cmdr.Ship.Health);
                setInt(ref intValues, "Ship cargo capacity", Cmdr.Ship.CargoCapacity);
                setInt(ref intValues, "Ship cargo carried", Cmdr.Ship.CargoCarried);

                setString(ref textValues, "Ship bulkheads", Cmdr.Ship.Bulkheads.Name);
                setDecimal(ref decimalValues, "Ship bulkheads health", Cmdr.Ship.Bulkheads.Health);
                setDecimal(ref decimalValues, "Ship bulkheads cost", (decimal)Cmdr.Ship.Bulkheads.Cost);
                setDecimal(ref decimalValues, "Ship bulkheads value", (decimal)Cmdr.Ship.Bulkheads.Value);
                setDecimal(ref decimalValues, "Ship bulkheads discount", Cmdr.Ship.Bulkheads.Value == 0 ? 0 : Math.Round((1 - (((decimal)Cmdr.Ship.Bulkheads.Cost) / ((decimal)Cmdr.Ship.Bulkheads.Value))) * 100, 1));

                setString(ref textValues, "Ship power plant", Cmdr.Ship.PowerPlant.Class + Cmdr.Ship.PowerPlant.Grade);
                setDecimal(ref decimalValues, "Ship power plant health", Cmdr.Ship.PowerPlant.Health);
                setDecimal(ref decimalValues, "Ship power plant cost", (decimal)Cmdr.Ship.PowerPlant.Cost);
                setDecimal(ref decimalValues, "Ship power plant value", (decimal)Cmdr.Ship.PowerPlant.Value);
                setDecimal(ref decimalValues, "Ship power plant discount", Cmdr.Ship.PowerPlant.Value == 0 ? 0 : Math.Round((1 - (((decimal)Cmdr.Ship.PowerPlant.Cost) / ((decimal)Cmdr.Ship.PowerPlant.Value))) * 100, 1));

                setString(ref textValues, "Ship thrusters", Cmdr.Ship.Thrusters.Class + Cmdr.Ship.Thrusters.Grade);
                setDecimal(ref decimalValues, "Ship thrusters health", Cmdr.Ship.Thrusters.Health);
                setDecimal(ref decimalValues, "Ship thrusters cost", (decimal)Cmdr.Ship.Thrusters.Cost);
                setDecimal(ref decimalValues, "Ship thrusters value", (decimal)Cmdr.Ship.Thrusters.Value);
                setDecimal(ref decimalValues, "Ship thrusters discount", Cmdr.Ship.Thrusters.Value == 0 ? 0 : Math.Round((1 - (((decimal)Cmdr.Ship.Thrusters.Cost) / ((decimal)Cmdr.Ship.Thrusters.Value))) * 100, 1));

                setString(ref textValues, "Ship frame shift drive", Cmdr.Ship.FrameShiftDrive.Class + Cmdr.Ship.FrameShiftDrive.Grade);
                setDecimal(ref decimalValues, "Ship frame shift drive health", Cmdr.Ship.FrameShiftDrive.Health);
                setDecimal(ref decimalValues, "Ship frame shift drive cost", (decimal)Cmdr.Ship.FrameShiftDrive.Cost);
                setDecimal(ref decimalValues, "Ship frame shift drive value", (decimal)Cmdr.Ship.FrameShiftDrive.Value);
                setDecimal(ref decimalValues, "Ship frame shift drive discount", Cmdr.Ship.FrameShiftDrive.Value == 0 ? 0 : Math.Round((1 - (((decimal)Cmdr.Ship.FrameShiftDrive.Cost) / ((decimal)Cmdr.Ship.FrameShiftDrive.Value))) * 100, 1));

                setString(ref textValues, "Ship life support", Cmdr.Ship.LifeSupport.Class + Cmdr.Ship.LifeSupport.Grade);
                setDecimal(ref decimalValues, "Ship life support health", Cmdr.Ship.LifeSupport.Health);
                setDecimal(ref decimalValues, "Ship life support cost", (decimal)Cmdr.Ship.LifeSupport.Cost);
                setDecimal(ref decimalValues, "Ship life support value", (decimal)Cmdr.Ship.LifeSupport.Value);
                setDecimal(ref decimalValues, "Ship life support discount", Cmdr.Ship.LifeSupport.Value == 0 ? 0 : Math.Round((1 - (((decimal)Cmdr.Ship.LifeSupport.Cost) / ((decimal)Cmdr.Ship.LifeSupport.Value))) * 100, 1));

                setString(ref textValues, "Ship power distributor", Cmdr.Ship.PowerDistributor.Class + Cmdr.Ship.PowerDistributor.Grade);
                setDecimal(ref decimalValues, "Ship power distributor health", Cmdr.Ship.PowerDistributor.Health);
                setDecimal(ref decimalValues, "Ship power distributor cost", (decimal)Cmdr.Ship.PowerDistributor.Cost);
                setDecimal(ref decimalValues, "Ship power distributor value", (decimal)Cmdr.Ship.PowerDistributor.Value);
                setDecimal(ref decimalValues, "Ship power distributor discount", Cmdr.Ship.PowerDistributor.Value == 0 ? 0 : Math.Round((1 - (((decimal)Cmdr.Ship.PowerDistributor.Cost) / ((decimal)Cmdr.Ship.PowerDistributor.Value))) * 100, 1));

                setString(ref textValues, "Ship sensors", Cmdr.Ship.Sensors.Class + Cmdr.Ship.Sensors.Grade);
                setDecimal(ref decimalValues, "Ship sensors health", Cmdr.Ship.Sensors.Health);
                setDecimal(ref decimalValues, "Ship sensors cost", (decimal)Cmdr.Ship.Sensors.Cost);
                setDecimal(ref decimalValues, "Ship sensors value", (decimal)Cmdr.Ship.Sensors.Value);
                setDecimal(ref decimalValues, "Ship sensors discount", Cmdr.Ship.Sensors.Value == 0 ? 0 : Math.Round((1 - (((decimal)Cmdr.Ship.Sensors.Cost) / ((decimal)Cmdr.Ship.Sensors.Value))) * 100, 1));

                setString(ref textValues, "Ship fuel tank", Cmdr.Ship.FuelTank.Class + Cmdr.Ship.FuelTank.Grade);
                setDecimal(ref decimalValues, "Ship fuel tank cost", (decimal)Cmdr.Ship.FuelTank.Cost);
                setDecimal(ref decimalValues, "Ship fuel tank value", (decimal)Cmdr.Ship.FuelTank.Value);
                setDecimal(ref decimalValues, "Ship fuel tank discount", Cmdr.Ship.FuelTank.Value == 0 ? 0 : Math.Round((1 - (((decimal)Cmdr.Ship.FuelTank.Cost) / ((decimal)Cmdr.Ship.FuelTank.Value))) * 100, 1));
                //                setInt(ref intValues, "Ship fuel tank capacity", 0); // TODO

                // Hardpoints
                int weaponHardpoints = 0;
                foreach (Hardpoint Hardpoint in Cmdr.Ship.Hardpoints)
                {
                    if (Hardpoint.Size > 0)
                    {
                        weaponHardpoints++;
                    }
                }
                setInt(ref intValues, "Ship hardpoints", weaponHardpoints);
                setInt(ref intValues, "Ship utility slots", Cmdr.Ship.Hardpoints.Count - weaponHardpoints);

                // Compartments
                //foreach (Compartment Compartment in Cmdr.Ship.Hardpoints)
                //{
                //    if (Compartment.Size > 0)
                //    {
                //        weaponHardpoints++;
                //    }
                //}
                setInt(ref intValues, "Ship compartments", Cmdr.Ship.Compartments.Count);

                //
                // Stored ships data
                //
                int currentStoredShip = 1;
                foreach (Ship StoredShip in Cmdr.StoredShips)
                {
                    string varBase = "Stored ship " + currentStoredShip;
                    setString(ref textValues, varBase + " model", StoredShip.Model);
                    setString(ref textValues, varBase + " system", StoredShip.StarSystem);
                    setString(ref textValues, varBase + " station", StoredShip.Station);
                    currentStoredShip++;
                }
                setInt(ref intValues, "Stored ships", Cmdr.StoredShips.Count);

                //
                // Outfitting data
                //
                SetOutfittingCost("bulkheads",  Cmdr.Ship.Bulkheads, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                SetOutfittingCost("power plant", Cmdr.Ship.PowerPlant, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                SetOutfittingCost("thrusters", Cmdr.Ship.Thrusters, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                SetOutfittingCost("frame shift drive", Cmdr.Ship.FrameShiftDrive, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                SetOutfittingCost("life support", Cmdr.Ship.LifeSupport, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                SetOutfittingCost("power distributor", Cmdr.Ship.PowerDistributor, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                SetOutfittingCost("sensors", Cmdr.Ship.Sensors, ref Cmdr.Outfitting, ref textValues, ref decimalValues);

                setPluginStatus(ref textValues, "Operational", null, null);
            }
            catch (Exception e)
            {
                setPluginStatus(ref textValues, "Failed", "Failed to access system data", e);
            }
        }
        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 InvokeUpdateProfile(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("InvokeUpdateProfile(): entered.  App service is " + (appService == null ? "disabled" : "enabled"));
            if (appService != null)
            {
                try
                {
                    // Obtain the command profile
                    Cmdr = appService.Profile();

                    debug("InvokeUpdateProfile(): Commander is " + JsonConvert.SerializeObject(Cmdr));

                    //
                    // Commander data
                    //
                    setString(ref textValues, "Name", Cmdr.Name);
                    setInt(ref intValues, "Combat rating", Cmdr.CombatRating);
                    setString(ref textValues, "Combat rank", Cmdr.CombatRank);
                    setInt(ref intValues, "Trade rating", Cmdr.TradeRating);
                    setString(ref textValues, "Trade rank", Cmdr.TradeRank);
                    setInt(ref intValues, "Explore rating", Cmdr.ExploreRating);
                    setString(ref textValues, "Explore rank", Cmdr.ExploreRank);
                    setInt(ref intValues, "Empire rating", Cmdr.EmpireRating);
                    setString(ref textValues, "Empire rank", Cmdr.EmpireRank);
                    setInt(ref intValues, "Federation rating", Cmdr.FederationRating);
                    setString(ref textValues, "Federation rank", Cmdr.FederationRank);
                    setDecimal(ref decimalValues, "Credits", (decimal)Cmdr.Credits);
                    setString(ref textValues, "Credits (spoken)", humanize(Cmdr.Credits));
                    setDecimal(ref decimalValues, "Debt", (decimal)Cmdr.Debt);
                    setString(ref textValues, "Debt (spoken)", humanize(Cmdr.Debt));

                    //
                    // Ship data
                    //
                    setString(ref textValues, "Ship model", Cmdr.Ship.Model);
                    setString(ref textValues, "Ship model (spoken)", Translations.ShipModel(Cmdr.Ship.Model));
                    setString(ref textValues, "Ship callsign", Cmdr.Ship.CallSign);
                    setString(ref textValues, "Ship callsign (spoken)", Translations.CallSign(Cmdr.Ship.CallSign));
                    setString(ref textValues, "Ship name", Cmdr.Ship.Name);
                    setString(ref textValues, "Ship role", Cmdr.Ship.Role.ToString());
                    setString(ref textValues, "Ship size", Cmdr.Ship.Size.ToString());
                    setDecimal(ref decimalValues, "Ship value", (decimal)Cmdr.Ship.Value);
                    setString(ref textValues, "Ship value (spoken)", humanize(Cmdr.Ship.Value));
                    setDecimal(ref decimalValues, "Ship health", Cmdr.Ship.Health);
                    setInt(ref intValues, "Ship cargo capacity", Cmdr.Ship.CargoCapacity);
                    setInt(ref intValues, "Ship cargo carried", Cmdr.Ship.CargoCarried);
                    // Add number of limpets carried
                    int limpets = 0;
                    foreach (Cargo cargo in Cmdr.Ship.Cargo)
                    {
                        if (cargo.Commodity.Name == "Limpet")
                        {
                            limpets += cargo.Quantity;
                        }
                    }
                    setInt(ref intValues, "Ship limpets carried", limpets);

                    SetModuleDetails("Ship bulkheads", Cmdr.Ship.Bulkheads, ref textValues, ref intValues, ref decimalValues);
                    SetOutfittingCost("Ship bulkheads", Cmdr.Ship.Bulkheads, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                    SetModuleDetails("Ship power plant", Cmdr.Ship.PowerPlant, ref textValues, ref intValues, ref decimalValues);
                    SetOutfittingCost("Ship power plant", Cmdr.Ship.PowerPlant, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                    SetModuleDetails("Ship thrusters", Cmdr.Ship.Thrusters, ref textValues, ref intValues, ref decimalValues);
                    SetOutfittingCost("Ship thrusters", Cmdr.Ship.Thrusters, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                    SetModuleDetails("Ship frame shift drive", Cmdr.Ship.FrameShiftDrive, ref textValues, ref intValues, ref decimalValues);
                    SetOutfittingCost("Ship frame shift drive", Cmdr.Ship.FrameShiftDrive, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                    SetModuleDetails("Ship life support", Cmdr.Ship.LifeSupport, ref textValues, ref intValues, ref decimalValues);
                    SetOutfittingCost("Ship life support", Cmdr.Ship.LifeSupport, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                    SetModuleDetails("Ship power distributor", Cmdr.Ship.PowerDistributor, ref textValues, ref intValues, ref decimalValues);
                    SetOutfittingCost("Ship power distributor", Cmdr.Ship.PowerDistributor, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                    SetModuleDetails("Ship sensors", Cmdr.Ship.Sensors, ref textValues, ref intValues, ref decimalValues);
                    SetOutfittingCost("Ship sensors", Cmdr.Ship.Sensors, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                    SetModuleDetails("Ship fuel tank", Cmdr.Ship.FuelTank, ref textValues, ref intValues, ref decimalValues);
                    SetOutfittingCost("Ship fuel tank", Cmdr.Ship.FuelTank, ref Cmdr.Outfitting, ref textValues, ref decimalValues);

                    // Hardpoints
                    int numTinyHardpoints = 0;
                    int numSmallHardpoints = 0;
                    int numMediumHardpoints = 0;
                    int numLargeHardpoints = 0;
                    int numHugeHardpoints = 0;
                    foreach (Hardpoint Hardpoint in Cmdr.Ship.Hardpoints)
                    {
                        string baseHardpointName = "";
                        switch (Hardpoint.Size)
                        {
                            case 0:
                                baseHardpointName = "Ship tiny hardpoint " + ++numTinyHardpoints;
                                break;
                            case 1:
                                baseHardpointName = "Ship small hardpoint " + ++numSmallHardpoints;
                                break;
                            case 2:
                                baseHardpointName = "Ship medium hardpoint " + ++numMediumHardpoints;
                                break;
                            case 3:
                                baseHardpointName = "Ship large hardpoint " + ++numLargeHardpoints;
                                break;
                            case 4:
                                baseHardpointName = "Ship huge hardpoint " + ++numHugeHardpoints;
                                break;
                        }

                        setBoolean(ref booleanValues, baseHardpointName + " occupied", Hardpoint.Module != null);
                        SetModuleDetails(baseHardpointName + " module", Hardpoint.Module, ref textValues, ref intValues, ref decimalValues);
                        SetOutfittingCost(baseHardpointName + " module", Hardpoint.Module, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                    }

                    setInt(ref intValues, "Ship hardpoints", numSmallHardpoints + numMediumHardpoints + numLargeHardpoints + numHugeHardpoints);
                    setInt(ref intValues, "Ship utility slots", numTinyHardpoints);

                    // Compartments
                    int curCompartment = 0;
                    foreach (Compartment Compartment in Cmdr.Ship.Compartments)
                    {
                        string baseCompartmentName = "Ship compartment " + ++curCompartment;
                        setInt(ref intValues, baseCompartmentName + " size", Compartment.Size);
                        setBoolean(ref booleanValues, baseCompartmentName + " occupied", Compartment.Module != null);
                        SetModuleDetails(baseCompartmentName + " module", Compartment.Module, ref textValues, ref intValues, ref decimalValues);
                        SetOutfittingCost(baseCompartmentName + " module", Compartment.Module, ref Cmdr.Outfitting, ref textValues, ref decimalValues);
                    }
                    setInt(ref intValues, "Ship compartments", curCompartment);

                    //
                    // Stored ships data
                    //
                    int currentStoredShip = 1;
                    foreach (Ship StoredShip in Cmdr.StoredShips)
                    {
                        string varBase = "Stored ship " + currentStoredShip;
                        setString(ref textValues, varBase + " model", StoredShip.Model);
                        setString(ref textValues, varBase + " system", StoredShip.StarSystem);
                        setString(ref textValues, varBase + " station", StoredShip.Station);
                        setString(ref textValues, varBase + " callsign", StoredShip.CallSign);
                        setString(ref textValues, varBase + " callsign (spoken)", Translations.CallSign(StoredShip.CallSign));
                        setString(ref textValues, varBase + " name", StoredShip.Name);
                        setString(ref textValues, varBase + " role", StoredShip.Role.ToString());

                        // Fetch the star system in which the ship is stored
                        EDDIStarSystem StoredShipStarSystemData = starSystemRepository.GetEDDIStarSystem(StoredShip.StarSystem);
                        if (StoredShipStarSystemData == null)
                        {
                            // We have no record of this system; set it up
                            StoredShipStarSystemData = new EDDIStarSystem();
                            StoredShipStarSystemData.Name = StoredShip.StarSystem;
                            StoredShipStarSystemData.StarSystem = DataProviderService.GetSystemData(StoredShip.StarSystem);
                            StoredShipStarSystemData.LastVisit = DateTime.Now;
                            StoredShipStarSystemData.StarSystemLastUpdated = StoredShipStarSystemData.LastVisit;
                            StoredShipStarSystemData.TotalVisits = 1;
                            starSystemRepository.SaveEDDIStarSystem(StoredShipStarSystemData);
                        }

                        // Have to grab a local copy of our star system as CurrentStarSystem might not have been initialised yet
                        EDDIStarSystem ThisStarSystemData = starSystemRepository.GetEDDIStarSystem(Cmdr.StarSystem);

                        // Work out the distance to the system where the ship is stored if we can
                        if (ThisStarSystemData != null && ThisStarSystemData.StarSystem != null && ThisStarSystemData.StarSystem.X != null && StoredShipStarSystemData.StarSystem != null && StoredShipStarSystemData.StarSystem.X != null)
                        {
                            decimal distance = (decimal)Math.Round(Math.Sqrt(Math.Pow((double)(ThisStarSystemData.StarSystem.X - StoredShipStarSystemData.StarSystem.X), 2)
                                + Math.Pow((double)(ThisStarSystemData.StarSystem.Y - StoredShipStarSystemData.StarSystem.Y), 2)
                                + Math.Pow((double)(ThisStarSystemData.StarSystem.Z - StoredShipStarSystemData.StarSystem.Z), 2)), 2);
                            setDecimal(ref decimalValues, varBase + " distance", distance);
                        }
                        else
                        {
                            // We don't know how far away the ship is
                            setDecimal(ref decimalValues, varBase + " distance", (decimal?)null);
                        }

                        currentStoredShip++;
                    }
                    setInt(ref intValues, "Stored ships", Cmdr.StoredShips.Count);
                    // We also clear out any ships that have been sold since the last run.  We don't know
                    // how many there are so just clear out the succeeding 10 slots and hope that the commander
                    // hasn't gone on a selling spree
                    for (int i = 0; i < 10; i++)
                    {
                        string varBase = "Stored ship " + (currentStoredShip + i);
                        setString(ref textValues, varBase + " model", null);
                        setString(ref textValues, varBase + " system", null);
                        setString(ref textValues, varBase + " station", null);
                        setString(ref textValues, varBase + " callsign", null);
                        setString(ref textValues, varBase + " callsign (spoken)", null);
                        setString(ref textValues, varBase + " name", null);
                        setString(ref textValues, varBase + " role", null);
                        setDecimal(ref decimalValues, varBase + " distance", null);
                    }

                    setString(ref textValues, "Last station name", Cmdr.LastStation);

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

                    setPluginStatus(ref textValues, "Operational", null, null);
                    setString(ref textValues, "EDDI plugin profile status", "Enabled");
                }
                catch (Exception ex)
                {
                    setPluginStatus(ref textValues, "Failed", "Failed to access profile", ex);
                    setString(ref textValues, "EDDI plugin profile status", "Disabled");
                }
            }
        }