using XFEEDToolBox.Core.Execution; using XFEEDToolBox.Core.Models; using XFEExtension.NetCore.XUnit.Attributes; namespace XFEEDToolBox.Test; [TestFixture] public class AutomaticTradeTests { private static Station Station(long id)=>new(){MarketId=id,Name="Station"+id,SystemName="System"+id}; private static CommodityQuote Quote(long market,string key,long buy,long sell,long stock=10000,long demand=10000)=>new() {MarketId=market,Commodity=key,DisplayName=key,BuyPrice=buy,SellPrice=sell,Supply=stock,Demand=demand,CollectedAt=DateTimeOffset.UtcNow,Source=DataSource.Journal}; [Test]public void ArbitraryUserStationsAndAutomaticCapacityAreValid() { using var directory=new TemporaryDirectory();var value=new AutomaticTradeConfiguration{Source=Station(7),Destination=Station(98),WorkingDirectory=directory.Path}; value.Validate();(value with{CargoCapacity=752}).Validate();(value with{CargoCapacity=2048}).Validate(); Check.Throws(()=>(value with{Destination=Station(7)}).Validate()); } [Test]public void InterdictionDefaultsToImmediateExitAndKeepsLegacyRoutesCompatible() { using var directory=new TemporaryDirectory();var value=new AutomaticTradeConfiguration{Source=Station(7),Destination=Station(98),WorkingDirectory=directory.Path}; Check.That(value.ExitOnInterdiction&&!value.RequireInterdictionEscape);value.Validate();(value with{RequireInterdictionEscape=true}).Validate(); Check.Throws(()=>(value with{ExitOnInterdiction=false}).Validate()); } [Test]public void OrdinaryCargoCanUseNonCgCommoditiesAndAllOfTheLiveHold() { var order=AutomaticTradePlanner.Select([Quote(1,"gold",100,90)],[Quote(2,"gold",50,120)],752,1000000,2000); Check.Equal("gold",order.Commodity);Check.Equal(752,order.Quantity); } [Test]public void ReserveStockDemandAndConfiguredCgGoodsAllBoundTheOrder() { var source=new[]{Quote(1,"gold",100,120,99),Quote(1,"uranium",10,20,1000)}; var target=new[]{Quote(2,"gold",1,900,demand:5),Quote(2,"uranium",1,20,demand:8)}; var ordinary=AutomaticTradePlanner.Select(source,target,752,1000000,1000);Check.Equal("gold",ordinary.Commodity);Check.Equal(5,ordinary.Quantity); var cg=AutomaticTradePlanner.Select(source,target,752,1025,1000,["uranium"]);Check.Equal("uranium",cg.Commodity);Check.Equal(2,cg.Quantity); Check.Throws(()=>AutomaticTradePlanner.Select(source,target,752,999,1000)); } [Test]public void ExplicitInvestmentCapsEveryPurchaseAfterWalletProfitsIncrease() { using var directory=new TemporaryDirectory(); var config=new AutomaticTradeConfiguration{Source=Station(1),Destination=Station(2),WorkingDirectory=directory.Path,ReserveCredits=100,InvestmentCredits=300}; config.Validate(); var source=new[]{Quote(1,"gold",10,8)};var target=new[]{Quote(2,"gold",8,20)}; foreach(var wallet in new[]{1000m,2000m,10000m}) { var protectedCredits=config.PurchaseReserve(wallet,50,20); var order=AutomaticTradePlanner.Select(source,target,752,wallet,protectedCredits); Check.Equal(28,order.Quantity);Check.That(order.Cost+20<=config.InvestmentCredits); } Check.Equal(920m,config.PurchaseReserve(1000,900,20)); } [Test]public void AllFundsAndLegacyConfigurationKeepOperationalReservesWithoutAnInvestmentCap() { using var directory=new TemporaryDirectory(); var config=new AutomaticTradeConfiguration{Source=Station(1),Destination=Station(2),WorkingDirectory=directory.Path,ReserveCredits=100}; Check.That(config.InvestmentCredits is null);Check.Equal(120m,config.PurchaseReserve(1000,50,20));Check.Equal(120m,config.PurchaseReserve(2000,50,20)); Check.Throws(()=>(config with{InvestmentCredits=0}).Validate()); Check.Throws(()=>(config with{InvestmentCredits=-1}).Validate()); } [Test]public void TradeCgSelectionUsesDestinationAndIdentityRatherThanOneFixedTitle() { var goal=new CommunityGoalInfo(42,"Other trade initiative","tradelist","trade",987,"Other system","Other station",DateTimeOffset.UtcNow.AddDays(1),true,true,10); Check.Equal(42UL,CommunityGoalCatalogue.RequireDestinationTrade([goal],987,42,DateTimeOffset.UtcNow,true).Id); Check.Throws(()=>CommunityGoalCatalogue.RequireDestinationTrade([goal],986,42,DateTimeOffset.UtcNow,true)); Check.Throws(()=>CommunityGoalCatalogue.RequireDestinationTrade([goal with{Subscribed=false}],987,42,DateTimeOffset.UtcNow,true)); } }