Beispiel #1
0
 public void insertSystems(string jsonFilePath)
 {
     using (var file = new StreamReader(jsonFilePath))
     {
         using (var con = SimpleDbConnection())
         {
             con.Open();
             using (var transaction = con.BeginTransaction())
             {
                 using (var cmd = new SQLiteCommand(con))
                 {
                     cmd.CommandText = INSERT_SYSTEM_SQL;
                     cmd.Prepare();
                     string line;
                     while ((line = file.ReadLine()) != null)
                     {
                         IDictionary <string, object> data = Deserializtion.DeserializeData(line);
                         cmd.Parameters.AddWithValue("@id", data["id"]);
                         cmd.Parameters.AddWithValue("@edsm_id", data["edsm_id"]);
                         cmd.Parameters.AddWithValue("@name", data["name"]);
                         cmd.Parameters.AddWithValue("@x", data["x"]);
                         cmd.Parameters.AddWithValue("@y", data["y"]);
                         cmd.Parameters.AddWithValue("@z", data["z"]);
                         cmd.ExecuteNonQuery();
                     }
                 }
                 transaction.Commit();
             }
             con.Close();
         }
         file.Close();
     }
 }
Beispiel #2
0
        private static List <StarSystem> PreserveUnsyncedProperties(List <StarSystem> updatedSystems, List <DatabaseStarSystem> systemsToUpdate)
        {
            if (updatedSystems is null)
            {
                return(new List <StarSystem>());
            }
            foreach (StarSystem updatedSystem in updatedSystems)
            {
                foreach (DatabaseStarSystem systemToUpdate in systemsToUpdate)
                {
                    if (updatedSystem.systemname == systemToUpdate.systemName)
                    {
                        IDictionary <string, object> oldStarSystem = Deserializtion.DeserializeData(systemToUpdate.systemJson);

                        if (oldStarSystem != null)
                        {
                            PreserveSystemProperties(updatedSystem, oldStarSystem);
                            PreserveBodyProperties(updatedSystem, oldStarSystem);
                            PreserveFactionProperties(updatedSystem, oldStarSystem);
                            // No station data needs to be carried over at this time.
                        }
                    }
                }
            }
            return(updatedSystems);
        }
Beispiel #3
0
        private void handleRawEvent(Event theEvent)
        {
            IDictionary <string, object> data = Deserializtion.DeserializeData(theEvent.raw);

            // Need to strip a number of entries
            data.Remove("CockpitBreach");
            data.Remove("BoostUsed");
            data.Remove("FuelLevel");
            data.Remove("FuelUsed");
            data.Remove("JumpDist");

            // Need to remove any keys ending with _Localised
            data = data.Where(x => !x.Key.EndsWith("_Localised")).ToDictionary(x => x.Key, x => x.Value);

            // Can only proceed if we know our current system

            // Need to add StarSystem to scan events - can only do so if we have the data
            if (theEvent is BeltScannedEvent || theEvent is StarScannedEvent || theEvent is BodyScannedEvent)
            {
                if (systemName == null || systemX == null || systemY == null || systemZ == null)
                {
                    Logging.Debug("Missing current starsystem information, cannot send message to EDDN");
                    return;
                }
                data.Add("StarSystem", systemName);
            }

            // Need to add StarPos to all events that don't already have them
            if (!data.ContainsKey("StarPos"))
            {
                if (systemName == null || systemX == null || systemY == null || systemZ == null)
                {
                    Logging.Debug("Missing current starsystem information, cannot send message to EDDN");
                    return;
                }
                IList <decimal> starpos = new List <decimal>
                {
                    systemX.Value,
                    systemY.Value,
                    systemZ.Value
                };
                data.Add("StarPos", starpos);
            }

            EDDNBody body = new EDDNBody
            {
                header = generateHeader(),
#if DEBUG
                // Use the test schema while in development.
                schemaRef = "https://eddn.edcd.io/schemas/journal/1/test",
#else
                schemaRef = "https://eddn.edcd.io/schemas/journal/1" + (EDDI.Instance.inBeta ? "/test" : ""),
#endif
                message = data
            };

            sendMessage(body);
        }
Beispiel #4
0
        public MicroResourceInfo FromFile(string filename = null)
        {
            var    inventory = new MicroResourceInfo();
            string json      = Files.FromSavedGames(filename);

            if (!string.IsNullOrEmpty(json))
            {
                var data = Deserializtion.DeserializeData(json);
                inventory = FromData(data);
            }
            return(inventory);
        }
Beispiel #5
0
        private void handleRawEvent(Event theEvent)
        {
            IDictionary <string, object> data = Deserializtion.DeserializeData(theEvent.raw);
            string edType = JsonParsing.getString(data, "event");

            if (edType == "FSDTarget" || edType == "StartJump")
            {
                // FSDTarget events describing the system we are targetting rather than the system we are in.
                // Scan events can register after StartJump and before we actually leave the originating system.
                // These must be ignored.
                return;
            }
            else if (edType == "Location" || edType == "FSDJump")
            {
                // We always start fresh from Location and FSDJump events
                invalidState = false;
                ClearLocation();
            }

            // Except as noted above, always attempt to obtain available location data from the active event
            GetLocationData(data);

            // Confirm the data in memory is as accurate as possible
            if (edType == "Docked" || edType == "Scan")
            {
                CheckLocationData(data);
            }

            if (LocationIsSet())
            {
                if (edType == "Docked" && systemName != null && stationName != null && marketId != null)
                {
                    // Send station data from the CAPI servers
                    sendCommodityInformation();
                    sendOutfittingInformation();
                    sendShipyardInformation();
                }

                if (edType == "Location" || edType == "FSDJump" || edType == "Docked" || edType == "Scan")
                {
                    data = StripPersonalData(data);
                    data = EnrichLocationData(edType, data);

                    if (data != null)
                    {
                        SendToEDDN(data);
                    }
                }
            }
        }
Beispiel #6
0
        private void handleRawEvent(Event theEvent)
        {
            IDictionary <string, object> data = Deserializtion.DeserializeData(theEvent.raw);
            string edType = JsonParsing.getString(data, "event");

            // Ignore any events that we've blacklisted for contaminating our location data
            if (ignoredEvents.Contains(edType))
            {
                return;
            }

            // We always start location data fresh when handling events containing complete location data
            if (fullLocationEvents.Contains(edType))
            {
                invalidState = false;
                ClearLocation();
            }

            // Except as noted above, always attempt to obtain available game version data from the active event
            GetGameVersionData(edType, data);

            // Except as noted above, always attempt to obtain available location data from the active event
            GetLocationData(data);

            // Confirm the location data in memory is as accurate as possible when handling an event with partial location data
            if (partialLocationEvents.Contains(edType))
            {
                CheckLocationData(data);
            }

            if (LocationIsSet())
            {
                if (fullLocationEvents.Contains(edType) || partialLocationEvents.Contains(edType))
                {
                    if (CheckSanity(edType, data))
                    {
                        data = StripPersonalData(data);
                        data = EnrichLocationData(edType, data);
                        data = AddGameVersionData(data);

                        if (data != null)
                        {
                            SendToEDDN("https://eddn.edcd.io/schemas/journal/1", data);
                        }
                    }
                }
            }
        }
