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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using XFEExtension.NetCore.XUnit.Attributes;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Engineering;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Outfitting;
using XFEEDToolBox.Core.Planning;
using XFEEDToolBox.Core.Rendering;
using XFEEDToolBox.Core.Session;
namespace XFEEDToolBox.Test;

[TestFixture]
public class RefinementTests
{
    private static readonly EngineerAccess Engineer=new(){Id=300260,Name="Tod 'The Blaster' McQuinn",Progress="Unlocked",Rank=4,ReputationMin=94.6,ReputationMax=94.6};
    private static readonly FittedModule Module=new(){Slot="LargeHardpoint1",Item="hpt_multicannon_gimbal_large",Enabled=true,Engineering=new(){Blueprint="Weapon_Overcharged",Level=3,Quality=.65,ExperimentalEffectId="special_incendiary_rounds"}};
    private static readonly RefitTarget Target=new("Overcharged Weapon",5,1,"special_incendiary_rounds",300260,false,true);
    private static PlayerState Player(FittedModule? module=null)=>new(){CommanderId="F1",CurrentShipId=7,Ships=[new(){ShipId=7,Type="anaconda",ConfigurationAt=DateTimeOffset.UtcNow,Modules=[module??Module]}],Engineers=[Engineer]};
    [Test] public void GradeThreeSixtyFivePercentStartsAtActualProgressAndPromotesEngineer()
    {
        var effect=EngineeringCatalog.Default.Recipes.Single(r=>r.Type=="Multi-cannon"&&r.JournalName=="special_incendiary_rounds");
        var plan=EngineeringPlanner.Calculate(EngineeringCatalog.Default,Module,Target.Blueprint,5,1,effect,Engineer,[]);
        Check.Equal(3,plan.Rolls[0].Grade);Check.Equal(.65,plan.Rolls[0].BeforeQuality);
        Check.That(plan.Rolls.All(r=>r.Grade>=3));Check.Equal(5,plan.Rolls[0].AfterRank);
        Check.Equal(10,plan.Rolls.Count);Check.That(plan.Complete);
        Check.That(!plan.Notes.Any(n=>n.Contains("更换蓝图")));
        Check.That(!plan.Materials.Any(m=>m.Key=="phosphorus"));
    }
    [Test] public void LiveProgressRebasesStaleShipWhilePreservingTargetsAndOriginalSnapshot()
    {
        var stale=Module with{Engineering=Module.Engineering! with{Level=1,Quality=0}};
        var doc=ShipRefit.Create(Player(stale).Ships.Single(),OutfittingCatalog.Default);
        doc=ShipRefit.SetTarget(doc,Module.Slot,Target);
        var current=ShipRefit.RefreshOwnedProgress(doc,Player());
        Check.Equal(1,doc.Slots.Single(s=>s.Slot==Module.Slot).Module!.Engineering!.Level);
        var slot=current.Slots.Single(s=>s.Slot==Module.Slot);
        Check.Equal(3,slot.Module!.Engineering!.Level);Check.Equal(.65,slot.Module.Engineering.Quality!.Value);Check.Equal(Target,slot.Target!);
        Check.That(ReferenceEquals(current,ShipRefit.RefreshOwnedProgress(current,Player())));
        var plan=ShipRefitPlanner.Calculate(current,EngineeringCatalog.Default,[Engineer],[]);
        Check.Equal(10,plan.Modules.Single().Rolls);
    }
    [Test] public void AddWholeShipUpdatesOwnedEntriesWithoutDuplicatingThemAndUsesLiveProgress()
    {
        var p=Player();var doc=ShipRefit.SetTarget(ShipRefit.Create(p.Ships.Single(),OutfittingCatalog.Default),Module.Slot,Target);
        var first=UpgradeListPlanner.AddShip([],doc);var second=UpgradeListPlanner.AddShip(first,doc);
        Check.Equal(1,second.Count);Check.Equal(first[0].Id,second[0].Id);Check.Equal("ship:7:LargeHardpoint1",second[0].SourceKey);
        var stale=second[0] with{Module=Module with{Engineering=null}};
        var plan=UpgradeListPlanner.Calculate([stale],p,EngineeringCatalog.Default);
        Check.Equal(10,plan.Engineering.Modules.Single().Rolls);
        Check.Throws<InvalidOperationException>(()=>UpgradeListPlanner.AddShip([],ShipRefit.Create(p.Ships.Single(),OutfittingCatalog.Default)));
    }
    [Test] public void ModuleIconIndexUsesRealBoundedTexturesAndActualGrades()
    {
        Check.That(EliteModuleIcons.References.Count>100);
        Check.Equal("module_category_multicannon_icon",EliteModuleIcons.IconName(Module.Item));
        Check.Equal("module_category_shieldgenerator_icon",EliteModuleIcons.IconName("int_shieldgenerator_size6_class5"));
        Check.That(EliteModuleIcons.References.All(r=>r.ResourceHash.Length==40&&r.SourceSha256.Length==64&&r.Width<=512&&r.Height<=512&&r.RowPitch>=r.Width/4*16));
        var slot=new RefitSlot{Module=Module,Capacity=3,Target=Target};Check.Equal("3",slot.SlotSize);Check.Equal("G3",slot.CurrentGrade);
        Check.That(!slot.CardName.Contains("武器挂点"));
    }
    [Test] public void CommanderProfileUsesOwnRecordedVisitsDeduplicatesScansAndResetsOnAccountChange()
    {
        var p=new PlayerProjector();
        p.Apply(Check.Json("""{"event":"LoadGame","timestamp":"2026-10-22T00:00:00Z","FID":"F1","Commander":"Test","Credits":42}"""));
        var scan=Check.Json("""{"event":"Scan","timestamp":"2026-10-22T00:00:03Z","SystemAddress":7,"BodyName":"Sol A","StarType":"G","WasDiscovered":false}""");
        p.Apply(Check.Json("""{"event":"FSDJump","timestamp":"2026-10-22T00:00:02Z","SystemAddress":7,"StarSystem":"Sol","StarPos":[0,0,0],"JumpDist":4.5}"""));p.Apply(scan);p.Apply(scan);
        Check.Equal(1,p.State.Profile.VisitedSystems.Count);Check.Equal(1,p.State.Profile.ScannedBodies);Check.Equal(1,p.State.Profile.FirstDiscoveredBodies);Check.Equal("G",p.State.Profile.VisitedSystems[0].StarClass);
        p.Apply(Check.Json("""{"event":"Status","timestamp":"2026-10-22T00:00:04Z","Flags":16777224,"Balance":125}"""));Check.Equal(125m,p.State.Credits!.Value);Check.That(p.State.CreditsReliable&&p.State.Profile.Arx is null);
        p.Apply(Check.Json("""{"event":"LoadGame","timestamp":"2026-10-22T00:00:05Z","FID":"F2","Commander":"Other"}"""));Check.Equal(0,p.State.Profile.VisitedSystems.Count);Check.Equal(0,p.State.Profile.ScannedBodies);
    }
}

