using XFEEDToolBox.Core.Models;
namespace XFEEDToolBox.Core.Execution;
/// <summary>Production orders bounded by the actual ship and reserved funds.</summary>
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("卖出需要在指定目的站确认本轮完整、合法货物。");
}
}
using XFEEDToolBox.Core.Models;
namespace XFEEDToolBox.Core.Execution;
/// <summary>Production orders bounded by the actual ship and reserved funds.</summary>
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("卖出需要在指定目的站确认本轮完整、合法货物。");
}
}