using System.Text.Json;
using XFEEDToolBox.Core.Navigation;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]public sealed class StationDepartureEnvelopeTests
{
private static readonly DateTimeOffset Now=DateTimeOffset.UtcNow;
private static readonly SystemNavigationTarget Station=new(1,22,"Verified station",SystemTargetKind.Station,42){NativeKind=10};
private static readonly Vector3d Centre=new(100,200,0),Origin=new(1e11,-2e11,3e11);
private static JsonElement Geometry(bool fresh=true,bool reference=true,string world="99",ulong body=22,int physicalKind=6,
double radius=3000,Vector3d? centre=null,bool duplicate=false,Vector3d? referenceOrigin=null,bool originVerified=true,
string originWorld="99",string originEntity="44",long? observedAt=null)
{
var translation=referenceOrigin??Origin;var point=centre??Centre-translation;
object row=new{bodyAddress=body.ToString(),bodyKind=physicalKind,exclusionRadius=radius,centre=new[]{point.X,point.Y,point.Z}};
return JsonSerializer.SerializeToElement(new{fresh,referenceFrameVerified=reference,worldAddress=world,position=new[]{7e11,8e11,9e11},
referenceOrigin=new{verified=originVerified,worldAddress=originWorld,entityId=originEntity,observedAtUnixMilliseconds=observedAt??Now.ToUnixTimeMilliseconds(),position=new[]{translation.X,translation.Y,translation.Z}},
nearbyBodies=duplicate?new[]{row,row}:new[]{row}});
}
private static double? Read(JsonElement geometry,SystemNavigationTarget? target=null,Vector3d? centre=null)
=>StationDepartureEnvelope.ReadRadius(geometry,99,44,target??Station,centre??Centre,Now);
[Test]public void PhysicalKindSixIsMatchedIndependentlyOfCatalogueStationKind()
{
Check.Equal(3000d,Read(Geometry())!.Value);
Check.Equal(3000d,Read(Geometry(),Station with{NativeKind=6})!.Value);
Check.Equal(3050.25d,Read(Geometry(radius:3050.25))!.Value);
Check.Equal(4500d,Read(Geometry(radius:4500))!.Value);
Check.That(Read(Geometry(),Station with{NativeKind=1}) is null);
Check.That(Read(Geometry(physicalKind:10)) is null);
Check.That(Read(Geometry(physicalKind:7)) is null);
}
[Test]public void FreshnessReferenceTargetAndCentreMustAllMatch()
{
foreach(var geometry in new[]{Geometry(fresh:false),Geometry(reference:false),Geometry(world:"88"),Geometry(body:23),Geometry(centre:Centre-Origin+new Vector3d(5,0,0)),
Geometry(duplicate:true),Geometry(radius:0),Geometry(radius:-1)})Check.That(Read(geometry) is null);
Check.That(Read(Geometry(),Station with{Kind=SystemTargetKind.Orbit}) is null);
Check.That(Read(Geometry(),Station with{BodyAddress=23}) is null);
Check.That(Read(Geometry(),centre:Centre+new Vector3d(0,0,2)) is null);
}
[Test]public void ProvenOriginRestoresStationCentreAcrossLargeCoordinateTranslationsWithoutUsingTheShipPose()
{
Check.Equal(3000d,Read(Geometry())!.Value);
Check.Equal(3000d,Read(Geometry(referenceOrigin:new(-5e12,7e12,2e12)))!.Value);
var movedShip=JsonSerializer.SerializeToNode(Geometry())!;
movedShip["position"]=JsonSerializer.SerializeToNode(new[]{-4e14,5e14,6e14});
Check.Equal(3000d,Read(JsonSerializer.SerializeToElement(movedShip))!.Value);
movedShip.AsObject().Remove("position");
Check.Equal(3000d,Read(JsonSerializer.SerializeToElement(movedShip))!.Value);
}
[Test]public void MissingUnverifiedForeignOrStaleOriginCannotAuthoriseDeparture()
{
foreach(var geometry in new[]{Geometry(originVerified:false),Geometry(originWorld:"88"),Geometry(originEntity:"45"),
Geometry(observedAt:Now.AddMilliseconds(-301).ToUnixTimeMilliseconds()),Geometry(observedAt:Now.AddSeconds(1).ToUnixTimeMilliseconds()),Geometry(observedAt:long.MaxValue)})
Check.That(Read(geometry) is null);
var missing=JsonSerializer.SerializeToNode(Geometry())!;missing.AsObject().Remove("referenceOrigin");
Check.That(Read(JsonSerializer.SerializeToElement(missing)) is null);
using var empty=JsonDocument.Parse("{}");Check.That(Read(empty.RootElement) is null);
Check.That(Read(Geometry(),centre:new(double.NaN,0,0)) is null);
}
[Test]public void OmittedUnknownStationNeverBecomesAuthorityAndDoesNotInvalidateAnotherVerifiedTarget()
{
var omitted=JsonSerializer.SerializeToNode(Geometry(body:1,physicalKind:1))!;
omitted["unverifiedStationEnvelopes"]=1;omitted["stationEnvelopeCoverageComplete"]=false;
Check.That(Read(JsonSerializer.SerializeToElement(omitted)) is null);
var known=JsonSerializer.SerializeToNode(Geometry())!;
known["unverifiedStationEnvelopes"]=1;known["stationEnvelopeCoverageComplete"]=false;
Check.Equal(3000d,Read(JsonSerializer.SerializeToElement(known))!.Value);
}
}
using System.Text.Json;
using XFEEDToolBox.Core.Navigation;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]public sealed class StationDepartureEnvelopeTests
{
private static readonly DateTimeOffset Now=DateTimeOffset.UtcNow;
private static readonly SystemNavigationTarget Station=new(1,22,"Verified station",SystemTargetKind.Station,42){NativeKind=10};
private static readonly Vector3d Centre=new(100,200,0),Origin=new(1e11,-2e11,3e11);
private static JsonElement Geometry(bool fresh=true,bool reference=true,string world="99",ulong body=22,int physicalKind=6,
double radius=3000,Vector3d? centre=null,bool duplicate=false,Vector3d? referenceOrigin=null,bool originVerified=true,
string originWorld="99",string originEntity="44",long? observedAt=null)
{
var translation=referenceOrigin??Origin;var point=centre??Centre-translation;
object row=new{bodyAddress=body.ToString(),bodyKind=physicalKind,exclusionRadius=radius,centre=new[]{point.X,point.Y,point.Z}};
return JsonSerializer.SerializeToElement(new{fresh,referenceFrameVerified=reference,worldAddress=world,position=new[]{7e11,8e11,9e11},
referenceOrigin=new{verified=originVerified,worldAddress=originWorld,entityId=originEntity,observedAtUnixMilliseconds=observedAt??Now.ToUnixTimeMilliseconds(),position=new[]{translation.X,translation.Y,translation.Z}},
nearbyBodies=duplicate?new[]{row,row}:new[]{row}});
}
private static double? Read(JsonElement geometry,SystemNavigationTarget? target=null,Vector3d? centre=null)
=>StationDepartureEnvelope.ReadRadius(geometry,99,44,target??Station,centre??Centre,Now);
[Test]public void PhysicalKindSixIsMatchedIndependentlyOfCatalogueStationKind()
{
Check.Equal(3000d,Read(Geometry())!.Value);
Check.Equal(3000d,Read(Geometry(),Station with{NativeKind=6})!.Value);
Check.Equal(3050.25d,Read(Geometry(radius:3050.25))!.Value);
Check.Equal(4500d,Read(Geometry(radius:4500))!.Value);
Check.That(Read(Geometry(),Station with{NativeKind=1}) is null);
Check.That(Read(Geometry(physicalKind:10)) is null);
Check.That(Read(Geometry(physicalKind:7)) is null);
}
[Test]public void FreshnessReferenceTargetAndCentreMustAllMatch()
{
foreach(var geometry in new[]{Geometry(fresh:false),Geometry(reference:false),Geometry(world:"88"),Geometry(body:23),Geometry(centre:Centre-Origin+new Vector3d(5,0,0)),
Geometry(duplicate:true),Geometry(radius:0),Geometry(radius:-1)})Check.That(Read(geometry) is null);
Check.That(Read(Geometry(),Station with{Kind=SystemTargetKind.Orbit}) is null);
Check.That(Read(Geometry(),Station with{BodyAddress=23}) is null);
Check.That(Read(Geometry(),centre:Centre+new Vector3d(0,0,2)) is null);
}
[Test]public void ProvenOriginRestoresStationCentreAcrossLargeCoordinateTranslationsWithoutUsingTheShipPose()
{
Check.Equal(3000d,Read(Geometry())!.Value);
Check.Equal(3000d,Read(Geometry(referenceOrigin:new(-5e12,7e12,2e12)))!.Value);
var movedShip=JsonSerializer.SerializeToNode(Geometry())!;
movedShip["position"]=JsonSerializer.SerializeToNode(new[]{-4e14,5e14,6e14});
Check.Equal(3000d,Read(JsonSerializer.SerializeToElement(movedShip))!.Value);
movedShip.AsObject().Remove("position");
Check.Equal(3000d,Read(JsonSerializer.SerializeToElement(movedShip))!.Value);
}
[Test]public void MissingUnverifiedForeignOrStaleOriginCannotAuthoriseDeparture()
{
foreach(var geometry in new[]{Geometry(originVerified:false),Geometry(originWorld:"88"),Geometry(originEntity:"45"),
Geometry(observedAt:Now.AddMilliseconds(-301).ToUnixTimeMilliseconds()),Geometry(observedAt:Now.AddSeconds(1).ToUnixTimeMilliseconds()),Geometry(observedAt:long.MaxValue)})
Check.That(Read(geometry) is null);
var missing=JsonSerializer.SerializeToNode(Geometry())!;missing.AsObject().Remove("referenceOrigin");
Check.That(Read(JsonSerializer.SerializeToElement(missing)) is null);
using var empty=JsonDocument.Parse("{}");Check.That(Read(empty.RootElement) is null);
Check.That(Read(Geometry(),centre:new(double.NaN,0,0)) is null);
}
[Test]public void OmittedUnknownStationNeverBecomesAuthorityAndDoesNotInvalidateAnotherVerifiedTarget()
{
var omitted=JsonSerializer.SerializeToNode(Geometry(body:1,physicalKind:1))!;
omitted["unverifiedStationEnvelopes"]=1;omitted["stationEnvelopeCoverageComplete"]=false;
Check.That(Read(JsonSerializer.SerializeToElement(omitted)) is null);
var known=JsonSerializer.SerializeToNode(Geometry())!;
known["unverifiedStationEnvelopes"]=1;known["stationEnvelopeCoverageComplete"]=false;
Check.Equal(3000d,Read(JsonSerializer.SerializeToElement(known))!.Value);
}
}