示例#1
0
 public MicroResourceInfo FromData(IDictionary <string, object> data)
 {
     timestamp   = JsonParsing.getDateTime("timestamp", data);
     Components  = ReadMicroResources("Components", data, "Component");
     Consumables = ReadMicroResources("Consumables", data, "Consumable");
     Data        = ReadMicroResources("Data", data, "Data");
     Items       = ReadMicroResources("Items", data, "Item");
     return(this);
 }
示例#2
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);
            }
        }
示例#3
0
        private Body ParseStarMapBody(JObject body, string systemName)
        {
            // General items
            long?    bodyId            = (long?)body["bodyId"];
            long?    EDSMID            = (long?)body["id"];
            string   bodyname          = (string)body["name"];
            BodyType bodyType          = BodyType.FromName((string)body["type"]) ?? BodyType.None;
            decimal? distanceLs        = (decimal?)body["distanceToArrival"]; // Light Seconds
            decimal? temperatureKelvin = (long?)body["surfaceTemperature"];   // Kelvin

            // Orbital characteristics
            decimal?orbitalPeriodDays         = (decimal?)body["orbitalPeriod"];                           // Days
            decimal?semimajoraxisLs           = ConstantConverters.au2ls((decimal?)body["semiMajorAxis"]); // Light seconds
            decimal?eccentricity              = (decimal?)body["orbitalEccentricity"];
            decimal?orbitalInclinationDegrees = (decimal?)body["orbitalInclination"];                      // Degrees
            decimal?periapsisDegrees          = (decimal?)body["argOfPeriapsis"];                          // Degrees
            decimal?rotationPeriodDays        = (decimal?)body["rotationalPeriod"];                        // Days
            decimal?axialTiltDegrees          = (decimal?)body["axialTilt"];                               // Degrees

            List <IDictionary <string, object> > parents = new List <IDictionary <string, object> >();

            if (body["parents"] != null)
            {
                // Parent body types and IDs
                parents = body["parents"].ToObject <List <IDictionary <string, object> > >() ?? new List <IDictionary <string, object> >();
            }

            List <Ring> rings = new List <Ring>();

            if ((JArray)body["rings"] != null || (JArray)body["belts"] != null)
            {
                var ringsData = body["rings"] ?? body["belts"];
                if (ringsData != null)
                {
                    foreach (JObject ring in ringsData)
                    {
                        rings.Add(new Ring(
                                      (string)ring["name"],
                                      RingComposition.FromName((string)ring["type"]),
                                      (decimal)ring["mass"],
                                      (decimal)ring["innerRadius"],
                                      (decimal)ring["outerRadius"]
                                      ));
                    }
                }
            }

            if ((string)body["type"] == "Star")
            {
                // Star-specific items
                string stellarclass      = ((string)body["subType"]).Split(' ')[0]; // Splits "B (Blue-White) Star" to "B"
                int?   stellarsubclass   = null;
                string endOfStellarClass = stellarclass.ToCharArray().ElementAt(stellarclass.Length - 1).ToString();
                if (int.TryParse(endOfStellarClass, out int subclass))
                {
                    // If our stellarclass ends in a number, we need to separate the class from the subclass
                    stellarsubclass = subclass;
                    stellarclass    = stellarclass.Replace(endOfStellarClass, "");
                }

                long?   ageMegaYears      = (long?)body["age"]; // Age in megayears
                string  luminosityclass   = (string)body["luminosity"];
                decimal?absolutemagnitude = (decimal?)body["absoluteMagnitude"];
                decimal?stellarMass       = (decimal?)body["solarMasses"];
                decimal?solarradius       = (decimal?)body["solarRadius"];
                decimal radiusKm          = (decimal)(solarradius != null ? solarradius * Constants.solarRadiusMeters / 1000 : null);

                Body Body = new Body(bodyname, bodyId, parents, distanceLs, stellarclass, stellarsubclass, stellarMass,
                                     radiusKm, absolutemagnitude, ageMegaYears, temperatureKelvin, luminosityclass, semimajoraxisLs,
                                     eccentricity, orbitalInclinationDegrees, periapsisDegrees, orbitalPeriodDays, rotationPeriodDays,
                                     axialTiltDegrees, rings, true, false, systemName, null)
                {
                    EDSMID = EDSMID
                };
                DateTime updatedAt = JsonParsing.getDateTime("updateTime", body);
                Body.updatedat = updatedAt == null ? null : (long?)Dates.fromDateTimeToSeconds(updatedAt);

                return(Body);
            }

            if ((string)body["type"] == "Planet")
            {
                // Planet and moon specific items
                PlanetClass    planetClass    = PlanetClass.FromName((string)body["subType"]) ?? PlanetClass.None;
                bool?          tidallylocked  = (bool?)body["rotationalPeriodTidallyLocked"] ?? false;
                bool?          landable       = (bool?)body["isLandable"];
                decimal?       gravity        = (decimal?)body["gravity"]; // G's
                decimal?       earthmass      = (decimal?)body["earthMasses"];
                decimal?       radiusKm       = (decimal?)body["radius"];  // Kilometers
                TerraformState terraformState = TerraformState.FromName((string)body["terraformingState"]) ?? TerraformState.NotTerraformable;

                Volcanism volcanism = null;
                if ((string)body["volcanismType"] != null)
                {
                    volcanism = Volcanism.FromName((string)body["volcanismType"]);
                }

                List <AtmosphereComposition> atmosphereCompositions = new List <AtmosphereComposition>();
                if (body["atmosphereComposition"] is JObject)
                {
                    var compositions = body["atmosphereComposition"].ToObject <Dictionary <string, decimal?> >();

                    foreach (KeyValuePair <string, decimal?> compositionKV in compositions)
                    {
                        string  compositionName = compositionKV.Key;
                        decimal?share           = compositionKV.Value;
                        if (compositionName != null && share != null)
                        {
                            atmosphereCompositions.Add(new AtmosphereComposition(compositionName, (decimal)share));
                        }
                    }
                    if (atmosphereCompositions.Count > 0)
                    {
                        atmosphereCompositions = atmosphereCompositions.OrderByDescending(x => x.percent).ToList();
                    }
                }
                decimal?        pressureAtm     = (decimal?)body["surfacePressure"];
                AtmosphereClass atmosphereClass = null;
                if (((string)body["subType"]).Contains("gas giant") &&
                    (string)body["atmosphereType"] == "No atmosphere")
                {
                    // EDSM classifies any body with an empty string atmosphere property as "No atmosphere".
                    // However, gas giants also receive an empty string. Fix it, since gas giants have atmospheres.
                    atmosphereClass = AtmosphereClass.FromEDName("GasGiant");
                }
                else
                {
                    atmosphereClass = AtmosphereClass.FromName((string)body["atmosphereType"]);
                }

                List <SolidComposition> solidCompositions = new List <SolidComposition>();
                if (body["solidComposition"] is JObject)
                {
                    var compositions = body["solidComposition"].ToObject <Dictionary <string, decimal?> >();

                    foreach (KeyValuePair <string, decimal?> compositionKV in compositions)
                    {
                        string  composition = compositionKV.Key;
                        decimal?share       = compositionKV.Value;
                        if (composition != null && share != null)
                        {
                            solidCompositions.Add(new SolidComposition(composition, (decimal)share));
                        }
                    }
                    if (solidCompositions.Count > 0)
                    {
                        solidCompositions = solidCompositions.OrderByDescending(x => x.percent).ToList();
                    }
                }

                List <MaterialPresence> materials = new List <MaterialPresence>();
                if (body["materials"] is JObject)
                {
                    var materialsData = body["materials"].ToObject <Dictionary <string, decimal?> >();
                    foreach (KeyValuePair <string, decimal?> materialKV in materialsData)
                    {
                        Material material = Material.FromName(materialKV.Key);
                        decimal? amount   = materialKV.Value;
                        if (material != null && amount != null)
                        {
                            materials.Add(new MaterialPresence(material, (decimal)amount));
                        }
                    }
                    if (materials.Count > 0)
                    {
                        materials = materials.OrderByDescending(o => o.percentage).ToList();
                    }
                }
                ReserveLevel reserveLevel = ReserveLevel.FromName((string)body["reserveLevel"]) ?? ReserveLevel.None;

                DateTime updatedAt = JsonParsing.getDateTime("updateTime", body);
                Body     Body      = new Body(bodyname, bodyId, parents, distanceLs, tidallylocked, terraformState, planetClass, atmosphereClass, atmosphereCompositions, volcanism, earthmass, radiusKm, (decimal)gravity, temperatureKelvin, pressureAtm, landable, materials, solidCompositions, semimajoraxisLs, eccentricity, orbitalInclinationDegrees, periapsisDegrees, orbitalPeriodDays, rotationPeriodDays, axialTiltDegrees, rings, reserveLevel, true, true, systemName, null)
                {
                    EDSMID    = EDSMID,
                    updatedat = updatedAt == null ? null : (long?)Dates.fromDateTimeToSeconds(updatedAt)
                };

                return(Body);
            }


            return(null);
        }
