using System.Text.Json;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Navigation;
internal static class NativeRepairAcceptance
{
public static async Task RunAsync(int pid,string address,string action,string path)
{
if(action is not("repair" or "integrity")||File.Exists(path)||File.Exists(path+".submitted.json"))throw new ArgumentException("A new bounded repair acceptance is required.");
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.MarketId is not {} market||initial.CurrentShipId!=7||!initial.StationServicesKnown||!initial.StationServices.Contains("repair"))throw new InvalidOperationException("Actual docked acceptance ship and repair service required.");
using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(100));
await using var protection=await FlightTestProtectionScope.ArmAsync(pid);var pipe=new NavigationPipeClient(pid);
async Task<JsonElement> Wait(JsonElement queued)
{
var generation=queued.GetProperty("generation").GetUInt64();
while(true){var value=await pipe.CallAsync(new{op="commerce.market.status",generation},stop.Token);if(value.GetProperty("state").GetInt32()>=3)return value;await Task.Delay(80,stop.Token);}
}
Task<JsonElement> Prices()=>ReadPrices();
async Task<JsonElement> ReadPrices()=>await Wait(await pipe.CallAsync(new{op="station.services.inspect",marketId=(uint)market,maintenanceAddress=address},stop.Token));
var key=Guid.NewGuid().ToString("N");var started=DateTimeOffset.UtcNow;string? failure=null;
JsonElement? before=null,quote=null,receipt=null,after=null,serverAfter=null;
try
{
before=await pipe.CallAsync(new{op="station.services.inventory"},stop.Token);quote=await Prices();
var repair=quote.Value.GetProperty("servicePrices").GetProperty("repair");var costs=action=="integrity"?repair.GetProperty("shipIntegrityCosts"):repair;var cost=costs.GetProperty("costToRepair").GetInt64();
if(cost is <=0 or >5000)throw new InvalidOperationException("Expected a nonzero bounded original repair quote.");
if(journal.State.LoadGameAt!=initial.LoadGameAt||journal.State.CurrentShipId!=initial.CurrentShipId||!journal.State.Docked||journal.State.MarketId!=market)throw new InvalidOperationException("Docking or session changed.");
await File.WriteAllTextAsync(path+".submitted.json",JsonSerializer.Serialize(new{key,market,pid,started,action,before,cost,instruction="Never resend an uncertain original service operation."},ToolboxSettings.JsonOptions));
receipt=await Wait(await pipe.CallAsync(new{op="station.services",marketId=(uint)market,maintenanceAddress=address,action,operationKey=key},stop.Token));
if(receipt.Value.GetProperty("state").GetInt32()!=3||!receipt.Value.GetProperty("serverConfirmed").GetBoolean()||!receipt.Value.GetProperty("clientApplied").GetBoolean())throw new InvalidOperationException("Original repair reply unconfirmed; reconcile before any further mutation.");
after=await pipe.CallAsync(new{op="station.services.inventory"},stop.Token);
if(after.Value.GetProperty("credits").GetInt64()!=before.Value.GetProperty("credits").GetInt64()-cost||after.Value.GetProperty("cargoCount").GetInt32()!=before.Value.GetProperty("cargoCount").GetInt32())throw new InvalidOperationException("Actual native wallet or cargo disagrees with repair receipt.");
serverAfter=await Prices();var nextRepair=serverAfter.Value.GetProperty("servicePrices").GetProperty("repair");var next=action=="integrity"?nextRepair.GetProperty("shipIntegrityCosts"):nextRepair;
if(next.GetProperty("costToRepair").GetInt64()!=0||action=="integrity"&&next.GetProperty("wear").GetInt32()!=0)throw new InvalidOperationException("A second original server quote did not confirm the repair.");
}
catch(Exception error){failure=error.ToString();}
var passed=failure is null;await File.WriteAllTextAsync(path,JsonSerializer.Serialize(new{pid,market,started,finished=DateTimeOffset.UtcNow,key,action,passed,before,quote,receipt,after,serverAfter,failure,screenUse=false,osInputsSent=0,journalEventsSynthesized=0},ToolboxSettings.JsonOptions));
Console.WriteLine(JsonSerializer.Serialize(new{passed,market,action,failure}));if(!passed)throw new InvalidOperationException("Native repair acceptance did not pass.");
}
}
using System.Text.Json;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Navigation;
internal static class NativeRepairAcceptance
{
public static async Task RunAsync(int pid,string address,string action,string path)
{
if(action is not("repair" or "integrity")||File.Exists(path)||File.Exists(path+".submitted.json"))throw new ArgumentException("A new bounded repair acceptance is required.");
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.MarketId is not {} market||initial.CurrentShipId!=7||!initial.StationServicesKnown||!initial.StationServices.Contains("repair"))throw new InvalidOperationException("Actual docked acceptance ship and repair service required.");
using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(100));
await using var protection=await FlightTestProtectionScope.ArmAsync(pid);var pipe=new NavigationPipeClient(pid);
async Task<JsonElement> Wait(JsonElement queued)
{
var generation=queued.GetProperty("generation").GetUInt64();
while(true){var value=await pipe.CallAsync(new{op="commerce.market.status",generation},stop.Token);if(value.GetProperty("state").GetInt32()>=3)return value;await Task.Delay(80,stop.Token);}
}
Task<JsonElement> Prices()=>ReadPrices();
async Task<JsonElement> ReadPrices()=>await Wait(await pipe.CallAsync(new{op="station.services.inspect",marketId=(uint)market,maintenanceAddress=address},stop.Token));
var key=Guid.NewGuid().ToString("N");var started=DateTimeOffset.UtcNow;string? failure=null;
JsonElement? before=null,quote=null,receipt=null,after=null,serverAfter=null;
try
{
before=await pipe.CallAsync(new{op="station.services.inventory"},stop.Token);quote=await Prices();
var repair=quote.Value.GetProperty("servicePrices").GetProperty("repair");var costs=action=="integrity"?repair.GetProperty("shipIntegrityCosts"):repair;var cost=costs.GetProperty("costToRepair").GetInt64();
if(cost is <=0 or >5000)throw new InvalidOperationException("Expected a nonzero bounded original repair quote.");
if(journal.State.LoadGameAt!=initial.LoadGameAt||journal.State.CurrentShipId!=initial.CurrentShipId||!journal.State.Docked||journal.State.MarketId!=market)throw new InvalidOperationException("Docking or session changed.");
await File.WriteAllTextAsync(path+".submitted.json",JsonSerializer.Serialize(new{key,market,pid,started,action,before,cost,instruction="Never resend an uncertain original service operation."},ToolboxSettings.JsonOptions));
receipt=await Wait(await pipe.CallAsync(new{op="station.services",marketId=(uint)market,maintenanceAddress=address,action,operationKey=key},stop.Token));
if(receipt.Value.GetProperty("state").GetInt32()!=3||!receipt.Value.GetProperty("serverConfirmed").GetBoolean()||!receipt.Value.GetProperty("clientApplied").GetBoolean())throw new InvalidOperationException("Original repair reply unconfirmed; reconcile before any further mutation.");
after=await pipe.CallAsync(new{op="station.services.inventory"},stop.Token);
if(after.Value.GetProperty("credits").GetInt64()!=before.Value.GetProperty("credits").GetInt64()-cost||after.Value.GetProperty("cargoCount").GetInt32()!=before.Value.GetProperty("cargoCount").GetInt32())throw new InvalidOperationException("Actual native wallet or cargo disagrees with repair receipt.");
serverAfter=await Prices();var nextRepair=serverAfter.Value.GetProperty("servicePrices").GetProperty("repair");var next=action=="integrity"?nextRepair.GetProperty("shipIntegrityCosts"):nextRepair;
if(next.GetProperty("costToRepair").GetInt64()!=0||action=="integrity"&&next.GetProperty("wear").GetInt32()!=0)throw new InvalidOperationException("A second original server quote did not confirm the repair.");
}
catch(Exception error){failure=error.ToString();}
var passed=failure is null;await File.WriteAllTextAsync(path,JsonSerializer.Serialize(new{pid,market,started,finished=DateTimeOffset.UtcNow,key,action,passed,before,quote,receipt,after,serverAfter,failure,screenUse=false,osInputsSent=0,journalEventsSynthesized=0},ToolboxSettings.JsonOptions));
Console.WriteLine(JsonSerializer.Serialize(new{passed,market,action,failure}));if(!passed)throw new InvalidOperationException("Native repair acceptance did not pass.");
}
}