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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Text.Json;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Session;
using XFEExtension.NetCore.XUnit.Attributes;

namespace XFEEDToolBox.Test;

[TestFixture]public class SessionMaintenanceFlightGateTests
{
    private static readonly DateTimeOffset Now=DateTimeOffset.Parse("2026-10-25T19:00:00Z");
    private static PlayerState Ship(DateTimeOffset at)=>new(){CommanderId="maintenance",CurrentShipId=8,CargoCapacity=1200,
        InGame=true,LoadGameAt=Now.AddHours(-1),CargoReliable=true,CreditsReliable=true,CargoCount=0,StatusReadAt=at,Ships=[new(){ShipId=8,HullHealth=1}]};
    private static JsonElement Raw(DateTimeOffset at,bool health=true,bool damage=false,bool emergency=false,double hull=1,bool manual=false,string entity="7",string world="9",long healthSequence=1)
        =>Check.Event(new{sequence=1,observedAtUnixMilliseconds=at.ToUnixTimeMilliseconds(),entityId=entity,referenceWorldAddress=world,
            inGame=true,localPlayerShipVerified=true,playerOverride=manual,shipHealth=new{sequence=healthSequence,observedAtUnixMilliseconds=at.ToUnixTimeMilliseconds(),
                entityId=entity,verified=health,damageObserved=damage,emergency,hullFraction=hull}});
    private static JsonElement Local(DateTimeOffset at,double speed=0,double throttle=0,int fsd=2,bool sc=false,bool duty=false,string entity="7",string world="9")
        =>Check.Event(new{sequence=1,observedAtUnixMilliseconds=at.ToUnixTimeMilliseconds(),entityId=entity,referenceWorldAddress=world,
            rawFsdState=fsd,inSupercruise=sc,speedMetresPerSecond=speed,throttle,docking=new{verified=true,nativeDutyActive=duty,nativeLaunchActive=false}});
    [Test]public void EmptyStationaryHealthyShipRequiresTenContinuousSecondsBeforeMenuUpdate()
    {
        var gate=new SessionMaintenanceFlightGate(Ship(Now));Check.That(!gate.Observe(Ship(Now),Raw(Now),Local(Now),Now));
        var at=Now.AddSeconds(9);Check.That(!gate.Observe(Ship(at),Raw(at),Local(at),at));
        at=Now.AddSeconds(10);Check.That(gate.Observe(Ship(at),Raw(at),Local(at),at));
    }
    [Test]public void CargoUnreliableStateAndExternalThreatCannotAuthorizeSpaceUpdate()
    {
        var at=Now.AddSeconds(10);
        foreach(var current in new[]{Ship(at) with{CargoCount=1},Ship(at) with{CargoReliable=false},Ship(at) with{CreditsReliable=false},
            Ship(at) with{StatusReadAt=at.AddSeconds(-3)},Ship(at) with{Navigation=new(){ExternalThreat=true}},Ship(at) with{Docked=true}})
        {
            var gate=new SessionMaintenanceFlightGate(Ship(Now));gate.Observe(Ship(Now),Raw(Now),Local(Now),Now);
            Check.That(!gate.Observe(current,Raw(at),Local(at),at));
            Check.That(!gate.Observe(Ship(at),Raw(at),Local(at),at));
        }
    }
    [Test]public void NativeDamageMotionActiveDutyAndMismatchedOrStaleFramesResetWaiting()
    {
        var at=Now.AddSeconds(10);
        foreach(var (raw,local) in new[]{(Raw(at,health:false),Local(at)),(Raw(at,damage:true),Local(at)),(Raw(at,emergency:true),Local(at)),
            (Raw(at,hull:.8),Local(at)),(Raw(at),Local(at,speed:1)),(Raw(at),Local(at,throttle:.1)),(Raw(at),Local(at,fsd:3)),
            (Raw(at),Local(at,sc:true)),(Raw(at),Local(at,duty:true)),(Raw(at),Local(at,entity:"8")),(Raw(at),Local(at,world:"10")),
            (Raw(at.AddSeconds(-1)),Local(at)),(Raw(at),Local(at.AddSeconds(-1))),(Raw(at,healthSequence:2),Local(at))})
        {
            var gate=new SessionMaintenanceFlightGate(Ship(Now));gate.Observe(Ship(Now),Raw(Now),Local(Now),Now);
            Check.That(!gate.Observe(Ship(at),raw,local,at));Check.That(!gate.Observe(Ship(at),Raw(at),Local(at),at));
        }
    }
    [Test]public void IdentitySessionChangesAndPhysicalTakeoverRemainTerminal()
    {
        foreach(var current in new[]{Ship(Now) with{CommanderId="other"},Ship(Now) with{CurrentShipId=9},Ship(Now) with{CargoCapacity=2000},Ship(Now) with{LoadGameAt=Now}})
            Check.Throws<InvalidOperationException>(()=>new SessionMaintenanceFlightGate(Ship(Now)).Observe(current,Raw(Now),Local(Now),Now));
        Check.Throws<InvalidOperationException>(()=>new SessionMaintenanceFlightGate(Ship(Now)).Observe(Ship(Now),Raw(Now,manual:true),Local(Now),Now));
    }
    [Test]public void ChangedEntityOrWorldNeedsANewCompleteStabilityWindow()
    {
        var gate=new SessionMaintenanceFlightGate(Ship(Now));gate.Observe(Ship(Now),Raw(Now),Local(Now),Now);
        var at=Now.AddSeconds(10);Check.That(!gate.Observe(Ship(at),Raw(at,entity:"8",world:"10"),Local(at,entity:"8",world:"10"),at));
        at=Now.AddSeconds(20);Check.That(gate.Observe(Ship(at),Raw(at,entity:"8",world:"10"),Local(at,entity:"8",world:"10"),at));
    }
    [Test]public void StableHistoricalHullCanExitForMaintenanceButAnyFurtherDecreaseRestartsTheWindow()
    {
        var gate=new SessionMaintenanceFlightGate(Ship(Now));
        Check.That(!gate.Observe(Ship(Now),Raw(Now,hull:.502883),Local(Now),Now));
        var at=Now.AddSeconds(10);Check.That(gate.Observe(Ship(at),Raw(at,hull:.502883),Local(at),at));
        at=Now.AddSeconds(11);Check.That(!gate.Observe(Ship(at),Raw(at,hull:.50),Local(at),at));
        at=Now.AddSeconds(20);Check.That(!gate.Observe(Ship(at),Raw(at,hull:.50),Local(at),at));
        at=Now.AddSeconds(21);Check.That(gate.Observe(Ship(at),Raw(at,hull:.50),Local(at),at));
        foreach(var hull in new[]{0d,-.1,1.1})
            Check.That(!new SessionMaintenanceFlightGate(Ship(Now)).Observe(Ship(at),Raw(at,hull:hull),Local(at),at));
    }
}