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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Text.Json;

namespace XFEEDToolBox.Core.Outfitting;

/// <summary>Effective outfitting values calculated from a complete, observed loadout.</summary>
public sealed record EquipmentStatistics(
    IReadOnlyDictionary<string,double> Ship,
    IReadOnlyDictionary<string,IReadOnlyDictionary<string,double>> Modules)
{
    public double? Value(string key)=>Ship.TryGetValue(key,out var value)?value:null;
}

public static partial class EdsyLinkCodec
{
    public static EquipmentStatistics Statistics(ShipRefitDocument document)
    {
        // Never fill unknown core slots with EDSY's stock modules or apply an unsaved target.
        if(new[]{"Armour","PowerPlant","MainEngines","FrameShiftDrive","LifeSupport","PowerDistributor","Radar","FuelTank"}
            .Any(name=>document.Slots.FirstOrDefault(s=>s.Slot==name)?.Module is null))
            throw new InvalidOperationException("等待完整装配,无法计算飞船属性。");
        var actual=document with{Slots=document.Slots.Select(s=>s with{Target=null}).ToArray()};
        var loadout=new{Ship=actual.ShipType,ShipName=actual.Name,ShipIdent=actual.Ident,Modules=actual.Slots.Select(JournalModule).ToArray()};
        var changed=actual.Slots.Where(s=>s.Module!=s.Original).Select(s=>s.Slot).ToArray();
        using var result=Invoke("xfeExport",JsonSerializer.Serialize(new{loadout,baselineHash=actual.EdsyHash,changed,statistics=true}));
        var root=result.RootElement;
        ThrowErrors(root);
        static IReadOnlyDictionary<string,double> Values(JsonElement value)=>value.EnumerateObject()
            .Where(p=>p.Value.ValueKind==JsonValueKind.Number&&p.Value.TryGetDouble(out var n)&&double.IsFinite(n))
            .ToDictionary(p=>p.Name,p=>p.Value.GetDouble(),StringComparer.OrdinalIgnoreCase);
        return new(Values(root.GetProperty("ship")),root.GetProperty("modules").EnumerateObject()
            .ToDictionary(p=>p.Name,p=>Values(p.Value),StringComparer.OrdinalIgnoreCase));
    }
}