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

AutoMiningScript

【SpaceEngineer】全自动挖矿脚本

公开
关注 0 Fork 0 Star 0
UTF-8
using System;
using System.Linq;
using VRage.Game.ModAPI.Ingame.Utilities;
using VRageMath;
using Xunit;
using P=AutoMiningScript.Program;

namespace AutoMiningScript.Tests
{
    public class BulkMiningTests
    {
        static void Drain(P.TaskPlanner p) {for(int n=0;n<1024;n++)p.Advance();}
        static P.Job Hit(P.TaskPlanner p,double radius=100)
        {
            p.Survey(Vector3D.Zero,Vector3D.Down,Vector3D.Forward,Vector3D.Up,radius);
            p.Report(p.Jobs[0],new P.JobReport {Outcome="SurveyHit",Position=new Vector3D(0,-10,0),Direction=Vector3D.Down,EntityId=42});
            return p.Jobs.Single(j=>j.Kind==P.JobKind.Probe);
        }
        [Theory]
        [InlineData(8)] [InlineData(12)] [InlineData(16)]
        public void SpaceExplorationUsesEveryReadyMinerAtADistinctObservation(int count)
        {
            var r=new FleetStateTests.Rig(count,true);foreach(var t in r.Miners)t.Radius=4.9;r.RegisterAll();
            r.Fleet.Command("survey 2000");r.Fleet.Command("start");
            for(int n=0;n<300;n++){if(n%5==0)foreach(var t in r.Miners)r.Receive("TELEMETRY",t);r.Tick(1);}
            var jobs=r.Planner.OwnedJobs.Values.ToList();Assert.Equal(count,jobs.Count);
            Assert.All(jobs,j=>Assert.Equal(P.JobKind.Survey,j.Kind));Assert.Equal(count,jobs.Select(j=>j.Entry).Distinct().Count());
            for(int i=0;i<jobs.Count;i++)for(int k=i+1;k<jobs.Count;k++)Assert.True(Vector3D.Distance(jobs[i].Entry,jobs[k].Entry)>=11.8);
            Assert.All(r.Planner.Jobs,j=>Assert.Equal(2000,Vector3D.Distance(Vector3D.Zero,j.Entry+j.Direction*j.Depth),6));
        }
        [Theory]
        [InlineData(0)] [InlineData(12)]
        public void SpaceObservationGenerationRestoresLegacyAndFleetSizedCursors(int ships)
        {
            var p=new P.TaskPlanner(TestRig.Program());p.Survey(Vector3D.Zero,Vector3D.Zero,Vector3D.Forward,Vector3D.Up,2000,ships);
            var saved=new MyIni();p.Save(saved);if(ships==0)saved.Set("region0","Rows",0);
            var after=new P.TaskPlanner(TestRig.Program());after.Load(saved);Drain(p);Drain(after);
            Assert.Equal(p.Jobs.Select(j=>j.Entry),after.Jobs.Select(j=>j.Entry));
            for(int n=0;n<p.Jobs.Count;n++)Assert.True(Vector3D.Distance(p.Jobs[n].Direction,after.Jobs[n].Direction)<1e-12);
            Assert.Equal(Math.Max(7,ships),after.Jobs.Select(j=>j.Entry).Distinct().Count());
        }
        [Fact]
        public void TwelveMinerSearchDoesNotSleepBetweenEveryAssignmentBatch()
        {
            var r=new FleetStateTests.Rig(12,true);r.RegisterAll();r.Fleet.Command("survey 2000");r.Fleet.Command("start");
            for(int n=0;n<240;n++)
            {
                if(n%60==0)foreach(var t in r.Miners)r.Receive("TELEMETRY",t);
                r.Program.Now+=1d/60;r.Fleet.Tick(1d/60);
            }
            Assert.Equal(504,r.Planner.Jobs.Count);Assert.Equal(12,r.Planner.OwnedJobs.Count);
        }
        [Theory]
        [InlineData(12)] [InlineData(16)]
        public void OneSurfaceHitCanEmployTheWholeReadyFleetWithoutOreConfirmation(int count)
        {
            var r=new FleetStateTests.Rig(count,true);foreach(var t in r.Miners)t.Radius=4.9;r.RegisterAll();
            r.Planner.Survey(Vector3D.Zero,Vector3D.Zero,Vector3D.Forward,Vector3D.Up,2000);
            r.Planner.Report(r.Planner.Jobs[0],new P.JobReport {Outcome="SurveyHit",Position=Vector3D.Forward*500,Direction=Vector3D.Forward,EntityId=42});Drain(r.Planner);
            foreach(var j in r.Planner.Jobs.Where(j=>j.Kind==P.JobKind.Survey).ToList())r.Planner.Report(j,new P.JobReport {Outcome="SurveyEmpty"});
            r.Fleet.Command("start");
            for(int n=0;n<200;n++){if(n%5==0)foreach(var t in r.Miners)r.Receive("TELEMETRY",t);r.Tick(1);}
            var jobs=r.Planner.OwnedJobs.Values.ToList();Assert.Equal(count,jobs.Count);Assert.Equal(count,jobs.Select(j=>j.Owner).Distinct().Count());
            Assert.All(jobs,j=>{Assert.Equal(P.JobKind.Probe,j.Kind);Assert.Equal(42,j.EntityId);Assert.Empty(j.ConfirmedOres);});
            for(int i=0;i<jobs.Count;i++)for(int k=i+1;k<jobs.Count;k++)
                Assert.True(P.Data.SegmentDistance(jobs[i].Entry-jobs[i].Direction*15,jobs[i].Entry+jobs[i].Direction*jobs[i].Depth,
                    jobs[k].Entry-jobs[k].Direction*15,jobs[k].Entry+jobs[k].Direction*jobs[k].Depth)>=11.8-1e-6);
        }
        [Fact]
        public void BulkGenerationResumesExactlyAfterCheckpoint()
        {
            var p=new P.TaskPlanner(TestRig.Program());Hit(p);p.Advance();p.Advance();
            var saved=new MyIni();p.Save(saved);var after=new P.TaskPlanner(TestRig.Program());after.Load(saved);Drain(p);Drain(after);
            Assert.Equal(p.Jobs.Select(j=>j.Id),after.Jobs.Select(j=>j.Id));Assert.Equal(p.Jobs.Select(j=>j.Entry),after.Jobs.Select(j=>j.Entry));
            Assert.Equal(p.Jobs.Count,p.Jobs.Select(j=>j.Id).Distinct().Count());Assert.Equal(0,after.PendingGeneration);
            Assert.True(after.Regions.Single(r=>r.Patch).Bulk);
        }
        [Theory]
        [InlineData(false)] [InlineData(true)]
        public void FleetRecordStorageResumesNewGridOrUpgradesLegacyRingWithoutLosingActiveWork(bool legacy)
        {
            var before=new FleetStateTests.Rig(1,true);before.RegisterAll();var seed=Hit(before.Planner);
            seed.Progress=12;before.Planner.SetOwner(seed,"miner-0");
            if(legacy)
            {
                var patch=before.Planner.Regions.Single(r=>r.Patch);patch.Bulk=false;patch.Generation="Ring";
                patch.Cursor=3;patch.Total=8;patch.Columns=patch.Rows=1;
            }
            else {before.Planner.Advance();before.Planner.Advance();}
            var after=new FleetStateTests.Rig(1,true);after.Restore(before.Checkpoint());Drain(after.Planner);
            var restored=after.Planner.Find(seed.Id);Assert.Equal(12,restored.Progress);Assert.Equal(seed.Entry,restored.Entry);
            Assert.Equal("miner-0",restored.Owner);Assert.Equal(restored,after.Planner.OwnedJobs["miner-0"]);
            Assert.True(after.Planner.Regions.Single(r=>r.Patch).Bulk);Assert.Equal(0,after.Planner.PendingGeneration);
            var holes=after.Planner.Jobs.Where(j=>j.Kind==P.JobKind.Probe).ToList();Assert.Equal(145,holes.Count);
            Assert.Equal(holes.Count,holes.Select(j=>j.Entry).Distinct().Count());
            if(!legacy)
            {
                Drain(before.Planner);Assert.Equal(before.Planner.Jobs.Select(j=>j.Id),after.Planner.Jobs.Select(j=>j.Id));
                Assert.Equal(before.Planner.Jobs.Select(j=>j.Entry),after.Planner.Jobs.Select(j=>j.Entry));
            }
        }
        [Fact]
        public void ExcavationNearSearchEdgeClipsBothEntriesAndBoreEndsToTheFrozenSphere()
        {
            var p=new P.TaskPlanner(TestRig.Program());p.Survey(Vector3D.Zero,Vector3D.Zero,Vector3D.Forward,Vector3D.Up,200);
            p.Report(p.Jobs[0],new P.JobReport {Outcome="SurveyHit",Position=Vector3D.Forward*198,Direction=Vector3D.Forward,EntityId=42});Drain(p);
            var holes=p.Jobs.Where(j=>j.Kind==P.JobKind.Probe).ToList();Assert.InRange(holes.Count,2,144);
            Assert.All(holes,j=>
            {
                Assert.True(j.Entry.Length()<=200+1e-6);Assert.True((j.Entry+j.Direction*j.Depth).Length()<=200+1e-6);
                Assert.InRange(j.Depth,1,2+1e-6);
            });
        }
        [Fact]
        public void LegacyIsolatedProbeExpandsWithoutChangingItsProgressOrOwnership()
        {
            var p=new P.TaskPlanner(TestRig.Program());p.Survey(Vector3D.Zero,Vector3D.Down,Vector3D.Forward,Vector3D.Up,100);Drain(p);
            string search=p.Regions[0].Id;p.Manual(new Vector3D(0,-10,0),Vector3D.Down,Vector3D.Forward,6,6,40);
            var seed=p.Jobs.Last();seed.Kind=P.JobKind.Probe;seed.EntityId=42;seed.RegionId=search;seed.Progress=12;p.SetOwner(seed,"old-miner");
            var saved=new MyIni();p.Save(saved);var after=new P.TaskPlanner(TestRig.Program());after.Load(saved);Drain(after);
            var restored=after.Find(seed.Id);Assert.Equal(12,restored.Progress);Assert.Equal(40,restored.Depth);Assert.Equal("old-miner",restored.Owner);
            Assert.Equal(seed.Entry,restored.Entry);Assert.True(after.Regions.Single(r=>r.Patch).Bulk);
            Assert.True(after.Jobs.Count(j=>j.Kind==P.JobKind.Probe)>100);
        }
        [Fact]
        public void LegacyStoppedEmptyRingsUpgradeWithoutRepeatingExistingHoles()
        {
            var p=new P.TaskPlanner(TestRig.Program());var seed=Hit(p);p.Report(seed,new P.JobReport {Outcome="Complete",Progress=seed.Depth});
            var saved=new MyIni();p.Save(saved);
            saved.Set("region1","Bulk",false);saved.Set("region1","Generation","");saved.Set("region1","Status","Sampling complete: two empty rings");saved.Set("region1","Ring",2);saved.Set("region1","EmptyRings",2);
            var after=new P.TaskPlanner(TestRig.Program());after.Load(saved);Drain(after);
            Assert.Equal("Complete",after.Find(seed.Id).Outcome);Assert.Equal("Pending",after.Regions.Single(r=>r.Patch).Status);
            var holes=after.Jobs.Where(j=>j.Kind==P.JobKind.Probe).ToList();Assert.True(holes.Count>100);Assert.Equal(holes.Count,holes.Select(j=>j.Entry).Distinct().Count());
        }
        [Fact]
        public void JobBudgetProducesFinitePartialWorkAndHonestIncompleteStatus()
        {
            var p=new P.TaskPlanner(TestRig.Program("[Survey]\nMaxJobs=32\n"));Hit(p);Drain(p);
            Assert.InRange(p.Jobs.Count,15,32);Assert.Equal(0,p.PendingGeneration);Assert.Equal("Pending",p.Regions.Single(r=>r.Patch).Status);
            Assert.True(p.Jobs.Count(j=>j.Kind==P.JobKind.Probe)>1);
            foreach(var j in p.Jobs.Where(j=>j.Kind==P.JobKind.Probe).ToList())p.Report(j,new P.JobReport {Outcome="Complete",Progress=j.Depth});Drain(p);
            Assert.Contains("job budget",p.Regions.Single(r=>r.Patch).Status);
        }
        [Fact]
        public void NewExcavationDepthUsesMaxDepthInsteadOfLegacyProbeDepth()
        {
            var p=new P.TaskPlanner(TestRig.Program("[Survey]\nMaxDepth=80\nProbeDepth=3\n"));Hit(p);Drain(p);
            Assert.All(p.Jobs.Where(j=>j.Kind==P.JobKind.Probe),j=>Assert.Equal(80,j.Depth));
        }

        [Fact]
        public void GrazingAsteroidDiscoveryBuildsAnInwardPatchInsteadOfFollowingTheTangentialRay()
        {
            var p=new P.TaskPlanner(TestRig.Program());p.Survey(Vector3D.Zero,Vector3D.Zero,Vector3D.Forward,Vector3D.Up,2000);
            var hit=new Vector3D(100,100,-700);var center=new Vector3D(200,250,-560);
            p.Report(p.Jobs[0],new P.JobReport {Outcome="SurveyHit",Position=hit,Direction=new Vector3D(.2,-.1,.97),EntityId=42,
                Scan=new P.ScanRecord {Start=Vector3D.Zero,End=hit,Center=center,Size=new Vector3D(512),Asteroid=42}});Drain(p);
            var direction=Vector3D.Normalize(center-hit);var holes=p.Jobs.Where(j=>j.Kind==P.JobKind.Probe).ToList();Assert.Equal(145,holes.Count);
            Assert.All(holes,j=>{Assert.True(Vector3D.Distance(direction,j.Direction)<1e-12);Assert.Equal(100,j.Depth);Assert.True(Vector3D.Distance(hit,j.Entry)<=43);});
        }
    }
}