using System.Text.Json;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Native;
using XFEEDToolBox.Core.Navigation;
internal static class NativeThrottleZeroAcceptance
{
public static async Task RunAsync(int pid,string exactName,string reportPath)
{
if(File.Exists(reportPath)||File.Exists(reportPath+".jsonl"))throw new IOException("Use a new evidence 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 initial=journal.State;
if(!initial.InGame||initial.Docked||initial.CurrentShipId!=7)throw new InvalidOperationException("Expected the identified acceptance ship in normal flight.");
var hello=await new NavigationPipeClient(pid).CallAsync(new{op="describe"});var hash=hello.GetProperty("gameSha256").GetString()!;
using var source=new NativeCurrentSystemSource(pid,hash,()=>journal.State);var catalogue=await source.ReadLocationsAsync();
var row=catalogue.Locations.Single(x=>x.Name==exactName);
var target=new SystemNavigationTarget(catalogue.SystemAddress,row.WorldAddress,row.Name,SystemTargetKind.Station,row.MarketId){NativeKey=row.Key,NativeKind=row.NativeKind,NativeIdentity=row.Identity};
await using var protection=await FlightTestProtectionScope.ArmAsync(pid);
var driver=new NativeSystemFlightControlDriver(pid,hash,()=>journal.State);
using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(100));
var start=DateTimeOffset.UtcNow;SystemFlightFrame? before=null,after=null;var applied=false;var released=false;string? failure=null;
var departureThrustSamples=0;DateTimeOffset? zeroAt=null;
await using var log=new StreamWriter(new FileStream(reportPath+".jsonl",FileMode.CreateNew,FileAccess.Write,FileShare.Read));
try
{
await driver.SelectAsync(target,stop.Token);before=await driver.ReadSystemFlightAsync(stop.Token);
if(before.Mode!=LocalFlightMode.Normal||before.Speed>20||before.PlayerOverride||before.ExternalThreat)
throw new InvalidOperationException("This acceptance only tests low-speed ordinary braking, without approach thrust.");
if(before.Speed<2)
{
if(before.TargetDistance<15000||initial.Status is null||(initial.Status.Flags&32)!=0)
throw new InvalidOperationException("The controlled low-speed braking fixture needs at least 15km station clearance and flight assist enabled.");
while(before.Speed<8)
{
var outward=(before.Position-before.TargetPosition).Unit();
var aligned=Vector3d.AngleDegrees(before.Forward,outward)<3;
var decision=new SystemFlightDecision(SystemNavigationPhase.Waiting,"站外低速制动验收",outward,aligned?.05:0);
if(before.Mode!=LocalFlightMode.Normal||before.PlayerOverride||before.ExternalThreat||before.TargetDistance<15000||(journal.State.Status!.Flags&32)!=0)
throw new InvalidOperationException("The controlled departure fixture changed safety conditions.");
await driver.ApplySystemFlightAsync(decision,before,target,before.ObservedAt.AddMilliseconds(250),stop.Token);
if(aligned)departureThrustSamples++;
await log.WriteLineAsync(JsonSerializer.Serialize(new{at=DateTimeOffset.UtcNow,stage="low-speed-outward",frame=before,decision}));await log.FlushAsync();
await Task.Delay(60,stop.Token);before=await driver.ReadSystemFlightAsync(stop.Token);
}
}
if(before.Speed is <2 or >20)throw new InvalidOperationException("A real bounded nonzero speed is required to prove braking.");
await driver.SetNormalThrottleZeroAsync(before,stop.Token);applied=true;zeroAt=DateTimeOffset.UtcNow;
while(true)
{
after=await driver.ReadSystemFlightAsync(stop.Token);
await log.WriteLineAsync(JsonSerializer.Serialize(new{at=DateTimeOffset.UtcNow,frame=after,driver.LastTelemetry}));await log.FlushAsync();
if(after.Mode!=LocalFlightMode.Normal||after.ShipEntity!=before.ShipEntity||after.PlayerOverride||after.ExternalThreat
||journal.State.CargoCount!=initial.CargoCount||journal.State.CurrentShipId!=initial.CurrentShipId)
throw new InvalidOperationException("The low-speed braking observation changed identity or mode.");
if(DateTimeOffset.UtcNow-zeroAt>TimeSpan.FromSeconds(1)&&after.Speed<1&&Math.Abs(after.Throttle)<.001)break;
if(DateTimeOffset.UtcNow-zeroAt>TimeSpan.FromSeconds(8))
{
await XFEEDToolBox.Core.Session.NativeFlightTestProtection.ExitForFailedHandoffAsync(pid);
throw new InvalidOperationException("The original zero input did not prove a stopped ship; protected exit requested.");
}
await Task.Delay(60,stop.Token);
}
}
catch(Exception error){failure=error.ToString();}
finally{try{await driver.ReleaseSystemFlightAsync();released=true;}catch(Exception error){failure=(failure??"")+" Release: "+error.Message;}}
var brakingObserved=before?.Speed>=2&&after?.Speed<1;
var passed=applied&&released&&brakingObserved&&failure is null;
await File.WriteAllTextAsync(reportPath,JsonSerializer.Serialize(new{pid,start,zeroAt,finished=DateTimeOffset.UtcNow,passed,applied,released,brakingObserved,departureThrustSamples,before,after,failure,approachThrustSent=0,screenUse=false,osInputsSent=0},ToolboxSettings.JsonOptions));
Console.WriteLine(JsonSerializer.Serialize(new{passed,applied,released,beforeSpeed=before?.Speed,afterSpeed=after?.Speed,failure}));
if(!passed)throw new InvalidOperationException("Original normal-throttle zero acceptance failed.");
}
}
using System.Text.Json;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Native;
using XFEEDToolBox.Core.Navigation;
internal static class NativeThrottleZeroAcceptance
{
public static async Task RunAsync(int pid,string exactName,string reportPath)
{
if(File.Exists(reportPath)||File.Exists(reportPath+".jsonl"))throw new IOException("Use a new evidence 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 initial=journal.State;
if(!initial.InGame||initial.Docked||initial.CurrentShipId!=7)throw new InvalidOperationException("Expected the identified acceptance ship in normal flight.");
var hello=await new NavigationPipeClient(pid).CallAsync(new{op="describe"});var hash=hello.GetProperty("gameSha256").GetString()!;
using var source=new NativeCurrentSystemSource(pid,hash,()=>journal.State);var catalogue=await source.ReadLocationsAsync();
var row=catalogue.Locations.Single(x=>x.Name==exactName);
var target=new SystemNavigationTarget(catalogue.SystemAddress,row.WorldAddress,row.Name,SystemTargetKind.Station,row.MarketId){NativeKey=row.Key,NativeKind=row.NativeKind,NativeIdentity=row.Identity};
await using var protection=await FlightTestProtectionScope.ArmAsync(pid);
var driver=new NativeSystemFlightControlDriver(pid,hash,()=>journal.State);
using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(100));
var start=DateTimeOffset.UtcNow;SystemFlightFrame? before=null,after=null;var applied=false;var released=false;string? failure=null;
var departureThrustSamples=0;DateTimeOffset? zeroAt=null;
await using var log=new StreamWriter(new FileStream(reportPath+".jsonl",FileMode.CreateNew,FileAccess.Write,FileShare.Read));
try
{
await driver.SelectAsync(target,stop.Token);before=await driver.ReadSystemFlightAsync(stop.Token);
if(before.Mode!=LocalFlightMode.Normal||before.Speed>20||before.PlayerOverride||before.ExternalThreat)
throw new InvalidOperationException("This acceptance only tests low-speed ordinary braking, without approach thrust.");
if(before.Speed<2)
{
if(before.TargetDistance<15000||initial.Status is null||(initial.Status.Flags&32)!=0)
throw new InvalidOperationException("The controlled low-speed braking fixture needs at least 15km station clearance and flight assist enabled.");
while(before.Speed<8)
{
var outward=(before.Position-before.TargetPosition).Unit();
var aligned=Vector3d.AngleDegrees(before.Forward,outward)<3;
var decision=new SystemFlightDecision(SystemNavigationPhase.Waiting,"站外低速制动验收",outward,aligned?.05:0);
if(before.Mode!=LocalFlightMode.Normal||before.PlayerOverride||before.ExternalThreat||before.TargetDistance<15000||(journal.State.Status!.Flags&32)!=0)
throw new InvalidOperationException("The controlled departure fixture changed safety conditions.");
await driver.ApplySystemFlightAsync(decision,before,target,before.ObservedAt.AddMilliseconds(250),stop.Token);
if(aligned)departureThrustSamples++;
await log.WriteLineAsync(JsonSerializer.Serialize(new{at=DateTimeOffset.UtcNow,stage="low-speed-outward",frame=before,decision}));await log.FlushAsync();
await Task.Delay(60,stop.Token);before=await driver.ReadSystemFlightAsync(stop.Token);
}
}
if(before.Speed is <2 or >20)throw new InvalidOperationException("A real bounded nonzero speed is required to prove braking.");
await driver.SetNormalThrottleZeroAsync(before,stop.Token);applied=true;zeroAt=DateTimeOffset.UtcNow;
while(true)
{
after=await driver.ReadSystemFlightAsync(stop.Token);
await log.WriteLineAsync(JsonSerializer.Serialize(new{at=DateTimeOffset.UtcNow,frame=after,driver.LastTelemetry}));await log.FlushAsync();
if(after.Mode!=LocalFlightMode.Normal||after.ShipEntity!=before.ShipEntity||after.PlayerOverride||after.ExternalThreat
||journal.State.CargoCount!=initial.CargoCount||journal.State.CurrentShipId!=initial.CurrentShipId)
throw new InvalidOperationException("The low-speed braking observation changed identity or mode.");
if(DateTimeOffset.UtcNow-zeroAt>TimeSpan.FromSeconds(1)&&after.Speed<1&&Math.Abs(after.Throttle)<.001)break;
if(DateTimeOffset.UtcNow-zeroAt>TimeSpan.FromSeconds(8))
{
await XFEEDToolBox.Core.Session.NativeFlightTestProtection.ExitForFailedHandoffAsync(pid);
throw new InvalidOperationException("The original zero input did not prove a stopped ship; protected exit requested.");
}
await Task.Delay(60,stop.Token);
}
}
catch(Exception error){failure=error.ToString();}
finally{try{await driver.ReleaseSystemFlightAsync();released=true;}catch(Exception error){failure=(failure??"")+" Release: "+error.Message;}}
var brakingObserved=before?.Speed>=2&&after?.Speed<1;
var passed=applied&&released&&brakingObserved&&failure is null;
await File.WriteAllTextAsync(reportPath,JsonSerializer.Serialize(new{pid,start,zeroAt,finished=DateTimeOffset.UtcNow,passed,applied,released,brakingObserved,departureThrustSamples,before,after,failure,approachThrustSent=0,screenUse=false,osInputsSent=0},ToolboxSettings.JsonOptions));
Console.WriteLine(JsonSerializer.Serialize(new{passed,applied,released,beforeSpeed=before?.Speed,afterSpeed=after?.Speed,failure}));
if(!passed)throw new InvalidOperationException("Original normal-throttle zero acceptance failed.");
}
}