[TestFixture]
public class ShieldRestartTests
{
    private static readonly DateTimeOffset Now=DateTimeOffset.Parse("2026-10-22T00:01:00Z");
    private static readonly GameSessionTarget Game=new(7,Now.AddMinutes(-1).UtcTicks,"game","launcher",true);
    private static PlayerState Player(bool up=true)=>new(){CommanderId="F1",CurrentShipId=7,InGame=true,LoadGameAt=Now.AddSeconds(-55),StatusAt=Now,Status=new((1L<<24)|(up?8:0),0,1,1,0,null,null,null,null,[]),Ships=[new(){ShipId=7,ConfigurationAt=Now,Modules=[new(){Item="int_shieldgenerator_size6_class5",Enabled=true}]}]};
    private static ObservedJournalEvent Event(long sequence,bool up,DateTimeOffset? time=null)=>new(sequence,Now,Check.Event(new{timestamp=time??Now,@event="ShieldState",ShieldsUp=up}));
    private static ShieldRestartGuard Guard(bool prime=true){var guard=new ShieldRestartGuard();guard.SetEnabled(true,Now.AddSeconds(-1));if(prime)guard.Prime(Player(),Game);return guard;}
    [Test] public void LiveShieldFailureTriggersExactlyOnceAndNeedsRecoveryToRearm()
    {
        var g=Guard();Check.That(g.Armed);Check.That(g.Observe(Event(1,false),Player(false),Game));Check.That(!g.Observe(Event(2,false),Player(false),Game));
        Check.That(!g.Observe(Event(3,true),Player(),Game));Check.That(g.Observe(Event(4,false),Player(false),Game));
    }
    [Test] public void DisabledAlreadyDownHistoricalAndDuplicateEventsCannotTrigger()
    {
        var g=new ShieldRestartGuard();Check.That(!g.Observe(Event(1,false),Player(false),Game));
        g=Guard(false);Check.That(!g.Observe(Event(1,false),Player(false),Game));
        g=Guard();Check.That(!g.Observe(Event(1,false,Now.AddMinutes(-5)),Player(false),Game));Check.That(g.Armed);
        Check.That(g.Observe(Event(2,false),Player(false),Game));Check.That(!g.Observe(Event(2,false),Player(false),Game));
    }
    [Test] public void DockedOnFootFighterShieldlessOtherProcessAndNewSessionCannotTrigger()
    {
        foreach(var p in new[]{Player(false) with{Docked=true},Player(false) with{Status=Player(false).Status! with{Flags2=1}},Player(false) with{Status=Player(false).Status! with{Flags=1L<<25}},Player(false) with{Ships=[]},Player(false) with{LoadGameAt=Now.AddSeconds(1)},Player(false) with{CommanderId="F2"},Player(false) with{CurrentShipId=8}})
            Check.That(!Guard().Observe(Event(1,false),p,Game));
        Check.That(!Guard().Observe(Event(1,false),Player(false),Game with{ProcessId=8}));
        Check.That(!new ToolboxSettings().ShieldZeroRestartEnabled);
    }
}