Beispiel #7
0
        public StarSystem ParseSystem(object response)
        {
            try
            {
                Logging.Debug($"Response from Elite BGS eddbRestClient endpoint {systemEndpoint} is: ", response);

                IDictionary <string, object> systemJson = Deserializtion.DeserializeData(response.ToString());
                StarSystem system = new StarSystem
                {
                    systemname    = Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(JsonParsing.getString(systemJson, "name")), // This is lower case by default from the API
                    systemAddress = long.Parse(JsonParsing.getString(systemJson, "ed_system_address")),                                  // Stored in this API as a string
                    EDSMID        = JsonParsing.getOptionalLong(systemJson, "edsm_id"),
                    updatedat     = Dates.fromDateTimeToSeconds(JsonParsing.getDateTime("updated_at", systemJson))
                };

                // Get powerplay data
                // Note: EDDB does not report the following powerplay state ednames:
                // `HomeSystem`, `InPrepareRadius`, `Prepared`, `Turmoil`
                // We can identify `HomeSystem` from static data, but  `InPrepareRadius`, `Prepared`, and `Turmoil`
                // are only available from the `Jumped` and `Location` events:
                // When in conflict, EDDB does not report the names of the conflicting powers.
                string power      = JsonParsing.getString(systemJson, "power");
                string powerstate = JsonParsing.getString(systemJson, "power_state");
                if (!string.IsNullOrEmpty(power))
                {
                    system.Power = Power.FromName(power) ?? Power.None;
                }
                if (!string.IsNullOrEmpty(powerstate))
                {
                    system.powerState = system.systemname == system.Power?.headquarters
                        ? PowerplayState.HomeSystem
                        : PowerplayState.FromName(powerstate) ?? PowerplayState.None;
                }

                return(system);
            }
            catch (Exception ex)
            {
                Dictionary <string, object> data = new Dictionary <string, object>()
                {
                    { "input", response },
                    { "exception", ex }
                };
                Logging.Error("Failed to parse BGS EDDB data.", data);
                return(null);
            }
        }
Beispiel #8
0
        private void handleRawEvent(Event theEvent)
        {
            IDictionary <string, object> data = Deserializtion.DeserializeData(theEvent.raw);

            // Need to strip a number of entries
            data.Remove("CockpitBreach");
            data.Remove("BoostUsed");
            data.Remove("FuelLevel");
            data.Remove("FuelUsed");
            data.Remove("JumpDist");

            // Need to remove any keys ending with _Localised
            data = data.Where(x => !x.Key.EndsWith("_Localised")).ToDictionary(x => x.Key, x => x.Value);

            // Need to add StarSystem to scan events
            if (theEvent is StarScannedEvent || theEvent is BodyScannedEvent)
            {
                data.Add("StarSystem", EDDI.Instance.CurrentStarSystem.name);
            }


            // Need to add StarPos to all events that don't already have them
            if (!data.ContainsKey("StarPos"))
            {
                if (EDDI.Instance.CurrentStarSystem == null || EDDI.Instance.CurrentStarSystem.x == null)
                {
                    Logging.Debug("Missing current starsystem information, cannot send message to EDDN");
                }
                IList <decimal> starpos = new List <decimal>();
                starpos.Add((decimal)EDDI.Instance.CurrentStarSystem.x);
                starpos.Add((decimal)EDDI.Instance.CurrentStarSystem.y);
                starpos.Add((decimal)EDDI.Instance.CurrentStarSystem.z);
                data.Add("StarPos", starpos);
            }

            EDDNBody body = new EDDNBody();

            body.header    = generateHeader();
            body.schemaRef = "http://schemas.elite-markets.net/eddn/journal/1";
            body.message   = data;

            sendMessage(body);
        }
Beispiel #9
0
        public void TestMicroResourceInfo()
        {
            var json = TestBase.DeserializeJsonResource <string>(Resources.shipLocker);
            var data = Deserializtion.DeserializeData(json);
            var info = new MicroResourceInfo().FromData(data);

            Assert.AreEqual(38, info.Items.Count);
            Assert.AreEqual("WeaponSchematic", info.Items[0].edname);
            Assert.AreEqual(1, info.Items[0].amount);
            Assert.AreEqual("Item", info.Items[0].microResource.Category.edname);
            Assert.AreEqual(770652507, info.Items[0].missionId);
            Assert.AreEqual(0, info.Items[0].ownerId);
            Assert.AreEqual(null, info.Items[0].price);

            Assert.AreEqual(33, info.Components.Count);
            Assert.AreEqual("Graphene", info.Components[1].edname);
            Assert.AreEqual(55, info.Components[1].amount);
            Assert.AreEqual("Component", info.Components[1].microResource.Category.edname);
            Assert.AreEqual(null, info.Components[1].missionId);
            Assert.AreEqual(0, info.Components[1].ownerId);
            Assert.AreEqual(null, info.Components[1].price);

            Assert.AreEqual(6, info.Consumables.Count);
            Assert.AreEqual("HealthPack", info.Consumables[0].edname);
            Assert.AreEqual(56, info.Consumables[0].amount);
            Assert.AreEqual("Consumable", info.Consumables[0].microResource.Category.edname);
            Assert.AreEqual(null, info.Consumables[0].missionId);
            Assert.AreEqual(0, info.Consumables[0].ownerId);
            Assert.AreEqual(null, info.Consumables[0].price);

            Assert.AreEqual(70, info.Data.Count);
            Assert.AreEqual("InternalCorrespondence", info.Data[0].edname);
            Assert.AreEqual(5, info.Data[0].amount);
            Assert.AreEqual("Data", info.Data[0].microResource.Category.edname);
            Assert.AreEqual(null, info.Data[0].missionId);
            Assert.AreEqual(0, info.Data[0].ownerId);
            Assert.AreEqual(null, info.Data[0].price);
        }
Beispiel #10
0
 public void insertStations(string jsonFilePath)
 {
     using (var file = new StreamReader(jsonFilePath))
     {
         using (var con = SimpleDbConnection())
         {
             con.Open();
             using (var transaction = con.BeginTransaction())
             {
                 using (var cmd = new SQLiteCommand(con))
                 {
                     cmd.CommandText = INSERT_STATION_SQL;
                     cmd.Prepare();
                     string line;
                     while ((line = file.ReadLine()) != null)
                     {
                         IDictionary <string, object> data = Deserializtion.DeserializeData(line);
                         cmd.Parameters.AddWithValue("@id", data["id"]);
                         cmd.Parameters.AddWithValue("@system_id", data["system_id"]);
                         cmd.Parameters.AddWithValue("@name", data["name"]);
                         var distance = data["distance_to_star"];
                         if (distance == null)
                         {
                             distance = 1000;
                         }
                         cmd.Parameters.AddWithValue("@distance", distance);
                         cmd.ExecuteNonQuery();
                     }
                 }
                 transaction.Commit();
             }
             con.Close();
         }
         file.Close();
     }
 }
