private static void TryAddOrUpdateMaterialShare(RawMaterialShare mat, string name) { DbContextOptionsBuilder <EliteDbContext> config = new DbContextOptionsBuilder <EliteDbContext>(); config.UseNpgsql(_connectionString); using (EliteDbContext context = new EliteDbContext(config.Options)) { mat.MaterialId = context.Material.Where(m => string.Equals(m.Name, name, StringComparison.OrdinalIgnoreCase)).Single().Id; if (context.RawMaterialShare.Count(r => r.MaterialId == mat.MaterialId && r.BodyId == mat.BodyId) == 0) { context.RawMaterialShare.Add(mat); context.SaveChanges(); } else { context.RawMaterialShare.Update(mat); context.SaveChanges(); } } }
/// <summary> /// EDSM's JSON is compressed, omits null-value properties /// </summary> /// <param name="path"></param> private static void ImportEdsmBodiesJson(string path) { // EDSM document is in a similar format to Newline-Delimited JSON, so streaming is the way to go using (StreamReader sr = File.OpenText(path)) { string line = sr.ReadLine(); // Skip the opening array token // Get the current line long numLines = long.Parse(File.ReadAllText("E:\\bodies_exit_line.txt").Trim()); // Skip to the current line to save time for (int i = 0; i < numLines; i++) { sr.ReadLine(); } Console.WriteLine("Started parsing bodies"); while ((line = sr.ReadLine()) != null) { line = line.TrimEnd(','); // Remove the ending comma to ensure valid JSON JObject jo = JObject.Parse(line); var pKeys = jo.Properties().Select(p => p.Name); bool added = false; try { Body body = new Body { Id = jo.Value <long>("id"), Type = jo.Value <string>("type").ToNormalCase(LookupOptions.BodyTypes), EdsmId = jo.Value <long?>("id"), StarSystemId = jo.Value <long>("systemId"), // Give it the EDSM ID, switch to my ID during inserts and updates Name = jo.Value <string>("name") }; if (pKeys.Contains("subType")) { body.SubType = jo.Value <string>("subType"); } if (pKeys.Contains("distanceToArrival")) { body.DistanceToArrival = jo.Value <double?>("distanceToArrival"); } if (pKeys.Contains("solarMasses")) { body.SolarMasses = jo.Value <float?>("solarMasses"); } if (pKeys.Contains("solarRadius")) { body.SolarRadius = jo.Value <double?>("solarRadius"); } if (pKeys.Contains("surfaceTemperature")) { body.SurfaceTemperature = jo.Value <int?>("surfaceTemperature"); } if (pKeys.Contains("orbitalPeriod")) { body.OrbitalPeriod = jo.Value <double?>("orbitalPeriod"); } if (pKeys.Contains("semiMajorAxis")) { body.SemiMajorAxis = jo.Value <double?>("semiMajorAxis"); } if (pKeys.Contains("orbitalEccentricity")) { body.OrbitalEccentricity = jo.Value <double?>("orbitalEccentricity"); } if (pKeys.Contains("orbitalInclination")) { body.OrbitalInclination = jo.Value <float?>("orbitalInclination"); } if (pKeys.Contains("argOfPeriapsis")) { body.ArgOfPeriapsis = jo.Value <double?>("argOfPeriapsis"); } if (pKeys.Contains("rotationalPeriod")) { body.RotationalPeriod = jo.Value <double?>("rotationalPeriod"); } if (pKeys.Contains("rotationalPeriodTidallyLocked")) { body.IsTidallyLocked = jo.Value <bool?>("rotationalPeriodTidallyLocked"); } if (pKeys.Contains("axialTilt")) { body.AxialTilt = jo.Value <double?>("axialTilt"); } if (pKeys.Contains("absoluteMagnitude")) { body.AbsoluteMagnitude = jo.Value <float?>("absoluteMagnitude"); } if (pKeys.Contains("age")) { body.Age = jo.Value <uint?>("age"); } if (pKeys.Contains("isMainStar")) { body.IsMainStar = jo.Value <bool?>("isMainStar"); } if (pKeys.Contains("isScoopable")) { body.IsScoopable = jo.Value <bool?>("isScoopable"); } if (pKeys.Contains("luminosity")) { body.LuminosityClass = jo.Value <string>("luminosity"); } // White Dwarf classes are 2-3 chars starting with D if (body.Type.ToLower().Equals("star") && body.SubType.ToLower().Contains("white dwarf")) { body.SpectralClass = body.SubType.Split('(')[1].Split(')')[0]; } // Herbig Stars are classed as Ae/Be else if (body.Type.ToLower().Equals("star") && body.SubType.ToLower().Contains("herbig")) { body.SpectralClass = "Ae/Be"; } // T Tauris / Proto-Stars are classed as T else if (body.Type.ToLower().Equals("star") && body.SubType.ToLower().Contains("tauri")) { body.SpectralClass = "TT"; } // Carbon Stars are classed as C or CN else if (body.Type.ToLower().Equals("star") && body.SubType.ToLower().Equals("c star")) { body.SpectralClass = "C"; } else if (body.Type.ToLower().Equals("star") && body.SubType.ToLower().Equals("cn star")) { body.SpectralClass = "CN"; } // Set Black Holes and Neutron Stars to blank else if (body.Type.ToLower().Equals("star") && (body.SubType.ToLower().Contains("black hole") || body.SubType.ToLower().Contains("neutron"))) { body.SpectralClass = ""; } // Set other stars to their letter class (e.g. M, F, O, etc.) else if (body.Type.ToLower().Equals("star")) { body.SpectralClass = body.SubType.Split('(')[0]; } // Rest are planets else { body.SpectralClass = default(string); } if (pKeys.Contains("isLandable")) { body.IsLandable = jo.Value <bool?>("isLandable"); } if (pKeys.Contains("gravity")) { body.Gravity = jo.Value <double?>("gravity"); } if (pKeys.Contains("earthMasses")) { body.EarthMasses = jo.Value <double?>("earthMasses"); } if (pKeys.Contains("radius")) { body.Radius = jo.Value <float?>("radius"); } if (pKeys.Contains("volcanismType")) { body.VolcanismType = jo.Value <string>("volcanismType"); } if (pKeys.Contains("atmosphereType")) { body.AtmosphereType = jo.Value <string>("atmosphereType"); } if (pKeys.Contains("terraformingState")) { body.TerraformingState = jo.Value <string>("terraformingState"); } // Don't even continue if this body wasn't added added = TryAddOrUpdateBody(body); if (added && jo.TryGetValue("materials", out JToken mats)) { foreach (JProperty jp in mats) { var mat = new RawMaterialShare { BodyId = body.Id, Share = float.Parse(jp.Value.Value <string>()) }; TryAddOrUpdateMaterialShare(mat, jp.Name); } } if (added && jo.TryGetValue("atmosphereComposition", out JToken atm)) { foreach (JProperty jp in atm) { var ac = new AtmosphereComposite { BodyId = body.Id, Component = jp.Name, Share = float.TryParse(jp.Value.Value <string>(), out float f) ? f : default(float?) }; TryAddOrUpdateAtmosComp(ac); } } if (added && jo.TryGetValue("rings", out JToken rings)) { foreach (JObject jp in rings) { var ring = new Ring { BodyId = body.Id, Name = jp.Value <string>("name"), Type = jp.Value <string>("type"), Mass = long.TryParse(jp.Value <string>("mass"), out long l) ? l : default(long?), InnerRadius = jp.Value <int?>("innerRadius"), OuterRadius = jp.Value <int?>("outerRadius") }; TryAddOrUpdateRing(ring); } } } catch { File.AppendAllText(@"E:\debug_bodies.txt", $"edsm_body,{jo.Value<string>("name")},{jo.Value<long?>("id")}\n"); } File.WriteAllText("E:\\bodies_exit_line.txt", $"{numLines++}"); } } }