XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
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
        };
    }
}