Beispiel #11
0
        private IDictionary <string, object> prepareEventData(Event theEvent)
        {
            // Prep transient game state info (metadata) per https://www.edsm.net/en/api-journal-v1.
            // Unpackage the event, add transient game state info as applicable, then repackage and send the event
            IDictionary <string, object> eventObject = Deserializtion.DeserializeData(theEvent.raw);
            string eventType = JsonParsing.getString(eventObject, "event");

            if (ignoredEvents.Contains(eventType) || theEvent.raw == null)
            {
                return(null);
            }

            // Add metadata from events
            switch (eventType)
            {
            case "LoadGame":
            {
                eventObject.Add("_systemAddress", null);
                eventObject.Add("_systemName", null);
                eventObject.Add("_systemCoordinates", null);
                eventObject.Add("_marketId", null);
                eventObject.Add("_stationName", null);
                break;
            }

            case "ShipyardBuy":
            {
                eventObject.Add("_shipId", null);
                break;
            }

            case "SetUserShipName":
            case "ShipyardSwap":
            case "Loadout":
            {
                eventObject.TryGetValue("ShipID", out object shipIdVal);
                if (shipIdVal != null)
                {
                    eventObject.Add("_shipId", (int)(long)shipIdVal);
                }
                break;
            }

            case "Undocked":
            {
                eventObject.Add("_marketId", null);
                eventObject.Add("_stationName", null);
                break;
            }

            case "Location":
            case "FSDJump":
            case "Docked":
            {
                if (eventObject.ContainsKey("StarSystem"))
                {
                    eventObject.Add("_systemName", JsonParsing.getString(eventObject, "StarSystem"));
                }
                if (eventObject.ContainsKey("SystemAddress"))
                {
                    long?systemAddress = JsonParsing.getOptionalLong(eventObject, "SystemAddress");
                    // Some events are bugged and return a SystemAddress of 1, regardles of the system we are in.
                    // We need to ignore data that matches this pattern.
                    systemAddress = (systemAddress > 1 ? systemAddress : null);
                    if (systemAddress != null)
                    {
                        eventObject.Add("_systemAddress", systemAddress);
                    }
                }
                if (eventObject.ContainsKey("StarPos"))
                {
                    eventObject.TryGetValue("StarPos", out object starpos);
                    if (starpos != null)
                    {
                        eventObject.Add("_systemCoordinates", starpos);
                    }
                }
                if (eventObject.ContainsKey("MarketID"))
                {
                    eventObject.Add("_marketId", JsonParsing.getOptionalLong(eventObject, "MarketID"));
                }
                if (eventObject.ContainsKey("StationName"))
                {
                    eventObject.Add("_stationName", JsonParsing.getString(eventObject, "StationName"));
                }
                break;
            }
            }

            // Supplement with metadata from the tracked game state, as applicable
            if (EDDI.Instance.CurrentStarSystem != null)
            {
                if (!eventObject.ContainsKey("_systemAddress"))
                {
                    eventObject.Add("_systemAddress", EDDI.Instance.CurrentStarSystem.systemAddress);
                }
                if (!eventObject.ContainsKey("_systemName"))
                {
                    eventObject.Add("_systemName", EDDI.Instance.CurrentStarSystem.systemname);
                }
                if (!eventObject.ContainsKey("_systemCoordinates"))
                {
                    List <decimal?> _coordinates = new List <decimal?>
                    {
                        EDDI.Instance.CurrentStarSystem.x,
                        EDDI.Instance.CurrentStarSystem.y,
                        EDDI.Instance.CurrentStarSystem.z
                    };
                    eventObject.Add("_systemCoordinates", _coordinates);
                }
            }
            if (EDDI.Instance.CurrentStation != null)
            {
                if (!eventObject.ContainsKey("_marketId"))
                {
                    eventObject.Add("_marketId", EDDI.Instance.CurrentStation.marketId);
                }
                if (!eventObject.ContainsKey("_stationName"))
                {
                    eventObject.Add("_stationName", EDDI.Instance.CurrentStation.name);
                }
            }
            if (EDDI.Instance.CurrentShip != null && !eventObject.ContainsKey("_shipId"))
            {
                eventObject.Add("_shipId", EDDI.Instance.CurrentShip.LocalId);
            }

            return(eventObject);
        }
