using System.Text.Json; using XFEEDToolBox.Core.Data; using XFEEDToolBox.Core.Models; using XFEEDToolBox.Core.Native; using XFEEDToolBox.Core.Navigation; internal static class LocalFlightFrameAcceptance { public static async Task RunAsync(int pid,string exactName,string reportPath) { if(File.Exists(reportPath))throw new IOException("Use a new report path."); var settings=ToolboxSettings.Load(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),"XFEstudio","XFEEDToolBox","settings.json")); await using var journal=new JournalMonitor(settings.JournalDirectory);await journal.StartAsync();var raw=new NavigationPipeClient(pid); var hash=(await raw.CallAsync(new{op="describe"})).GetProperty("gameSha256").GetString()!; using var source=new NativeCurrentSystemSource(pid,hash,()=>journal.State);var before=await source.ReadLocationsAsync(); var row=before.Locations.Single(x=>x.Name.Equals(exactName,StringComparison.Ordinal)); var target=new SystemNavigationTarget(before.SystemAddress,row.WorldAddress,row.Name,row.MarketId is >0?SystemTargetKind.Station:SystemTargetKind.Orbit,row.MarketId) {NativeKey=row.Key,NativeKind=row.NativeKind,NativeIdentity=row.Identity}; var driver=new NativeSystemFlightControlDriver(pid,hash,()=>journal.State);var samples=new List();string? failure=null;var suspended=false; try { using var timeout=new CancellationTokenSource(TimeSpan.FromSeconds(10));await driver.SelectAsync(target,timeout.Token); while(samples.Count<20) { SystemFlightFrame frame; try{frame=await driver.ReadSystemFlightAsync(timeout.Token);} catch(FlightTelemetryUnavailableException){await Task.Delay(40,timeout.Token);continue;} var independently=(await source.ReadLocationsAsync(timeout.Token)).Locations.Single(x=>x.Identity==row.Identity); if(!independently.Selected||independently.DistanceMetres is not {} distance||Math.Abs(frame.TargetDistance-distance)>Math.Max(10,distance*.0001))throw new InvalidDataException("Target or independently read distance does not agree."); if(frame.Speed>=1)throw new InvalidOperationException("Observation fixture requires a stationary ship."); samples.Add(frame);await Task.Delay(45,timeout.Token); } await driver.SuspendSystemFlightAsync();suspended=true; var after=await driver.ReadSystemFlightAsync(timeout.Token);if(after.SelectedTarget?.SameIdentity(target)!=true)throw new InvalidDataException("Suspension lost target identity."); } catch(Exception error){failure=error.ToString();} finally{await driver.ReleaseSystemFlightAsync();} var passed=failure is null&&samples.Count==20&&suspended; await File.WriteAllTextAsync(reportPath,JsonSerializer.Serialize(new{pid,target,samples,suspended,passed,failure,flightInputsSent=0},ToolboxSettings.JsonOptions)); Console.WriteLine(JsonSerializer.Serialize(new{passed,samples=samples.Count,suspended,failure,flightInputsSent=0})); if(!passed)throw new InvalidOperationException("System-flight frame acceptance failed."); } }