using XFEEDToolBox.Core.Models; namespace XFEEDToolBox.Core.Execution; /// Production orders bounded by the actual ship and reserved funds. public sealed class NativeTradeBatchPolicy(int capacity,decimal reserveCredits) { public const int MaximumQuantity=int.MaxValue; public const long MaximumUnitPrice=uint.MaxValue; public int Capacity{get;}=capacity is >0 and <=MaximumQuantity?capacity:throw new ArgumentOutOfRangeException(nameof(capacity)); public decimal ReserveCredits{get;}=reserveCredits>=0?reserveCredits:throw new ArgumentOutOfRangeException(nameof(reserveCredits)); public static bool Allows(string commodity)=>commodity is "uranium" or "coffee" or "polymers" or "liquidoxygen"; public static bool AllowsFormal(string commodity)=>commodity.Length is >0 and <128&&commodity.All(c=>char.IsAsciiLetterOrDigit(c)||c is '_' or '-'); public void ValidateAction(TradeAction action,PlayerState player) { var order=action.Order??throw new InvalidOperationException("正式交易缺少实际订单。"); var buy=action.Kind==TradeActionKind.Buy;var market=buy?action.Leg.From.MarketId:action.Leg.To.MarketId; if(action.Kind is not(TradeActionKind.Buy or TradeActionKind.Sell)||!AllowsFormal(order.Commodity)||order.Quantity<=0 ||order.Quantity>Capacity||player.CargoCapacity!=Capacity||action.Leg.Orders.Count!=1||action.Leg.Orders[0]!=order||action.Leg.Quantity!=order.Quantity ||order.BuyPrice is <=0 or >MaximumUnitPrice||order.SellPrice is <=0 or >MaximumUnitPrice ||!player.InGame||!player.Docked||player.MarketId!=market||!player.CargoReliable||!player.CreditsReliable||player.Credits is null or <0) throw new InvalidOperationException("订单、实际货舱或停靠状态与本次计划不一致。"); if(buy) { if(player.CargoCount!=0||player.Inventory.Any(item=>item.Count!=0)||order.Quantity>player.FreeCargo ||(decimal)order.BuyPrice*order.Quantity>player.Credits-ReserveCredits) throw new InvalidOperationException("买入超出实际空货舱、钱包或保留资金。"); } else if(player.CargoCount!=order.Quantity ||player.Inventory.Any(item=>item.Count>0&&(item.Key!=order.Commodity||item.Stolen!=0||item.MissionId is not null)) ||player.Inventory.Where(item=>item.Key==order.Commodity).Sum(item=>item.Count)!=order.Quantity) throw new InvalidOperationException("卖出需要在指定目的站确认本轮完整、合法货物。"); } }