Beispiel #12
0
        private void handleRawEvent(Event theEvent)
        {
            IDictionary <string, object> data = Deserializtion.DeserializeData(theEvent.raw);
            string edType = JsonParsing.getString(data, "event");

            if (edType == "FSDTarget" || edType == "StartJump")
            {
                // FSDTarget events describing the system we are targetting rather than the system we are in.
                // Scan events can register after StartJump and before we actually leave the originating system.
                // These must be ignored.
                return;
            }
            else if (edType == "Location" || edType == "FSDJump")
            {
                // We always start fresh from Location and FSDJump events
                invalidState = false;
                ClearLocation();
            }

            // Except as noted above, always attempt to obtain available location data from the active event
            GetLocationData(data);

            // Confirm the data in memory is as accurate as possible
            if (edType == "Docked" || edType == "Scan")
            {
                CheckLocationData(data);
            }

            if (LocationIsSet())
            {
                if (edType == "Docked" && systemName != null && stationName != null && marketId != null)
                {
                    if (EDDI.Instance.CurrentStation?.name == stationName && EDDI.Instance.CurrentStarSystem?.systemAddress == systemAddress)
                    {
                        try
                        {
                            // Send station data from the CAPI servers
                            sendCommodityInformation();
                            sendOutfittingInformation();
                            sendShipyardInformation();
                        }
                        catch (Exception ex)
                        {
                            Dictionary <string, object> exdata = new Dictionary <string, object>
                            {
                                { "Responder state", this },
                                { "Exception", ex }
                            };
                            Logging.Error("Failed to send Frontier API data to EDDN", exdata);
                        }
                    }
                }

                if (edType == "Location" || edType == "FSDJump" || edType == "Docked" || edType == "Scan")
                {
                    data = StripPersonalData(data);
                    data = EnrichLocationData(edType, data);

                    if (data != null)
                    {
                        SendToEDDN("https://eddn.edcd.io/schemas/journal/1", data);
                    }
                }
            }
        }
        public StarSystem GetStarSystem(string name, bool refreshIfOutdated = true)
        {
            if (!File.Exists(DbFile))
            {
                return(null);
            }

            StarSystem result = null;

            try
            {
                bool needToUpdate = false;
                using (var con = SimpleDbConnection())
                {
                    con.Open();
                    using (var cmd = new SQLiteCommand(con))
                    {
                        cmd.CommandText = SELECT_BY_NAME_SQL;
                        cmd.Prepare();
                        cmd.Parameters.AddWithValue("@name", name);
                        using (SQLiteDataReader rdr = cmd.ExecuteReader())
                        {
                            if (rdr.Read())
                            {
                                string data = rdr.GetString(2);
                                // Old versions of the data could have a string "No volcanism" for volcanism.  If so we remove it
                                data = data.Replace(@"""No volcanism""", "null");

                                try
                                {
                                    result = JsonConvert.DeserializeObject <StarSystem>(data);
                                    if (result == null)
                                    {
                                        Logging.Info("Failed to obtain system for " + name + " from the SQLiteRepository");
                                    }
                                    if (result != null)
                                    {
                                        if (result.visits < 1)
                                        {
                                            // Old-style system; need to update
                                            result.visits    = rdr.GetInt32(0);
                                            result.lastvisit = rdr.GetDateTime(1);
                                            needToUpdate     = true;
                                        }
                                        if (result.lastupdated == null)
                                        {
                                            result.lastupdated = rdr.GetDateTime(4);
                                        }
                                        if (result.comment == null)
                                        {
                                            if (!rdr.IsDBNull(4))
                                            {
                                                result.comment = rdr.GetString(4);
                                            }
                                        }
                                    }
                                    if (refreshIfOutdated && result.lastupdated < DateTime.UtcNow.AddHours(-1))
                                    {
                                        // Data is stale
                                        StarSystem updatedResult = DataProviderService.GetSystemData(name);
                                        if (updatedResult.systemAddress == null && result.systemAddress != null)
                                        {
                                            // The "updated" data might be a basic system, empty except for the name.
                                            // If so, return the old result.
                                            return(result);
                                        }
                                        else
                                        {
                                            updatedResult.visits      = result.visits;
                                            updatedResult.lastvisit   = result.lastvisit;
                                            updatedResult.lastupdated = DateTime.UtcNow;
                                            result       = updatedResult;
                                            needToUpdate = true;
                                        }
                                    }
                                }
                                catch (Exception)
                                {
                                    Logging.Warn("Problem reading data for star system '" + name + "' from database, re-obtaining from source. ");
                                    try
                                    {
                                        result = DataProviderService.GetSystemData(name);
                                        // Recover data unique to the local user and database
                                        IDictionary <string, object> system = Deserializtion.DeserializeData(data);
                                        system.TryGetValue("visits", out object visitVal);
                                        result.visits = (int)(long)visitVal;
                                        system.TryGetValue("comment", out object commentVal);
                                        result.comment = (string)commentVal;
                                        system.TryGetValue("lastvisit", out object lastVisitVal);
                                        result.lastvisit   = (DateTime?)lastVisitVal;
                                        result.lastupdated = DateTime.UtcNow;
                                        needToUpdate       = true;
                                    }
                                    catch (Exception ex)
                                    {
                                        Logging.Warn("Problem obtaining data from source: " + ex);
                                        result = null;
                                    }
                                }
                            }
                        }
                    }
                }
                if (needToUpdate)
                {
                    updateStarSystem(result);
                }
            }
            catch (SQLiteException)
            {
                Logging.Warn("Problem reading data for star system '" + name + "' from database, refreshing database and re-obtaining from source.");
                RecoverStarSystemDB();
                GetStarSystem(name);
            }

            return(result);
        }
        public List <StarSystem> GetStarSystems(string[] names, bool refreshIfOutdated = true)
        {
            if (!File.Exists(DbFile))
            {
                return(null);
            }
            if (names.Count() == 0)
            {
                return(null);
            }

            List <StarSystem> results         = new List <StarSystem>();
            List <string>     systemsToUpdate = new List <string>();
            List <KeyValuePair <string, string> > dataSets = Instance.ReadStarSystems(names);

            foreach (KeyValuePair <string, string> kv in dataSets)
            {
                bool       needToUpdate = false;
                StarSystem result       = null;

                if (kv.Value != null && kv.Value != "")
                {
                    string name = kv.Key;

                    // Old versions of the data could have a string "No volcanism" for volcanism.  If so we remove it
                    string data = kv.Value?.Replace(@"""No volcanism""", "null");

                    // Determine whether our data is stale (We won't deserialize the the entire system if it's stale)
                    IDictionary <string, object> system = Deserializtion.DeserializeData(data);
                    system.TryGetValue("comment", out object commentVal);
                    system.TryGetValue("lastupdated", out object lastUpdatedVal);
                    system.TryGetValue("systemAddress", out object systemAddressVal);
                    system.TryGetValue("EDSMID", out object edsmIdVal);

                    string   comment       = (string)commentVal ?? "";
                    DateTime?lastupdated   = (DateTime?)lastUpdatedVal;
                    long?    systemAddress = (long?)systemAddressVal;
                    long?    edsmId        = (long?)edsmIdVal;

                    if (refreshIfOutdated)
                    {
                        if (lastupdated < DateTime.UtcNow.AddHours(-1))
                        {
                            // Data is stale
                            needToUpdate = true;
                        }
                        else if (lastupdated is null)
                        {
                            // We have no record of ever updating this star system
                            needToUpdate = true;
                        }
                        else if (SCHEMA_VERSION >= 2 && (systemAddress is null || edsmId is null))
                        {
                            // Obtain data for optimized data searches starting with schema version 2
                            needToUpdate = true;
                        }
                    }

                    if (needToUpdate)
                    {
                        // We want to update this star system
                        systemsToUpdate.Add(name);
                    }
                    else
                    {
                        // Deserialize the old result
                        result = DeserializeStarSystem(name, data, ref needToUpdate);
                        if (result != null)
                        {
                            results.Add(result);
                        }
                    }
                }
            }

            if (systemsToUpdate.Count > 0)
            {
                List <StarSystem> updatedSystems = DataProviderService.GetSystemsData(systemsToUpdate.ToArray());

                // If the newly fetched star system is an empty object except (for the object name), reject it
                List <string> systemsToRevert = new List <string>();
                foreach (StarSystem starSystem in updatedSystems)
                {
                    if (starSystem.systemAddress == null)
                    {
                        systemsToRevert.Add(starSystem.systemname);
                    }
                }
                updatedSystems.RemoveAll(s => systemsToRevert.Contains(s.systemname));

                // Return old results when new results have been rejected
                foreach (string systemName in systemsToRevert)
                {
                    results.Add(GetStarSystem(systemName, false));
                }

                // Synchronize EDSM visits and comments
                updatedSystems = DataProviderService.syncFromStarMapService(updatedSystems);

                // Add our updated systems to our results
                results.AddRange(updatedSystems);

                // Save changes to our star systems
                Instance.updateStarSystems(updatedSystems);
            }

            foreach (StarSystem starSystem in results)
            {
                starSystem.lastupdated = DateTime.UtcNow;
            }
            return(results);
        }
