using XFEExtension.NetCore.XUnit.Attributes; using XFEEDToolBox.Core.Data; using XFEEDToolBox.Core.Models; using XFEEDToolBox.Core.Planning; namespace XFEEDToolBox.Test; [TestFixture]public sealed class TradePlanningInputTests { [Test]public async Task FreshCompatibleMarketsSurviveNearerCarriersAndExpiredStationsBeforeTheLimit() { using var temporary=new TemporaryDirectory();var repository=new MarketRepository(temporary.File("markets.db"));repository.InitializeCheap(); var at=DateTimeOffset.UtcNow;var request=Check.Request with{AsOf=at,Loop=false,MaxLegs=1,SearchRadiusLy=500}; await repository.SaveSnapshotAsync(new(Check.Station(1),[Check.Quote(1,"water",100,90)],at,DataSource.Journal)); for(var id=10;id<210;id++) await repository.SaveSnapshotAsync(new(Check.Station(id,.1) with{IsFleetCarrier=id%2==0,IsRestricted=id%2==0},[Check.Quote(id,"water",0,200)],id%2==0?at:at.AddDays(-2),DataSource.Journal)); await repository.SaveSnapshotAsync(new(Check.Station(2,7.23),[Check.Quote(2,"water",0,180)],at,DataSource.Journal)); var old=repository.LoadRegion(1,500);Check.That(old.Truncated);Check.That(!old.Stations.Any(station=>station.MarketId==2)); var book=repository.LoadPlanningRegion(request);Check.Equal(2,book.Stations.Count);Check.That(book.Stations.Any(station=>station.MarketId==2)); var result=new TradeRoutePlanner().CalculateCandidatesWithDiagnostics(book,request); Check.That(result.Candidates.Count>0);Check.Equal(2,result.Diagnostics.FreshStations);Check.Equal("found",result.Diagnostics.Code); Check.Equal(2L,result.Candidates[0].Legs.Single().To.MarketId); } [Test]public void DiagnosticsSeparateStaleInputAndMissingMarketsFromAnEconomicSearch() { var planner=new TradeRoutePlanner();var request=Check.Request with{AsOf=DateTimeOffset.UtcNow,Loop=false,MaxLegs=1}; var stale=Check.TwoStations with{Quotes=Check.TwoStations.Quotes.Select(quote=>quote with{CollectedAt=request.AsOf.AddDays(-2)}).ToArray()}; var result=planner.CalculateCandidatesWithDiagnostics(stale,request); Check.Equal("expired-or-restricted-quotes",result.Diagnostics.Code);Check.Equal(0,result.Diagnostics.FreshQuotes);Check.That(result.Diagnostics.Message.Contains("不表示")); var one=planner.CalculateCandidatesWithDiagnostics(Check.TwoStations with{Quotes=Check.TwoStations.Quotes.Where(quote=>quote.MarketId==1).ToArray()},request); Check.Equal("insufficient-fresh-markets",one.Diagnostics.Code);Check.Equal(1,one.Diagnostics.FreshStations); } [Test]public async Task PlanningReadHonoursCancellationAndDoesNotInventMissingOriginQuotes() { using var temporary=new TemporaryDirectory();var repository=new MarketRepository(temporary.File("markets.db"));repository.InitializeCheap(); await repository.SaveStationAsync(Check.Station(1),localObservation:true); using var cancelled=new CancellationTokenSource();cancelled.Cancel(); Check.Throws(()=>repository.LoadPlanningRegion(Check.Request,token:cancelled.Token)); var book=repository.LoadPlanningRegion(Check.Request);Check.Equal(1,book.Stations.Count);Check.Equal(0,book.Quotes.Count); Check.Equal("no-fresh-quotes",new TradeRoutePlanner().CalculateCandidatesWithDiagnostics(book,Check.Request).Diagnostics.Code); } }