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);});
}
}
}
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);});
}
}
}