Beispiel #15
0
        private static Faction ParseFaction(object response)
        {
            IDictionary <string, object> factionJson = Deserializtion.DeserializeData(response.ToString());
            Faction faction = new Faction
            {
                EDDBID     = (long)factionJson["eddb_id"],
                name       = (string)factionJson["name"],
                updatedAt  = (DateTime)factionJson["updated_at"],
                Government = Government.FromName((string)factionJson["government"]),
                Allegiance = Superpower.FromName((string)factionJson["allegiance"]),
            };

            foreach (object presence in (List <object>)factionJson["faction_presence"])
            {
                IDictionary <string, object> presenceJson = (IDictionary <string, object>)presence;
                FactionPresence factionPresence           = new FactionPresence()
                {
                    systemName   = (string)presenceJson["system_name"],
                    influence    = (decimal?)(double?)presenceJson["influence"] * 100, // Convert from a 0-1 range to a percentage
                    FactionState = FactionState.FromEDName((string)presenceJson["state"]) ?? FactionState.None,
                    Happiness    = Happiness.FromEDName((string)presenceJson["happiness"]) ?? Happiness.None,
                    updatedAt    = (DateTime)presenceJson["updated_at"],
                };

                // Active states
                presenceJson.TryGetValue("active_states", out object activeStatesVal);
                if (activeStatesVal != null)
                {
                    var activeStatesList = (List <object>)activeStatesVal;
                    foreach (IDictionary <string, object> activeState in activeStatesList)
                    {
                        factionPresence.ActiveStates.Add(FactionState.FromEDName(JsonParsing.getString(activeState, "state") ?? "None"));
                    }
                }

                // Pending states
                presenceJson.TryGetValue("pending_states", out object pendingStatesVal);
                if (pendingStatesVal != null)
                {
                    var pendingStatesList = (List <object>)pendingStatesVal;
                    foreach (IDictionary <string, object> pendingState in pendingStatesList)
                    {
                        FactionTrendingState pTrendingState = new FactionTrendingState(
                            FactionState.FromEDName(JsonParsing.getString(pendingState, "state") ?? "None"),
                            JsonParsing.getInt(pendingState, "trend")
                            );
                        factionPresence.PendingStates.Add(pTrendingState);
                    }
                }

                // Recovering states
                presenceJson.TryGetValue("recovering_states", out object recoveringStatesVal);
                if (recoveringStatesVal != null)
                {
                    var recoveringStatesList = (List <object>)recoveringStatesVal;
                    foreach (IDictionary <string, object> recoveringState in recoveringStatesList)
                    {
                        FactionTrendingState rTrendingState = new FactionTrendingState(
                            FactionState.FromEDName(JsonParsing.getString(recoveringState, "state") ?? "None"),
                            JsonParsing.getInt(recoveringState, "trend")
                            );
                        factionPresence.RecoveringStates.Add(rTrendingState);
                    }
                }

                faction.presences.Add(factionPresence);
            }

            return(faction);
        }
Beispiel #16
0
        public Faction ParseFaction(object response)
        {
            try
            {
                IDictionary <string, object> factionJson = Deserializtion.DeserializeData(response.ToString());
                Faction faction = new Faction
                {
                    EDDBID     = (long)factionJson["eddb_id"],
                    name       = (string)factionJson["name"],
                    updatedAt  = (DateTime)factionJson["updated_at"],
                    Government = Government.FromName((string)factionJson["government"]),
                    Allegiance = Superpower.FromName((string)factionJson["allegiance"]),
                };

                foreach (object presence in (List <object>)factionJson["faction_presence"])
                {
                    IDictionary <string, object> presenceJson = (IDictionary <string, object>)presence;
                    FactionPresence factionPresence           = new FactionPresence()
                    {
                        systemName   = JsonParsing.getString(presenceJson, "system_name"),
                        influence    = (JsonParsing.getOptionalDecimal(presenceJson, "influence") ?? 0) * 100, // Convert from a 0-1 range to a percentage
                        FactionState = FactionState.FromEDName(JsonParsing.getString(presenceJson, "state")) ?? FactionState.None,
                    };

                    // These properties may not be present in the json, so we pass them after initializing our FactionPresence object.
                    factionPresence.Happiness = Happiness.FromEDName(JsonParsing.getString(presenceJson, "happiness")) ?? Happiness.None;
                    presenceJson.TryGetValue("updated_at", out object updatedVal);
                    factionPresence.updatedAt = (DateTime?)updatedVal ?? DateTime.MinValue;

                    // Active states
                    presenceJson.TryGetValue("active_states", out object activeStatesVal);
                    if (activeStatesVal != null)
                    {
                        var activeStatesList = (List <object>)activeStatesVal;
                        foreach (IDictionary <string, object> activeState in activeStatesList)
                        {
                            factionPresence.ActiveStates.Add(FactionState.FromEDName(JsonParsing.getString(activeState, "state")) ?? FactionState.None);
                        }
                    }

                    // Pending states
                    presenceJson.TryGetValue("pending_states", out object pendingStatesVal);
                    if (pendingStatesVal != null)
                    {
                        var pendingStatesList = (List <object>)pendingStatesVal;
                        foreach (IDictionary <string, object> pendingState in pendingStatesList)
                        {
                            FactionTrendingState pTrendingState = new FactionTrendingState(
                                FactionState.FromEDName(JsonParsing.getString(pendingState, "state")) ?? FactionState.None,
                                JsonParsing.getInt(pendingState, "trend")
                                );
                            factionPresence.PendingStates.Add(pTrendingState);
                        }
                    }

                    // Recovering states
                    presenceJson.TryGetValue("recovering_states", out object recoveringStatesVal);
                    if (recoveringStatesVal != null)
                    {
                        var recoveringStatesList = (List <object>)recoveringStatesVal;
                        foreach (IDictionary <string, object> recoveringState in recoveringStatesList)
                        {
                            FactionTrendingState rTrendingState = new FactionTrendingState(
                                FactionState.FromEDName(JsonParsing.getString(recoveringState, "state")) ?? FactionState.None,
                                JsonParsing.getInt(recoveringState, "trend")
                                );
                            factionPresence.RecoveringStates.Add(rTrendingState);
                        }
                    }

                    faction.presences.Add(factionPresence);
                }

                return(faction);
            }
            catch (Exception ex)
            {
                Dictionary <string, object> data = new Dictionary <string, object>()
                {
                    { "input", response },
                    { "exception", ex }
                };
                Logging.Error("Failed to parse BGS faction data.", data);
                return(null);
            }
        }
