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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using XFEEDToolBox.Core.Models;

namespace XFEEDToolBox.Core.Execution;

/// <summary>Explicit restrictions for real trade acceptance; ordinary user routes keep their own capacity.</summary>
public sealed class TradeAcceptancePolicy(IReadOnlyList<InventoryItem>? reservedCargo=null)
{
    private readonly InventoryItem[] reserved=[..reservedCargo??[]];
    public const long MaximumUnitPrice=500;
    private static readonly HashSet<string> CheapGoods=new(StringComparer.OrdinalIgnoreCase)
        {"algae","biowaste","foodcartridges","grain","hydrogenfuel","scrap","water"};
    public static bool Allows(string commodity,long unitPrice)=>CheapGoods.Contains(commodity)&&unitPrice is >0 and <=MaximumUnitPrice;

    public void ValidatePlan(RoutePlan plan,PlayerState player)
    {
        if(plan.Request.CargoCapacity!=1||plan.Legs.Count==0)throw new InvalidOperationException("实机跑商测试每次只能运输 1t。");
        if(!CargoMatches(player,null))
            throw new InvalidOperationException("测试需要空货舱;不会出售、丢弃或覆盖原有货物。");
        foreach(var leg in plan.Legs)
        {
            if(leg.Orders.Count!=1||leg.Quantity!=1||leg.Orders[0].Quantity!=1||!Allows(leg.Orders[0].Commodity,leg.Orders[0].BuyPrice))
                throw new InvalidOperationException("测试只允许 1t 常见低价货物,单价不得超过 500 Cr。");
        }
    }
    public void ValidateAction(TradeAction action,PlayerState player)
    {
        if(!player.CargoReliable)throw new InvalidOperationException("货舱状态无法核实,已停止测试。");
        var order=action.Order;
        if(action.Leg.Orders.Count!=1||action.Leg.Quantity!=1||!Allows(action.Leg.Orders[0].Commodity,action.Leg.Orders[0].BuyPrice))
            throw new InvalidOperationException("测试航段超出 1t 低价货物限制。");
        if(action.Kind==TradeActionKind.Travel)
        {
            RequireCargo(player,action.Leg.Orders[0].Commodity);
            return;
        }
        if(order is null||order!=action.Leg.Orders[0]||order.Quantity!=1||!Allows(order.Commodity,order.BuyPrice))
            throw new InvalidOperationException("测试交易指令与获准的 1t 低价货物不一致。");
        if(action.Kind==TradeActionKind.Buy)
        {
            if(!player.Docked||player.MarketId!=action.Leg.From.MarketId||!CargoMatches(player,null))
                throw new InvalidOperationException("买入前站点或空货舱状态改变,已停止测试。");
        }
        else
        {
            if(!player.Docked||player.MarketId!=action.Leg.To.MarketId)throw new InvalidOperationException("当前不是测试卖出站点。");
            RequireCargo(player,order.Commodity);
        }
    }
    private void RequireCargo(PlayerState player,string commodity)
    {
        if(!CargoMatches(player,commodity))
            throw new InvalidOperationException("测试货舱必须恰好为指定的 1t 合法货物。");
    }
    private bool CargoMatches(PlayerState player,string? testCommodity)
    {
        // Existing limpets are equipment consumables. Preserve their exact count;
        // no existing commodity, mission cargo or stolen item can become a test sale.
        if(reserved.Any(x=>!x.Key.Equals("drones",StringComparison.OrdinalIgnoreCase)||x.Stolen!=0||x.MissionId is not null||x.Count<0))return false;
        var expected=reserved.Where(x=>x.Count>0).ToList();
        if(testCommodity is not null)expected.Add(new(testCommodity,testCommodity,1));
        if(!player.CargoReliable||player.CargoCount!=expected.Sum(x=>x.Count)||player.Inventory.Any(x=>x.Count>0&&(x.Stolen!=0||x.MissionId is not null)))return false;
        var actual=player.Inventory.Where(x=>x.Count>0).GroupBy(x=>x.Key,StringComparer.OrdinalIgnoreCase).ToDictionary(x=>x.Key,x=>x.Sum(i=>i.Count),StringComparer.OrdinalIgnoreCase);
        var totals=expected.GroupBy(x=>x.Key,StringComparer.OrdinalIgnoreCase).ToDictionary(x=>x.Key,x=>x.Sum(i=>i.Count),StringComparer.OrdinalIgnoreCase);
        return actual.Count==totals.Count&&totals.All(x=>actual.GetValueOrDefault(x.Key)==x.Value);
    }
}