using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Sandbox.ModAPI.Ingame;
using VRage.Game.GUI.TextPanel;
using VRage.Game.ModAPI.Ingame.Utilities;
using VRageMath;
using Xunit;
using P=AutoMiningScript.Program;
namespace AutoMiningScript.Tests
{
public class ExplorationMapTests
{
static MyDetectedEntityInfo Hit(long id=42, MyDetectedEntityType type=MyDetectedEntityType.Asteroid)
{
return new MyDetectedEntityInfo(id,"rock",type,new Vector3D(80,60,-20),MatrixD.Identity,Vector3.Zero,
VRage.Game.MyRelationsBetweenPlayerAndBlock.NoOwnership,new BoundingBoxD(new Vector3D(50,30,-40),new Vector3D(110,90,20)),1);
}
static P.ScanRecord Scan(long id=42) { return P.ScanRecord.Capture(Vector3D.Zero,new Vector3D(300,225,-75),Hit(id)); }
sealed class MapRole:P.RoleLogic
{
public readonly List<P.Job> Jobs=new List<P.Job>();
public readonly List<P.Telemetry> Fleet=new List<P.Telemetry>();
public P.MiningRegion Region=new P.MiningRegion {Id="search-1",Search=true,Radius=300,Center=Vector3D.Zero};
public MapRole(P p):base(p){}
public override List<P.Job> GetJobs(){return Jobs;}
public override List<P.Telemetry> GetTelemetry(){return Fleet;}
public override P.MiningRegion MapRegion(string id){return Region.Id==id?Region:null;}
}
sealed class Rig
{
public readonly P Program=TestRig.Program("[Display]\nBuiltInPage=map\n");
public readonly List<MySprite> Sprites=new List<MySprite>();
public readonly P.Dashboard Dashboard;
public readonly MapRole Role;
public Rig(int width=1024,int height=512)
{
var surface=new Stub<IMyTextSurface>().Set("SurfaceSize",new Vector2(width,height)).Set("TextureSize",new Vector2(width,height))
.Method("MeasureStringInPixels",a=>new Vector2(a[0].ToString().Sum(ch=>ch>=0x2e80?32:16),32)*(float)a[2])
.Method("DrawFrame",a=>new MySpriteDrawFrame(f=>{Sprites.Clear();f.AddToList(Sprites);}));
var pb=new Stub<IMyProgrammableBlock>().Set("EntityId",20L).Set("CubeGrid",Program.Me.CubeGrid).Set("CustomData","")
.Set("CustomName","PB").Set("SurfaceCount",1).Method("GetSurface",a=>surface.Value);
TestRig.SetBase(Program,"Me",pb.Value);TestRig.SetBase(Program,"GridTerminalSystem",new Stub<IMyGridTerminalSystem>().Value);
Dashboard=new P.Dashboard(Program);Role=new MapRole(Program);
}
public void Add(P.ScanRecord scan=null,string outcome="",long entity=0)
{
Role.Jobs.Add(new P.Job {Id="ray-"+Role.Jobs.Count,RegionId=Role.Region.Id,Kind=P.JobKind.Survey,Entry=Vector3D.Zero,Depth=300,Scan=scan,Outcome=outcome,EntityId=entity});
}
public void Draw(double now=0){Program.Now=now;Dashboard.Draw(Role);}
public string[] Text=>Sprites.Where(s=>s.Type==SpriteType.TEXT).Select(s=>s.Data).ToArray();
public MySprite[] Cells=>Sprites.Where(s=>s.Color==new Color(34,84,113)).ToArray();
}
[Fact]
public void ActualHitStopsTheRecordedRayAndCarriesWorldBoundsThroughMessageAndJob()
{
var scan=Scan();Assert.Equal(Hit().HitPosition,scan.End);Assert.NotEqual(new Vector3D(300,225,-75),scan.End);
var report=P.JobReport.FromIni(new P.JobReport {Scan=scan,Outcome="SurveyHit"}.ToIni());
var job=P.Job.FromIni(new P.Job {Id="j",Scan=report.Scan}.ToIni());
Assert.Equal(42,job.Scan.Asteroid);Assert.Equal(Hit().BoundingBox.Center,job.Scan.Center);Assert.Equal(new Vector3D(60),job.Scan.Size);Assert.Equal(Vector3D.Zero,job.Scan.Start);
}
[Fact]
public void LegacyMessagesAndJobsHaveNoInventedRayOrSize()
{
Assert.Null(P.JobReport.FromIni(new MyIni()).Scan);Assert.Null(P.Job.FromIni(new P.Job {Id="old"}.ToIni()).Scan);
var r=new Rig();r.Add(outcome:"SurveyEmpty");r.Draw();Assert.Empty(r.Cells);
Assert.Contains(P.L.F(P.L.DisplayScanSummary,0,1,0,0),r.Text);
}
[Fact]
public void EmptyRayIsRecordedWhilePlanetAndGridAreNotCountedAsAsteroids()
{
var end=new Vector3D(20,30,40);var empty=P.ScanRecord.Capture(Vector3D.Zero,end,new MyDetectedEntityInfo());
Assert.Equal(end,empty.End);Assert.Equal(0,empty.Asteroid);
Assert.Equal(0,P.ScanRecord.Capture(Vector3D.Zero,end,Hit(type:MyDetectedEntityType.Planet)).Asteroid);
Assert.Equal(0,P.ScanRecord.Capture(Vector3D.Zero,end,Hit(type:MyDetectedEntityType.LargeGrid)).Asteroid);
}
[Fact]
public void InvalidAndMissingCoordinatesDoNotInventMapEvidence()
{
Assert.Null(P.ScanRecord.Capture(new Vector3D(double.NaN),Vector3D.Zero,Hit()));
var i=new MyIni();i.Set("job","ScanStart","NaN,0,0");Assert.Null(P.ScanRecord.Read(i,"job"));
var info=new MyDetectedEntityInfo(42,"rock",MyDetectedEntityType.Asteroid,null,MatrixD.Identity,Vector3.Zero,VRage.Game.MyRelationsBetweenPlayerAndBlock.NoOwnership,new BoundingBoxD(),1);
Assert.Null(P.ScanRecord.Capture(Vector3D.Zero,Vector3D.Forward,info));
}
[Fact]
public void RepeatedHitsCountOneAsteroidAndOneBoundingProjection()
{
var r=new Rig();r.Add(Scan(),"SurveyHit");r.Add(Scan(),"SurveyHit");r.Draw();
Assert.Contains(P.L.F(P.L.DisplayScanSummary,2,2,1,0),r.Text);
Assert.Contains(P.L.F(P.L.DisplayRockArea,"3600 m2",1,1,1),r.Text);
Assert.Single(r.Text,s=>s.StartsWith("A1 "));Assert.DoesNotContain(r.Text,s=>s.StartsWith("A2 "));
}
[Fact]
public void UnknownSizeRemainsUnknownAndCanBeReplacedByMeasuredBounds()
{
var r=new Rig();var unknown=Scan();unknown.Size=Vector3D.Zero;r.Add(unknown,"SurveyHit");r.Draw();
Assert.Contains("A1 ?",r.Text);Assert.Contains(P.L.F(P.L.DisplayScanSummary,1,1,1,1),r.Text);
r.Add(Scan(),"SurveyHit");r.Draw(1);Assert.Contains("A1 ~3600 m2",r.Text);Assert.Contains(P.L.F(P.L.DisplayScanSummary,2,2,1,0),r.Text);
}
[Fact]
public void RotatedMapUsesProjectedDimensionsRatherThanWorldXYArea()
{
var r=new Rig();r.Role.Region.Direction=Vector3D.Right;r.Role.Region.Up=Vector3D.Up;
var scan=Scan();scan.Size=new Vector3D(40,50,60);r.Add(scan,"SurveyHit");r.Draw();
Assert.Contains("A1 ~3000 m2",r.Text);
}
[Fact]
public void UnexecutedAndBlockedWithoutScanDoNotPaintCoverage()
{
var r=new Rig();r.Add();r.Add(outcome:"Blocked");r.Draw();Assert.Empty(r.Cells);
r.Add(new P.ScanRecord {Start=Vector3D.Zero,End=new Vector3D(90,0,0)},"SurveyEmpty");r.Draw(1);
Assert.NotEmpty(r.Cells);Assert.All(r.Cells,s=>Assert.InRange(s.Position.Value.X,512,555));
Assert.Contains(P.L.DisplayScanCaution,r.Text);
}
[Fact]
public void ParallelRayEntirelyOutsideSearchDoesNotPaintAnEdge()
{
var r=new Rig();r.Add(new P.ScanRecord {Start=new Vector3D(400,-200,0),End=new Vector3D(400,200,0)},"SurveyEmpty");r.Draw();Assert.Empty(r.Cells);
}
[Theory]
[InlineData(512,512)] [InlineData(1024,512)] [InlineData(512,1024)]
public void SixteenCoincidentMinersKeepDistinctIdRowsAndMarkOffline(int width,int height)
{
var r=new Rig(width,height);r.Add(Scan(),"SurveyHit");
for(int n=1;n<=16;n++)r.Role.Fleet.Add(new P.Telemetry {Id="miner-"+n.ToString("00"),State=P.FlightState.Transit,ReceivedAt=n==16?-100:0});
r.Draw();var labels=r.Sprites.Where(s=>s.Type==SpriteType.TEXT && s.Data.StartsWith("miner-")).ToArray();
Assert.Equal(16,labels.Length);Assert.Equal(16,labels.Select(s=>s.Position.Value).Distinct().Count());
Assert.Contains(labels,s=>s.Data.Contains(P.L.DisplayOffline));
Assert.All(labels,s=>{Assert.InRange(s.Position.Value.X,0,width);Assert.InRange(s.Position.Value.Y,0,height);});
}
[Fact]
public void MoreAsteroidsCarouselWithoutLosingTotalOrCoverage()
{
var r=new Rig();for(int n=0;n<12;n++)r.Add(Scan(42+n),"SurveyHit");r.Draw();var cells=r.Cells.Length;
Assert.Contains(r.Text,s=>s.StartsWith("A1 "));Assert.DoesNotContain(r.Text,s=>s.StartsWith("A9 "));
r.Draw(8);Assert.Contains(r.Text,s=>s.StartsWith("A9 "));Assert.Equal(cells,r.Cells.Length);
Assert.Contains(P.L.F(P.L.DisplayScanSummary,12,12,12,0),r.Text);
}
[Fact]
public void PlannerCheckpointRetainsBoundsAndClearTasksRemovesThem()
{
var planner=new P.TaskPlanner(TestRig.Program());planner.Survey(Vector3D.Zero,Vector3D.Zero,Vector3D.Forward,Vector3D.Up,300);
var job=planner.Jobs.First();planner.Report(job,new P.JobReport {JobId=job.Id,Outcome="SurveyHit",Position=Scan().End,Direction=Vector3D.Forward,EntityId=42,Scan=Scan()});
var save=new MyIni();planner.Save(save);var restored=new P.TaskPlanner(TestRig.Program());restored.Load(save);
Assert.Equal(new Vector3D(60),restored.Find(job.Id).Scan.Size);restored.ClearTasks();Assert.Empty(restored.Jobs);
}
[Fact]
public void CameraSurveySendsActualRayEvidenceToTheFleet()
{
var r=new MinerStateTests.MinerRig();r.Task();var flags=BindingFlags.Instance|BindingFlags.NonPublic;
var job=(P.Job)r.Miner.GetType().GetField("job",flags).GetValue(r.Miner);job.Kind=P.JobKind.Survey;r.CameraHit=Hit();r.State(P.FlightState.Survey);
r.Miner.GetType().GetMethod("Survey",flags).Invoke(r.Miner,new object[]{.1});
var report=P.JobReport.FromIni(Assert.Single(r.Sent,p=>p.Kind=="RESULT").Body);
Assert.Equal(r.Position,report.Scan.Start);Assert.Equal(Hit().HitPosition,report.Scan.End);Assert.True(report.Scan.Sized);
}
[Fact]
public void RepresentativeMapFrameContainsRaysRocksAndMinerIds()
{
var r=new Rig();for(int n=0;n<24;n++){double a=n*Math.PI/12;r.Add(new P.ScanRecord {Start=Vector3D.Zero,End=new Vector3D(Math.Cos(a)*280,Math.Sin(a)*280,0)},"SurveyEmpty");}
r.Add(Scan(),"SurveyHit");var other=Scan(99);other.Center=new Vector3D(-120,-100,0);other.End=other.Center;other.Size=new Vector3D(90,70,30);r.Add(other,"SurveyHit");
for(int n=1;n<=5;n++)r.Role.Fleet.Add(new P.Telemetry {Id=P.L.Language=="zh-CN"?"深空工业"+n+"号":"Miner-"+n,Position=new Vector3D((n-3)*40,40,0),ReceivedAt=n==5?-100:0});
r.Draw();Assert.NotEmpty(r.Cells);Assert.Contains("A1 ~3600 m2",r.Text);
string path=Environment.GetEnvironmentVariable("AMS_MAP_PREVIEW");if(string.IsNullOrEmpty(path))return;
File.WriteAllLines(path,r.Sprites.Select(s=>string.Join("\t",new[]{s.Type.ToString(),Convert.ToBase64String(Encoding.UTF8.GetBytes(s.Data??"")),
(s.Position??Vector2.Zero).X.ToString(P.Data.Culture),(s.Position??Vector2.Zero).Y.ToString(P.Data.Culture),(s.Size??Vector2.Zero).X.ToString(P.Data.Culture),(s.Size??Vector2.Zero).Y.ToString(P.Data.Culture),
s.RotationOrScale.ToString(P.Data.Culture),s.Alignment.ToString(),(s.Color??Color.White).R.ToString(),(s.Color??Color.White).G.ToString(),(s.Color??Color.White).B.ToString(),(s.Color??Color.White).A.ToString()})),Encoding.UTF8);
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Sandbox.ModAPI.Ingame;
using VRage.Game.GUI.TextPanel;
using VRage.Game.ModAPI.Ingame.Utilities;
using VRageMath;
using Xunit;
using P=AutoMiningScript.Program;
namespace AutoMiningScript.Tests
{
public class ExplorationMapTests
{
static MyDetectedEntityInfo Hit(long id=42, MyDetectedEntityType type=MyDetectedEntityType.Asteroid)
{
return new MyDetectedEntityInfo(id,"rock",type,new Vector3D(80,60,-20),MatrixD.Identity,Vector3.Zero,
VRage.Game.MyRelationsBetweenPlayerAndBlock.NoOwnership,new BoundingBoxD(new Vector3D(50,30,-40),new Vector3D(110,90,20)),1);
}
static P.ScanRecord Scan(long id=42) { return P.ScanRecord.Capture(Vector3D.Zero,new Vector3D(300,225,-75),Hit(id)); }
sealed class MapRole:P.RoleLogic
{
public readonly List<P.Job> Jobs=new List<P.Job>();
public readonly List<P.Telemetry> Fleet=new List<P.Telemetry>();
public P.MiningRegion Region=new P.MiningRegion {Id="search-1",Search=true,Radius=300,Center=Vector3D.Zero};
public MapRole(P p):base(p){}
public override List<P.Job> GetJobs(){return Jobs;}
public override List<P.Telemetry> GetTelemetry(){return Fleet;}
public override P.MiningRegion MapRegion(string id){return Region.Id==id?Region:null;}
}
sealed class Rig
{
public readonly P Program=TestRig.Program("[Display]\nBuiltInPage=map\n");
public readonly List<MySprite> Sprites=new List<MySprite>();
public readonly P.Dashboard Dashboard;
public readonly MapRole Role;
public Rig(int width=1024,int height=512)
{
var surface=new Stub<IMyTextSurface>().Set("SurfaceSize",new Vector2(width,height)).Set("TextureSize",new Vector2(width,height))
.Method("MeasureStringInPixels",a=>new Vector2(a[0].ToString().Sum(ch=>ch>=0x2e80?32:16),32)*(float)a[2])
.Method("DrawFrame",a=>new MySpriteDrawFrame(f=>{Sprites.Clear();f.AddToList(Sprites);}));
var pb=new Stub<IMyProgrammableBlock>().Set("EntityId",20L).Set("CubeGrid",Program.Me.CubeGrid).Set("CustomData","")
.Set("CustomName","PB").Set("SurfaceCount",1).Method("GetSurface",a=>surface.Value);
TestRig.SetBase(Program,"Me",pb.Value);TestRig.SetBase(Program,"GridTerminalSystem",new Stub<IMyGridTerminalSystem>().Value);
Dashboard=new P.Dashboard(Program);Role=new MapRole(Program);
}
public void Add(P.ScanRecord scan=null,string outcome="",long entity=0)
{
Role.Jobs.Add(new P.Job {Id="ray-"+Role.Jobs.Count,RegionId=Role.Region.Id,Kind=P.JobKind.Survey,Entry=Vector3D.Zero,Depth=300,Scan=scan,Outcome=outcome,EntityId=entity});
}
public void Draw(double now=0){Program.Now=now;Dashboard.Draw(Role);}
public string[] Text=>Sprites.Where(s=>s.Type==SpriteType.TEXT).Select(s=>s.Data).ToArray();
public MySprite[] Cells=>Sprites.Where(s=>s.Color==new Color(34,84,113)).ToArray();
}
[Fact]
public void ActualHitStopsTheRecordedRayAndCarriesWorldBoundsThroughMessageAndJob()
{
var scan=Scan();Assert.Equal(Hit().HitPosition,scan.End);Assert.NotEqual(new Vector3D(300,225,-75),scan.End);
var report=P.JobReport.FromIni(new P.JobReport {Scan=scan,Outcome="SurveyHit"}.ToIni());
var job=P.Job.FromIni(new P.Job {Id="j",Scan=report.Scan}.ToIni());
Assert.Equal(42,job.Scan.Asteroid);Assert.Equal(Hit().BoundingBox.Center,job.Scan.Center);Assert.Equal(new Vector3D(60),job.Scan.Size);Assert.Equal(Vector3D.Zero,job.Scan.Start);
}
[Fact]
public void LegacyMessagesAndJobsHaveNoInventedRayOrSize()
{
Assert.Null(P.JobReport.FromIni(new MyIni()).Scan);Assert.Null(P.Job.FromIni(new P.Job {Id="old"}.ToIni()).Scan);
var r=new Rig();r.Add(outcome:"SurveyEmpty");r.Draw();Assert.Empty(r.Cells);
Assert.Contains(P.L.F(P.L.DisplayScanSummary,0,1,0,0),r.Text);
}
[Fact]
public void EmptyRayIsRecordedWhilePlanetAndGridAreNotCountedAsAsteroids()
{
var end=new Vector3D(20,30,40);var empty=P.ScanRecord.Capture(Vector3D.Zero,end,new MyDetectedEntityInfo());
Assert.Equal(end,empty.End);Assert.Equal(0,empty.Asteroid);
Assert.Equal(0,P.ScanRecord.Capture(Vector3D.Zero,end,Hit(type:MyDetectedEntityType.Planet)).Asteroid);
Assert.Equal(0,P.ScanRecord.Capture(Vector3D.Zero,end,Hit(type:MyDetectedEntityType.LargeGrid)).Asteroid);
}
[Fact]
public void InvalidAndMissingCoordinatesDoNotInventMapEvidence()
{
Assert.Null(P.ScanRecord.Capture(new Vector3D(double.NaN),Vector3D.Zero,Hit()));
var i=new MyIni();i.Set("job","ScanStart","NaN,0,0");Assert.Null(P.ScanRecord.Read(i,"job"));
var info=new MyDetectedEntityInfo(42,"rock",MyDetectedEntityType.Asteroid,null,MatrixD.Identity,Vector3.Zero,VRage.Game.MyRelationsBetweenPlayerAndBlock.NoOwnership,new BoundingBoxD(),1);
Assert.Null(P.ScanRecord.Capture(Vector3D.Zero,Vector3D.Forward,info));
}
[Fact]
public void RepeatedHitsCountOneAsteroidAndOneBoundingProjection()
{
var r=new Rig();r.Add(Scan(),"SurveyHit");r.Add(Scan(),"SurveyHit");r.Draw();
Assert.Contains(P.L.F(P.L.DisplayScanSummary,2,2,1,0),r.Text);
Assert.Contains(P.L.F(P.L.DisplayRockArea,"3600 m2",1,1,1),r.Text);
Assert.Single(r.Text,s=>s.StartsWith("A1 "));Assert.DoesNotContain(r.Text,s=>s.StartsWith("A2 "));
}
[Fact]
public void UnknownSizeRemainsUnknownAndCanBeReplacedByMeasuredBounds()
{
var r=new Rig();var unknown=Scan();unknown.Size=Vector3D.Zero;r.Add(unknown,"SurveyHit");r.Draw();
Assert.Contains("A1 ?",r.Text);Assert.Contains(P.L.F(P.L.DisplayScanSummary,1,1,1,1),r.Text);
r.Add(Scan(),"SurveyHit");r.Draw(1);Assert.Contains("A1 ~3600 m2",r.Text);Assert.Contains(P.L.F(P.L.DisplayScanSummary,2,2,1,0),r.Text);
}
[Fact]
public void RotatedMapUsesProjectedDimensionsRatherThanWorldXYArea()
{
var r=new Rig();r.Role.Region.Direction=Vector3D.Right;r.Role.Region.Up=Vector3D.Up;
var scan=Scan();scan.Size=new Vector3D(40,50,60);r.Add(scan,"SurveyHit");r.Draw();
Assert.Contains("A1 ~3000 m2",r.Text);
}
[Fact]
public void UnexecutedAndBlockedWithoutScanDoNotPaintCoverage()
{
var r=new Rig();r.Add();r.Add(outcome:"Blocked");r.Draw();Assert.Empty(r.Cells);
r.Add(new P.ScanRecord {Start=Vector3D.Zero,End=new Vector3D(90,0,0)},"SurveyEmpty");r.Draw(1);
Assert.NotEmpty(r.Cells);Assert.All(r.Cells,s=>Assert.InRange(s.Position.Value.X,512,555));
Assert.Contains(P.L.DisplayScanCaution,r.Text);
}
[Fact]
public void ParallelRayEntirelyOutsideSearchDoesNotPaintAnEdge()
{
var r=new Rig();r.Add(new P.ScanRecord {Start=new Vector3D(400,-200,0),End=new Vector3D(400,200,0)},"SurveyEmpty");r.Draw();Assert.Empty(r.Cells);
}
[Theory]
[InlineData(512,512)] [InlineData(1024,512)] [InlineData(512,1024)]
public void SixteenCoincidentMinersKeepDistinctIdRowsAndMarkOffline(int width,int height)
{
var r=new Rig(width,height);r.Add(Scan(),"SurveyHit");
for(int n=1;n<=16;n++)r.Role.Fleet.Add(new P.Telemetry {Id="miner-"+n.ToString("00"),State=P.FlightState.Transit,ReceivedAt=n==16?-100:0});
r.Draw();var labels=r.Sprites.Where(s=>s.Type==SpriteType.TEXT && s.Data.StartsWith("miner-")).ToArray();
Assert.Equal(16,labels.Length);Assert.Equal(16,labels.Select(s=>s.Position.Value).Distinct().Count());
Assert.Contains(labels,s=>s.Data.Contains(P.L.DisplayOffline));
Assert.All(labels,s=>{Assert.InRange(s.Position.Value.X,0,width);Assert.InRange(s.Position.Value.Y,0,height);});
}
[Fact]
public void MoreAsteroidsCarouselWithoutLosingTotalOrCoverage()
{
var r=new Rig();for(int n=0;n<12;n++)r.Add(Scan(42+n),"SurveyHit");r.Draw();var cells=r.Cells.Length;
Assert.Contains(r.Text,s=>s.StartsWith("A1 "));Assert.DoesNotContain(r.Text,s=>s.StartsWith("A9 "));
r.Draw(8);Assert.Contains(r.Text,s=>s.StartsWith("A9 "));Assert.Equal(cells,r.Cells.Length);
Assert.Contains(P.L.F(P.L.DisplayScanSummary,12,12,12,0),r.Text);
}
[Fact]
public void PlannerCheckpointRetainsBoundsAndClearTasksRemovesThem()
{
var planner=new P.TaskPlanner(TestRig.Program());planner.Survey(Vector3D.Zero,Vector3D.Zero,Vector3D.Forward,Vector3D.Up,300);
var job=planner.Jobs.First();planner.Report(job,new P.JobReport {JobId=job.Id,Outcome="SurveyHit",Position=Scan().End,Direction=Vector3D.Forward,EntityId=42,Scan=Scan()});
var save=new MyIni();planner.Save(save);var restored=new P.TaskPlanner(TestRig.Program());restored.Load(save);
Assert.Equal(new Vector3D(60),restored.Find(job.Id).Scan.Size);restored.ClearTasks();Assert.Empty(restored.Jobs);
}
[Fact]
public void CameraSurveySendsActualRayEvidenceToTheFleet()
{
var r=new MinerStateTests.MinerRig();r.Task();var flags=BindingFlags.Instance|BindingFlags.NonPublic;
var job=(P.Job)r.Miner.GetType().GetField("job",flags).GetValue(r.Miner);job.Kind=P.JobKind.Survey;r.CameraHit=Hit();r.State(P.FlightState.Survey);
r.Miner.GetType().GetMethod("Survey",flags).Invoke(r.Miner,new object[]{.1});
var report=P.JobReport.FromIni(Assert.Single(r.Sent,p=>p.Kind=="RESULT").Body);
Assert.Equal(r.Position,report.Scan.Start);Assert.Equal(Hit().HitPosition,report.Scan.End);Assert.True(report.Scan.Sized);
}
[Fact]
public void RepresentativeMapFrameContainsRaysRocksAndMinerIds()
{
var r=new Rig();for(int n=0;n<24;n++){double a=n*Math.PI/12;r.Add(new P.ScanRecord {Start=Vector3D.Zero,End=new Vector3D(Math.Cos(a)*280,Math.Sin(a)*280,0)},"SurveyEmpty");}
r.Add(Scan(),"SurveyHit");var other=Scan(99);other.Center=new Vector3D(-120,-100,0);other.End=other.Center;other.Size=new Vector3D(90,70,30);r.Add(other,"SurveyHit");
for(int n=1;n<=5;n++)r.Role.Fleet.Add(new P.Telemetry {Id=P.L.Language=="zh-CN"?"深空工业"+n+"号":"Miner-"+n,Position=new Vector3D((n-3)*40,40,0),ReceivedAt=n==5?-100:0});
r.Draw();Assert.NotEmpty(r.Cells);Assert.Contains("A1 ~3600 m2",r.Text);
string path=Environment.GetEnvironmentVariable("AMS_MAP_PREVIEW");if(string.IsNullOrEmpty(path))return;
File.WriteAllLines(path,r.Sprites.Select(s=>string.Join("\t",new[]{s.Type.ToString(),Convert.ToBase64String(Encoding.UTF8.GetBytes(s.Data??"")),
(s.Position??Vector2.Zero).X.ToString(P.Data.Culture),(s.Position??Vector2.Zero).Y.ToString(P.Data.Culture),(s.Size??Vector2.Zero).X.ToString(P.Data.Culture),(s.Size??Vector2.Zero).Y.ToString(P.Data.Culture),
s.RotationOrScale.ToString(P.Data.Culture),s.Alignment.ToString(),(s.Color??Color.White).R.ToString(),(s.Color??Color.White).G.ToString(),(s.Color??Color.White).B.ToString(),(s.Color??Color.White).A.ToString()})),Encoding.UTF8);
}
}
}