Beispiel #17
0
        public List <StarSystem> GetStarSystems(string[] names, bool refreshIfOutdated = true)
        {
            if (!File.Exists(DbFile))
            {
                return(null);
            }
            if (!names.Any())
            {
                return(null);
            }

            List <StarSystem> results = new List <StarSystem>();
            List <KeyValuePair <string, object> > systemsToUpdate = new List <KeyValuePair <string, object> >();
            List <KeyValuePair <string, string> > dataSets        = Instance.ReadStarSystems(names);

            bool needToUpdate = false;

            foreach (KeyValuePair <string, string> kv in dataSets)
            {
                if (!string.IsNullOrEmpty(kv.Value))
                {
                    string name = kv.Key;

                    // Old versions of the data could have a string "No volcanism" for volcanism.  If so we remove it
                    string data = kv.Value?.Replace(@"""No volcanism""", "null");

                    // Old versions of the data could have a string "InterstellarFactorsContact" for the facilitator station service.  If so we update it
                    data = kv.Value?.Replace(@"""InterstellarFactorsContact""", @"""Facilitator""");

                    // Determine whether our data is stale (We won't deserialize the the entire system if it's stale)
                    IDictionary <string, object> system = Deserializtion.DeserializeData(data);
                    system.TryGetValue("lastupdated", out object lastUpdatedVal);
                    system.TryGetValue("systemAddress", out object systemAddressVal);
                    system.TryGetValue("EDSMID", out object edsmIdVal);

                    DateTime?lastupdated   = (DateTime?)lastUpdatedVal;
                    long?    systemAddress = (long?)systemAddressVal;
                    long?    edsmId        = (long?)edsmIdVal;

                    if (refreshIfOutdated)
                    {
                        if (lastupdated < DateTime.UtcNow.AddHours(-1))
                        {
                            // Data is stale
                            needToUpdate = true;
                        }
                        else if (lastupdated is null)
                        {
                            // We have no record of ever updating this star system
                            needToUpdate = true;
                        }
                        else if (SCHEMA_VERSION >= 2 && (systemAddress is null || edsmId is null))
                        {
                            // Obtain data for optimized data searches starting with schema version 2
                            needToUpdate = true;
                        }
                    }

                    if (needToUpdate)
                    {
                        // We want to update this star system (don't deserialize the old result at this time)
                        systemsToUpdate.Add(new KeyValuePair <string, object>(name, system));
                    }
                    else
                    {
                        // Deserialize the old result
                        StarSystem result = DeserializeStarSystem(name, data, ref needToUpdate);
                        if (result != null)
                        {
                            results.Add(result);
                        }
                    }
                }
            }

            if (systemsToUpdate.Count > 0)
            {
                List <StarSystem> updatedSystems = dataProviderService.GetSystemsData(systemsToUpdate.Select(s => s.Key).ToArray());

                // If the newly fetched star system is an empty object except (for the object name), reject it
                // Return old results when new results have been rejected
                List <string> systemsToRevert = new List <string>();
                foreach (StarSystem starSystem in updatedSystems)
                {
                    if (starSystem.systemAddress == null)
                    {
                        systemsToRevert.Add(starSystem.systemname);
                    }
                }
                updatedSystems.RemoveAll(s => systemsToRevert.Contains(s.systemname));
                foreach (string systemName in systemsToRevert)
                {
                    results.Add(GetStarSystem(systemName, false));
                }

                // Synchronize EDSM visits and comments
                updatedSystems = dataProviderService.syncFromStarMapService(updatedSystems);

                // Update properties that aren't synced from the server and that we want to preserve
                foreach (StarSystem updatedSystem in updatedSystems)
                {
                    foreach (KeyValuePair <string, object> systemToUpdate in systemsToUpdate)
                    {
                        if (updatedSystem.systemname == systemToUpdate.Key)
                        {
                            Dictionary <string, object> oldStarSystem = (Dictionary <string, object>)systemToUpdate.Value;

                            if (oldStarSystem != null)
                            {
                                // Carry over StarSystem properties that we want to preserve
                                updatedSystem.totalbodies = JsonParsing.getOptionalInt(oldStarSystem, "discoverableBodies") ?? 0;

                                // Carry over Body properties that we want to preserve (e.g. exploration data)
                                oldStarSystem.TryGetValue("bodies", out object bodiesVal);
                                List <Body> oldBodies = JsonConvert.DeserializeObject <List <Body> >(JsonConvert.SerializeObject(bodiesVal));
                                updatedSystem.PreserveBodyData(oldBodies, updatedSystem.bodies);

                                // Carry over Faction properties that we want to preserve (e.g. reputation data)
                                oldStarSystem.TryGetValue("factions", out object factionsVal);
                                if (factionsVal != null)
                                {
                                    List <Faction> oldFactions = JsonConvert.DeserializeObject <List <Faction> >(JsonConvert.SerializeObject(factionsVal));
                                    if (oldFactions?.Count > 0)
                                    {
                                        foreach (var updatedFaction in updatedSystem.factions)
                                        {
                                            foreach (var oldFaction in oldFactions)
                                            {
                                                if (updatedFaction.name == oldFaction.name)
                                                {
                                                    updatedFaction.myreputation = oldFaction.myreputation;
                                                }
                                            }
                                        }
                                    }
                                }

                                // No station data needs to be carried over at this time.
                            }
                        }
                    }
                }

                // Update the `lastupdated` timestamps for the systems we have updated
                foreach (StarSystem starSystem in updatedSystems)
                {
                    starSystem.lastupdated = DateTime.UtcNow;
                }

                // Add our updated systems to our results
                results.AddRange(updatedSystems);

                // Save changes to our star systems
                Instance.updateStarSystems(updatedSystems);
            }
            return(results);
        }
Beispiel #18
0
        public static Status ParseStatusEntry(string line)
        {
            Status status = new Status();

            try
            {
                Match match = JsonRegex.Match(line);
                if (match.Success)
                {
                    IDictionary <string, object> data = Deserializtion.DeserializeData(line);

                    // Every status event has a timestamp field
                    if (data.ContainsKey("timestamp"))
                    {
                        if (data["timestamp"] is DateTime)
                        {
                            status.timestamp = ((DateTime)data["timestamp"]).ToUniversalTime();
                        }
                        else
                        {
                            status.timestamp = DateTime.Parse(JsonParsing.getString(data, "timestamp")).ToUniversalTime();
                        }
                    }
                    else
                    {
                        Logging.Warn("Status event without timestamp; using current time");
                    }

                    status.flags = (Status.Flags)(JsonParsing.getOptionalLong(data, "Flags") ?? 0);
                    if (status.flags == Status.Flags.None)
                    {
                        // No flags are set. We aren't in game.
                        return(status);
                    }

                    object val;
                    data.TryGetValue("Pips", out val);
                    List <long> pips = ((List <object>)val)?.Cast <long>()?.ToList(); // The 'TryGetValue' function returns these values as type 'object<long>'
                    status.pips_sys = pips != null ? ((decimal?)pips[0] / 2) : null;  // Set system pips (converting from half pips)
                    status.pips_eng = pips != null ? ((decimal?)pips[1] / 2) : null;  // Set engine pips (converting from half pips)
                    status.pips_wea = pips != null ? ((decimal?)pips[2] / 2) : null;  // Set weapon pips (converting from half pips)

                    status.firegroup = JsonParsing.getOptionalInt(data, "FireGroup");
                    int?gui_focus = JsonParsing.getOptionalInt(data, "GuiFocus");
                    switch (gui_focus)
                    {
                    case 0:     // No focus
                    {
                        status.gui_focus = "none";
                        break;
                    }

                    case 1:     // InternalPanel (right hand side)
                    {
                        status.gui_focus = "internal panel";
                        break;
                    }

                    case 2:     // ExternalPanel (left hand side)
                    {
                        status.gui_focus = "external panel";
                        break;
                    }

                    case 3:     // CommsPanel (top)
                    {
                        status.gui_focus = "communications panel";
                        break;
                    }

                    case 4:     // RolePanel (bottom)
                    {
                        status.gui_focus = "role panel";
                        break;
                    }

                    case 5:     // StationServices
                    {
                        status.gui_focus = "station services";
                        break;
                    }

                    case 6:     // GalaxyMap
                    {
                        status.gui_focus = "galaxy map";
                        break;
                    }

                    case 7:     // SystemMap
                    {
                        status.gui_focus = "system map";
                        break;
                    }
                    }
                    status.latitude  = JsonParsing.getOptionalDecimal(data, "Latitude");
                    status.longitude = JsonParsing.getOptionalDecimal(data, "Longitude");
                    status.altitude  = JsonParsing.getOptionalDecimal(data, "Altitude");
                    status.heading   = JsonParsing.getOptionalDecimal(data, "Heading");

                    return(status);
                }
            }
            catch (Exception ex)
            {
                Logging.Warn("Failed to parse Status.json line: " + ex.ToString());
                Logging.Error(ex);
            }
            return(status = null);
        }