示例#4
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);
        }
示例#5
0
        private void SendEventBatch(List <IDictionary <string, object> > eventData, StarMapConfiguration starMapConfiguration)
        {
            if (!EdsmCredentialsSet())
            {
                return;
            }

            // Filter any stale data
            eventData = eventData
                        .Where(e => JsonParsing.getDateTime("timestamp", e) > starMapConfiguration.lastJournalSync)
                        .ToList();
            if (eventData.Count == 0)
            {
                return;
            }

            // The EDSM responder has a `gameIsBeta` flag that it checks prior to sending data via this method.
            var request = new RestRequest("api-journal-v1", Method.POST);

            request.AddParameter("commanderName", commanderName);
            request.AddParameter("apiKey", apiKey);
            request.AddParameter("fromSoftware", Constants.EDDI_NAME);
            request.AddParameter("fromSoftwareVersion", Constants.EDDI_VERSION);
            request.AddParameter("message", JsonConvert.SerializeObject(eventData).Normalize());
            request.Timeout = JournalTimeoutMilliseconds;

            try
            {
                Logging.Debug("Sending message to EDSM: " + restClient.BuildUri(request).AbsoluteUri);
                var clientResponse          = restClient.Execute <StarMapLogResponse>(request);
                StarMapLogResponse response = clientResponse.Data;

                if (response is null)
                {
                    Logging.Warn(clientResponse.ErrorMessage);
                    ReEnqueueEvents(eventData);
                }
                else if (response.msgnum >= 100 && response.msgnum <= 103)
                {
                    // 100 -  Everything went fine!
                    // 101 -  The journal message was already processed in our database.
                    // 102 -  The journal message was already in a newer version in our database.
                    // 103 -  Duplicate event request (already reported from another software client).
                    starMapConfiguration.lastJournalSync = eventData
                                                           .Select(e => JsonParsing.getDateTime("timestamp", e))
                                                           .Max();
                    starMapConfiguration.ToFile();
                }
                if (response?.msgnum != 100)
                {
                    if (!string.IsNullOrEmpty(response?.msg))
                    {
                        Logging.Warn("EDSM responded with: " + response.msg);
                    }
                    else
                    {
                        Logging.Warn("EDSM responded with: " + JsonConvert.SerializeObject(response));
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.Warn("Failed to send event to EDSM", ex);
            }
        }