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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

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

namespace XFEEDToolBox.Test;

[TestFixture]
public class GalaxyJournalMarkersTests
{
    [Test] public void ActualQueryEvidenceRoundTripsWithPersistentGalaxyCacheWithoutChangingUnknownFacts()
    {
        var system=new GalacticSystem("Measured",new(1,2,3),27){Data=new(){AccountFid="F1",ConfirmedQueries=new HashSet<string>{"Power:actualcontroller"},PersonalMarkers=["bookmark"],BookmarkStyles=[new(7,false),new(2,true)],Visited=true}};
        var json=System.Text.Json.JsonSerializer.Serialize(system);
        var loaded=System.Text.Json.JsonSerializer.Deserialize<GalacticSystem>(json)!;
        Check.That(loaded.Data.ConfirmedQueries.Contains("Power:actualcontroller"));Check.That(loaded.Data.Visited==true&&loaded.Data.Population is null);Check.Equal("bookmark",loaded.Data.PersonalMarkers![0]);
        Check.That(loaded.Data.BookmarkStyles!.SequenceEqual(system.Data.BookmarkStyles!));Check.That(loaded.Data.ForAccount("F2").BookmarkStyles is null);
        Check.That(ReferenceEquals(system.Data,system.Data.Merge(new(){BookmarkStyles=[new(7,false),new(2,true)]})));
    }
    [Test] public void MissionMarkersFollowRealRedirectCompletionSnapshotAndExpiry()
    {
        var markers=new GalaxyJournalMarkers();var at=DateTimeOffset.Parse("2026-10-23T00:00:00Z");
        markers.Apply(Check.Json("""{"event":"MissionAccepted","MissionID":11,"DestinationSystem":"Original","Expiry":"2026-10-23T01:00:00Z"}"""),at);
        markers.Apply(Check.Json("""{"event":"MissionAccepted","MissionID":12,"DestinationSystem":"Finished","Expiry":"2026-10-23T01:00:00Z"}"""),at);
        markers.Apply(Check.Json("""{"event":"MissionRedirected","MissionID":11,"NewDestinationSystem":"Redirected"}"""),at);
        markers.Apply(Check.Json("""{"event":"MissionCompleted","MissionID":12}"""),at);
        Check.That(markers.MissionSystems(at).SetEquals(new[]{"Redirected"}));
        markers.Apply(Check.Json("""{"event":"Missions","Active":[{"MissionID":11,"Expires":600},{"MissionID":13,"Expires":600}]}"""),at);
        Check.That(markers.MissionSystems(at.AddSeconds(599)).SetEquals(new[]{"Redirected"}));
        Check.Equal(0,markers.MissionSystems(at.AddSeconds(601)).Count);
        markers.Apply(Check.Json("""{"event":"Missions","Active":[]}"""),at);Check.Equal(0,markers.MissionSystems(at).Count);
        markers.Apply(Check.Json("""{"event":"MissionAccepted","MissionID":14,"DestinationSystem":"No optional expiry"}"""),at);Check.That(markers.MissionSystems(at).Contains("No optional expiry"));
        markers.Apply(Check.Json("""{"event":"MissionAbandoned","MissionID":14}"""),at);Check.Equal(0,markers.MissionSystems(at).Count);
    }
    [Test] public void OnlySubscribedUnfinishedUnexpiredCommunityGoalsCreateMarkers()
    {
        var markers=new GalaxyJournalMarkers();var at=DateTimeOffset.Parse("2026-10-23T00:00:00Z");
        markers.Apply(Check.Json("""{"event":"CommunityGoal","CurrentGoals":[{"CGID":1,"SystemName":"Active","IsComplete":false,"Expiry":"2026-10-23T01:00:00Z"},{"CGID":2,"SystemName":"Finished","IsComplete":true,"Expiry":"2026-10-23T01:00:00Z"},{"CGID":3,"SystemName":"Expired","IsComplete":false,"Expiry":"2026-10-22T01:00:00Z"}]}"""),at);
        Check.That(markers.CommunityGoalSystems(at).SetEquals(new[]{"Active"}));
        markers.Apply(Check.Json("""{"event":"CommunityGoalDiscard","CGID":1}"""),at);Check.Equal(0,markers.CommunityGoalSystems(at).Count);
    }
    [Test] public void AcquiredMapDataIsIndependentOfVisitationAndTimestampDoesNotProveTradeValidity()
    {
        var map=GalaxySystemData.FromAcquisition(Check.Json("""{"event":"BuyExplorationData","System":"Remote","timestamp":"2026-10-23T00:00:00Z"}"""))!;
        Check.That(map.ExplorationPurchasedAt is not null&&map.Exploration is null&&map.Visited is null);
        var trade=GalaxySystemData.FromAcquisition(Check.Json("""{"event":"BuyTradeData","System":"Remote","timestamp":"2026-10-23T00:00:00Z"}"""))!;
        Check.That(trade.TradeDataPurchasedAt is not null&&trade.TradeData is null&&trade.Visited is null);
        var historicalCache=new GalaxySystemData{AccountFid="F1",Exploration="havedata",ExplorationPurchasedAt=map.ExplorationPurchasedAt};
        var corrected=historicalCache.ForAccount("F1");Check.That(corrected.Exploration is null&&corrected.ExplorationPurchasedAt is not null);
    }
    [Test] public void AccountSwitchRemovesPrivateFactsAndDynamicMarkersCanBeClearedWithoutLosingWorldFacts()
    {
        var data=new GalaxySystemData{AccountFid="F1",Visited=true,Government="Democracy",PersonalMarkers=["mission"],TradeDataRecordedAt=DateTimeOffset.UtcNow,ConfirmedQueries=new HashSet<string>{"Visited:visited","Exploration:havedata","TradeData:havedata","Markers:bookmark","Government:democracy"}};
        var foreign=data.ForAccount("F2");Check.That(foreign.Visited is null&&foreign.PersonalMarkers is null&&foreign.TradeDataRecordedAt is null);Check.Equal("Democracy",foreign.Government);
        Check.That(foreign.ConfirmedQueries.SetEquals(new[]{"Government:democracy"}));
        var done=data.Merge(new(){PersonalMarkers=[]});Check.That(done.PersonalMarkers is {Count:0});Check.That(done.Visited==true);
        Check.That(ReferenceEquals(data,data.Merge(new(){Services=null,Visited=true,PersonalMarkers=["mission"]})));
    }
    [Test] public void VerifiedOwnedColonyIsIndependentOfReportedColonialStatusAndNeverMakesOtherSystemsUnclaimed()
    {
        var filter=new GalaxyMapFilter{Mode=GalaxyMapMode.Colonisation,Category=GalaxyFilterCategory.Colonisation,Values=new HashSet<string>{"localplayerclaimed"}};
        var data=new GalaxySystemData{AccountFid="F1",OwnedColony=true,Colonisation="colonised"};
        var merged=data.Merge(new(){Colonisation="beingcolonised"});Check.That(merged.OwnedColony==true);Check.That(filter.Matches(new("Owned",new(0,0,0)){Data=merged}));
        var unknown=new GalacticSystem("Unknown",new(0,0,0)){Data=new(){Colonisation="colonised"}};Check.That(!filter.Matches(unknown));Check.That(filter.IsUnknown(unknown));Check.That((filter with{IncludeUnknown=true}).Matches(unknown));
        var switched=merged.ForAccount("F2");Check.That(switched.OwnedColony is null);Check.Equal("beingcolonised",switched.Colonisation);
    }
    [Test] public void ExplicitNativeSnapshotNullsClearOldClassificationsAndCannotSurviveOriginPidAccountOrDiskChanges()
    {
        var first=new GalaxyNativeSystemFacts("F1",27,100,Visited:false,Exploration:"dataavailable",TradeData:"havedata",WithinDataRange:true,MetadataStatus:3);
        var data=new GalaxySystemData().Merge(new(){NativeFilterFacts=first});
        var trade=new GalaxyMapFilter{Mode=GalaxyMapMode.Map,Category=GalaxyFilterCategory.TradeData,Values=new HashSet<string>{"havedata"}};
        Check.That(trade.Matches(new("Measured",new(0,0,0)){Data=data}));Check.That(ReferenceEquals(data,data.Merge(new(){NativeFilterFacts=first with{}})));
        var unknown=data.Merge(new(){NativeFilterFacts=first with{Visited=null,Exploration=null,TradeData=null,WithinDataRange=false,MetadataStatus=null}});
        Check.That(!trade.Matches(new("Measured",new(0,0,0)){Data=unknown}));Check.That(!trade.Matches(new("Measured",new(0,0,0)){Data=unknown with{ConfirmedQueries=new HashSet<string>{trade.QueryKey}}}));
        Check.That(unknown.NativeFilterFacts is {TradeData:null,Exploration:null,Visited:null,WithinDataRange:false});
        Check.That(data.ForNativeContext("F1",27,101).NativeFilterFacts is null);Check.That(data.ForNativeContext("F1",28,100).NativeFilterFacts is null);Check.That(data.ForNativeContext("F2",27,100).NativeFilterFacts is null);Check.That(data.ForNativeContext("F1",null,100).NativeFilterFacts is null);
        var disk=System.Text.Json.JsonSerializer.Deserialize<GalaxySystemData>(System.Text.Json.JsonSerializer.Serialize(data))!;Check.That(disk.NativeFilterFacts is null&&disk.Exploration is null&&disk.TradeData is null);
        var untrustedNegative=new GalaxySystemData{AccountFid="F1",Visited=false,ConfirmedQueries=new HashSet<string>{"Visited:notvisited"}}.ForNativeContext("F1",27,100);
        Check.That(untrustedNegative.Visited is null&&!untrustedNegative.ConfirmedQueries.Contains("Visited:notvisited"));
        Check.That(GalaxyMapFilter.Keys(new("Original",new(0,0,0)){Data=data.ForNativeContext("F1",27,100)},GalaxyFilterCategory.Visited)!.Contains("notvisited"));
        var visitedHistory=new GalaxySystemData{AccountFid="F1",Visited=true}.Merge(new(){NativeFilterFacts=unknown.NativeFilterFacts});Check.That(GalaxyMapFilter.Keys(new("Measured",new(0,0,0)){Data=visitedHistory},GalaxyFilterCategory.Visited)!.Contains("visited"));
        Check.That(new GalaxySystemData{Visited=true}.Merge(new(){NativeFilterFacts=unknown.NativeFilterFacts}).Visited is null);
        var switched=new GalaxySystemData{AccountFid="F1",Visited=true,OwnedColony=true,Government="Democracy"}.Merge(new(){NativeFilterFacts=first with{AccountFid="F2",Visited=null}});
        Check.That(switched.Visited is null&&switched.OwnedColony is null);Check.Equal("Democracy",switched.Government);
    }
    [Test] public void NativeColonisationEligibilityUsesActualRulesAndClaimStatusNeverInventsCommanderOwnership()
    {
        var filter=new GalaxyMapFilter{Mode=GalaxyMapMode.Colonisation,Category=GalaxyFilterCategory.Colonisation,Values=new HashSet<string>{"unclaimed"}};
        GalacticSystem Original(int? state)=>new("Original",new(0,0,0)){Data=new(){AccountFid="F1",NativeFilterFacts=new("F1",27,100,ColonisationStatus:state)}};
        Check.That(filter.Matches(Original(0)));Check.That(!filter.Matches(Original(1)));Check.That(!filter.IsUnknown(Original(1)));
        var denied=filter with{Values=new HashSet<string>{"excluded"}};
        foreach(var state in new[]{5,6,7,8,9,10,11})Check.That(denied.Matches(Original(state))&&!filter.Matches(Original(state))&&!filter.IsUnknown(Original(state)));
        foreach(var state in new int?[]{null,12,13,14})Check.That(!denied.Matches(Original(state))&&denied.IsUnknown(Original(state)));
        var owned=filter with{Values=new HashSet<string>{"localplayerclaimed"}};
        foreach(var state in new[]{1,2,3}){var claim=Original(state);Check.That(!owned.Matches(claim)&&owned.IsUnknown(claim));Check.That(owned.Matches(claim with{Data=claim.Data with{OwnedColony=true}}));}
        var populated=filter with{Values=new HashSet<string>{"alreadypopulated"}};Check.That(populated.Matches(Original(3))&&populated.Matches(Original(4)));
        var cleared=Original(0);cleared=cleared with{Data=cleared.Data.Merge(new(){NativeFilterFacts=cleared.Data.NativeFilterFacts! with{ColonisationStatus=null}})};Check.That(!filter.Matches(cleared));
    }
    [Test] public void DiskCacheAndOldQueryProofCannotResurrectLiveSocialPositions()
    {
        var live=new GalaxySystemData{AccountFid="F1",PersonalMarkers=["bookmark","friend","wing"],ConfirmedQueries=new HashSet<string>{"Markers:friend"}};
        var disk=System.Text.Json.JsonSerializer.Deserialize<GalaxySystemData>(System.Text.Json.JsonSerializer.Serialize(live))!;
        Check.That(disk.PersonalMarkers!.SequenceEqual(new[]{"bookmark"}));
        var oldDisk=System.Text.Json.JsonSerializer.Deserialize<GalaxySystemData>("""{"AccountFid":"F1","PersonalMarkers":["friend","wing","bookmark"]}""")!;Check.That(oldDisk.PersonalMarkers!.SequenceEqual(new[]{"bookmark"}));
        var friend=new GalaxyMapFilter{Mode=GalaxyMapMode.Map,Category=GalaxyFilterCategory.Markers,Values=new HashSet<string>{"friend"}};
        Check.That(friend.Matches(new("Actual",new(0,0,0)){Data=live}));Check.That(!friend.Matches(new("Old",new(0,0,0)){Data=disk}));
    }
    [Test] public void OriginalRecentActivityThresholdUsesExactScopeAndAcceptsARealZero()
    {
        var filter=new GalaxyMapFilter{Mode=GalaxyMapMode.Powerplay,Category=GalaxyFilterCategory.PowerActivityEligibility,ActivityPowerName="Actual Power",ActivityInternalPowerId=4,Activity=GalaxyPowerActivity.Acquiring,UseMinimumActivity=true,MinimumActivity=.5};
        GalacticSystem Evidence(GalaxyPowerActivityEvidence? evidence)=>new("Measured",new(0,0,0)){Data=new(){PowerActivities=["reinforcement","undermining"],NativeFilterFacts=new("F1",27,100,PowerActivity:evidence),ConfirmedQueries=new HashSet<string>{filter.QueryKey}}};
        Check.That(!filter.Matches(Evidence(null)));Check.That(!filter.Matches(Evidence(new("Other Power",GalaxyPowerActivity.Acquiring,.7,4))));
        Check.That(!filter.Matches(Evidence(new("Actual Power",GalaxyPowerActivity.Undermining,.7,4))));Check.That(!filter.Matches(Evidence(new("Actual Power",GalaxyPowerActivity.Acquiring,.7,1))));
        var measured=Evidence(new("Actual Power",GalaxyPowerActivity.Acquiring,.7,4));Check.That(filter.Matches(measured));
        Check.That(!(filter with{MinimumActivity=.8}).Matches(measured));Check.That(filter.Matches(Evidence(new("Actual Power",GalaxyPowerActivity.Acquiring,2,4))));
        var zero=Evidence(new("Actual Power",GalaxyPowerActivity.Acquiring,0,4));Check.That(!(filter with{MinimumActivity=.1}).Matches(zero));Check.That((filter with{MinimumActivity=0}).Matches(zero));
        var missing=Evidence(new("Actual Power",GalaxyPowerActivity.Acquiring,null,4));Check.That(!filter.Matches(missing)&&filter.IsUnknown(missing));Check.That((filter with{IncludeUnknown=true}).Matches(missing));
        Check.That(!(filter with{ActivityPowerName=null,IncludeUnknown=true}).Matches(measured));Check.That(!(filter with{MinimumActivity=double.NaN}).ActivityQueryReady);
        var disabled=filter with{UseMinimumActivity=false,ActivityPowerName=null,ActivityInternalPowerId=null};Check.That(disabled.Matches(Evidence(null))&&!disabled.IsUnknown(Evidence(null)));Check.That(disabled.Evaluate(Evidence(null)).Matches);
        Check.That(filter.QueryKey!=(filter with{Activity=GalaxyPowerActivity.BeingUndermined}).QueryKey&&filter.QueryKey!=disabled.QueryKey);
        Check.That(!filter.Matches(measured with{Data=measured.Data.ForNativeContext("F1",27,101)}));
        var all=filter with{ActivityAllPowers=true,ActivityPowerName=null,ActivityInternalPowerId=null};
        Check.That(all.Matches(Evidence(new("",GalaxyPowerActivity.Acquiring,.7,AllPowers:true))));Check.That(!all.Matches(measured));Check.That(all.QueryKey!=filter.QueryKey);
    }
}