Beispiel #19
0
        private string prepareEventData(Event theEvent)
        {
            // Prep transient game state info (metadata) per https://www.edsm.net/en/api-journal-v1.
            // Unpackage the event, add transient game state info as applicable, then repackage and send the event
            IDictionary <string, object> eventObject = Deserializtion.DeserializeData(theEvent.raw);
            string eventType = JsonParsing.getString(eventObject, "event");

            if (ignoredEvents.Contains(eventType) || theEvent.raw == null)
            {
                return(null);
            }

            // Add metadata from events
            switch (eventType)
            {
            case "LoadGame":
            {
                eventObject.Add("_systemAddress", null);
                eventObject.Add("_systemName", null);
                eventObject.Add("_systemCoordinates", null);
                eventObject.Add("_marketId", null);
                eventObject.Add("_stationName", null);
                break;
            }

            case "SetUserShipName":
            {
                ShipRenamedEvent shipRenamedEvent = (ShipRenamedEvent)theEvent;
                eventObject.Add("_shipId", shipRenamedEvent.shipid);
                break;
            }

            case "ShipyardBuy":
            {
                eventObject.Add("_shipId", null);
                break;
            }

            case "ShipyardSwap":
            {
                ShipSwappedEvent shipSwappedEvent = (ShipSwappedEvent)theEvent;
                eventObject.Add("_shipId", shipSwappedEvent.shipid);
                break;
            }

            case "Loadout":
            {
                ShipLoadoutEvent shipLoadoutEvent = (ShipLoadoutEvent)theEvent;
                eventObject.Add("_shipId", shipLoadoutEvent.shipid);
                break;
            }

            case "Undocked":
            {
                eventObject.Add("_marketId", null);
                eventObject.Add("_stationName", null);
                break;
            }

            case "Location":
            {
                LocationEvent locationEvent = (LocationEvent)theEvent;
                eventObject.Add("_systemAddress", null);         // We don't collect this info yet
                eventObject.Add("_systemName", locationEvent.system);
                List <decimal?> _systemCoordinates = new List <decimal?>
                {
                    locationEvent.x,
                    locationEvent.y,
                    locationEvent.z
                };
                eventObject.Add("_systemCoordinates", _systemCoordinates);
                eventObject.Add("_marketId", null);         // We don't collect this info yet
                eventObject.Add("_stationName", locationEvent.station);
                break;
            }

            case "FSDJump":
            {
                JumpedEvent jumpedEvent = (JumpedEvent)theEvent;
                eventObject.Add("_systemAddress", null);         // We don't collect this info yet
                eventObject.Add("_systemName", jumpedEvent.system);
                List <decimal?> _systemCoordinates = new List <decimal?>
                {
                    jumpedEvent.x,
                    jumpedEvent.y,
                    jumpedEvent.z
                };
                eventObject.Add("_systemCoordinates", _systemCoordinates);
                break;
            }

            case "Docked":
            {
                DockedEvent dockedEvent = (DockedEvent)theEvent;
                eventObject.Add("_systemAddress", null);         // We don't collect this info yet
                eventObject.Add("_systemName", dockedEvent.system);
                eventObject.Add("_systemCoordinates", null);
                eventObject.Add("_marketId", null);         // We don't collect this info yet
                eventObject.Add("_stationName", dockedEvent.station);
                break;
            }
            }

            // Supplement with metadata from the tracked game state, as applicable
            if (EDDI.Instance.CurrentStarSystem != null)
            {
                if (!eventObject.ContainsKey("_systemAddress") && !eventObject.ContainsKey("SystemAddress"))
                {
                    eventObject.Add("_systemAddress", null); // We don't collect this info yet
                }
                if (!eventObject.ContainsKey("_systemName") && !eventObject.ContainsKey("SystemName"))
                {
                    eventObject.Add("_systemName", EDDI.Instance.CurrentStarSystem.name);
                }
                if (!eventObject.ContainsKey("_systemCoordinates") && !eventObject.ContainsKey("StarPos"))
                {
                    List <decimal?> _coordinates = new List <decimal?>
                    {
                        EDDI.Instance.CurrentStarSystem.x,
                        EDDI.Instance.CurrentStarSystem.y,
                        EDDI.Instance.CurrentStarSystem.z
                    };
                    eventObject.Add("_systemCoordinates", _coordinates);
                }
            }
            if (EDDI.Instance.CurrentStation != null)
            {
                if (!eventObject.ContainsKey("_marketId") && !eventObject.ContainsKey("MarketID"))
                {
                    eventObject.Add("_marketId", null); // We don't collect this info yet
                }
                if (!eventObject.ContainsKey("_stationName") && !eventObject.ContainsKey("StationName"))
                {
                    eventObject.Add("_stationName", EDDI.Instance.CurrentStation.name);
                }
            }
            if (EDDI.Instance.CurrentShip != null && !eventObject.ContainsKey("ShipId") && !eventObject.ContainsKey("_shipId"))
            {
                eventObject.Add("_shipId", EDDI.Instance.CurrentShip.LocalId);
            }

            return(JsonConvert.SerializeObject(eventObject).Normalize());
        }
