using System.Text.Json; using XFEEDToolBox.Core.Data; using XFEEDToolBox.Views; namespace XFEEDToolBox; public partial class App { private static async Task RunMarketProbeAsync(string reportPath) { var directory=Path.GetDirectoryName(Path.GetFullPath(reportPath))!;Directory.CreateDirectory(directory); string? failure=null;var results=new List(); void Require(bool condition,string error){if(!condition)throw new InvalidOperationException(error);} try { Require(ViewModel.OfflinePreview&&Runtime.FlightDriver is null&&Runtime.Journal.Sequence==0,"Market probe must not connect to or control the game."); ViewModel.DemoMode=false;ViewModel.OnlyCurrentStation=false; await ViewModel.RefreshCommand.ExecuteAsync(null); Require(!ViewModel.HasError,ViewModel.ErrorMessage); Require(ViewModel.MarketRows.Count>0,"Actual client did not load cached commodity rows."); var before=await Task.Run(Runtime.Markets.Statistics); Require(before.Quotes>1000000&&before.Stations>10000,"This acceptance requires the recovered real cache, not a small fixture."); MainWindow.AppWindow.Move(new(-30000,-30000));MainWindow.AppWindow.Resize(new(1680,1080));MainWindow.AppWindow.Show(false); var shell=AppShellPage.Current!; shell.Navigate(typeof(MainPage));await Task.Delay(300);shell.UpdateLayout(); await CapturePageAsync(shell,Path.Combine(directory,"overview.png")); shell.Navigate(typeof(MarketPage));await Task.Delay(300);shell.UpdateLayout(); await CapturePageAsync(shell,Path.Combine(directory,"market.png")); for(var cycle=0;cycle<2;cycle++) { foreach(var sort in Enum.GetValues()) { var count=await Task.Run(()=>Runtime.Markets.Search("",null,sort:sort).Count); Require(count==150,"Client query returned an unexpected number of rows: "+sort); results.Add(new{cycle,sort=sort.ToString(),rows=count}); } await ViewModel.RefreshCommand.ExecuteAsync(null); Require(!ViewModel.HasError,ViewModel.ErrorMessage); } var first=Runtime.Markets.Search("",null).First(); Require(Runtime.Markets.Search(first.Quote.Commodity,first.Station.MarketId).Count>0,"Station/commodity filter failed."); var origin=Runtime.Markets.GetStations(limit:10000).First(s=>s.Position is not null); Require(Runtime.Markets.LoadRegion(origin.MarketId,50).Stations.Count>0,"Regional planner could not read recovered cache."); var after=await Task.Run(Runtime.Markets.Statistics); results.Add(new{before.Stations,before.Quotes,before.Latest,afterStations=after.Stations,afterQuotes=after.Quotes,visibleRows=ViewModel.MarketRows.Count, ViewModel.CoverageText,ViewModel.QuoteCountText,ViewModel.HasError,ViewModel.ErrorMessage,gameCommandsInvoked=false,journalEvents=Runtime.Journal.Sequence}); } catch(Exception error){failure=error.ToString();} await File.WriteAllTextAsync(reportPath,JsonSerializer.Serialize(new{pid=Environment.ProcessId,Runtime.DataDirectory,Runtime.Markets.LastRecovery,results,failure,uiError=ViewModel.ErrorMessage},new JsonSerializerOptions{WriteIndented=true})); MainWindow.Close(); } private static async Task WriteMarketRuntimeReportAsync(string path) { var samples=new List(); for(var i=0;i<4;i++) { try { var stats=await Task.Run(Runtime.Markets.Statistics); samples.Add(new{time=DateTimeOffset.UtcNow,stats.Stations,stats.Quotes,stats.Latest,ViewModel.HasError,ViewModel.ErrorMessage, rows=ViewModel.MarketRows.Count,received=Runtime.Eddn?.MessagesReceived,accepted=Runtime.Eddn?.MarketsAccepted, navigation=Runtime.Navigator.State.ToString(),diagnostics=Runtime.Activity.Take(40).ToArray()}); Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(path))!); await File.WriteAllTextAsync(path,JsonSerializer.Serialize(new{pid=Environment.ProcessId,Runtime.DataDirectory,eventDatabase=Runtime.GameEvents.DatabasePath,eventRecovery=Runtime.GameEvents.LastRecovery,samples},new JsonSerializerOptions{WriteIndented=true})); } catch(Exception error) { Runtime.Log("行情验收",error.ToString()); await File.WriteAllTextAsync(path+".error",error.ToString());return; } if(i<3)await Task.Delay(TimeSpan.FromSeconds(20)); } } }