using System.Text.Json;
using XFEEDToolBox.Core.Models;
namespace XFEEDToolBox.Core.Data;
public static class MarketParser
{
public static MarketSnapshot ParseLocalMarket(JsonElement root, Station? known = null, DataSource source = DataSource.Journal)
{
var time = root.Time() ?? throw new JsonException("行情缺少 timestamp。");
var id = root.Long("MarketID");
if (id <= 0) throw new JsonException("行情缺少有效 MarketID。");
var type = root.Text("StationType");
var station = (known?.MarketId == id ? known : new Station())! with
{
MarketId = id, Name = root.Text("StationName"), SystemName = root.Text("StarSystem"),
Type = type, IsFleetCarrier = type.Equals("FleetCarrier", StringComparison.OrdinalIgnoreCase),
IsPlanetary = type.StartsWith("Crater", StringComparison.OrdinalIgnoreCase),
MaxLandingPad = known?.MaxLandingPad is > LandingPad.Unknown ? known.MaxLandingPad : JsonFields.PadFromType(type),
UpdatedAt = time
};
var items = root.Get("Items");
if (items.ValueKind != JsonValueKind.Array) throw new JsonException("行情缺少 Items 数组。");
return new(station, items.Items().Select(x => ParseQuote(x, id, time, source)).Where(x => x.Commodity.Length > 0).ToArray(), time, source);
}
public static MarketSnapshot? ParseEddn(JsonElement root)
{
var schema = root.Text("$schemaRef");
if (!schema.EndsWith("/commodity/3", StringComparison.Ordinal) || !Uri.TryCreate(schema, UriKind.Absolute, out var uri) || uri.Host != "eddn.edcd.io") return null;
var header = root.Get("header");
var version = header.Text("gameversion");
if (version.StartsWith("3.", StringComparison.Ordinal) || version.Contains("Legacy", StringComparison.OrdinalIgnoreCase)) return null;
var message = root.Get("message");
var time = message.Time() ?? throw new JsonException("EDDN 行情缺少时间。");
if (time > DateTimeOffset.UtcNow.AddMinutes(5) || time < DateTimeOffset.UtcNow.AddDays(-30)) return null;
var id = message.Long("marketId");
if (id <= 0 || string.IsNullOrWhiteSpace(message.Text("systemName")) || string.IsNullOrWhiteSpace(message.Text("stationName"))) return null;
if (message.Get("commodities").ValueKind != JsonValueKind.Array) throw new JsonException("EDDN 行情缺少 commodities。");
var type = message.Text("stationType");
var station = new Station
{
MarketId = id, Name = message.Text("stationName"), SystemName = message.Text("systemName"),
Type = type, MaxLandingPad = JsonFields.PadFromType(type),
IsFleetCarrier = type.Equals("FleetCarrier", StringComparison.OrdinalIgnoreCase),
IsPlanetary = type.StartsWith("Crater", StringComparison.OrdinalIgnoreCase),
IsRestricted = message.Text("carrierDockingAccess") is "friends" or "squadron" or "none",
UpdatedAt = time
};
var prohibited = message.Get("prohibited").Items().Where(x => x.ValueKind == JsonValueKind.String).Select(x => CommodityCatalog.Key(x.GetString()!)).ToHashSet();
var quotes = message.Get("commodities").Items().Select(x => ParseQuote(x, id, time, DataSource.Eddn))
.Where(x => x.Commodity.Length > 0).Select(x => x with { Illegal = x.Illegal || prohibited.Contains(x.Commodity) }).ToArray();
return new(station, quotes, time, DataSource.Eddn);
}
public static CommodityQuote ParseQuote(JsonElement item, long id, DateTimeOffset time, DataSource source)
{
var name = item.Text("Name");
var key = CommodityCatalog.Key(name, item.Long("id", item.Long("commodityId")), item.Text("symbol"));
var illegal = item.Get("statusFlags").Items().Any(x => x.ValueKind == JsonValueKind.String && x.GetString()!.Contains("illegal", StringComparison.OrdinalIgnoreCase));
return new()
{
MarketId = id, Commodity = key, DisplayName = item.Text("Name_Localised", name.Trim('$', ';').Replace("_name", "")),
Category = item.Text("Category_Localised", item.Text("categoryname", item.Text("Category"))),
BuyPrice = Math.Max(0, item.Long("buyPrice")), SellPrice = Math.Max(0, item.Long("sellPrice")),
MeanPrice = Math.Max(0, item.Long("meanPrice")), Supply = Math.Max(0, item.Long("stock", item.Long("supply"))),
Demand = Math.Max(0, item.Long("demand")), Illegal = illegal || item.Flag("illegal") || item.Flag("isIllegal") || item.Text("legality").Equals("illegal", StringComparison.OrdinalIgnoreCase),
Rare = item.Flag("rare") || item.Flag("isRare"), CollectedAt = time, Source = source
};
}
}
using System.Text.Json;
using XFEEDToolBox.Core.Models;
namespace XFEEDToolBox.Core.Data;
public static class MarketParser
{
public static MarketSnapshot ParseLocalMarket(JsonElement root, Station? known = null, DataSource source = DataSource.Journal)
{
var time = root.Time() ?? throw new JsonException("行情缺少 timestamp。");
var id = root.Long("MarketID");
if (id <= 0) throw new JsonException("行情缺少有效 MarketID。");
var type = root.Text("StationType");
var station = (known?.MarketId == id ? known : new Station())! with
{
MarketId = id, Name = root.Text("StationName"), SystemName = root.Text("StarSystem"),
Type = type, IsFleetCarrier = type.Equals("FleetCarrier", StringComparison.OrdinalIgnoreCase),
IsPlanetary = type.StartsWith("Crater", StringComparison.OrdinalIgnoreCase),
MaxLandingPad = known?.MaxLandingPad is > LandingPad.Unknown ? known.MaxLandingPad : JsonFields.PadFromType(type),
UpdatedAt = time
};
var items = root.Get("Items");
if (items.ValueKind != JsonValueKind.Array) throw new JsonException("行情缺少 Items 数组。");
return new(station, items.Items().Select(x => ParseQuote(x, id, time, source)).Where(x => x.Commodity.Length > 0).ToArray(), time, source);
}
public static MarketSnapshot? ParseEddn(JsonElement root)
{
var schema = root.Text("$schemaRef");
if (!schema.EndsWith("/commodity/3", StringComparison.Ordinal) || !Uri.TryCreate(schema, UriKind.Absolute, out var uri) || uri.Host != "eddn.edcd.io") return null;
var header = root.Get("header");
var version = header.Text("gameversion");
if (version.StartsWith("3.", StringComparison.Ordinal) || version.Contains("Legacy", StringComparison.OrdinalIgnoreCase)) return null;
var message = root.Get("message");
var time = message.Time() ?? throw new JsonException("EDDN 行情缺少时间。");
if (time > DateTimeOffset.UtcNow.AddMinutes(5) || time < DateTimeOffset.UtcNow.AddDays(-30)) return null;
var id = message.Long("marketId");
if (id <= 0 || string.IsNullOrWhiteSpace(message.Text("systemName")) || string.IsNullOrWhiteSpace(message.Text("stationName"))) return null;
if (message.Get("commodities").ValueKind != JsonValueKind.Array) throw new JsonException("EDDN 行情缺少 commodities。");
var type = message.Text("stationType");
var station = new Station
{
MarketId = id, Name = message.Text("stationName"), SystemName = message.Text("systemName"),
Type = type, MaxLandingPad = JsonFields.PadFromType(type),
IsFleetCarrier = type.Equals("FleetCarrier", StringComparison.OrdinalIgnoreCase),
IsPlanetary = type.StartsWith("Crater", StringComparison.OrdinalIgnoreCase),
IsRestricted = message.Text("carrierDockingAccess") is "friends" or "squadron" or "none",
UpdatedAt = time
};
var prohibited = message.Get("prohibited").Items().Where(x => x.ValueKind == JsonValueKind.String).Select(x => CommodityCatalog.Key(x.GetString()!)).ToHashSet();
var quotes = message.Get("commodities").Items().Select(x => ParseQuote(x, id, time, DataSource.Eddn))
.Where(x => x.Commodity.Length > 0).Select(x => x with { Illegal = x.Illegal || prohibited.Contains(x.Commodity) }).ToArray();
return new(station, quotes, time, DataSource.Eddn);
}
public static CommodityQuote ParseQuote(JsonElement item, long id, DateTimeOffset time, DataSource source)
{
var name = item.Text("Name");
var key = CommodityCatalog.Key(name, item.Long("id", item.Long("commodityId")), item.Text("symbol"));
var illegal = item.Get("statusFlags").Items().Any(x => x.ValueKind == JsonValueKind.String && x.GetString()!.Contains("illegal", StringComparison.OrdinalIgnoreCase));
return new()
{
MarketId = id, Commodity = key, DisplayName = item.Text("Name_Localised", name.Trim('$', ';').Replace("_name", "")),
Category = item.Text("Category_Localised", item.Text("categoryname", item.Text("Category"))),
BuyPrice = Math.Max(0, item.Long("buyPrice")), SellPrice = Math.Max(0, item.Long("sellPrice")),
MeanPrice = Math.Max(0, item.Long("meanPrice")), Supply = Math.Max(0, item.Long("stock", item.Long("supply"))),
Demand = Math.Max(0, item.Long("demand")), Illegal = illegal || item.Flag("illegal") || item.Flag("isIllegal") || item.Text("legality").Equals("illegal", StringComparison.OrdinalIgnoreCase),
Rare = item.Flag("rare") || item.Flag("isRare"), CollectedAt = time, Source = source
};
}
}