Beispiel #20
0
        public Status ParseStatusEntry(string line)
        {
            Status status = new Status();

            try
            {
                Match match = JsonRegex.Match(line);
                if (match.Success)
                {
                    IDictionary <string, object> data = Deserializtion.DeserializeData(line);

                    // Every status event has a timestamp field
                    status.timestamp = DateTime.UtcNow;
                    try
                    {
                        status.timestamp = JsonParsing.getDateTime("timestamp", data);
                    }
                    catch
                    {
                        Logging.Warn("Status without timestamp; using current time");
                    }

                    status.flags = (Status.Flags)(JsonParsing.getOptionalLong(data, "Flags") ?? 0);
                    if (status.flags == Status.Flags.None)
                    {
                        // No flags are set. We aren't in game.
                        return(status);
                    }

                    data.TryGetValue("Pips", out object val);
                    List <long> pips = ((List <object>)val)?.Cast <long>()?.ToList(); // The 'TryGetValue' function returns these values as type 'object<long>'
                    status.pips_sys = pips != null ? ((decimal?)pips[0] / 2) : null;  // Set system pips (converting from half pips)
                    status.pips_eng = pips != null ? ((decimal?)pips[1] / 2) : null;  // Set engine pips (converting from half pips)
                    status.pips_wea = pips != null ? ((decimal?)pips[2] / 2) : null;  // Set weapon pips (converting from half pips)

                    status.firegroup = JsonParsing.getOptionalInt(data, "FireGroup");
                    int?gui_focus = JsonParsing.getOptionalInt(data, "GuiFocus");
                    switch (gui_focus)
                    {
                    case 0:     // No focus
                    {
                        status.gui_focus = "none";
                        break;
                    }

                    case 1:     // InternalPanel (right hand side)
                    {
                        status.gui_focus = "internal panel";
                        break;
                    }

                    case 2:     // ExternalPanel (left hand side)
                    {
                        status.gui_focus = "external panel";
                        break;
                    }

                    case 3:     // CommsPanel (top)
                    {
                        status.gui_focus = "communications panel";
                        break;
                    }

                    case 4:     // RolePanel (bottom)
                    {
                        status.gui_focus = "role panel";
                        break;
                    }

                    case 5:     // StationServices
                    {
                        status.gui_focus = "station services";
                        break;
                    }

                    case 6:     // GalaxyMap
                    {
                        status.gui_focus = "galaxy map";
                        break;
                    }

                    case 7:     // SystemMap
                    {
                        status.gui_focus = "system map";
                        break;
                    }

                    case 8:     // Orrery
                    {
                        status.gui_focus = "orrery";
                        break;
                    }

                    case 9:     // FSS mode
                    {
                        status.gui_focus = "fss mode";
                        break;
                    }

                    case 10:     // SAA mode
                    {
                        status.gui_focus = "saa mode";
                        break;
                    }

                    case 11:     // Codex
                    {
                        status.gui_focus = "codex";
                        break;
                    }
                    }
                    status.latitude  = JsonParsing.getOptionalDecimal(data, "Latitude");
                    status.longitude = JsonParsing.getOptionalDecimal(data, "Longitude");
                    status.altitude  = JsonParsing.getOptionalDecimal(data, "Altitude");
                    status.heading   = JsonParsing.getOptionalDecimal(data, "Heading");
                    if (data.TryGetValue("Fuel", out object fuelData))
                    {
                        if (fuelData is IDictionary <string, object> fuelInfo)
                        {
                            status.fuelInTanks     = JsonParsing.getOptionalDecimal(fuelInfo, "FuelMain");
                            status.fuelInReservoir = JsonParsing.getOptionalDecimal(fuelInfo, "FuelReservoir");
                        }
                    }
                    status.cargo_carried = (int?)JsonParsing.getOptionalDecimal(data, "Cargo");
                    status.legalStatus   = LegalStatus.FromEDName(JsonParsing.getString(data, "LegalState")) ?? LegalStatus.Clean;
                    status.bodyname      = JsonParsing.getString(data, "BodyName");
                    status.planetradius  = JsonParsing.getOptionalDecimal(data, "PlanetRadius");

                    // Calculated data
                    SetFuelExtras(status);
                    SetSlope(status);

                    return(status);
                }
            }
            catch (Exception ex)
            {
                Logging.Warn("Failed to parse Status.json line: " + ex.ToString());
                Logging.Error("", ex);
            }
            return(null);
        }
        public List <StarSystem> GetStarSystems(string[] names, bool refreshIfOutdated = true)
        {
            if (!File.Exists(DbFile))
            {
                return(null);
            }
            if (names.Count() == 0)
            {
                return(null);
            }

            List <StarSystem> results         = new List <StarSystem>();
            List <StarSystem> systemsToUpdate = new List <StarSystem>();
            List <KeyValuePair <string, string> > dataSets = Instance.ReadStarSystems(names);

            foreach (KeyValuePair <string, string> kv in dataSets)
            {
                bool       needToUpdate = false;
                StarSystem result       = null;

                if (kv.Value != null && kv.Value != "")
                {
                    string name = kv.Key;

                    // Old versions of the data could have a string "No volcanism" for volcanism.  If so we remove it
                    string data = ((string)kv.Value)?.Replace(@"""No volcanism""", "null");

                    // Determine whether our data is stale (We won't deserialize the the entire system if it's stale)
                    IDictionary <string, object> system = Deserializtion.DeserializeData(data);
                    system.TryGetValue("visits", out object visitVal);
                    system.TryGetValue("comment", out object commentVal);
                    system.TryGetValue("lastvisit", out object lastVisitVal);
                    system.TryGetValue("lastupdated", out object lastUpdatedVal);
                    system.TryGetValue("systemAddress", out object systemAddressVal);

                    int      visits        = (int)(long)visitVal;
                    string   comment       = (string)commentVal ?? "";
                    DateTime?lastvisit     = (DateTime?)lastVisitVal;
                    DateTime?lastupdated   = (DateTime?)lastUpdatedVal;
                    long?    systemAddress = (long?)systemAddressVal;

                    if (lastvisit == null || lastupdated == null || comment == "")
                    {
                        if (Instance.OldDataFormat(name, ref visits, comment, ref lastupdated, ref lastvisit))
                        {
                            needToUpdate = true;
                        }
                    }

                    if (refreshIfOutdated && lastupdated < DateTime.UtcNow.AddHours(-1))
                    {
                        // Data is stale
                        StarSystem updatedResult = DataProviderService.GetSystemData(name);
                        if (updatedResult.systemAddress == null && systemAddress != null)
                        {
                            // The "updated" data might be a basic system, empty except for the name. If so, return the old result.
                            updatedResult = DeserializeStarSystem(name, data, ref needToUpdate);
                        }
                        else
                        {
                            needToUpdate = true;
                        }
                        result = updatedResult;
                    }
                    else
                    {
                        // Data is fresh
                        result = DeserializeStarSystem(name, data, ref needToUpdate);
                    }

                    result.visits      = visits;
                    result.comment     = comment;
                    result.lastvisit   = lastvisit;
                    result.lastupdated = DateTime.UtcNow;

                    if (needToUpdate)
                    {
                        systemsToUpdate.Add(result);
                    }
                }
                results.Add(result);
            }
            Instance.updateStarSystems(systemsToUpdate);
            return(results);
        }