XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using XFEEDToolBox.Core.Navigation;
using XFEExtension.NetCore.XUnit.Attributes;

namespace XFEEDToolBox.Test;

[TestFixture]
public class AssistAvailabilityTests
{
    private static readonly DateTimeOffset Now=DateTimeOffset.Parse("2026-10-23T00:00:00Z");
    private static readonly SystemNavigationTarget Target=new(1,101,"Station",SystemTargetKind.Station,77);
    private static SystemFlightFrame Frame=>new(){Sequence=1,ObservedAt=Now,GameSha256=new('a',64),LoadoutFingerprint="ship",ShipEntity=1,SystemAddress=1,ReferenceWorld=101,
        InGame=true,GeometryVerified=true,Mode=LocalFlightMode.Supercruise,SelectedTarget=Target,Forward=new(0,0,1),Up=new(0,1,0),TargetPosition=new(0,0,6e8),TargetDistance=6e8,
        MaximumNormalSpeed=300,MaximumCruiseSpeed=1e10,CruiseParametersVerified=true,CruiseApproachSeconds=6,CruiseApproachThrottle=.75,
        BrakingAcceleration=10,TranslationAcceleration=5,LegalApproachSpeed=100,AssistAlignmentDegrees=5,Assists=new(false,true,true)};

    [Test] public void InstalledHardwareIsFilteredByLiveModuleAvailability()
    {
        var fitted=new NavigationAssists(true,true,true);
        Check.Equal(new NavigationAssists(false,false,true),fitted.Available(false,true));
        Check.Equal(new NavigationAssists(true,true,false),fitted.Available(true,false));
        Check.Equal(new NavigationAssists(false,false,false),fitted.Available(false,false));
        Check.Equal(new NavigationAssists(false,false,false),new NavigationAssists(false,false,false).Available(true,true));
    }
    [Test] public void StaleDutyFlagsCannotOverrideAnUnavailableModule()
    {
        Check.Equal(NativeAssistState.Unavailable,NativeSystemFlightObservation.CruiseAssist(false,true,true,true,true));
        Check.Equal(NativeAssistState.Unavailable,NativeSystemFlightObservation.DockingAssist(false,true,true));
        Check.Equal(NativeAssistState.Ready,NativeSystemFlightObservation.DockingAssist(true,false,false));
    }
    [Test] public void LostCruiseAssistImmediatelyResumesSoftwareApproachWithoutAnotherEnableRequest()
    {
        foreach(var failure in new[]{NativeAssistState.Unavailable,NativeAssistState.Disabled,NativeAssistState.Failed})
        {
            var policy=new SystemFlightNavigator();
            var native=policy.Decide(Frame with{SupercruiseAssist=NativeAssistState.Engaged},Target,Now);
            Check.That(native.Throttle is null&&native.Direction is null);
            var next=Frame with{SupercruiseAssist=failure,ObservedAt=Now.AddSeconds(1)};
            var fallback=policy.Decide(next,Target,next.ObservedAt);
            Check.Equal(.75,fallback.Throttle);Check.That(fallback.Direction is not null);
            Check.That(fallback.Actions.HasFlag(SystemNavigationAction.CancelOwnedAssists));
            for(var second=2;second<=25;second++)
            {
                next=next with{ObservedAt=Now.AddSeconds(second)};
                var decision=policy.Decide(next,Target,next.ObservedAt);
                Check.That(!decision.Actions.HasFlag(SystemNavigationAction.EnableSupercruiseAssist));
                Check.Equal(.75,decision.Throttle);
            }
        }
    }
    [Test] public void LostDockingComputerUsesGrantedPadPathAndNeverRepeatsNativeHandoff()
    {
        foreach(var failure in new[]{NativeAssistState.Unavailable,NativeAssistState.Disabled,NativeAssistState.Failed})
        {
            var policy=new SystemFlightNavigator();var grant=new DockingClearance(77,DockingPermission.Granted,3,Now,Now.AddMinutes(5));
            var frame=Frame with{Mode=LocalFlightMode.Normal,TargetDistance=7000,Clearance=grant,DockingAssist=NativeAssistState.Engaged};
            Check.Equal(SystemNavigationPhase.NativeLanding,policy.Decide(frame,Target,Now).Phase);
            for(var second=1;second<=35;second++)
            {
                var at=Now.AddSeconds(second);
                frame=frame with{ObservedAt=at,DockingAssist=failure,DockingPath=new(77,3,1,[new(new(0,0,20),Vector3d.Zero,new(0,0,1),new(0,1,0),10,1,true,true)],at,15)};
                var decision=policy.Decide(frame,Target,at);
                Check.Equal(SystemNavigationPhase.ApplicationLanding,decision.Phase);
                Check.That(decision.Translation is {Length:>0});
                Check.That(!decision.Actions.HasFlag(SystemNavigationAction.EnableDockingAssist));
                Check.That(!decision.Actions.HasFlag(SystemNavigationAction.ExitForFailedHandoff));
            }
        }
    }
    [Test] public void UnavailableDockingHardwareStillRequiresAtcBeforeAnyLanding()
    {
        var frame=Frame with{Mode=LocalFlightMode.Normal,TargetDistance=7500,DockingAssist=NativeAssistState.Unavailable};
        var request=new SystemFlightNavigator().Decide(frame,Target,Now);
        Check.Equal(SystemNavigationPhase.RequestingDocking,request.Phase);Check.Equal(0d,request.Throttle);
        Check.That(request.Actions.HasFlag(SystemNavigationAction.RequestDocking));Check.That(request.Translation is null);
    }
    [Test] public void LostDockingComputerBrakesWhileWaitingForTheRealPadPath()
    {
        var policy=new SystemFlightNavigator();
        var frame=Frame with{Mode=LocalFlightMode.Normal,TargetDistance=7000,DockingAssist=NativeAssistState.Engaged,
            Clearance=new(77,DockingPermission.Granted,3,Now,Now.AddMinutes(5)),Throttle=.8,Speed=60};
        Check.Equal(SystemNavigationPhase.NativeLanding,policy.Decide(frame,Target,Now).Phase);
        foreach(var state in new[]{NativeAssistState.Unavailable,NativeAssistState.Ready,NativeAssistState.Ready})
        {
            frame=frame with{ObservedAt=frame.ObservedAt.AddMilliseconds(80),DockingAssist=state};
            var decision=policy.Decide(frame,Target,frame.ObservedAt);
            Check.Equal(SystemNavigationPhase.Waiting,decision.Phase);Check.Equal(0d,decision.Throttle);
            Check.Equal(Vector3d.Zero,decision.Translation);Check.That(decision.Actions.HasFlag(SystemNavigationAction.CancelOwnedAssists));
            Check.That(!decision.Actions.HasFlag(SystemNavigationAction.EnableDockingAssist));
            Check.That(!decision.Actions.HasFlag(SystemNavigationAction.ReleaseFlightAxes));
        }
    }
    [Test] public void FailedHardwareDoesNotHideOriginalDutiesWhichStillNeedCancellation()
    {
        using var active=System.Text.Json.JsonDocument.Parse("{\"available\":false,\"enabled\":false,\"engaged\":true,\"matchesTarget\":true}");
        using var inactive=System.Text.Json.JsonDocument.Parse("{\"available\":false,\"enabled\":false,\"engaged\":false,\"matchesTarget\":true}");
        using var landing=System.Text.Json.JsonDocument.Parse("{\"computerAvailable\":false,\"nativeDutyActive\":true,\"nativeLaunchActive\":false}");
        using var launch=System.Text.Json.JsonDocument.Parse("{\"nativeDutyActive\":true,\"nativeLaunchActive\":true}");
        using var complete=System.Text.Json.JsonDocument.Parse("{\"nativeDutyActive\":false,\"nativeLaunchActive\":false}");
        Check.That(NativeSystemFlightObservation.CruiseNeedsCancellation(active.RootElement));
        Check.That(!NativeSystemFlightObservation.CruiseNeedsCancellation(inactive.RootElement));
        Check.That(NativeSystemFlightObservation.DockingNeedsCancellation(landing.RootElement));
        Check.That(!NativeSystemFlightObservation.DockingNeedsCancellation(launch.RootElement));
        Check.That(!NativeSystemFlightObservation.DockingNeedsCancellation(complete.RootElement));
    }
    [Test] public void AssistPowerSwitchesDoNotAbortFallbackAsAChangedLoadout()
    {
        var ship=new XFEEDToolBox.Core.Models.ShipRecord{ShipId=7,Type="anaconda",UnladenMass=400,Modules=[
            new(){Slot="Slot01",Item="int_supercruiseassist",Enabled=true,Priority=0,Health=1},
            new(){Slot="Slot02",Item="int_dockingcomputer_advanced",Enabled=true,Priority=0,Health=1},
            new(){Slot="MainEngines",Item="int_engine_size7_class5",Enabled=true,Priority=0,Health=1}]};
        var original=NativeSystemFlightObservation.LoadoutFingerprint(ship);
        var unavailable=ship with{Modules=ship.Modules.Select(m=>m.Item=="int_engine_size7_class5"?m:m with{Enabled=false,Priority=4,Health=0}).ToArray()};
        Check.Equal(original,NativeSystemFlightObservation.LoadoutFingerprint(unavailable));
        var replaced=ship with{Modules=ship.Modules.Select(m=>m.Slot=="Slot01"?m with{Item="int_cargorack_size1_class1"}:m).ToArray()};
        Check.That(original!=NativeSystemFlightObservation.LoadoutFingerprint(replaced));
        var enginesOff=ship with{Modules=ship.Modules.Select(m=>m.Slot=="MainEngines"?m with{Enabled=false}:m).ToArray()};
        Check.That(original!=NativeSystemFlightObservation.LoadoutFingerprint(enginesOff));
    }
}